아래 코드는 Spring 기반 게시판 예제에서 Author(회원) 관련 API를 제공하는 AuthorController를, “컨트롤러가 맡아야 할 책임”과 “예외 처리 개선 흐름” 중심으로 정리한 글이다. (요청/응답 DTO 설계 의도까지 포함)
AuthorController는 Author 관련 HTTP 요청을 받아서 Service에 위임하고, Service가 반환한 DTO를 그대로 응답으로 내려주는 레이어다.
@RequestBody, @PathVariable) @Valid) ResponseEntity) @RestController는 @Controller + @ResponseBody 조합으로, 메서드 반환값을 View 이름이 아니라 HTTP 응답 바디(JSON/Text)로 바로 내려준다.
즉 이 컨트롤러는 “서버 사이드 렌더링(MVC View)”이 아니라 REST API 응답을 만드는 형태다.
클래스 레벨의 @RequestMapping("/author")는 이 컨트롤러가 처리하는 URL에 공통 prefix를 부여한다.
/author/create, /author/list, /author/{id}컨트롤러는 AuthorService 없이는 동작하지 않는다. 코드에서는 이를 명확히 하기 위해 다음 구조를 쓴다.
private final AuthorService authorService;
@Autowired
public AuthorController(AuthorService authorService) {
this.authorService = authorService;
}
여기서 포인트:
final로 선언: 필수 의존성임을 명확히 하고, 생성 시점에 주입이 강제되어 “불완전한 객체”를 방지new AuthorService()를 매번 만들면 in-memory 레포지토리 사용 시 데이터가 매번 초기화되는 문제가 생길 수 있는데, 스프링 DI는 이 문제를 구조적으로 막아준다POST /author/create{"name":"lee", "email":"lee@naver.com", "password":"1234"}
@PostMapping("/create")
public ResponseEntity<?> create(@RequestBody @Valid AuthorCreateDto dto) {
authorService.save(dto);
return ResponseEntity.status(HttpStatus.CREATED).body("OK");
}
@RequestBody: JSON 바디를 AuthorCreateDto로 바인딩@Valid: DTO 필드에 선언된 validation 어노테이션을 동작시키는 트리거201 Created 반환: “생성” API에 더 적절한 상태코드IllegalArgumentException)는 Service에서 발생하고, 컨트롤러는 정상 흐름만 유지하는 방향으로 개선됨AuthorListDto를 사용@GetMapping("/list")
public List<AuthorListDto> findAll() {
return authorService.findAll();
}
ResponseEntity를 쓰지 않아도 기본적으로 200 OK로 내려가며 JSON으로 직렬화된다@GetMapping("/{id}")
public ResponseEntity<?> findById(@PathVariable Long id) {
AuthorDetailDto dto = authorService.findById(id);
return ResponseEntity.status(HttpStatus.OK).body(dto);
}
예전 코드에서는 컨트롤러에서 try-catch로 예외를 잡고 CommonErrorDto를 반환하는 방식이 있었는데, 이 방식은 다음 문제가 있었다.
그래서 개선 방향은:
@RestControllerAdvice 기반 전역 예외 핸들러에서 공통 처리이렇게 하면 응답 포맷(CommonErrorDto)과 상태코드(404, 400 등)를 한 곳에서 통일할 수 있다.
@DeleteMapping("/{id}")
public String delete(@PathVariable Long id) {
authorService.delete(id);
return "OK";
}
"OK" 문자열 반환이지만, 실무적으로는 보통 ResponseEntity<Void>로 204 No Content를 주거나, 표준 응답 포맷을 맞추는 경우도 많다(프로젝트 정책에 따라 선택)이 코드가 의도하는 가장 중요한 학습 포인트는 아래 2가지로 요약된다.
@RestControllerAdvice로 전역 공통 처리하면 코드 중복이 줄고 응답 정책이 통일된다.