HwangHub

[JDBC] batch query를 작성해보며 고민해본 '좋은 코드' 본문

DEV-STUDY/Spring

[JDBC] batch query를 작성해보며 고민해본 '좋은 코드'

HwangJerry 2023. 11. 4. 22:38

돌아가는 코드 짜기

아래 코드는 돌아가는 코드다.

jdbc.connectJDBC();
Statement stmt = conn.createStatement();
for (String ssn : ssnList) {
    sb = new StringBuilder();
    String sql = sb.append(baseDeleteClause).append("ssn = ").append(ssn).append(";").toString();
    stmt.execute(sql);
}
jdbc.disconnectJDBC();

 

 

그렇다. 원하는 현상을 구현하기 위해 개발을 하다 보면 가장 먼저 해야 할 일이 " 1. 돌아가는 코드 짜기 " 이다.

 

하지만 돌아가는 코드를 짜기만 하면 우리의 일은 끝인가?

 

아니다.

 

두 번째로 해야 할 일은 " 2. 효율적인 코드 짜기 " 이다.

 

효율적인 코드 짜기

단순히 '작동'은 되지만 1분 걸리는 로직과, 1초 걸리는 로직이 있다면 당신은 무엇을 선택할 것인가. 두 코드가 같은 결과를 불러온다면 당연히 1초 걸리는 로직을 선택할 것이다. 나는 '다양한' 분야에서 효율화할 수 있는 능력을 갖추다보면 '중급 개발자'로 진출할 수 있을 것으로 (막연히) 생각한다.

 

위 코드를 설명하자면, ssn이라고 하는 직원의 id 넘버를 담은 리스트를 순회하면서 해당 ssn을 가진 직원 레코드를 지우는 sql을 작성한 뒤, 한 건 한 건 실행하는 로직이다.

 

DB에 sql을 한 건 한 건 실행하게 하는건 비효율적이다. 한 번에 여러 SQL을 보내어 실행시키면 훨씬 효율적일 것이다. 따라서 아래와 같이 수정할 수 있다.

conn.setAutoCommit(false);
PreparedStatement pstmt;
StringBuilder sb = new StringBuilder();
String sql = sb.append(baseDeleteClause).append("ssn = ?;").toString();
pstmt = conn.prepareStatement(sql);

try {
    for (String ssn : ssnList) {
        pstmt.setString(1, ssn);
        pstmt.addBatch();
        pstmt.clearParameters();
    }
    pstmt.executeBatch();
    conn.commit();
} catch(Exception e) {
    conn.rollback();
    e.printStackTrace();

 

위처럼 preparedStatement 객체를 이용하면 batch query를 이용하여 여러 반복적인 sql을 parameter 형식을 통해 작성하고, preparedStatement 객체에 담아둔 뒤에 한번에 실행 및 DB 커밋이 가능하다.

 

조금 더 구체적으로 보이기 위해 오토 커밋을 취소하여 코드 노출량이 늘어나긴 했지만, DB와의 소통 면에서는 훨씬 효율적이고, 내 눈에 작업들이 전부 보이기 때문에 안정적인 코드라고 할 수 있다.

 

그렇다면 효율적이기만 하면 능사인걸까?

 

아니다.

 

세 번째로 해야 할 일은 " 3. 인간 친화적인 코드 짜기 " 이다.

 

인간 친화적인 코드 짜기

인간이 할 일을 기계에게 시키기 위해 시작된 것이 코딩이다. 컴퓨터가 세상에 나오고, 복잡한 조건일수록 사람의 뛰어난 뇌를 거쳐야 하지만, 단순 작업은 사람보다 컴퓨터가 빠르기에 컴퓨터를 시키기 위해 컴퓨터에게 명령을 내리고자 코딩이 시작되었다.

 

AI가 발전함에 따라 앞으로는 어떻게 될지 모르겠지만, 결국 AI도 기계에 불과하기 때문에 기계를 컨트롤하는 명령어의 디테일을 컨트롤하기 위해서 기계 자동화의 끝에는 항상 전문적인 사람 엔지니어가 필요할 것이다. 따라서 사람이 알아볼 수 있고, 읽었을 때 코드의 의도가 명확할수록, 그리고 추가/수정 작업을 할 때에 가장 적은 노동을 통해 반영할 수 있는 구조가 가장 좋은 구조일 것이다.

 

위 코드를 예시로 들면, 아래와 같이 할 수 있을 것 같다.

conn.setAutoCommit(false);
PreparedStatement pstmt = getQueryForm(conn);
try {
    setQueryForm(ssnList, pstmt);
    pstmt.executeBatch();
    conn.commit();
} catch(Exception e) {
    conn.rollback();
    e.printStackTrace();
} finally {
    pstmt.close();
}

 

위 코드가 베스트라던지, 모범 답안이라던지 하는 것은 아니다. 일종의 하나의 예시로써, 중괄호 { } 내부에 너무 여러 줄이 포함되어 있으면 읽는 것에 피곤함을 느끼기 쉬우므로, 메서드로 매핑하여 로직을 조각내어 각 로직의 목적을 표기하면 훨씬 이해하기 편할 것이다.

 

자바는 객체지향 프로그래밍 언어로써, 클래스 매핑과 메서드 매핑을 적극적으로 활용한다. 비단 자주 사용하기 때문에 뽑아두는 경우 외에도 이렇게 사람 친화적인 코드를 작성하기 위한 기술로 활용되기도 한다.

 

결론

별 거 아닌 batch query commit 을 알아보면서 고민을 많이 하게 되었다. 개발을 할 때에도 고민으로 작업이 느려지는 것은 아닌가 하며 불안함을 느낄 때가 있는데, 오히려 충분한 고민이 작업량을 줄여주기도 한다. 앞으로도 적극적으로 고민하는 기술자가 되고자 한다.

 

 

Comments