인코딩 문제로 오늘 또 하루종일 씨름했다.
사실 그닥 어려운게 아닌데.. 처음 설정을 잘못해놓으면,.
고생하기 쉽상이다.

웹개발에서 인코딩과 관련해서 신경써야할 부분

아래와 같은 3가지라고 보면 되겠다.
1. 클라이언트 (javascript)
2. 서버 (apache or tomcat 설정)
3. DB

1. DB 캐릭터셋 설정하기

그중에서 가장 실수하기 쉬운 것중에 하나는 DB 설정.
mysql 을 설치하고, 꼭 아래와 같은 명령어로 현재 mysql 의 설정 상태를 확인해야한다.
mysql> \s
mysql 을 설치할대, 기본 캐릭터셋이 latin1 으로 설정되어 있기때문에
신경써서 설치하지 않으면, 원하는 utf8 설정이 안된다.
설정이 제대로 안되어 있다면, 설치 폴더로 가서 my.ini 파일을 열어
인코딩 관련 부분을 모두 수정해줘야한다.

여기서 그렇게 했는데도 불구하고, \s 명령어를 이용해, mysql 설정상태를 확인 했을때,
DB character set 이 latin1 로 나오는 경우가 있는데..
이런 경우는, create database로 db를 생성할 당시의 캐릭터 셋이 latin1이 었기 때문에
뒤늦게 수정해봐야 수정되지 않는다. 결국엔 db를 날리고 다시 생성해야한다.

이런 경우 때문에 초기 설치시에 주의해서 원하는 캐릭터셋으로 설정을 해야한다.

2. 스프링 프레임웍에서 설정하기
두번째로 서버 설정을 확인해야하는데.. tomcat에서 server.xml 을 열어서 8080포트와 8009번 포트의
커넥터에 URIEncoding="UTF-8" 를 추가해준다.
스프링 프레임웍을 이용할경우, web.xml 열어서 아래와 같은 필터를 추가해준다.

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

그리고 xxxx-servlet.xml 파일을 열어서, viewResolver를 아래와 같이 또 수정해준다.

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/WEB-INF/view/"/>

<property name="suffix" value=".jsp" />

<property name="contentType" value="text/html; charset=UTF-8"/>

</bean>

이렇게 해주면, 기본적으로 클라이언트딴에서 특별한 인코딩을 수행하지 않아도 UTF8로 인식을 한다.
때문에 응답할때도 특별한 디코딩을 해주지 않아도 된다.


3. 서버 설정없이 클라이언트에서 무조건 UTF-8로 넘겨주기

위와 같이 서버딴에서 특별한 설정을 해주지 않았다면,
다소 귀찮은 작업을 해줘야하는데..
그것은 클라이언트에서 서버로 정보를 날릴때, 무조건 인코딩을 해서 넘겨야 한다는 것이다.

인코딩하는 방법은 간단하다.
아래와 같이 자바스크립트를 이용해, 넘기고자 하는 정보를 encodeURIComponent()
함수를 이용해 인코딩 해주면, 넘기는 정보를 UTF-8로 인코딩해서 넘기게 된다.

4. 인코딩 파헤치기

보통은 클라이언트에서 서버로 요청 파라메터 정보를 넘기게 되면,
아래와 같은 3가지 인코딩 방식으로 넘기게 된다. 아래 1번을 제외한 나머지 방법은
브라우저가 설정된 인코딩 방식을 따르게 된다. 1번방법은 자바스크립트에서 강제로 인코딩한다.
예를 들어 "한글"이란 문자열을 넘기면,
1. encodeURIComponent() 로 인코딩 할때, "%25ED%2595%259C%25EA%25B8%2580"
2. UTF8 인코딩을 할때,  "%ED%95%9C%EA%B8%80"
3. EUC-KR로 넘길 때, "%C7%D1%B1%DB"

위 3가지 타입을 UTF8로 설정된 서블릿에서 각각 request.getParameter() 로 넘겨받은 정보를 읽어오게 되면,
UTF8로 디코딩 되어 각각  
1. "%ED%95%9C%EA%B8%80"
2. "한글"
3. "???"
로 읽혀오게 된다.
여기서 문제는 3번이 문제가 된다. 3번은 실제로 "한글"이란 정보를 EUC-KR로 인코딩해서 넘기게 되는데..
서블릿에서 UTF-8로 디코딩을 하게 되어 알수없는 값이 되어버린다.

그리고 서버에서 이것을 다시 UTF8 캐릭터셋으로 설정된 DB에 그대로 저장하면,. 각각
1. "%ED%95%9C%EA%B8%80"
2. "?쒓?"
3. "ㅁ싼깍옙"
로 다시 저장된다.
1번을 제외한 2,3번 방식으로 DB에 저장이 되면, 본래 기대했던 값들과 다른 값들로 저장이 되는데..
DB 정보를 서블릿에서 다시 읽어볼때, 같은 UTF8로 디코딩을 하게 되면 사실 큰문제 없다.
하지만 위 DB정보를 다른 캐릭터셋으로 설정된 서블릿에서 읽어오게 되면 이식성에 문제가 생긴다.
또한 DB 캐릭터 셋이 UTF8이 아닌 다른 캐릭터셋으로 설정이 되었다면, DB에 저장될때 마찬가지로
문제가 생길수있다.

때문에 UTF8로 다국어를 지원해야하는 특별한 상황이라면, 1번 방법을 사용하는것이 보다 안전하다.
하지만 보통 하나의 캐릭터셋만을 지원하거나 통일하기 때문에 2번 방식으로 대부분 커버가 가능하다.

사실 더 중요한 것은, 인코딩과 디코딩할때,
클라이언트(브라우저인코딩) - 서버 - DB
3박자를 모두 잘 맞춰서 해줘야 한다는 것이다.

이상 정리 끝~
2009/06/14 23:58 2009/06/14 23:58

Trackback URL : http://miconblog.com/tc/sohn/trackback/563

오늘은 Microtime 에 대해서 이야기 해봐야겠당.
사실 나도 정확히 요놈에 대해 알지 못한다. 그런데 오늘 이놈 때문에 삽질을 한게 있어서..
적고 넘어간다.

사실 내가 하고 싶었던건, zeroboard에서 reg_date로 들어가 있는 날짜를 jsp에서 불러와 출력하고 싶었다.
내가 검색 능력이 딸려서 못찾은건지, php에서는 기본 함수로 있는데.. jsp에서는 microtime을 현재 시간으로 변환해주는 메소드를 찾지 못했다.

여기저기 Q/A를 뒤져봤지만.. 못찾았다.. 그래서 그냥 나몰라라 접어두고 있었는데..

오늘 마침 TDD(테스트 주도개발) 연습을 하면서 날짜를 컨트롤하는 예제를 뚝딱뚝딱 하고 있었다.
그래서 이왕 하는 김에 DateTime  클래스를 java로 구현해봤다.
이름 하야 myDateTime ㅋㅋㅋ

이놈의 역할은 간단하다. microtime 을 인자로 받아서 현재시간으로 출력해주기위한 클래스다.
이것을 구현하기 위해 microtime을 다시 찾아봤다.

검색 결과에 의하면, microtime은 100/1 초까지 유닉스시간형태로 반환을 해준다고 한다.
기준은 1970년 1월 1일 0시 ㅇ분 00초를 부터 시작이다.

중요한건 1970년 1월 1일 0시 00분 00초가 기준이라는것이다.
아마도 1970년도가 유닉스 탄생해가 아닌가하는 추측해본다. 물론 찾아보지 않았다..귀찮아서..
( 누군가 유닉스 탄생시기를 알면 리플 달아주삼~ )

다시 본론으로 돌아와서,
zeroboard 의 reg_date는 mysql에 int(13)으로 잡혀있다. 실제로 값을 불러오면, 10자리 숫자가 나온다.
추측해보건데,.. 이 10자리 숫자를 환산하면, 0000년 00월 00일 00시 00분 00초로 나올것이다.
마침 32비트 컴퓨터의 int형 범위도 대략 10자리수가 나온다.

여기서 재밌는 사실을 알아냈다. microtime의 유효범위가 2037년쯤 된다고 한다.
만약에 2037년이 지나면, 이상해 진다고 하던데..
아마도 그 이유는 int 범위에 굉장히 밀접한 관계가 있지 싶다.

시간을 계산해 보면,
1분은 60초,
1시간은 3600초,
하루는 86400초,

한달은 날짜마다 계산이 다르다.
단, 1년은 365일이고, 윤년일 경우 1년은 366일..
즉, 1년은 31536000초이고, 윤년인 해일 경우엔, 31622400초가 된다.

int의 최대범위는 2147483647 이고, 이것을 평년으로 나누면,..
대략 68년이 나온다. 그러므로 1970년을 기준으로하면,
2038년이 딱떨어진다. ㅋㅋㅋ

이것으로, 마이크로타임은 32비트 컴에서 내부적으로 int형 4바이트로 구현되어 있음을 짐작 할수있다.

이미 microtime을 로컬타임으로 변환하기 위한, 모든 아이디어는 앞에 서술한거 같다.
다시한번 짚어보면,

윤년을 계산해 내야하고,
날짜를 계산해 내기 위해, 달별로 일수를 짚어내야한다.
물론 윤년이 낀 해의 2월은 29일이다.

요 날짜만 구해낸다면, 시간은 식은죽먹기~!
시간구할때 한가지 더 생각해봐야할껀 로컬타임..
우리나라의 경우 +9 시간을 해야한다.

ps
그밖에 TDD 연습을 위한 페이지..
http://wiki.javajigi.net/display/OSS/TDD

2008/03/06 00:18 2008/03/06 00:18

Trackback URL : http://miconblog.com/tc/sohn/trackback/365

현재 진행상황...

2007/09/29 22:25

오랜만에 포스트를 남기는군...
요새 너무 바빴다도.. 아니고.. 계속 바쁘고 있는중이다..
아마도 다음달까지 여전히 바쁠듯...

당장 닥친건.. 짬뽕나 프로젝트랑... 졸업논문..
어서 마무리 지어야할껀.. IRS과제
서둘러 봐야할껀.. 동구권 과제...

그리고 예상하지 못하는 .. 영문과 과제..ㅜㅜ..

정말 하고 싶어서 하는건 짬뽕나 밖에 없구나.. 나머지는.. 먹고살기위해.. 졸업하기위해 하는것들..

맥북도 사놓고.. 바빠서 열어보지도 못하고 있다.. 애물단지..ㅜㅜ..
예전같았음.. 사놓고.. 한 일주일간 질리도록 가지고 놀텐데.. 가지고 놀정신도 없다..ㅎㅎㅎ

여튼...
오늘 짬뽕나 DB 등록 마무리했음..ㅋㅋㅋ
오늘 날 삽질하게 만든 MySQL과 우분투 미워할테다..ㅎㅎㅎ

-mysql 한글문제 해결한 방법과 mysql 원격 접속-
일단 설정 환경은...
서버용 우분투 7.04 버젼에..
MySQL 버전은 apt-get 으로 받은 Server version: 5.0.38-Ubuntu 버젼..
그리고 DB 접속하려는 클라이언트는 로컬이 아닌 외부IP의 Java 프로그램..

먼저, 원격 접속의 경우는.. /etc/mysql/my.cnf 에서..
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address           = 203.253.22.151
#
이부분 주석처리 해주고...
우분투 리눅스에서 iptables 로 3306번 mysql 포트 방화벽 풀어줬다..

KIST안에서는 중앙네트웍에서 포트를 관리해서 그런지.. 안됐는데..
학교와서 해보니.. 아주 잘된다..ㅎㅎ

그리고 mysql은.. phpmyadmin 이것도 역시.. apt-get 으로 받아서.. 설치해놓고..
my.cnf 파일에 아래와 같이 설정 추가하고..
mysql의 데이타 베이스랑.. 테이블 모드 euckr_korean_ci 로 했더니 한글된다..ㅋㅋㅋ
----------------------------------------------------------
[client]
port            = 3306
socket          = /var/run/mysqld/mysqld.sock
default-character-set = euckr

[mysqld]
language        = /usr/share/mysql/korean

character-set-client-handshake=FALSE
init_connect="SET collation_connection = euckr_korean_ci"
init_connect="SET NAMES euckr"

default-character-set = euckr
character-set-server = euckr
collation-server = euckr_korean_ci

[mysqldump]
default-character-set = euckr

[mysql]
default-character-set = euckr
-----------------------------------------------
위에 같이 설정하고 나서 mysql 재시작하고..

mysql> status  해보면...
..
..
Server characterset:    euckr
Db     characterset:    euckr
Client characterset:    euckr
Conn.  characterset:    euckr
..
..

저렇게 euckr 로 설정되게 된다..
요렇게 되면.. 한글 설정 완료!!

2007/09/29 22:25 2007/09/29 22:25

Trackback URL : http://miconblog.com/tc/sohn/trackback/299

mysql 1037에러...

2007/08/18 11:21
흠.. 자꾸 서비스 등록이 안되서...
검색한번 쳐보니.. 바로 나오는군...

연구실에서 할때는 아무런 이유없이 잘 됐는데..-_-
집에선 왜 이러냥?..ㅎㅎㅎ

암튼... /윈도우즈/my.ini 파일을 생성해서 설정해주란다..


2007/08/18 11:21 2007/08/18 11:21

Trackback URL : http://miconblog.com/tc/sohn/trackback/274