본문으로 건너뛰기
Advertisement

3.4 ResponseEntity로 HTTP 응답 완전히 제어하기

1. 단순 반환의 한계

지금까지 컨트롤러에서 객체를 그냥 return하면 스프링이 자동으로 200 OK 상태 코드와 함께 JSON을 보내줬습니다.

@GetMapping("/api/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id); // 항상 200 OK만 반환
}

하지만 실제 API에서는 상황에 따라 다른 HTTP 상태 코드를 정확하게 돌려줘야 합니다.

상황적절한 상태 코드
리소스를 찾을 수 없음404 Not Found
새 리소스 생성 성공201 Created
인증 실패401 Unauthorized
요청 데이터 오류400 Bad Request

이때 사용하는 것이 ResponseEntity<T>입니다.


2. ResponseEntity란?

ResponseEntity<T>는 HTTP 응답의 상태 코드(Status), ** 헤더(Headers)**, ** 본문(Body)**을 모두 직접 제어할 수 있는 스프링의 응답 래퍼 객체입니다.

ResponseEntity<T>
├── Status Code (200, 201, 400, 404 등)
├── Headers (Content-Type, Location 등)
└── Body (T 타입의 응답 데이터)

3. 기본 사용법

3-1. 정적 팩토리 메서드 스타일 (권장)

@GetMapping("/api/users/{id}")
public ResponseEntity<UserResponseDto> getUser(@PathVariable Long id) {
UserResponseDto user = userService.findById(id);

if (user == null) {
// Body 없이 404 상태만 반환
return ResponseEntity.notFound().build();
}

// 200 OK + JSON Body 반환
return ResponseEntity.ok(user);
}

3-2. 리소스 생성 (201 Created)

@PostMapping("/api/users")
public ResponseEntity<UserResponseDto> createUser(@RequestBody UserCreateRequestDto request) {
UserResponseDto created = userService.create(request);

// 201 Created 상태코드 + 생성된 리소스 위치를 Location 헤더에 포함
URI location = URI.create("/api/users/" + created.getId());
return ResponseEntity.created(location).body(created);
}

3-3. 자주 쓰는 정적 메서드 목록

ResponseEntity.ok(body)                   // 200 OK
ResponseEntity.ok().build() // 200 OK (body 없음)
ResponseEntity.created(uri).body(body) // 201 Created
ResponseEntity.noContent().build() // 204 No Content (삭제 등)
ResponseEntity.badRequest().body(body) // 400 Bad Request
ResponseEntity.notFound().build() // 404 Not Found
ResponseEntity.status(HttpStatus.FORBIDDEN).body(body) // custom 상태코드

4. 빌더 스타일 (상세 제어)

상태 코드와 헤더, 본문을 모두 세밀하게 제어해야 할 때는 빌더 패턴을 사용합니다.

@GetMapping("/api/users/{id}")
public ResponseEntity<UserResponseDto> getUser(@PathVariable Long id) {
UserResponseDto user = userService.findById(id);

return ResponseEntity
.status(HttpStatus.OK) // 상태 코드 지정
.header("X-Custom-Header", "value") // 커스텀 헤더 추가
.body(user); // 응답 본문
}

5. DELETE API 예시 (204 No Content)

삭제 성공 시, 일반적으로 응답 본문은 비우고 204 No Content를 돌려주는 것이 REST API 관례입니다.

@DeleteMapping("/api/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204 No Content
}

핵심 정리: ResponseEntity를 사용하면 단순한 객체 반환에서 벗어나, HTTP 표준에 맞는 정확한 상태 코드와 헤더를 포함한 응답을 자유자재로 설계할 수 있습니다. 실무에서는 거의 모든 API 메서드에서 활용합니다.

Advertisement