기술과 산업/언어 및 프레임워크

Java JSON 처리 실전 시리즈 7화 – JSON 응답 필드 제어 전략: null 제외, 조건부 출력, 필터링 방법

B컷개발자 2025. 5. 19. 10:52
728x90

Spring Boot + Jackson 환경에서 JSON 응답 필드를 제어하는 방법을 정리합니다. @JsonInclude, @JsonView, @JsonFilter를 활용한 null 제거, 조건부 노출, 민감 정보 제외 전략을 실전 예제 중심으로 소개합니다.


REST API를 설계하다 보면 다음과 같은 고민이 자주 발생합니다:

  • 값이 null인 필드는 응답에서 빼고 싶다
  • 일부 필드는 관리자만 볼 수 있어야 한다
  • 한 객체를 다양한 응답 구조로 재사용하고 싶다

Jackson은 이런 문제를 해결하기 위한 어노테이션과 설정 옵션을 제공합니다. 이번 글에서는 API 응답을 더 가볍고 안전하게 만들 수 있는 필드 제어 전략을 정리합니다.


1. @JsonInclude – null 또는 빈 값 제외

가장 기본이 되는 필드 제어 전략입니다.

사용 예

@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserResponse {
    private String userName;
    private String email;
    private String phone;
}

동작

UserResponse user = new UserResponse();
user.setUserName("홍길동");
user.setEmail(null);
user.setPhone("");

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);

출력 결과

{
  "userName": "홍길동",
  "phone": ""
}

주요 옵션

설정값 설명

ALWAYS 기본값. 모든 필드 포함
NON_NULL null 필드 제외
NON_EMPTY null 또는 빈 값 제외 ("", 빈 배열 등)
NON_DEFAULT 기본값과 같은 필드 제외

전역 설정 예시 (application.yml):

spring:
  jackson:
    default-property-inclusion: non_null

2. @JsonView – 조건에 따라 다른 응답 구조 만들기

정의

한 객체를 여러 응답 용도로 재사용하고 싶을 때 @JsonView를 사용합니다.

View 정의

public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

적용

public class User {

    @JsonView(Views.Public.class)
    private String userName;

    @JsonView(Views.Internal.class)
    private String email;

    @JsonView(Views.Internal.class)
    private String phone;
}

컨트롤러에서 사용

@GetMapping("/user")
@JsonView(Views.Public.class)
public User getUser() {
    return new User("홍길동", "test@example.com", "010-1234-5678");
}

결과 (Public 뷰)

{
  "userName": "홍길동"
}

역할별로 보여줄 필드를 다르게 할 수 있어 관리자 vs 사용자 응답 분리에 유용합니다.


3. @JsonFilter – 런타임 조건에 따라 필드 포함/제외

정적이 아닌 동적으로 필드를 필터링할 수 있는 고급 전략입니다.

클래스 정의

@JsonFilter("UserFilter")
public class User {
    private String userName;
    private String email;
    private String phone;
}

필터 생성

SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
        .filterOutAllExcept("userName", "email");

FilterProvider filters = new SimpleFilterProvider()
        .addFilter("UserFilter", filter);

ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filters);

String json = mapper.writeValueAsString(user);

결과

{
  "userName": "홍길동",
  "email": "test@example.com"
}

로그인한 사용자 권한에 따라 응답 내용을 다르게 해야 하는 상황에 유용합니다.


4. 기타 실무 전략 요약

목적 방법

null 값 제거 @JsonInclude(Include.NON_NULL) 또는 application.yml 설정
빈 값 제거 @JsonInclude(Include.NON_EMPTY)
응답 대상 분기 @JsonView
런타임 필터링 @JsonFilter + FilterProvider
민감 정보 제외 @JsonIgnore, @JsonView, 또는 별도 DTO 사용

5. 추천 설계 전략

  • 단순한 제외는 @JsonInclude 또는 @JsonIgnore로 처리
  • 권한/상황에 따른 분기는 @JsonView 또는 DTO 분리 전략을 고려
  • 런타임 필터링이 필요한 경우만 @JsonFilter 사용 (복잡도 ↑)

지나치게 복잡한 필터링은 오히려 코드 가독성을 떨어뜨릴 수 있습니다.
목적이 명확한 경우가 아니라면 DTO를 분리하는 것이 장기적으로는 유지보수에 유리합니다.


다음 회차 예고

8화에서는 Jackson의 커스텀 Serializer/Deserializer를 구현해 복잡한 필드나 특수한 포맷을 가진 데이터를 어떻게 처리할 수 있는지 정리합니다. 예: Base64 인코딩 필드, 특수 문자 제거, 복합 타입 등.

728x90