
이 글은 스프링부트3 백엔드 개발자 되기 책을 바탕으로 공부한 내용을 정리한 게시글 입니다.
스프링 계층구조에 맞춰 블로그에 글 삭제 및 수정 메소드를 구성해보겠습니다.
먼저 블로그 글 삭제 API를 구현해보겠습니다.
1. 블로그 삭제 API 구현
1. 서비스 메서드 코드 작성
글 ID에 해당하는 블로그 글을 삭제하는 API를 구현합니다. 삭제 API도 서비스 메서드 코드부터 작성하겠습니다.
엔티티에 요청받을 내용으로 값을 수정하는 메서드를 작성하였습니다.
BlogService.java 파일을 열어 delete()메서드를 추가합니다.
public void delete(long id) {
blogRepository.deleteById(id);
}
delete()메서드는 Spring Data JPA의 CRUD메서드 중 하나로 메서드가 실행되면 따로 쿼리문을 작성할 필요 없이 SQL문을 자동으로 실행시켜 해당 id에 일치하는 글을 제거해 줍니다.
2. 컨트롤러 메서드 코드 작성
이제 컨트롤러 메소드를 작성하겠습니다.
api/articles/{id}에 DELETE 요청이 들어오면 해당 글을 삭제하기 위한 findArticles() 메서드를 작성하겠습니다.
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Void> deleteArticle(@PathVariable long id) {
blogService.delete(id);
return ResponseEntity.ok()
.build();
}
api/articles/{id} DELETE요청이 오면 {id}에 해당하는 값이 @PathVariable 애너테이션을 통해 들어옵니다.
3. 테스트 코드 작성
given-when-then 패턴을 이용하여 테스트 코드를 작성하겠습니다.
given: 블로그 글을 저장합니다.
when: 저장한 블로그 글의 id값으로 삭제 API를 호출합니다.
then: 응답코드가 200OK이고 블로그 글 리스트를 전체 조회해 조회한 배열 크기가 0인지 확인 합니다.
@DisplayName("deleteArticle: 블로그 글 삭제에 성공한다.")
@Test
public void deleteArticle() throws Exception {
// given
final String url = "/api/articles/{id}";
final String title = "title";
final String content = "content";
Article savedArticle = blogRepository.save(Article.builder()
.title(title)
.content(content)
.build());
// when
mockMvc.perform(delete(url, savedArticle.getId()))
.andExpect(status().isOk());
// then
List<Article> articles = blogRepository.findAll();
assertThat(articles).isEmpty();
}

테스트 코드를 실행해보면 다음과 같이 테스트가 성공한 걸 확인 할 수 있습니다.
2. 블로그 글 수정 API 구현하기
이제 글 수정 API를 구현합니다. 수정API도 서비스 메서드 코드부터 작성하겠습니다. 여기서 작성할 update()메서드는 특정 아이디의 글을 수정합니다.
1. 엔티티에 수정로직 추가해 주기
엔티티에 요청받은 내용으로 값을 수정하는 메서드를 작성하겠습니다. Ariticles.java파일을 열어 update메서드를 추가해주겠습니다.
public void update(String title, String content) {
this.title = title;
this.content = content;
}
엔티티에 Update메서드를 작성하면 엔티티의 수정로직이 엔티티 내부에서 관리되기 때문에 객체 지향적 접근이 가능해집니다.
이렇게 하면 객체의 상태를 변경하는 방법이 명확해지고 코드의 일관성을 유지 할 수 있습니다.
2.DTO 생성하여 객체형식으로 데이터 전송하기
그 다음에는 블로그 글 수정 요청을 받을 DTO를 작성하겠습니다. dto 디렉터리에 UpdateArticleRequest.java 파일을 만들겠습니다.
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class UpdateArticleRequest {
private String title;
private String content;
}
dto를 생성하게 되면 요청객체와 엔티티를 다르게 관리할 수 있어 보안/ 유지 보수 측면에서 이점을 가질 수 있습니다.
3. 서비스 메서드 코드 작성하기
DTO가 완성되었으니 BlogService.java 파일을 열어 repository를 사용해 글을 수정하는Update()메서드를 추가하겠습니다.
@Transactional
public Article update(long id, UpdateArticleRequest request) {
Article article = blogRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found : " + id));
article.update(request.getTitle(), request.getContent());
return article;
}
@Transactional 에너테이션은 매칭한 메서드를 하나의 트랜잭션으로 묶는역할을 합니다. 스프링에서 트랜젝션을 적용하기 위해서는 다른 작업을 할 필요 없이 @Transactional 애너테이션만 사용하면 됩니다. update()메서드는 엔티티의 필드값이 바뀌면 중간에 에러가 발생해도 제대로 된 값 수정을 보장하게 되었습니다.
4. 컨트롤러 메서드 코드 작성하기
/api/articles/{id} PUT 요청이 오면 글을 수정하기 위한 updateArticle() 메서드를 작성하겠습니다.
@PutMapping("/api/articles/{id}")
public ResponseEntity<Article> updateArticle(@PathVariable long id,
@RequestBody UpdateArticleRequest request) {
Article updatedArticle = blogService.update(id, request);
return ResponseEntity.ok()
.body(updatedArticle);
}
/api/articles/{id} PUT요청이 오면 Request Body 정보가 request로 넘어옵니다. 그리고 다시 서비스 클래스의 update()메서드의 id와 request를 넘겨주게 됩니다. 응답 값은 body에 담아 전송합니다.
5. 테스트 코드 작성
이제 테스트 코드를 작성하겠습니다.
@DisplayName("updateArticle: 블로그 글 수정에 성공한다.")
@Test
public void updateArticle() throws Exception {
// given
final String url = "/api/articles/{id}";
final String title = "title";
final String content = "content";
Article savedArticle = blogRepository.save(Article.builder()
.title(title)
.content(content)
.build());
final String newTitle = "new title";
final String newContent = "new content";
UpdateArticleRequest request = new UpdateArticleRequest(newTitle, newContent);
// when
ResultActions result = mockMvc.perform(put(url, savedArticle.getId())
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request)));
// then
result.andExpect(status().isOk());
Article article = blogRepository.findById(savedArticle.getId()).get();
assertThat(article.getTitle()).isEqualTo(newTitle);
assertThat(article.getContent()).isEqualTo(newContent);
}
given-when-then 패턴을 적용하여 테스트 코드를 작성했습니다.
given:블로그에 글을 저장하고 글 수정에 필요한 객체를 만듭니다.
when: UPDATE API로 수정요청을 보냅니다. 이때 요청 타입은 JSON이며, given절에서 미리 만들어둔 객체를 요청본문으로 함께 보냅니다.
then: 응답코드가 200OK인지 확인 합니다 블로그 글 id로 조회한 후에 값이 수정되었는지 확인합니다.
테스트를 실행해보면

이렇게 성공적으로 실행되는것을 확인 할 수 있습니다.
3. 결론
이렇게 Spring JPA의 메소드를 이용하여 직접 쿼리문을 작성하지 않고도 자동적으로 데이터베이스에 CRUD처리를 할 수 있는 로직을 작성하였습니다. JPA를 사용하면 코드가 간결해지고 객체로 데이터베이스에 접근 할 수 있기 때문에 로직이 훨씬 간단해지고 유지보수성 또한 증가하게 됩니다.
또한 계층구조를 구성하여 프로젝트를 구현하였습니다. . 프레젠테이션계층, 비즈니스계층, 퍼시스턴스계층, 데이터베이스 이렇게 4개의 계층을 구성한 뒤 각 계층간의 상호작용은 dto를 이용하여 상호작용을 할 수 있게 처리하였습니다.
계층을 분리함으로써 각 역할에 맞는 책임을 명확하게 구분할 수 있으며, 코드의 가독성과 유지보수성이 크게 향상되었습니다. 각 계층이 독립적으로 동작하여 변경이 발생해도 다른 계층에 미치는 영향이 최소화 할 수 있었으며 코드 구조가 체계적으로 정리되어있어 기능 추가나 수정을 용이하게 하였습니다. 테스트 환경을 구축하기도 적당하였으며 dto를 활용해서 계층간에 상호작용을 효울적으로 할 수 있게 되었습니다. 결과적으로 계층구조와 dto를 활용한 설계는 보다 안정적이고 효율적인 프로젝트 개발을 가능하게 해주었습니다.
'개발자 취업준비 > springboot' 카테고리의 다른 글
| 스프링시큐리티 (0) | 2025.03.11 |
|---|---|
| 데이터베이스 트랜잭션과 병행 제어 (0) | 2025.02.20 |
| 스프링부트 프로젝트2 글 목록 조회하기 (1) | 2025.02.16 |
| 스프링부트 프로젝트1 계층구조를 구성하여 글 저장 로직 작성하기 (0) | 2025.02.16 |
| API와 REST API (1) | 2025.02.13 |