본문 바로가기

Server Oriented/Java & JSP

오라클 varchar2(4000) 과 한글의 오묘한 만남..?

원문1 : https://javafreak.tistory.com/98

원문2 : http://egloos.zum.com/realcool/v/2585694

 

SQLInjection 을 막기 위해,

PreparedStatement 를 사용하는 것이 기본이겠죠.

 

DB 칼럼에 varchar2(4000) 이 있고,

한글 2000 자를 insert 또는 update 하려 할 때..

에러가 발생합니다, 글자를 너무 많이 입력했다공..

 

이것은, 오라클이..

setString() 을 사용할 때 한글을 UTF-8 로 자동변환 하면서,

한글 1글자를 3bytes 로 인식하기 때문이라네요.

이걸 JDBC 버그라 말하기도 하는데,

Statement 를 사용할 때는 setString() 으로 진행해도,

한글 2000자가 잘 들어가집니다.

물론, PreparedStatement 라도 ? 대신 파라미터를 넣는 방식이 아니고,

sql 문 자체에 한글 2000자를 넣어 버리면

Statement 를 사용할 때의 방식 처럼 정상 처리됩니다.

이를테면 String sql = "... "+str4000bytes+"..." 처럼요.

그러나 이런 방식은 칼럼이 여럿인 경우,

오라클의 sql 문 파싱이 무제한이 아니다 보니,

간헐적으로 오류가 발생할 수 있습니다.

그리고 SQLInjection 에도 취약하구요.

DB 가 NVarchar2() 로 세팅되었다면 문제 없을 수도..

 

이걸 피하는 해법이..

setCharacterStream() 사용하는 거라네요.

예전에 long 이나 Clob, Blob 이용시 사용하던 메소드입니다.

이러면 한글을 1byte 단위로 쪼개기 때문에,

우리가 익히 알고 있듯이

한글 1글자 당 2bytes  로 인식하는 거겠죠.

 

그런데, varchar2(4000) 인 칼럼이 하나의 테이블에 여럿 있다면..

a, b, c 칼럼이 varchar2(4000) 이라 할 때,

어떤 때는 a 칼럼에 들어갈 내용이 b 칼럼에 들어가는 식으로

제멋대로 데이타가 들어가진다는 건데..

이걸 피하려면 varchar2(4000) 대신에,

clob 이나 blob 을 이용하는 겁니다.

이 때는 여러 칼럼이 clob 이나 blob 이라 해도,

순서 오류 없이 제 칼럼에 정확하게 들어갑니다.

이제는 varchar2(4000) 과 같이 하는 것은 포기해야 하겠습니다.


substrb(?,0,4000) 를 이야기하는 분이 있던데..

oracle 에 파라미터가 전달된 다음에 byte 로 4,000 을 끊는거라서,

파라미터 전달될 때 문자열 길이 관련 에러가 납니다.

 

그리고, 간혹 4천 바이트를 넘기는 문자열이 들어갈 수 있으니..

파라미터 세팅 전에 4천 바이트 체크하는 로직을 넣는 것이 필요합니다.

java 는 n-byte 가 기본적으로 지원되기 때문에,

byte[] 에 넣어서 length 를 구하고 4천을 넘기면,

new String 으로 4천 바이트 까지 잘라서 다시 담아야 합니다.

String stringOver4000 = "...";

byte[] bs = stringOver4000.getBytes();

if(bs.length>4000) StringOver4000 = new String(stringOver4000,0,4000)

 

.Fine.