📝인코딩 체계
한국에서는 인코딩 체계는 크게 한글이 포함된 인코딩 코드표를 가지고 있냐 없냐로 나뉩니다 기본적으로 한글이 포함되면 영어 특수문자 등은 포함되기 때문에 신경 안 쓰셔도 됩니다
- 한글이 포함된 인코딩
- UTF-8
- UTF-16
- UTF-32
- EUC-KR
- CP949
- KSC-5601
- 등...
📝화면의 글자가 깨지는 이유
- 해당 페이지의 인코딩 설정과 웹브라우저의 인코딩 설정이 다르기 때문에 일어납니다 간단히 이야기하자면 종이에 한국어가 적혀있는데 번역기가 영어로 번역해 보여주기 때문에 안 맞는 것입니다
JSP 예제
<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
JSP에서 EUC-KR로 페이지 설정을 해놨는데 웹브라우저에서 다른 언어로 읽으면 깨질 수 밖에 없습니다
📝파라미터로 넘긴 글자가 깨지는 이유 (GET)
- GET방식으로 요청시 글자가 깨져서 서버에 들어갔다면 위에 설명한 "화면의 글자가 깨지는 이유"가 있을 수 있습니다
간단한 예제를 한번 보시죠
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<html>
<script>
var text = "가";
fetch("http://localhost:8080/reqServer?word=" + text, {
method: "GET",
})
.then(response => response.text()) // 응답을 텍스트로 변환
.then(data => console.log(data)) // 응답 데이터 출력
.catch(error => console.error(error)); // 오류 처리
</script>
<body>
<h1>웹화면에 PDF 출력해보기</h1>
</body>
</html>
GET방식 통신을 이용해 word라는 키에 text를 담아서 보내고 있습니다 reqServer에서 로그를 찍었습니다. 웹브라우저의 인코딩 상태를 EUC-KR로 했을 때 결과는 "가" 입니다 KO18-U로 설정했을 때는 "╟║" 이상한 문자가 넘어갑니다. 자바스크립트에 적은 하드코딩 한글 때문에 그렇습니다 → 물론 input 박스로 받은 데이터는 잘 넘어갑니다
- URI Encode 설정이 UTF-8이 아닌 경우
이 부분에 대해서는 WAS서버가 역할을 해주는 경우가 많습니다 예를 들면 톰캣이 있겠습니다 server.xml 설정에서 URIEncoding 설정을 UTF-8이 아닌 다른 인코딩 체계로 되어있는 경우 GET방식 통신때 깨져버립니다
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
참고로 톰캣 9.0 부터는 기본적 Default가 UTF-8로 설정되어 있습니다
📝URLEncoding vs Encode
- URLEncoding
- GET방식으로 호출할 때 "키=값"으로 데이터를 전달할 때 값에 한글 및 #, $, %, = 등... 특수문자가 들어가는 경우 비정상적으로 동작(예약어 동작 등...)할 수 있기 때문에 URL 인코딩 과정이 필요하다
- Encode
- 데이터를 보내려면 해당 데이터를 이진데이터로 보내는데 UTF-8 체계를 따라 이진데이터로 만들지에 대한 설정을 합니다 간단히 이야기하면 데이터를 2글자씩 끊어서 보내는 것과 3글자씩 끊어서 보내는 느낌이다
📝POST 통신후 내려온 데이터가 깨진 경우
- MIME-TYPE이 일치하지 않아서 발생한다 즉, HTTP 통신시 Header의 Content-Type 불일치로 일어나게 된다
- Content-Type은 Request와 Response로 나뉘게 된다
아래는 POST 방식 통신에 대한 Request 예제입니다
fetch("http://localhost:8080/reqServer2", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(jsonData),
})
.then((response) => response.text())
.then((data) => console.log(data))
.catch((error) => console.error(error));
(application/json) json형식으로 읽어주세요 + (charset=utf=8)utf-8로 인코딩 되었으니 utf-8로 디코딩해서 읽어주세요
→ 이렇게 해야 백엔드(서버)에서 정상적으로 데이터를 받게 된다
아래는 POST 방식 통신에 대한 Response 예제입니다
Servlet 예제
@PostMapping(value = "reqServer")
public void server(@RequestBody HashMap<String, String> bodyVO, HttpServletResponse res) {
/** 응답 헤더 설정**/
res.setContentType("application/json; charset=EUC-KR");
/** 응답 헤더 설정값으로 데이터를 화면에 그려준다**/
PrintWriter out = res.getWriter();
out.print(responseData);
}
Serlvet의 경우 이러한 형식으로 데이터를 반환해줍니다
Spring 예제
@PostMapping(value = "reqServer", produces = "application/json;charset=UTF-8", consumes = "application/json;charset=UTF-8")
@ResponseBody
public String server(@RequestBody HashMap<String, String> bodyVO){
return bodyVO.get("word");
}
Spring의 경우 consumes랑 produces라는 옵션이 존재합니다 Request 와 Response의 Content-Type을 설정합니다
- consumes
- Request 에 대한 Content-Type 설정 제한합니다 → 어차피 Request Hedaer는 Client에서 하기 때문에 해당 Content-Type외에는 호출 못하게끔 서버에서 막습니다
- produces
- Response에 대한 Content-Type 설정을 해줍니다 이 부분에 따라 리턴에 대한 형태가 깨질지 안 깨질지가 결정됩니다
※ 웹브라우저 및 JSP인코딩 설정을 EUC-KR로하고 POST방식으로 EUC-KR로 데이터를 보낼 때 깨지는 경우가 있는데 내가 Input 박스 따위에 적은 값이 EUC-KR이 아니라 UTF-8이고 UTF-8이 EUC-KR로 인코딩되어 Request때 깨지는 경우도 있고 Response할 때도 EUC-KR로 내려준다고 선언했지만 실제로는 UTF-8이 EUC-KR로 인코딩 되어서 보내지기 때문에 깨져버리는 경우도 있다
📝결론
어떤 깨진 글자는 복구가 가능하지만 어떤 깨진 글자는 복구가 불가능합니다 예를 들면 移���이러한 글자는 아무리해도 복구가 불가능합니다 그렇기 때문에 주먹구구식 처리보다는 근본적인 원인을 파악하기 바랍니다
요즘은 거의 UTF-8을 기본적으로 두고 코딩하기 때문에 UTF-8로 맞춰준다는 생각을 하시면 됩니다 물론 프로젝트 특성이 EUC-KR이런 걸 쓰는 곳도 있겠죠