JSON을 Java DTO로 변환 — Jackson·Lombok 가이드

JSON을 Java DTO로 정리하는 가장 빠른 출발점

샘플 JSON을 붙여 넣고 Java DTO 초안을 바로 확인할 수 있는 작업 화면입니다. Validation, 숫자 추론, nullable 배열 옵션을 함께 검토할 수 있어 Java API 모델링 페이지로서 충분한 문맥을 제공합니다.

Input

JSON Payload

JSON을 Java DTO와 POJO로 변환하고 Jackson, Lombok, nullability, 중첩 객체 타입 매핑까지 한 페이지에서 확인합니다.

{
  "orderId": "ORD-2026-001",
  "status": "PAID",
  "amount": 12900,
  "customer": {
    "name": "Lee",
    "email": "lee@example.com"
  }
}

Output

생성 예시

public class OrderResponse {
  private final String orderId;
  private final String status;
  private final Integer amount;
  private final Customer customer;
}

Explanation

왜 Java DTO가 필요한가

Java에서는 DTO가 생기면 필드 계약을 컴파일 단계에서 검토하기 쉬워지고, 리뷰와 테스트도 구조 중심으로 바뀝니다.

왜 Java DTO 생성이 필요한가

Java 서비스는 정적 타입의 장점을 크게 누리는 환경입니다. 컨트롤러에서 받은 JSON 요청이나 외부 API 응답을 DTO로 고정하면, 필드 누락이나 타입 변경을 테스트와 컴파일 단계에서 더 빨리 확인할 수 있습니다.

특히 Spring 기반 프로젝트에서는 Jackson, Validation, Lombok, record 같은 도구들과 DTO가 자연스럽게 연결됩니다. JSON을 그대로 Map으로 들고 다니는 방식은 빠른 실험에는 편하지만, 필드 계약이 퍼져 나가면서 유지보수 비용이 급격히 올라갑니다.

JSON2Class는 이 초기 정리 작업을 줄여 줍니다. 예시 JSON을 넣고 루트 클래스명만 정하면, 중첩 객체와 배열 구조를 따라가며 기본 타입, 컬렉션 타입, 내부 클래스를 한 번에 만들어 볼 수 있습니다.

  • 파트너 API 응답을 DTO로 빠르게 고정하고 싶을 때
  • 테스트 픽스처용 JSON을 모델 클래스로 먼저 정리할 때
  • 프런트엔드와 합의한 응답 구조를 서버 코드에 명확히 반영할 때

대표적인 활용 장면

운영에서 가장 자주 보는 시나리오는 API 연동 초반입니다. 아직 OpenAPI 문서가 완전하지 않거나, 실서버 샘플 응답만 먼저 전달받은 경우 JSON을 붙여 넣고 DTO 구조를 만든 뒤 필요한 Validation과 네이밍 규칙을 추가하는 편이 훨씬 빠릅니다.

두 번째는 리팩터링입니다. 레거시 코드에서 `Map<String, Object>`나 `JsonNode` 의존도가 높아지면, 특정 필드가 어디서 쓰이는지 추적하기 어려워집니다. 이때 샘플 응답을 DTO로 바꿔 두면 서비스 경계를 명확하게 나눌 수 있습니다.

JSON에서 Java로 바뀌는 예시

아래처럼 주문 응답 JSON이 있다고 가정하면, 문자열은 `String`, 정수는 `Integer` 또는 `Long`, 배열은 `List<T>`, 중첩 객체는 내부 클래스로 매핑하는 식으로 초안을 잡을 수 있습니다.

입력 JSON

{
  "orderId": "ORD-2026-001",
  "status": "PAID",
  "amount": 12900,
  "customer": {
    "name": "Lee",
    "email": "lee@example.com"
  },
  "items": [
    {
      "sku": "SKU-100",
      "quantity": 2
    }
  ]
}

생성 예시

@Getter
@AllArgsConstructor
public class OrderResponse {
  private final String orderId;
  private final String status;
  private final Integer amount;
  private final Customer customer;
  private final List<Item> items;

  @Getter
  @AllArgsConstructor
  public static class Customer {
    private final String name;
    private final String email;
  }

  @Getter
  @AllArgsConstructor
  public static class Item {
    private final String sku;
    private final Integer quantity;
  }
}

타입 매핑과 커스터마이징 포인트

샘플 JSON에서 문자열과 숫자는 비교적 단순하지만, 실무에서는 날짜, 금액, nullable 필드가 곧바로 등장합니다. 생성기는 초안을 빠르게 만들기 위한 도구이므로, 금액은 `BigDecimal`, 시간은 `OffsetDateTime`, 식별자는 `Long`처럼 팀 규칙에 맞는 타입으로 후처리할 수 있어야 합니다.

JSON2Class 메인 변환기에서는 Validation flavor, 배열 nullable 허용, 숫자 추론 같은 옵션을 조절할 수 있습니다. 이 옵션은 모든 필드를 정답으로 확정하는 기능이라기보다, DTO 초안을 프로젝트 규칙에 더 가깝게 맞추는 장치라고 보는 편이 맞습니다.

  • 문자열 날짜 필드는 `String`에서 `LocalDateTime` 또는 `OffsetDateTime`으로 검토
  • 금액과 정밀도 값은 `Double`보다 `BigDecimal` 후보를 먼저 점검
  • nullable 배열과 optional 필드는 Jackson 역직렬화 기준으로 재검토

자주 겪는 문제

첫 번째는 nullability입니다. 샘플 JSON에 없는 필드가 실제 운영 응답에는 들어올 수도 있고, 반대로 샘플에는 있지만 일부 고객사 응답에는 빠질 수 있습니다. 이 경우 DTO를 지나치게 엄격하게 만들면 연동 초기에 예외가 과하게 발생합니다. 반대로 너무 느슨하면 도메인 규칙이 흐려집니다.

두 번째는 네이밍입니다. snake_case JSON 키를 Java 필드명으로 그대로 두면 코드 스타일이 흔들립니다. 보통은 camelCase 필드명으로 정리하고, 필요하면 `@JsonProperty`를 통해 원본 키를 보존합니다.

세 번째는 중첩 객체가 과도하게 깊은 경우입니다. 생성기는 내부 클래스로 표현해도, 실제 서비스 코드에서는 별도 파일로 분리하는 편이 더 읽기 좋을 수 있습니다.

DTO 초안 이후에 바로 확인할 것

생성 결과를 붙여 넣은 직후에는 필드 순서보다 경계가 더 중요합니다. 이 클래스가 외부 응답용인지, 내부 이벤트용인지, 컨트롤러 요청 바인딩용인지에 따라 Validation과 직렬화 전략이 달라집니다.

예를 들어 외부 API 응답 DTO라면 허용 가능한 null 범위를 넓게 가져가고, 내부 명령 DTO라면 필수 필드를 더 강하게 검증하는 편이 안전합니다. JSON2Class로 초안을 만든 뒤 이 분류를 먼저 하는 것이 유지보수에 도움이 됩니다.

타입 안정성과 생산성을 동시에 확보하는 방법

생성된 DTO는 IDE 자동완성, 리팩터링 도구, 테스트 코드 작성 속도에 직접 영향을 줍니다. 필드명이 고정되면 문자열 키 오타를 줄일 수 있고, 응답 구조 변경이 발생했을 때 컴파일 단계에서 수정 지점을 찾기 쉬워집니다.

또한 같은 JSON으로 TypeScript나 Kotlin 출력까지 비교해 보면, 서버와 클라이언트 간 계약을 더 쉽게 맞출 수 있습니다. 이 사이트의 장점은 하나의 JSON을 여러 언어 출력으로 함께 검토할 수 있다는 점입니다.

  • API 응답 DTO와 요청 DTO를 같은 샘플에서 분리 설계
  • 테스트 JSON fixture와 DTO를 같은 PR에서 관리
  • 팀 문서에는 Markdown 출력까지 함께 남겨 계약 변경 이력 확보

실무 팁

Lombok을 쓰는 팀이라면 `@Getter`, `@AllArgsConstructor`, `@Builder` 채택 기준을 미리 정해 두는 편이 좋습니다. record 기반 프로젝트라면 생성 결과를 참고해 record로 다시 정리하는 방식도 괜찮습니다.

Jackson 역직렬화가 필요한 클래스라면 기본 생성자, `@JsonCreator`, `@JsonProperty` 여부를 확인해야 합니다. 생성기가 모든 프레임워크 제약을 자동으로 해결해 주지는 않기 때문에, 초안 생성 이후의 기준을 팀이 명확히 가지고 있어야 합니다.

Related Tools

같이 보면 좋은 도구

언어별 변환기와 JSON 보조 도구를 연결해 내부 링크 구조를 강화했습니다.

JSON to Kotlin

nullable 규칙과 data class 구조를 빠르게 검토합니다.

JSON Formatter

샘플 JSON을 정리한 뒤 변환기에 다시 넣어 타입 추론을 안정화합니다.