728x90
편집
ObjectMapper의 **스레드 안전성(Thread Safety)**에 대해 설명드리겠습니다.
ObjectMapper의 스레드 안전성
기본적으로 스레드-세이프함
- ObjectMapper는 한 번 설정된 후에는 스레드-세이프합니다
- 여러 스레드가 동시에 readValue(), writeValue() 등의 메서드를 호출해도 안전합니다
단, 설정 변경 시에는 주의 필요
java
ObjectMapper mapper = new ObjectMapper();
// ❌ 위험: 설정 변경은 스레드-세이프하지 않음
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
// ✅ 안전: 읽기 작업은 스레드-세이프
String json = mapper.writeValueAsString(object);
MyObject obj = mapper.readValue(json, MyObject.class);
실무에서의 올바른 사용법
1. 싱글톤 패턴으로 사용 (권장)
java
public class JsonUtil {
private static final ObjectMapper MAPPER = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
public static <T> T readValue(String json, Class<T> valueType) throws Exception {
return MAPPER.readValue(json, valueType);
}
public static String writeValueAsString(Object value) throws Exception {
return MAPPER.writeValueAsString(value);
}
}
2. Spring에서 Bean으로 등록
java
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new JavaTimeModule())
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
}
}
@Service
public class MyService {
private final ObjectMapper objectMapper;
public MyService(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public void processData(String json) throws Exception {
// 스레드-세이프하게 사용 가능
MyData data = objectMapper.readValue(json, MyData.class);
}
}
잘못된 사용 예시
❌ 매번 새로운 ObjectMapper 생성 (비효율적)
java
public String convertToJson(Object obj) throws Exception {
ObjectMapper mapper = new ObjectMapper(); // 매번 생성 - 비효율적
return mapper.writeValueAsString(obj);
}
❌ 멀티스레드 환경에서 설정 변경
java
public class UnsafeService {
private ObjectMapper mapper = new ObjectMapper();
public void method1() {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 다른 스레드에서 동시에 설정을 변경하면 문제 발생 가능
}
public void method2() {
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.CAMEL_CASE);
// 스레드-세이프하지 않음
}
}
성능 최적화 관점
ObjectMapper 생성 비용
- ObjectMapper 생성은 상당히 무거운 작업입니다
- 내부적으로 리플렉션 정보, 직렬화 규칙 등을 초기화하기 때문
권장 사용 패턴
java
public class OptimizedJsonProcessor {
// 애플리케이션 전체에서 하나의 인스턴스 공유
private static final ObjectMapper MAPPER = createObjectMapper();
private static ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.registerModule(new JavaTimeModule());
return mapper;
}
public static <T> T fromJson(String json, Class<T> clazz) throws Exception {
return MAPPER.readValue(json, clazz);
}
public static <T> T fromJson(String json, TypeReference<T> typeRef) throws Exception {
return MAPPER.readValue(json, typeRef);
}
public static String toJson(Object obj) throws Exception {
return MAPPER.writeValueAsString(obj);
}
}
요약
- ✅ 스레드-세이프: 설정 완료 후 읽기/쓰기 작업
- ❌ 스레드-세이프 아님: 설정 변경 작업
- 권장: 애플리케이션 시작 시 한 번 설정하고 싱글톤으로 사용
- 성능: 매번 새로 생성하지 말고 재사용
따라서 앞서 제공한 코드에서 ObjectMapper를 매번 새로 생성하는 것보다는, 클래스 레벨의 상수로 선언하거나 스프링 빈으로 주입받아 사용하는 것이 더 효율적입니다.
728x90
'프로그램 개발(분석, 설계, 코딩, 배포) > 2.2.1 java' 카테고리의 다른 글
| ObjectMapper는 스레드 안전성(thread safety,스레드-세이프) 의미 (1) | 2025.06.19 |
|---|---|
| public static <T> T, class<T> 의미 (0) | 2025.06.19 |
| List<map> 이 코드는 어떤 형태로 데이터가 구성되는지? (0) | 2025.06.19 |
| `param.getMap()`이 null 값을 반환하면 NullPointerException (NPE) (1) | 2025.06.19 |
| java == equals 차이점 (0) | 2025.06.19 |