Skip to content
isdnetworks
Go back

화면 파일 안의 조회 코드

앱 쪽 일을 하다가 웹 쪽으로 넘어갔다. 넘겨받은 코드를 열어 보니 화면을 그리는 파일 안에 DB 조회가 들어 있었다.

Table of contents

Open Table of contents

한 파일에 다 있었다

처음에는 아무 생각이 없었다. 오히려 편했다. JSP 하나만 열면 되고 값이 어디서 오는지도 바로 위 scriptlet 에 적혀 있다. 나중에 안 것인데 이 구조를 Model 1 이라고 부른다.

<%
    Connection conn = DriverManager.getConnection(...);
    PreparedStatement ps = conn.prepareStatement(
        "SELECT id, name, point FROM member WHERE id = ?");
    ps.setString(1, request.getParameter("id"));
    ResultSet rs = ps.executeQuery();
%>
<table>
<% while (rs.next()) { %>
    <tr><td><%= rs.getString("name") %></td></tr>
<% } %>
</table>

이 파일을 처음 열었을 때는 화면에 표를 그리는 코드로만 보였다.

증상 — 닫는 코드가 없었다

그 scriptlet 에 conn.close() 가 없었다. ResultSetPreparedStatement 도 그대로였다.

한동안 문제가 안 났다. 접속이 적을 때는 커넥션이 남아도 티가 안 난다. 사람이 몰리는 시간에 화면이 멈춘다는 이야기가 나오고서야 봤다.

DriverManager.getConnection() 은 부를 때마다 새 커넥션을 연다. 안 닫으면 MySQL 쪽 max_connections 에 걸릴 때까지 쌓인다. SHOW PROCESSLIST 로 보니 Sleep 상태가 백 개가 넘었다.

finally 에서 닫게 고쳤다. 다만 JSP 안에서 try·finally 를 쓰니 HTML 과 섞여 읽기가 더 어려워졌다.

두 번째 화면과 복사

같은 회원 정보를 다른 화면에서도 보여 달라는 요청이 왔다. 마이페이지와 관리자 화면 두 곳이었다. 내가 한 일은 조회 부분을 그대로 복사해 새 파일에 붙이는 것이었다.

문제는 그다음이었다. 회원 테이블에 컬럼이 하나 늘었다. 그 값을 화면에 추가해야 하는데 같은 조회가 몇 군데 있는지 몰랐다. Eclipse 로 SELECT 를 찾아 다녔고, 세 곳을 고쳤다고 생각했는데 네 번째가 있었다. 그건 QA에서 나왔다.

화면 파일 안에 조회를 두면 안 된다는 말은 전에도 들었는데 왜 안 되는지는 몰랐다. 잘 돌아가고 있었기 때문이다. 이 일을 겪고 나서 이유가 손에 잡혔다. 같은 조회가 필요하면 복사하게 된다. 복사하고 나면 고칠 곳이 몇 개인지 알 방법이 전체 검색밖에 없다.

조회를 밖으로 뺐다

조회 코드를 MemberDao 라는 클래스로 옮겨 봤다. JSP 에는 그 클래스를 부르는 두 줄만 남았다.

<%
    MemberDao dao = new MemberDao();
    Member m = dao.findById(request.getParameter("id"));
%>

컬럼이 늘면 그 클래스 한 곳만 고치면 됐다. 화면 네 개는 그대로 두고. 이때 처음으로 고칠 곳이 하나가 되게 만든다는 감각이 생겼다. 설계라는 말을 이런 데 쓰는 것 같다.

얼마 뒤 프로젝트에 iBATIS 가 들어왔다. Java 안에 문자열로 쓰던 쿼리를 sqlmap XML 로 옮기는 것이다.

처음에는 왜 굳이 파일을 하나 더 만드나 싶었다. 자바 안에 있을 때가 더 가까워 보였다. 써 보니 쿼리가 여러 줄이어도 문자열을 이어 붙이지 않아도 됐다. 쿼리만 따로 보면서 고칠 수 있었다.

가장 컸던 것은 자바를 모르는 사람도 쿼리를 읽을 수 있다는 점이다. 성능 문제를 상의할 때 그 파일만 보내면 됐다.

정리하다 보니 아직 모르는 것이 하나 남았다. 요청에서 받은 값을 쿼리에 넣는 자리가 둘이었다. 어떤 자리는 # 를 쓰고 어떤 자리는 $ 를 썼다. 동작이 같아 보여서 넘어갔는데 굳이 두 방식이 있다면 이유가 있을 것이다. 다음에는 이것부터 알아봐야겠다.

정리


Share this post on:

Previous Post
손으로 돌리면 되는데 예약으로는 안 됐다
Next Post
내 코드 때문인 줄 알았다