@Data를 사용하면서, Boolean 메서드명이 is로 시작하는 경우

  • private final을 사용하면, Setter를 제외하고 사용

@Data
public class SampleDomain {

    private final Long id;
    private final String name;
    private final Boolean hidden; 

    // 다른 객체에서 Sample Domain의 로직이 필요한 경우
    @JsonIgnore
    public Boolean isHiddenItem(){ 
        return name.equals("sample");
    } // --> jsonIgnore가 없으면 직렬화시 해당 로직이 계속 수행
}

적용 범위

위치 애너테이션 없음 (@JsonIgnore X) @JsonIgnore 붙인 경우
hidden 필드 (및 Lombok가 만든 getHidden())
→ JSON 속성 hidden
✅ 포함 🔒 빠짐
isHiddenItem() 메서드
→ JSON 속성 hiddenItem
✅ 포함 🔒 빠짐

Jackson-databind는 모든 “getter”( getXxx() 또는 isXxx() )를 JavaBean 프로퍼티로 간주해 직렬화‧역직렬화를 시도한다. 따라서 아무 표시를 하지 않으면 두 속성이 모두 적용된다.

// 애너테이션 없음
{
  "id": 1,
  "name": "sample",
  "hidden": true,
  "hiddenItem": true
}

@JsonIgnore를 어디에 붙이느냐에 따른 차이

붙이는 위치 결과 주 사용 목적
private final Boolean hidden;
(또는 Lombok가 만든 getHidden()에)
hidden 속성이 제거된다. hiddenItem은 그대로 남음. 저장용 플래그 는 서버 안에서만 쓰고, 클라이언트에는 숨길 때.
public Boolean isHiddenItem() hiddenItem 속성이 제거된다. hidden은 그대로 남음. 계산된 파생값 을 노출하지 않거나, 동일 내용을 두 번 보낼 필요가 없을 때.
둘 다 두 속성 모두 제거 → { "id": …, "name": … } 완전히 감추고 싶을 때.

역직렬화(요청 → 객체) 도 동일하게 적용 JSON 이 속성을 포함하고 있어도 @JsonIgnore 가 붙은 필드/메서드는 무시


Kyro를 사용한 DTO Serialization

특징 설명
매우 작은 바이너리 reflection·필드 이름을 포함하지 않으므로 Java Serializable 대비 10 배 이상 작아지는 경우도 많음
고속 필드 오프셋·ASM 바이트코드를 활용해 getter/setter 호출을 건너뜀
Afterburner 적용 Jackson JSON < Kryo < protobuf 처럼, “텍스트형보다는 빠르고 스키마 기반보다는 느릴 수 있음” 정도 성능.
객체 그래프 보존 동일 객체 중복 참조, 순환 참조 모두 지원.
클래스 등록 직렬화 대상 클래스를 ID(정수) 로 등록 → 바이트 수 절감·역직렬화 안전성 확보.
스레드 안전 X Kryo 인스턴스를 ThreadLocal 로 보관하거나 풀(pool)로 관리해야 함.

의존성 추가

implementation 'com.esotericsoftware:kryo5:5.6.0'

KyroUtil.java


public class KryoUtil {
    /* ───────── Kryo 풀(Thread-safe) ───────── */
    private static final int                       POOL_SIZE = 16;
    private static final ArrayBlockingQueue<Kryo> POOL      = new ArrayBlockingQueue<>(POOL_SIZE);

    static {
        for (int i = 0; i < POOL_SIZE; i++) POOL.add(create());
    }

    /** Kryo 인스턴스 하나 생성 */
    private static Kryo create() {
        Kryo kryo = new Kryo();

        /* ① 전역 기본 직렬화기를 TaggedFieldSerializer 로 지정 */
        kryo.setDefaultSerializer(TaggedFieldSerializer.class);

        /* ② DTO 등록(ID=10) — 클래스 이름을 쓰지 않아 바이트 절감 */
        kryo.register(ItemDto.class, 10);

        return kryo;
    }

    public static byte[] write(ItemDto dto) {
        Kryo kryo = POOL.poll();
        if (kryo == null) kryo = create();

        try (Output output = new Output(128, -1)) {  // 128B부터 자동 확장
            kryo.writeObject(output, dto);
            return output.toBytes();
        } finally {
            POOL.offer(kryo);
        }
    }

    public static ItemDto read(byte[] bytes) {
        Kryo kryo = POOL.poll();
        if (kryo == null) kryo = create();

        try (Input input = new Input(bytes)) {
            return kryo.readObject(input, ItemDto.class);
        } finally {
            POOL.offer(kryo);
        }
    }
}


ItemDto


@Data
@AllArgsConstructor
@NoArgsConstructor
public class ItemDto {

    private static final int UID = 13;

    @TaggedFieldSerializer.Tag(1)
    private Long id;

    @TaggedFieldSerializer.Tag(2)
    private String name;

    @TaggedFieldSerializer.Tag(3)
    private Boolean hidden;
}

biz.java


ItemDto original = new ItemDto(1L, "sample", true);

byte [] serialized = write(original);
System.out.printf("바이트 길이: %d%n", serialized.length);

ItemDto restored = read(serialized);
System.out.println("역직렬화 결과: " + restored);

결과

바이트 길이: 14
역직렬화 결과: ItemDto(id=1, name=sample, hidden=true)