오늘은 박재성님의 Next Step 스터디를 진행 중에 겪었던 문제인
Java의 InputStreamReader가 UTF-8로 decode를 해도 한글 변환이 안되는 이유
에 대해서 알아보고자 합니다.
글 내용 중 잘못된 부분이 있거나 질문이 있으시다면, 언제든 댓글 주시면 감사하겠습니다! 🙏
목차
Next Step의 3장 HTTP로 통신하는 웹서버를 구현하는 미션
을 진행 중에 있었습니다.
기존 Base code가 HTTP Request를 InputStream으로 받아오는데,
이를 InputStreamReader로 읽고 BufferedReader로 읽습니다.
InputStreamReader의 생성자 파라미터에 StandardCharsets.UTF_8
을 넣어주었는데도,
HTTP Request Message에 있는 한글이 decode 되지 않는 상태로 들어오는 문제가 발생했습니다.
public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
InputStreamReader inputStreamReader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
log.debug("RequestLine ={}", bufferedReader.readLine());
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
상황 가정 : http://localhost:8080/user/create?userId=nathan&password=123123&name=나단&email=nathan@velog.io
를 GET 요청받는다.
위 코드에서 log.debug("RequestLine ={}", bufferedReader.readLine());
이 부분이 실행되면 아래와 같이 들어오게 된다.
HTTP method : GET
URI path :/user/create?userId=nathan&password=123123&name=%EB%82%98%EB%8B%A8&email=nathan@velog.io
HTTP version : HTTP/1.1
분명 InputStreamReader 생성자에 StandardCharsets.UTF_8
을 넣어 주었음에도 불구하고, name 부분에 나단
이 아닌, %EB%82%98%EB%8B%A8
가 들어오는 것을 확인할 수 있다.
InputStreamReader
와 BufferedReader
가 InputStream을 처리하는 데이터의 길이 단위는 1byte인데, UTF-8
로 디코딩을 하게되는 경우 한글은 한 글자에 3byte를 차지한다.EUC-KR
인코딩을 쓰면 한글은 한 글자에 2Byte를 차지한다.URLDecoder
) public void run() {
log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(),
connection.getPort());
try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
InputStreamReader inputStreamReader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
log.debug("RequestLine ={}", URLDecoder.decode(bufferedReader.readLine(), StandardCharsets.UTF_8));
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
responseBody(dos, body);
} catch (IOException e) {
log.error(e.getMessage());
}
}
URLDecoder.decode(bufferedReader.readLine(), StandardCharsets.UTF_8))
http://localhost:8080/user/create?userId=nathan&password=123123&name=나단&email=nathan@velog.io
이열 냐하~~ 잘 보고 가요우~~