Spring Boot에서 request body의 선택적 필드를 어떻게 처리하나요?
Source: Dev.to
온라인에서 회원가입 양식을 작성하는 것을 생각해 보세요.
username과 password와 같은 일부 필드는 필수이지만, profile description이나 preferences와 같은 다른 필드는 선택 사항입니다.
선택적인 필드를 건너뛰었다고 해서 양식이 실패하길 기대하지 않겠죠—맞나요?
이와 같은 개념은 REST API에도 적용됩니다. 클라이언트가 요청 본문을 보낼 때, 모든 필드가 반드시 필요하지는 않습니다. Spring Boot에서 요청 본문의 선택적 필드를 처리하는 방법을 아는 것은 유연하고, 이전 버전과 호환되며, 초보자 친화적인 API를 구축하는 데 필수적입니다.
이 블로그에서는 간단한 언어, 실제 사례 비유, 그리고 cURL 요청 및 응답을 포함한 완전한 엔드‑투‑엔드 예제를 사용해 이 개념을 단계별로 배우게 됩니다.
핵심 개념
요청 본문에서 선택적 필드란 무엇인가요?
선택적 필드는 JSON 속성으로서:
- 요청에 포함될 수도 있고 포함되지 않을 수도 있음
- 누락되더라도 API가 오류를 일으키지 않음
- 보통 기본값이 있거나 조건부 로직을 가짐
예시 요청 본문
{
"username": "sample_user",
"password": "secret123",
"description": "Loves backend development"
}
여기서:
username,password→ 필수description→ 선택적
🧠 비유
요청 본문은 양식과 같습니다:
- 필수 필드 = 반드시 답해야 하는 질문
- 선택적 필드 = 건너뛸 수 있는 추가 세부 사항
Spring Boot이 누락된 필드를 처리하는 방법
Spring Boot (Jackson 사용):
- JSON을 자동으로 Java 객체에 매핑
- 누락된 필드는
null로 설정 - 기본값 및 검증 어노테이션을 지원
수동 파싱이 필요하지 않습니다.
일반적인 사용 사례
- ✅ 부분 데이터 제출
- ✅ 이전 버전과의 호환성 유지
- ✅ 선택적 사용자 환경설정
- ✅ 기능 토글
- ✅ API 진화에 따른 확장
코드 예제 (엔드‑투‑엔드)
✅ 예시 1: 검증 및 기본값이 있는 선택적 필드
사용 사례
일부 필드가 선택적인 사용자를 생성합니다.
1단계 – 요청 DTO
package com.example.demo.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class CreateUserRequest {
@NotBlank(message = "Username is required")
private String username;
@NotBlank(message = "Password is required")
@Size(min = 6, message = "Password must be at least 6 characters")
private String password;
// Optional field
private String description;
// Optional field with default value
private boolean notificationsEnabled = false;
// Getters and setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isNotificationsEnabled() {
return notificationsEnabled;
}
public void setNotificationsEnabled(boolean notificationsEnabled) {
this.notificationsEnabled = notificationsEnabled;
}
}
2단계 – REST 컨트롤러
package com.example.demo.controller;
import com.example.demo.dto.CreateUserRequest;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@Valid @RequestBody CreateUserRequest request) {
String description = request.getDescription() != null
? request.getDescription()
: "No description provided";
return "User created successfully. " +
"username=" + request.getUsername() +
", description=" + description +
", notificationsEnabled=" + request.isNotificationsEnabled();
}
}
3단계 – cURL 로 테스트
✅ 요청 (선택적 필드 누락)
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{
"username": "sample_user",
"password": "secret123"
}'
✅ 응답
User created successfully. username=sample_user, description=No description provided, notificationsEnabled=false
❌ 요청 (필수 필드 누락)
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{
"username": "sample_user"
}'
❌ 응답
{
"status": 400,
"error": "Bad Request",
"message": "Password is required"
}
✅ 예시 2: Optional 을 사용한 선택적 필드 (PATCH에 최적)
사용 사례
사용자 선호도를 부분적으로 업데이트합니다.
1단계 – 요청 DTO
package com.example.demo.dto;
import java.util.Optional;
public class UpdatePreferencesRequest {
private Optional<String> theme = Optional.empty();
private Optional<Boolean> notificationsEnabled = Optional.empty();
public Optional<String> getTheme() {
return theme;
}
public void setTheme(Optional<String> theme) {
this.theme = theme;
}
public Optional<Boolean> getNotificationsEnabled() {
return notificationsEnabled;
}
public void setNotificationsEnabled(Optional<Boolean> notificationsEnabled) {
this.notificationsEnabled = notificationsEnabled;
}
}
2단계 – 컨트롤러
package com.example.demo.controller;
import com.example.demo.dto.UpdatePreferencesRequest;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserPreferenceController {
@PatchMapping("/{id}/preferences")
public String updatePreferences(@PathVariable Long id,
@RequestBody UpdatePreferencesRequest request) {
// Simulated existing user data
String currentTheme = "light";
boolean currentNotifications = true;
// Apply updates only if present
String newTheme = request.getTheme().orElse(currentTheme);
boolean newNotifications = request.getNotificationsEnabled()
.orElse(currentNotifications);
// In a real app you would persist the changes here
return "Preferences updated for user " + id +
". theme=" + newTheme +
", notificationsEnabled=" + newNotifications;
}
}
단계 3 – cURL로 테스트
✅ 부분 업데이트 (테마만)
curl -X PATCH http://localhost:8080/users/42/preferences \
-H "Content-Type: application/json" \
-d '{"theme":"dark"}'
✅ 응답
Preferences updated for user 42. theme=dark, notificationsEnabled=true
✅ 부분 업데이트 (알림 플래그만)
curl -X PATCH http://localhost:8080/users/42/preferences \
-H "Content-Type: application/json" \
-d '{"notificationsEnabled":false}'
✅ 응답
Preferences updated for user 42. theme=light, notificationsEnabled=false
요약
- Optional fields는 기존 클라이언트를 깨뜨리지 않고 API가 진화하도록 합니다.
- Spring Boot (Jackson)는 누락된 JSON 속성을 자동으로
null또는 기본값에 매핑합니다. - 필수 필드에는 validation annotations(
@NotBlank,@Size등)를 사용합니다. - partial updates(
PATCH)의 경우, 필드를Optional로 감싸면 의도가 명확해지고null‑검사 보일러플레이트를 피할 수 있습니다.
이러한 패턴을 적용하면 견고하고 개발자‑친화적인 API를 만들 수 있습니다. 즐거운 코딩 되세요!
package com.example.demo.dto;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/preferences")
public class PreferencesController {
@PatchMapping
public String updatePreferences(@RequestBody UpdatePreferencesRequest request) {
request.getTheme()
.ifPresent(t -> System.out.println("Updating theme to: " + t));
request.getNotificationsEnabled()
.ifPresent(n -> System.out.println("Updating notifications: " + n));
return "Preferences updated successfully";
}
}
Step 3: cURL 로 테스트
✅ 요청 (하나의 필드만 제공)
curl -X PATCH http://localhost:8080/preferences \
-H "Content-Type: application/json" \
-d '{
"theme": "dark"
}'
✅ 응답
Preferences updated successfully
Best Practices
- 필수 필드만 검증 – 선택적 필드에 검증 제약을 적용하지 마세요.
- 합리적인 기본값 제공 – 불필요한 클라이언트‑사이드 작업을 방지합니다.
Optional은 주로 부분 업데이트에 사용 –PATCH에 이상적이며 모든 DTO에 사용할 필요는 없습니다.- 역호환성을 고려한 API 설계 – 선택적 필드는 안전한 진화를 가능하게 합니다.
null값을 명시적으로 처리 – 선택적 필드가 항상 존재한다고 가정하지 마세요.
결론
옵션 필드를 올바르게 처리하는 것은 Spring Boot에서 핵심 API‑설계 기술입니다. 다음과 같이 사용함으로써:
- 검증 어노테이션
- 기본값
- 적절한 경우
Optional
유연하고, 견고하며, 초보자 친화적인 API를 구축할 수 있습니다.
Spring Boot에서 요청 본문의 옵션 필드 처리를 마스터하면 Java 프로그래밍 기본기를 강화하고 실제 백엔드 패턴을 통해 Java를 배우는 데 도움이 됩니다.
행동 촉구
💬 선택적 필드 또는 요청 검증에 대한 질문이 있나요?
👇 아래 댓글에 남겨 주세요!