첫 회사 프로젝트를 받았다. 화면 하나를 고치려면 그 화면이 DB에서 무슨 값을 가져오는지부터 봐야 하는데, 그 부분을 못 찾겠다.
Table of contents
Open Table of contents
SQL이 어디에도 없다
Eclipse 에서 Java 파일을 하나씩 열었다. DAO 라는 이름이 붙은 클래스부터 봤다. 메서드 안에 SELECT가 없다. 그 위 서비스 클래스도 열었다. 컨트롤러까지 올라가 봤지만 마찬가지였다. 프로젝트 전체에 SELECT로 검색을 걸었다. 자바 파일에서는 하나도 안 나온다. 확장자를 안 걸고 다시 돌렸다. 그제야 결과가 나왔는데 전부 iBATIS sqlmap XML 이었다.
<select id="selectUser" parameterClass="map" resultClass="user">
SELECT * FROM users WHERE id = #id#
</select>
자바 쪽은 이름으로 부르기만 한다. 코드만 봐서는 쿼리가 어디 있는지 모른다. 저 selectUser를 XML에서 다시 찾아야 한다.
sqlMap.queryForObject("selectUser", param);
처음에는 두 파일로 나눈 것이 불편해 보였다. 며칠 쓰다 보니 이유가 짐작됐다. XML을 열면 그 화면의 쿼리가 한자리에 모여 있다. 자바에 SQL을 쓰면 따옴표와 더하기가 섞인다. XML에는 SQL을 그대로 적는다. 쿼리만 고칠 때는 자바를 안 건드린다. 그러면 다시 빌드하지 않아도 되는 경우가 있었다.
값 표시가 두 종류였다
XML을 보다 보니 값 넣는 표시가 두 가지였다. #값#으로 적힌 자리가 있고 $값$으로 적힌 자리가 있다. 같은 일 같은데 모양이 다르다. 무슨 차이인지 찾아봤다.
# PreparedStatement 의 ? 자리표시자로 들어간다
$ 문자열이 SQL 에 그대로 붙는다
#는 iBATIS 가 ?로 바꿔 PreparedStatement에 값을 바인딩한다. 그러면 #만 쓰면 될 것 같은데 왜 $가 남아 있는지가 다음 의문이었다. 자리표시자로 못 넣는 자리가 있어서였다. 테이블명이나 컬럼명은 값이 아니라 SQL의 구조다. 그 자리는 자리표시자로 대체되지 않는다.
SELECT * FROM users ORDER BY #컬럼# -- 안 된다
SELECT * FROM users ORDER BY $컬럼$ -- 된다
대신 $는 값이 그대로 붙는다. 외부 입력을 넣으면 SQL 자체가 바뀐다. %'; DROP TABLE users-- 같은 것을 보내면 그게 문장의 일부가 된다. 어느 쪽이 어느 쪽인지 자꾸 헷갈렸다. 값은 #, 이름은 $로 외웠다. 값이면 무조건 #이다. $를 쓰고 싶어지면 정말 이름 자리인지 한 번 더 본다.
목록과 조건 태그
조건에 목록이 들어가는 쿼리가 있었다. WHERE id IN (1, 2, 3) 같은 것이다. 개수가 매번 다르다. 자바에서 문자열로 만들면 결국 $로 넣게 된다. 그건 위험한 쪽이다. XML에 반복 태그가 있어서 그걸로 처리했다.
<iterate property="ids" open="(" close=")" conjunction=",">
#ids[]#
</iterate>
목록을 돌면서 만들어 주고 각 값은 #로 들어간다. 검색 조건이 선택인 경우도 비슷했다. 값이 있을 때만 조건을 붙이는 것을 자바에서 하면 if 문과 SQL이 섞인다. 그러면 문장이 조각난다. XML에서는 SQL 안에 조건이 들어간다.
<isNotEmpty property="name">
AND name LIKE #name#
</isNotEmpty>
어느 쪽이 읽기 쉬운지는 갈릴 것 같다. 자바 쪽은 조건 로직이 익숙한 대신 SQL이 조각난다. XML 쪽은 SQL이 온전한 대신 태그를 알아야 한다. 나는 SQL을 통으로 보고 싶어서 XML 쪽이 편했다.
파일이 셋으로 늘었다
다만 한 기능을 고치는 데 열 파일이 늘었다. 자바 파일과 XML 파일이 있다. 어느 XML을 읽을지 적어 둔 설정 파일까지 셋이다. 처음에는 어디부터 봐야 할지 몰랐다. 화면 하나 고치는 데 파일을 열었다 닫았다 했다.
며칠 지나니 규칙이 보였다. 화면 이름과 XML 파일 이름이 맞춰져 있다. 화면을 알면 XML을 바로 찾을 수 있다. 파일이 많은 것 자체가 문제는 아닌 것 같다. 어디 있는지 모르는 것이 문제였다.
정리
- SQL이 자바가 아니라 XML에 있었다. 자바는 이름으로 부르기만 한다
- 쿼리가 한자리에 모여 있고 문자열 이어붙이기가 없어 SQL이 온전하게 보인다
- 값 넣는 표시가 둘이고
$는 외부 입력에 쓰면 SQL이 바뀔 수 있다 - 값은
#, 이름은$로 외웠다.$를 쓸 때는 한 번 더 본다 - 목록과 선택 조건은 태그로 처리하면 문자열 조립을 안 해도 된다
- 파일이 셋으로 늘지만 이름 규칙이 있으면 찾을 수 있다