Spring이 제공하는 빌더 클래스 알아보기

게으른 사람·2022년 12월 4일
1
post-thumbnail

1. 개요

이 글은 스프링이 제공하는 빌더 클래스를 통해 보다 편리하고 가독성 높게 클래스 속성을 정의하는 방법을 알아봅니다.

2. UriComponentsBuilder

외부 API를 요청할 때 우리는 해당 API 경로를 적고 파라미터를 작성하는 등 Url을 작성해주어야합니다.
WebClientFeginClient를 사용하면 이미 자체적으로 빌더나 매핑 방법을 제공하여 편리합니다.
하지만 RestTemplate은 그러한 편의방법을 제공하지 않습니다. 만약 특정 API의 get요청을 보낼 시 다음과 같이 작성해주어야합니다.

public String getFoo(String fooId) {
    RestTemplate restTemplate = new RestTemplate();

    Map<String, Object> params = new HashMap<>();
    params.put("id", fooId);
    params.put("isFoo", true);
    
    return restTemplate.getForObject("https://fooapi.com/{id}?isFoo={isFoo}", String.class, params);
}

보다시피 경로와 파라미터 변수를 직접 작성해서 바인딩해야하므로 조금 귀찮습니다.

이럴 경우 스프링이 제공하는 Url 빌더인 UriComponentsBuilder를 사용할 수 있습니다.

public String getFoo(String fooId) {
    RestTemplate restTemplate = new RestTemplate();
    
    return restTemplate.getForObject(
        UriComponentsBuilder.fromHttpUrl("https://fooapi.com/{id}") // 1
                .queryParam("isFoo", true) // 2
                .build(fooId) // 3
                .toUriString(), // 4
        String.class); 
}
  1. fromHttpUrl메소드로 호스트와 경로를 넘겨 빌더 작성을 시작합니다.
  2. queryParam메소드로 파라미터를 작성합니다.
  3. build메소드로 url의 변수를 바인딩합니다.
  4. toUriString메소드로 url 문자열을 완성시킵니다.

그 외 UriComponentsBuilder에서 여러 메소드를 제공하니 한번 살펴보시기 바랍니다.

3. RestTemplateBuilder

RestTemplate은 현재 유지보수만 지원하고 스프링 진영에선 WebClient 사용을 강권하지만 여전히 많은 프로젝트에서 RestTemplate을 사용합니다.
RestTemplate을 사용할 때 보통 빈으로 등록해 전역에서 사용하거나 직접 생성하는 사용하는 경우도 있습니다.
빈으로 사용하는 것은 요청하는 API가 하나라면 문제가 없겠지만 여러게하면 해당 API의 기본 헤더라던가 필수 파라미터 등 각 API만의 조건을 충족시킬 수 없어 결국 빈으로 등록한 RestTemplate을 복제하여 사용하거나 직접 생성하기 마련입니다.
이럴 때 RestTemplateBuilder을 사용하면 좀 더 편리하게 RestTemplate을 생성할 수 있습니다.

public class FooApiProvider {
    private final RestTemplate restTemplate;
    
    public FooApiProvider(RestTemplateBuilder restTemplateBuilder) { // 1
        restTemplate = restTemplateBuilder
                .rootUri("https://fooapi.com") // 2
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // 3
                .defaultHeader("userid", "fooId")
                .build(); // 4
    }
    
    ...
}
  1. FooApi를 호출하는 FooApiProvider클래스의 생성자입니다. 생성 시 RestTemplateBuilder를 인자로 받아 final 변수인 restTemplate를 초기화해줍시다.
  2. RestTemplate의 기본 url을 지정해줍니다. 지정해주면 요청 시 나머지 경로만 작성해줘도 됩니다.
  3. 기본 헤더를 정의합니다. 지정해주면 요청 시 정의한 헤더가 전송됩니다.
  4. build메소드로 RestTemplate를 생성합니다.

그 외 RestTemplateBuilder에서 여러 메소드를 제공하니 한번 살펴보시기 바랍니다.

4. Jackson2ObjectMapperBuilder

Jackson 라이브러리는 스프링에서 json을 다루기 위해 기본으로 사용되는 라이브러리입니다. 그 중 ObjectMapper로 우리는 문자열을 객체로 변환하거나 객체를 문자열로 변환합니다.
보통 json을 다룰 때 네이밍 전략을 통일하여 ObjectMapper를 빈으로 등록해 사용하지만 기본 전략과 다르게 사용할 때는 다른 때와 같이 빈으로 등록한 ObjectMapper을 복제하거나 직접 생성하여 사용합니다.
이 역시 스프링에서 Jackson2ObjectMapperBuilder라는 ObjectMapper의 빌더 클래스를 제공합니다.

public static Jackson2ObjectMapperBuilder objectMapperBuilder() {
        return Jackson2ObjectMapperBuilder.json() // 1
                .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) // 2
                .featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) // 3
                .featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // 4
                .featuresToDisable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
                .modules(new JavaTimeModule()); // 5
}
  1. 변환할 형식을 지정합니다. 우리는 json을 사용하니 json()메소드를 사용하여 빌더 클래스를 시작합니다.
  2. 네이밍 전략을 지정합니다. 여기선 SNAKE_CASE를 사용하였습니다.
  3. 활성화할 기능을 지정합니다. 여기선 속성과 enum의 대소문자를 무시하여 구분하도록 하였습니다.
  4. 비활성화할 기능을 지정합니다. 여기선 Date와 Duration을 Timestamp로 변환하는 기능을 비활성화 하였습니다.
  5. Jackson에서 제공하는 모듈을 지정해줍니다. 여기선 java8의 시간 관련 클래스들을 지원해주는 JavaTimeModule을 지정했습니다.

이런식으로 Jackson2ObjectMapperBuilder을 static 메소드로 지정하거나 빈으로 등록해 전역에서 사용할 수 있게하여 각 클래스에서 재정의해 사용하도록 할 수 있습니다.

그 외 Jackson2ObjectMapperBuilder에서 여러 메소드를 제공하니 한번 살펴보시기 바랍니다.

5. 결론

스프링이 제공하는 클래스를 사용한다면 해당 클래스의 빌더 클래스가 있는지 미리 확인해봅시다.
보다 편리하고 가독성 높게 클래스를 생성하여 사용할 수 있을겁니다.

profile
웹/앱 백앤드 개발자

0개의 댓글