RESTful API를 설계할 때, 클라이언트가 서버로부터 의미 있는 응답을 받을 수 있도록 설계하는 것은 매우 중요합니다. 스프링 부트는 ResponseEntity
를 활용하여 HTTP 응답을 유연하고 직관적으로 처리할 수 있도록 지원하며, 기본적으로 JSON 형식의 응답을 제공하여 클라이언트와 효율적으로 데이터를 주고받습니다.
1. ResponseEntity
를 통한 응답 처리
ResponseEntity
는 HTTP 응답의 상태 코드, 헤더, 본문(body)을 설정할 수 있는 클래스입니다. 이를 활용하면 API 응답을 더욱 명확하게 설계할 수 있습니다.
주요 기능
- HTTP 상태 코드 설정: 성공, 실패 여부를 명확히 전달.
- 응답 헤더 추가: 필요한 메타데이터를 포함.
- 응답 본문 설정: 클라이언트에게 반환할 데이터 포함.
1.1 기본 사용 예제
아래 예제는 사용자 정보를 조회한 뒤, 결과에 따라 적절한 HTTP 상태 코드를 반환합니다.
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.findUserById(id);
if (user == null) {
// 404 상태 코드와 빈 응답 반환
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
// 200 상태 코드와 사용자 데이터 반환
return ResponseEntity.ok(user);
}
1.2 상태 코드와 본문 설정
ResponseEntity
를 활용하면 상태 코드와 본문을 유연하게 설정할 수 있습니다.
예제: 리소스 생성
@PostMapping("/users")
public ResponseEntity<String> createUser(@RequestBody User user) {
userService.saveUser(user);
// 201 상태 코드와 성공 메시지 반환
return ResponseEntity.status(HttpStatus.CREATED)
.body("User created successfully!");
}
예제: 리소스 삭제
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
boolean deleted = userService.deleteUser(id);
if (!deleted) {
// 404 상태 코드 반환
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
// 204 상태 코드 반환 (본문 없음)
return ResponseEntity.noContent().build();
}
1.3 헤더 포함 응답
ResponseEntity
를 사용하면 응답 헤더를 쉽게 추가할 수 있습니다.
예제: 응답에 커스텀 헤더 추가
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserWithHeader(@PathVariable Long id) {
User user = userService.findUserById(id);
if (user == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
// 커스텀 헤더 추가
return ResponseEntity.ok()
.header("X-Custom-Header", "CustomHeaderValue")
.body(user);
}
2. JSON 응답 처리
스프링 부트는 Jackson
라이브러리를 통해 객체를 자동으로 JSON으로 변환합니다. 따라서 @RestController
또는 @ResponseBody
를 사용하면 추가 작업 없이도 JSON 응답을 쉽게 생성할 수 있습니다.
2.1 기본 JSON 응답
예제: 객체를 JSON으로 반환
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findUserById(id);
}
- 스프링 부트는 자동으로
User
객체를 JSON으로 변환하여 클라이언트에 반환합니다.
2.2 JSON 필드 제어
@JsonIgnore
또는 @JsonProperty
를 사용하면 JSON 응답의 필드를 세밀하게 제어할 수 있습니다.
- JSON 관련 어노테이션(@JsonIgnore, @JsonProperty, @JsonInclude)은 과거에 많이 사용되었지만, 현재 실무에서는 DTO를 사용하여 응답 데이터를 명확히 관리하고 보안을 강화하는 방식이 훨씬 더 보편적이고 권장되는 방식입니다.
예제: 필드 숨기기
public class User {
private Long id;
private String name;
@JsonIgnore
private String password;
// Getter, Setter
}
password
필드는 JSON 응답에서 제외됩니다.
예제: 필드 이름 변경
public class User {
private Long id;
@JsonProperty("full_name")
private String name;
// Getter, Setter
}
name
필드는 JSON에서full_name
으로 표시됩니다.
2.3 커스터마이징 JSON 출력
스프링에서 ObjectMapper
를 커스터마이징하여 JSON 응답의 형식을 제어할 수 있습니다.
예제: 전역 설정
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // null 값 제외
return mapper;
}
}
3. ResponseEntity
와 JSON의 결합
ResponseEntity
와 JSON 응답을 함께 활용하면 상태 코드, 헤더, JSON 데이터를 조합한 응답을 생성할 수 있습니다.
예제: JSON 데이터와 상태 코드 반환
@GetMapping("/users/{id}")
public ResponseEntity<Map<String, Object>> getUserAsMap(@PathVariable Long id) {
User user = userService.findUserById(id);
if (user == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("message", "User not found");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse);
}
Map<String, Object> successResponse = new HashMap<>();
successResponse.put("id", user.getId());
successResponse.put("name", user.getName());
return ResponseEntity.ok(successResponse);
}
4. 응답 처리 모범 사례
- 적절한 상태 코드 사용: 요청의 결과를 명확히 표현하기 위해 올바른 HTTP 상태 코드를 반환하세요.
- JSON 응답 일관성 유지: 클라이언트가 예측 가능한 구조의 데이터를 받을 수 있도록 통일된 JSON 형식을 유지하세요.
- 에러 메시지 포함: 에러 상황에서는 상태 코드와 함께 명확한 에러 메시지를 JSON으로 제공하세요.
예제: 에러 처리 공통화
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<Map<String, Object>> handleUserNotFound(UserNotFoundException ex) {
Map<String, Object> response = new HashMap<>();
response.put("error", "User Not Found");
response.put("message", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
결론
ResponseEntity
는 상태 코드, 헤더, 본문을 유연하게 처리하여 응답의 가독성과 신뢰성을 높입니다.- 스프링 부트의 JSON 처리 기능을 활용하면 최소한의 설정으로 직관적인 API를 설계할 수 있습니다.
'SpringBoot' 카테고리의 다른 글
Spring Boot: Controller, Service, DAO, DTO (2) | 2024.11.15 |
---|---|
Spring Boot: MyBatis를 활용한 데이터베이스 연동 (0) | 2024.11.14 |
Spring Boot: HTTP 메서드와 매핑 (1) | 2024.11.12 |
Spring Boot: RESTful API란? (0) | 2024.11.11 |
Spring Boot: 의존성 관리 - Starter 패키지 (0) | 2024.11.10 |