5 minute read

인코딩 기본 개념

인코딩은 동일해야한다
💡 파일인코딩서버인코딩 이 동일해야한다.

조치방법
💡 문제가 발생하면 현재 인코딩을 파악해본다.

  1. 시스템 레벨의 인코딩을 확인

    • 시스템 레벨의 인코딩을 확인하는 이유는 혼동을 방지하기 위해서다.
      실제로 로그 파일의 인코딩이 깨지면 어디가 문제인지 파악할때 
      서버와 파일인코딩은 정상인데, 이 문제를 몰라서
      문제를 못찾는 경우가 많기 때문이다.
       
      요약하면 시스템레벨과 서버레벨의 인코딩은 별개지만
      서버측으로 부터 파일처리가 존재하면 인코딩이 꼬일 수 있다.
      그리고 자신이 보는 기준의 인코딩이다.
      
  2. 서버 인코딩을 확인
    • WEB서버의 서버 인코딩이 설정파일에 없다면 클라이언트(브라우저)설정으로 결정된다.
      WAS서버의 서버 인코딩이 설정파일에 없다면 서블릿 컨테이너의 내부로직으로 ISO-8859-1 가 설정된다.
      
  3. 파일 인코딩을 확인

  4. 파일 메타태그 인코딩을 확인

시스템레벨 인코딩

STEP1. 시스템 레벨 인코딩을 확인

# 서버인코딩 확인(1)
wasadm@cddawso1:/ $ echo $LANG
en_GB.UTF-8

# 서버인코딩 확인(2)
wasadm@cddawso1:/ $ locale
LANG=en_GB.UTF-8

en_GB.UTF-8 인코딩
💡 한글 출력이 불가능한 (영어,영국) en_GB.UTF-8 인코딩이다.
💡 시스템레벨 인코딩이 apache web 서버 동작에 영향이 가지는 않지만,
💡 향후 서버인코딩이 문제아가 될 수 있다! 정도를 인지할 수 있다.

STEP2. 시스템 레벨 인코딩을 변경

# 1. 로케일 재설치 명령어 수행
wasadm@cddawso1:/ $ apt-get install --reinstall locales && sudo dpkg-reconfigure locales
wasadm@cddawso1:/ $ install --reinstall  # 재설치
wasadm@cddawso1:/ $ dpkg-reconfigure     # 이미 설치된 패키지를 재설정한다.


# 2. GUI가 나오면 `ko.KR.UTF-8 UTF-8` 을 선택

# 3. 저장

KR.UTF-8
💡 시스템에 관련된 (문서편집 등) 모든 것들을 한글로 출력하기 위해 KR.UTF-8 으로 변경했다.

서버 레벨 인코딩 (WEB:아파치)

STEP1. 서버인코딩을 확인

wasadm@cddawso1:/ $ vi [웹서버]/conf/httpd.conf


# CASE1. (설치시 기본) 아예 존재하지 않거나 아래처럼 OFF
AddDefaultCharset off

리눅스 배포판 별로 다르다
💡 웹 서버(Apache) 인코딩 설정이다.
💡 하지만 내 기본패키지에서 AddDefaultCharset 설정자체가 없었다.
💡 다양한 처리를 유연하게 하기위해 아파치재단의 목적으로 보인다.
💡 웹서버는 특별한 경우를 제외하고는 인코딩을 정하지 말자.

STEP2. 서버 인코딩을 변경

인코딩 변경

wasadm@cddawso1:/ $ vi [웹서버]/conf/httpd.conf


AddDefaultCharset off
AddDefaultCharset EUC-KR
AddDefaultCharset UTF-8

AddDefaultCharset 없는 경우

# CASE1. 캐릭셋이 없다. 브라우저에서 결정한다.
wasadm@cddawso1:/ $ curl -s -I http://www.blang.co.kr/jktest/jktest.html
HTTP/1.1 200 OK
Date: Tue, 15 Aug 2023 06:34:25 GMT
Server: Apache/2.4.54 (Unix) OpenSSL/1.1.1n mod_jk/1.2.48
Last-Modified: Mon, 05 Dec 2022 04:19:40 GMT
ETag: "39-5ef0cfefc07ca"
Accept-Ranges: bytes
Content-Length: 57
Content-Type: text/html # 캐릭셋 없음

AddDefaultCharset UTF-8 인 경우 (또는 UTF-8)

# CASE1. 고정적인 캐릭셋이 생겼다.
wasadm@cddawso1:/ $ curl -s -I http://www.blang.co.kr/jktest/jktest.html

HTTP/1.1 200 OK
Date: Tue, 15 Aug 2023 06:30:59 GMT
Server: Apache/2.4.54 (Unix) OpenSSL/1.1.1n mod_jk/1.2.48
Last-Modified: Mon, 05 Dec 2022 04:19:40 GMT
ETag: "39-5ef0cfefc07ca"
Accept-Ranges: bytes
Content-Length: 57
Content-Type: text/html; charset=EUC-KR  # 캐릭셋 정상설정 확인

사진1

학습용으로 웹서버인코딩을 변경해보았다
💡 나의 디폴트 아파치에는 설정조차 없지만 학습목적으로 변경해보았다.

크롬에서 확인시 주의
💡 반드시 깨끗한 상태로 테스트 해야한다.
💡 캐쉬가 있는 경우 Context-Tyep 내용이 제대로 나오지 않는다.

정확히 보는 과정

  1. 시크릿모드가 완전히 없는 상태에서 시크릿모드 OPEN
  2. F12 미리 진입
  3. GET 요청 후 리스폰스헤더 확인

결론
💡 특별한 경우를 제외하고 웹서버는 인코딩을 명시적으로 지정해두지 말자.

서버 레벨 인코딩 (WAS: 톰캣)

문제점

💡 톰캣 서버는 웹 애플리케이션을 실행하며, 이 애플리케이션은 주로 클라이언트와의 통신에 문자 데이터를 리턴한다.

WAS 서버의 설정 방법은 조금 다양하다.

STEP1. WAS 서버인코딩을 설정

(server.xml)

wasadm@cddawso1:/ $ vi [WAS서버]/conf/server.xml 


<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
               URIEncoding="UTF-8"/>

요약
💡 웹 애플리케이션의 URL에 포함된 문자열 (특히 쿼리 스트링)의 인코딩을 지정한다.
💡 즉, 사용자가 웹 페이지에서 입력한 한글 등의 문자열이 올바르게 인코딩되어 서버로 전달하는 역할이다.

URIEncoding = “UTF-8”
💡 POST 요청은 관련 없다. (%D0%B6 같은 형태니까. )
💡 커넥터가 UTF-8을 사용하여 URL(GET 요청) 이 온다면 쿼리스트링을 인코딩하도록 구성한다.
💡 이제 Tomcat은 들어오는 모든 GET 쿼리스트링을 UTF-8로 인코딩하여 처리된다.

https://localhost:8443/ID/Users?action=search&name=*ж*

💡 문자 ж는 UTF-8로 처리되며 (일반적으로 서버에 도달하기 전에 브라우저에 의해)
💡 톰캣의 설정으로 인해 %D0%B6 으로 인코딩된다.

STEP2. web어플리케이션 인코딩을 변경

(web.xml)

wasadm@cddawso1:/ $ vi [WAS서버]/conf/web.xml 


<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- Request(요청)에 전송되는 문자열을 UTF-8로 인코딩 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- Response(응답)에 전송되는 문자열을 UTF-8로 인코딩 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

설명
💡 톰캣에서 요청을 받으면 이제 어플리케이션 레벨에서 인코딩을 처리하는 곳이다.
💡 스프링의 java webapp가 UTF-8로 인코딩 된 모든 요청과 응답을 처리하도록 한 모습이다.
💡 이렇게 문자 집합 필터를 정의하면 톰캣으로 들어온 요청, 응답을 인코딩처리한다.

결론
💡 이제 컨트롤에서 request.setCharacterEncoding(“UTF-8”);과 response.setCharacterEncoding(“UTF-8”);를 사용하지않아도 자동으로 문자열이 UTF-8로 인코딩 가능해짐.
💡 <web-app> 태그 내에 존재하며 설치버전의 경우 주석처리되어있어 주석을 해제.

STEP3. java어플리케이션 인코딩을 변경

STS실행 

1. 사용중인 서버 클릭
2. Open Launch configuration 
3. Arguments - VM arguments 작성
4. 아래 내용 추가

-Dfile.encoding=UTF-8

5. 그러면 아래 명령이 가능해진다.
java -Dfile.encoding=UTF-8 -jar myapp.jar

설명
💡 자바 애플리케이션 실행 시 JVM 옵션으로 설정되는 것을 의미한다.

파일 자체 인코딩

🎆필수 개념
파일인코딩과 메타태그 인코딩은 전혀 다른 개념이다.
💡 <meta charset=”UTF-8”> 메타태그는 웹 브라우저에게 해당 HTML 문서가 “UTF-8 인코딩을 사용할게요~” 라는 정보를 전달하는 것이 전부다.
💡 즉, 이 메타태그는 브라우저(클라이언트)가 해당 HTML 문서를 표시할 때 사용되는 것이지, 파일 자체의 인코딩을 변경하지 않는다.
💡 HTML 파일을 UTF-8 인코딩으로 사용하고자 한다면, <meta charset=”UTF-8”> 태그 뿐만 아니라 파일 자체의 인코딩도 UTF-8로 설정되어 있어야 한다.

파일인코딩과 메타태그 인코딩이 다르면?
💡 만약 두 인코딩이 일치하지 않는다면, 브라우저는 파일의 실제 인코딩을 기준으로 해석 한다.
💡 이로 인해 깨진 문자나 오류가 발생할 수 있다.

STEP1. 파일자체 인코딩을 확인

wasadm@cddawso1:/ $ file -bi index_html.html # html
text/html; charset=utf-8

wasadm@cddawso1:/ $ file -bi index_js.js # js
text/html; charset=us-ascii

wasadm@cddawso1:/ $ file -bi index_css.css # css
text/plain; charset=us-ascii

wasadm@cddawso1:/ $ file -bi index_xml.xml # xml
text/xml; charset=us-ascii

wasadm@cddawso1:/ $ file -bi index_php.php # php
text/x-php; charset=us-ascii

STEP2. 파일자체 인코딩을 변경

방법1

# iconv -f [원본인코딩] -t [대상인코딩] 원본파일 > 대상파일

# 새롭게 생성
wasadm@cddawso1:/ $ iconv -f utf-8 -t euc-kr index_html.html > converted.html

# 덮어쓰기
wasadm@cddawso1:/ $ iconv -f utf-8 -t euc-kr index_html.html > index_html.html

방법2

vi <파일명> 

# 아래 입력
:set fileencoding=utf-8

# 저장

방법2를 권장
💡 2번을 사용하자.

인코딩 변경시 임시파일은 필수
💡 파일의 인코딩을 변경하려면 일반적으로 임시 파일을 만들어서 변환 후 원본 파일로 복사하는 방법을 사용한다.

재밌는 실험

📃index_html.html

# index_html.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<!-- 여기부터 문서 내용 시작 -->
<b>안녕</b>
</body>
</html>

📃정상 테스트

  1. 서버 인코딩 확인
    • 현재 아파치 기본설정 없음. 즉, 브라우저가 해석하는 모드이다.
  2. 파일 자체 인코딩을 확인
    • 파일의 인코딩은 utf-8 임을 확인 완료.

      file -bi index_html.html # 인코딩 확인
      text/html; charset=utf-8
      
      
  3. 파일 메타태그 인코딩을 확인
    • 아까 위에서 meta 태그의 charset 이 UTF-8 임을 확인했다.
  4. 정상적으로 파일과 메타태그의 인코딩이 일치하므로 정상출력 한다.

📃파일자체 인코딩 다르게 테스트

  1. 파일 자체의 인코딩을 변경
    • 파일의 인코딩을 의도적으로 메타태그와 불일치 시킨다.
    • 문서 내부의 한글이 모두 깨졌다.

      vi <파일명> 
      
      # 아래 입력
      :set fileencoding=euc-kr
      
      # 저장시 인코딩
      text/html; charset=iso-8859-1
      
      
      <!-- converted.html -->
      
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      </head>
      <body>
      <!-- ¿©±âºÎÅÍ ¹®¼­ ³»¿ë ½ÃÀÛ -->
      <b>¾È³ç</b>
      </body>
      </html>
      
      
  2. 파일 자체의 인코딩을 무시하고 한글로 저장
    • 개발자는 위 처럼 변경되어서 당황한다. 그리고 한글로 바꾸고 저장한다.
    • 이때 우리 눈에는 에디터로 즉시 수정하고 저장누르기 때문에 한글로 저장되는 것처럼 보인다.
    • 참고로 vi에디터는 이런경우를 방지하게끔 저장못하게 알려준다.
    • 처음에는 이 부분이 정말 멘붕이 오는 구간인듯.
  3. 테스트
    • 파일을 닫고 다시 오픈하면 역시 깨진다. 지원하지않기 때문이다.

파일 메타태그 인코딩

STEP1. 파일인코딩을 확인

<meta charset="UTF-8">

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8” /> VS <meta charset=”EUC-KR”>
💡 전자는 HTML4 또는 XHTML을 사용하거나 같은 오래된 레거시한 명시
💡 후자는 HTML5 기본
💡 후자를 사용해서 파일인코딩을 명시하자. (크롬도 네이버도 동일)

정리
💡 파일의 인코딩을 서버와 동일한지 확인했다.
💡 서버와 동일한 utf-8 이므로 정상이다.
💡 한글 출력이 가능해진다.

해결완료

웹서버에 접속해보면 한글이 정상적으로 출력함을 알 수있다.

추가내용) STS IDE 툴 기본 캐릭터셋 설정해주기

vi C:\KBCard\STS\sts-3.9.12.RELEASE

-startup
plugins/org.eclipse.equinox.launcher_1.5.700.v20200207-2156.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.1100.v20190907-0426
-product
org.springsource.sts.ide
--launcher.defaultAction
openFile
-vmargs
-Dosgi.requiredJavaVersion=1.8
-Xms256m
-Xmx1024m
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.module.lock.timeout=10
-Dfile.encoding=UTF-8 # 추가

Leave a comment