Spring Boot
강의

#9 - Controller 코딩 레벨 에서 순서 및 설명

중년개발자
중년개발자

@loxo

4일 전

9

Controller 실무 가이드

Spring Boot에서 Controller를 실제로 어떻게 작성하는가
어노테이션, 클래스, Response 설계를 코딩 순서대로 정리한다


이 문서의 목적

Controller를 설명할 때 가장 많이 나오는 말은 이것이다.

“Controller는 얇아야 한다”

하지만 실무에서는 곧바로 이런 질문이 나온다.

그래서 뭐를 쓰고, 뭐를 어디까지 작성하라는 건데?

이 문서는:

  • Controller에서 반드시 알아야 할 클래스와 어노테이션
  • 실제 코딩 순서에 맞게 설명하고
  • 특히 Response 설계를 실무 기준으로 정리한다.

1. Controller 작성 순서 (이 순서를 지키면 흔들리지 않는다)

Controller는 보통 아래 순서로 작성한다.

  1. Controller 선언
  2. Request 매핑 정의
  3. 요청 데이터 바인딩
  4. 검증 선언
  5. Service 위임
  6. Response 반환

이 순서를 기준으로 하나씩 정리한다.


2. Controller 선언에 필요한 어노테이션

@RestController

java
@RestController

의미:

  • 이 클래스는 HTTP API의 입구
  • 모든 메서드는 기본적으로 JSON Response를 반환한다

포함 관계:

  • @Controller
  • @ResponseBody

👉 API 서버에서는 @Controller 대신 @RestController만 사용한다.


@RequiredArgsConstructor

java
@RequiredArgsConstructor

의미:

  • final 필드에 대해 생성자를 자동 생성
  • Controller에서 Service 주입을 강제적으로 명확하게 만든다

👉 필드 주입(@Autowired)은 사용하지 않는다.


3. Request 매핑 어노테이션

@PostMapping / @GetMapping / @PutMapping / @DeleteMapping

java
@PostMapping("/orders")

의미:

  • HTTP Method + URL을 하나의 유스케이스로 고정

실무 기준:

  • 하나의 Controller 메서드 = 하나의 유스케이스
  • 여러 Service를 조합하지 않는다

4. 요청 데이터 바인딩

@RequestBody

java
public ResponseEntity<Void> create(@RequestBody CreateOrderRequest request)

의미:

  • HTTP Body(JSON)를 Java 객체로 변환

중요한 기준:

  • Entity를 직접 받지 않는다
  • 반드시 전용 Request DTO를 사용한다

@PathVariable / @RequestParam

java
@GetMapping("/orders/{id}") public ResponseEntity<OrderResponse> get(@PathVariable Long id)

역할:

  • URL 자체가 갖는 정보를 명시적으로 드러낸다

5. 검증 어노테이션: 프론트를 믿지 않겠다는 선언

@Valid

java
public ResponseEntity<Void> create( @Valid @RequestBody CreateOrderRequest request )

의미:

  • 이 요청은 검증을 통과해야만 시스템 안으로 들어온다

자주 쓰는 검증 어노테이션:

어노테이션역할
@NotNullnull 금지
@NotBlank빈 문자열 금지
@Positive양수
@Email이메일 형식

👉 검증은 Controller에서 끝내고, Service는 전제를 믿는다.

아래는 실제로 사용하는 @Valid Request DTO 예시다.

java
public record CreateOrderRequest( @NotNull(message = "상품 ID는 필수입니다") Long productId, @Positive(message = "수량은 1 이상이어야 합니다") int quantity, @NotBlank(message = "수령인 이름은 필수입니다") String receiverName, @Email(message = "이메일 형식이 올바르지 않습니다") String receiverEmail ) {}

이 Request DTO의 특징은 다음과 같다.

  • 검증 규칙이 데이터 옆에 붙어 있다
  • if 문이 Controller에 등장하지 않는다
  • "이 값이 유효한가"라는 질문이 Service로 내려가지 않는다

Request DTO는 요청을 신뢰 가능한 형태로 고정하는 역할만 맡는다.


6. Service 호출 기준 (가장 중요한 원칙)

java
orderService.create(request);

Controller에서 Service 호출에 대한 기준은 단순하다.

  • 한 요청 → 한 Service 메서드 호출
  • 여러 규칙이 필요하면 Service를 새로 만든다

Controller는 지휘하지 않는다.
Controller는 위임만 한다.


7. ResponseEntity: 응답의 표준 컨테이너

왜 ResponseEntity를 쓰는가

java
return ResponseEntity.ok(response);

ResponseEntity는 다음을 한 번에 표현한다.

  • HTTP Status
  • Response Body
  • Header

👉 "응답의 의도를 코드로 드러내는 도구"다.


자주 사용하는 Response 패턴

java
// 200 OK ResponseEntity.ok(body) // 201 Created ResponseEntity.status(HttpStatus.CREATED).build() // 204 No Content ResponseEntity.noContent().build() // 400 / 404 / 500 은 예외로 처리

실무 팁:

  • 성공 응답만 Controller에서 만든다
  • 실패 응답은 예외 + @RestControllerAdvice로 통일한다

8. Response 설계의 핵심 원칙

Response는 항상 일관돼야 한다

Response는 클라이언트와의 계약이다.

그래서 실무에서는 보통 다음 중 하나를 선택한다.

패턴 1. HTTP Status + Body 최소화

json
{ "id": 1 }

패턴 2. 공통 Response Wrapper

json
{ "success": true, "data": {...} }

👉 팀 내에서 반드시 하나로 통일해야 한다.


9. DTO → Response DTO 변환 위치

java
Order order = orderService.get(id); return ResponseEntity.ok(OrderResponse.from(order));

허용 기준:

  • 의미 변경 ❌
  • 판단 ❌
  • 표현 변환 ⭕

Controller는 보이게만 바꾼다.


10. Controller 코드 예시 (정석 형태)

java
@RestController @RequiredArgsConstructor class OrderController { private final OrderService orderService; @PostMapping("/orders") public ResponseEntity<Void> create( @Valid @RequestBody CreateOrderRequest request ) { orderService.create(request); return ResponseEntity.status(HttpStatus.CREATED).build(); } @GetMapping("/orders/{id}") public ResponseEntity<OrderResponse> get(@PathVariable Long id) { Order order = orderService.get(id); return ResponseEntity.ok(OrderResponse.from(order)); } }

이 Controller는:

  • 의심하고
  • 위임하고
  • 전달한다

그 이상도, 그 이하도 아니다.


11. 마지막 정리

Controller를 잘 작성했다는 신호는 이것이다.

  • 읽자마자 역할이 보인다
  • 테스트가 쉽다
  • 비즈니스 질문이 떠오르지 않는다

Controller는 코드를 쓰는 곳이 아니라, 경계를 긋는 곳이다.

이 기준을 지키면, Controller는 더 이상 어려운 레이어가 아니다.

#Spring Boot#Controller#REST API#Java#실무가이드

댓글 0

Ctrl + Enter를 눌러 등록할 수 있습니다
※ AI 다듬기는 내용을 정제하는 보조 기능이며, 최종 내용은 사용자가 확인해야 합니다.