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"));
'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 |