티스토리 뷰
재검토중 이 글에서 설명하는 방법으로 이슈가 해결되지 않음을 확인했습니다. 하나의 탐구과정으로 봐주시면 감사하겠습니다.
문제의 발생
- ObjectMapper의 NamingStrategies를 여러개 쓰이게 되는 상황이 발생했다.
- 여러 종류의 외부 API를 반영하는 서비스였기에 외부 API 마다의 json 네이밍 컨벤션이 달랐다.
- 특히, 하나의 NamingStrategies가 늘어날 때 마다 ObjectMapper에 대한 빈을 하나 더 등록하면서 주입 받을 때도 빈이 여러개라서 신경을 써야 하는 등의 불편함이 발생했다.
이 문제를 해결하는 방법을 찾던 중, 디자인 패턴인 Composite 패턴을 통해 해결하기로 했다.
Composite 패턴이란?
- Component 라 불리는 최상위 클래스와 Leaf, Composite 라 불리는 하위 클래스가 협력하는 패턴이다.
- Leaf는 Composite에서 사용될 클래스로 Composite에 여러 다른 구현체가 등록되어 사용된다.
- 클라이언트에서는 다양한 구현체를 한 번에 사용 가능하다.
뭔 소리지? 다이어그램을 살펴보자
구조는 알겠으니 이제 코드를 통해 알아보자
- 아래 코드에서 클래스의 각 역할은 다음과 같다.
- PropertyNamingStrategy = Component
- CompositePropertyNamingStrategy = Composite
- ComponentPropertyNamingStrategy의 생성자로 받는 PropertyNamingStrategy = Leaf
- objectMapper 메서드 = 클라이언트 (Component를 사용하는 주체)
CompositePropertyNamingStrategy
public class CompositePropertyNamingStrategy extends PropertyNamingStrategy {
private final PropertyNamingStrategy[] strategies;
public CompositePropertyNamingStrategy(final PropertyNamingStrategy... strategies) {
this.strategies = strategies;
}
@Override
public String nameForField(final MapperConfig<?> config, final AnnotatedField field, final String defaultName) {
String name = defaultName;
for (final PropertyNamingStrategy strategy : strategies) {
name = strategy.nameForField(config, field, name);
}
return name;
}
@Override
public String nameForGetterMethod(final MapperConfig<?> config, final AnnotatedMethod method, final String defaultName) {
String name = defaultName;
for (final PropertyNamingStrategy strategy : strategies) {
name = strategy.nameForGetterMethod(config, method, name);
}
return name;
}
@Override
public String nameForSetterMethod(final MapperConfig<?> config, final AnnotatedMethod method, final String defaultName) {
String name = defaultName;
for (final PropertyNamingStrategy strategy : strategies) {
name = strategy.nameForSetterMethod(config, method, name);
}
return name;
}
}
objectMapper 메서드
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
.setPropertyNamingStrategy(
new CompositePropertyNamingStrategy( // 여기서 사용된다.
PropertyNamingStrategies.SNAKE_CASE, // 첫 번째 Leaf
PropertyNamingStrategies.LOWER_CAMEL_CASE)); // 두 번째 Leaf
}
결론
- 위와 같은 코드를 통해 ObjectMapper를 하나만 사용할 수 있게 되었다.
- 또한, 여러개의 PropertyNamingStrategy를 한 번에 사용할 수 있게 되었다.
'프로젝트 탐구 > 이길저길' 카테고리의 다른 글
Redis Cache 적용과 만료 전략 수립 (0) | 2024.03.25 |
---|---|
RabbitMQ 비동기 처리와 데드레터 처리 적용기 (0) | 2024.03.25 |
FULL Text Index 적용기 (0) | 2024.03.25 |
배포 프로세스 자동화를 위한 Github Actions 기반 CI/CD 적용 (0) | 2024.03.25 |
실시간 양방향 위치 공유 시스템 설계 및 지속적으로 갱신되는 위치 좌표 저장 고민 (0) | 2024.03.25 |