Java 기초 (Json)

최병현·2026년 1월 10일

Java

목록 보기
35/38

이번 글은 Backend / Java(JSON 직렬화·역직렬화) 영역에서 자주 쓰는 JSON 변환을 정리한다. Java에서 API 응답(JSON)을 다룰 때 핵심은 두 가지다.

  • Java 객체(또는 Map)를 JSON 문자열로 바꾸기(Object → JSON)
  • JSON 문자열을 다시 Java 객체(또는 Map)로 복원하기(JSON → Object/Map)

여기서는 Gson을 사용해서 Gson 생성 방식 차이, Pretty Printing, Map ↔ JSON, DTO(User) ↔ JSON까지 흐름을 잡는다.


1. Gson이 뭔가?

Gson은 Google에서 만든 JSON 라이브러리로, 자바 객체를 JSON으로 직렬화(serialize)하고 JSON을 다시 자바 객체로 역직렬화(deserialize)할 수 있다.

JSON을 다루는 흐름은 보통 아래처럼 연결된다.

  • Frontend(웹/앱) → Backend(Spring Boot)로 JSON 요청
  • Backend에서 JSON을 DTO로 파싱
  • DB(SQL)에 저장하거나 로직 처리
  • 처리 결과를 다시 DTO/Map으로 만들고 JSON으로 응답

2. Gson() vs GsonBuilder()

Gson을 만드는 방법은 크게 2가지다.

  • new Gson(): 기본 설정(기본 포맷)
  • new GsonBuilder().create(): 옵션을 붙여서 생성 가능(Pretty Printing 등)

즉, GsonBuilder는 “설정 가능한 생성기”고, 마지막에 create()로 Gson 인스턴스를 만든다.


3. Map ↔ JSON 변환

Map은 JSON의 Key-Value 구조와 1:1로 잘 맞는다. 그래서 구조가 유동적인 데이터(옵션/설정/간단한 임시 JSON)에서는 Map이 편하다.

  • Map → JSON: toJson(map)
  • JSON → Map: fromJson(json, Map.class)

다만 JSON → Map으로 받을 때는 제네릭 타입 정보가 사라지기 때문에 값이 Object로 떨어지고, 숫자도 Double로 들어오는 등 타입이 깔끔하지 않을 수 있다. 이건 Gson의 일반적인 특성이라서 “빠르게 찍어보기/디버깅”에는 Map이 좋고, “정확한 타입”은 DTO가 좋다.


4. DTO(User) ↔ JSON 변환

User처럼 필드 구조가 고정된 “도메인 데이터”는 DTO 클래스로 다루는 게 정석이다.

  • 객체 → JSON: toJson(user)
  • JSON → 객체: fromJson(userJson, User.class)

이 방식은 Spring Boot에서 API 응답을 DTO로 받고, 다시 DTO로 응답하는 구조와 완전히 동일하다.


5. 예제 코드

아래 코드는 네가 준 예제를 “Gson 생성 → Map JSON → DTO JSON → JSON에서 Map 변환” 흐름으로 정리한 것이다.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.HashMap;
import java.util.Map;

public class GsonExample {
    public static void main(String[] args) {

        // 1) Gson() 생성자를 통해 생성 (기본 설정)
        Gson gson1 = new Gson();
        System.out.println(gson1.toString());

        // 2) GsonBuilder() 생성자를 통해 생성 (옵션 설정 가능)
        Gson gson2 = new GsonBuilder().create();

        // Pretty Printing(가독성 좋은 JSON 출력)
        Gson gson3 = new GsonBuilder().setPrettyPrinting().create();

        // Map -> JSON
        Map<String, String> map = new HashMap<>();
        map.put("username", "gildong");
        map.put("password", "1234");
        map.put("name", "길동");
        map.put("email", "gildong@gmail.com");

        String json2 = gson2.toJson(map);
        System.out.println(json2);

        System.out.println();

        String json3 = gson3.toJson(map);
        System.out.println(json3);

        // DTO(User) 생성
        User user = UserService.createUser();

        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        // 객체 -> Json
        String userJson = gson.toJson(user);
        System.out.println(userJson);

        // Json -> 객체
        User user2 = gson.fromJson(userJson, User.class);
        System.out.println(user2);
        System.out.println(user2.getAddress());

        // Json -> Map (디버깅/동적 구조 확인 용도)
        Map<String, Object> mapObj = gson.fromJson(userJson, Map.class);
        System.out.println(mapObj);
    }
}

6. User DTO 클래스

DTO는 “데이터 구조”를 표현하는 클래스고, JSON 파싱/응답에서 가장 깔끔한 타입 안정성을 제공한다.

import java.util.List;
import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class User {

    private int userCode;
    private String username;
    private String password;
    private String name;
    private String email;
    private String address;
    private String phone;
    private List<String> hobby;
}

7. UserService: 테스트용 객체 생성

실무에서도 “테스트 데이터”를 만들 때 Service에서 DTO를 만들어 반환하는 방식은 매우 자주 쓴다. 여기서는 Builder 패턴으로 User 객체를 깔끔하게 생성하고 있다.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class UserService {

    public static User createUser() {
        List<String> hobby = new ArrayList<>();
        hobby.addAll(Arrays.asList(new String[]{"축구", "농구", "야구", "골프"}));

        User user = User.builder()
                .userCode(1)
                .username("gildong")
                .password("1234")
                .name("길동")
                .email("gildong@gmail.com")
                .address("부산 진구")
                .phone("010-1234-5678")
                .hobby(hobby)
                .build();

        return user;
    }
}

8. 주의점 / 확장 포인트

  • Map으로 JSON을 받을 때는 값 타입이 Object로 떨어져서 타입 안정성이 약해진다. “구조 확인/빠른 처리”에만 적합하다.
  • 실서비스에서는 JSON 구조가 정해져 있으므로 DTO로 파싱하는 게 유지보수에 유리하다.
  • 필드명이 JSON 키와 다를 경우, Gson에서는 @SerializedName을 붙여 매핑할 수 있다.
  • Spring Boot에서는 보통 Jackson이 기본이라, 컨트롤러에서 DTO를 리턴하면 JSON 변환이 자동으로 된다. Gson은 “직접 변환”이 필요할 때나 특정 프로젝트 스타일에서 사용한다.

9. 정리

  • Gson: 기본 설정으로 JSON 변환
  • GsonBuilder: Pretty Printing 같은 옵션을 붙여 Gson 생성
  • Map: 동적 Key-Value JSON에 편함(타입 안정성 낮음)
  • DTO(User): 구조가 고정된 데이터에 정석(타입 안정성 높음)

10. 느낀 점

JSON 변환은 “문법”보다 “구조 선택(Map vs DTO)”가 더 중요하다. 동적 데이터는 Map으로 빨리 처리하고, 핵심 도메인 데이터는 DTO로 안정적으로 관리하는 습관이 실서비스 유지보수에서 큰 차이를 만든다.

profile
No Pain No Gain

0개의 댓글