Backend/Spring+Boot

UriComponentsBuilder

findmypiece 2021. 7. 19. 11:17
728x90

URL 에는 사용할 수 있는 문자가 제한되어 있기 때문에 한글과 일부 특수문자, 공백 등의 문자들이 포함될 경우 반드시 인코딩을 해줘야 한다. 

 

일반적으로 RestTemplate 나 브라우저 같은 클라이언트 통할 경우 자동으로 인코딩을 해주지만 몇몇 클라이언트에서는 인코딩을 해주지 않기 때문에 그때는 우리가 URL을 만들 때 인코딩을 미리 해줘야 한다.

 

 

POST 방식이라면 Content-Type 헤더에 charset를 직접 명시하던지 HttpServletRequest.setCharacterEncoding() 로 문자셋을 지정해주면 되고 GET 방식이라면 가장 기본적으로 아래와 같은 방법을 사용할 수 있다.

 

StringBuilder uri = new StringBuilder("http://localhost:8080?param=");
uri.append(URLEncoder.encode("한글입니다만?", "UTF-8"));

System.out.println(uri.toString());

System.out.println(URLDecoder.decode(uri, "UTF-8"));

 

그런데 위 방식은 뭔가 직관적이지가 않고 queryString 이 많아진다면 코딩 실수도 많이 나올 것 같은 방식이다. 이를 위해 Spring에서는 UriComponentsBuilder 라는 모듈을 제공한다. 이를 사용할 경우 URL은 아래와 같이 생성하면 된다.

String uri2 = UriComponentsBuilder.fromHttpUrl("http://localhost:8080")
  .queryParam("param", "한글입니다만?")
  .toUriString();

System.out.println(uri2);
System.out.println(URLDecoder.decode(uri2, "UTF-8"));

이 방식은 코드가 더 직관적이라는 장점도 있지만 또 다른 장점은 인코딩 역시 자동으로 해준다는 점이다. 위의 경우 "한글입니다만?" 을 자동으로 UTF-8로 인코딩 해준다.

 

만약 인코딩 문자셋을 바꾸고 싶은 경우는 어떻게 해야 하나? 

위 코드에서 toUriString() 메소드를 디버깅해보면 알겠지만 이는 내부적으로 build().encode().toUriString() 를 수행하고 encode() 는 인자가 없을 경우 UTF-8을 기본 문자셋으로 지정한다. 이에 문자셋을 변경하고 싶다면 아래와 같이 풀어서 쓰면 된다.

String uri3 = UriComponentsBuilder.fromHttpUrl("http://localhost:8080")
  .queryParam("param", "한글입니다만?")
  .build()
  .encode(Charsets.toCharset("EUC-KR"))
  .toUriString();

System.out.println(uri3);

System.out.println(URLDecoder.decode(uri3, "EUC-KR"));

 

다만 RestTemplate 과 함께 사용할 경우 한가지 주의할 점이 있다. RestTemplate 은 url 을 지정할 때 URI 타입과 String 타입을 선택적으로 적용할 수 있고 String 타입일 때는 내부적으로 인코딩을 수행하기 때문에 원치않게 인코딩이 중복으로 수행될 수 있다. 이에 RestTemplate 과 함께 사용한다면 인코딩 되지 않은 String을 생성하던가 인코딩이 완료된 URI 를 생성해서 사용하면 된다.

 

인코딩 되지 않은 String을 생성한다면 아래와 같이 하면 될 것이고

String uri4 = UriComponentsBuilder.fromHttpUrl("http://localhost:8080")
		.queryParam("param", "한글입니다만?")
		.build()
        .toUriString();

System.out.println(uri4);

 

인코딩이 완료된 URI 타입을 생성한다면 아래와 같이 하면 된다.

URI uri5 = UriComponentsBuilder.fromHttpUrl("http://localhost:8080")
		.queryParam("param", "한글입니다만?")
		.build()
		.encode()
		.toUri();

System.out.println(uri5.toString());
System.out.println(URLDecoder.decode(uri5.toString(), "UTF-8"));

 

 

728x90

'Backend > Spring+Boot' 카테고리의 다른 글

Spring에서 권장되는 의존성 주입 방법  (0) 2021.07.23
RestClient 구성시 고려사항  (0) 2021.07.20
@RunWith(SpringRunner.class)  (0) 2021.07.13
@Async 설정  (0) 2021.07.13
CircuitBreaker, Resilience4j, RestClient  (0) 2021.07.09