JAVA

자바 트랜잭션 — 여러 작업을 하나로 묶기(COMMIT·ROLLBACK)

PANCO_IT
#자바#JAVA#트랜잭션#JDBC#데이터베이스

트랜잭션: 전부 성공하면 커밋, 중간에 실패하면 롤백

중간에 실패하면 앞의 작업까지 통째로 되돌립니다.

10편에서 JDBC로 데이터베이스에 말을 걸었습니다. 이제 한 가지 상황을 생각해 봅시다.

친구에게 1만 원을 이체합니다. 순서는 이렇죠. 내 계좌에서 1만 원을 빼고, 친구 계좌에 1만 원을 넣습니다. 그런데 첫 번째는 성공했는데 두 번째에서 오류가 났다면 어떻게 될까요.

내 돈은 사라졌는데 친구는 못 받았습니다. 1만 원이 세상에서 증발한 것입니다.

이런 사고를 막는 장치가 오늘의 주제, 트랜잭션입니다.

트랜잭션이 뭔가요?

트랜잭션(Transaction)은 여러 작업을 하나의 덩어리로 묶는 것입니다.

묶어 놓으면 규칙이 하나 생깁니다.

전부 성공하거나, 전부 없던 일이 되거나. 절반만 반영되는 상태는 만들지 않는다.

이체에서 출금과 입금을 한 덩어리로 묶으면, 입금이 실패하는 순간 출금도 자동으로 취소됩니다. 돈이 증발할 수 없게 되는 것이죠.

사실 지금까지는 매번 저장되고 있었습니다

10편에서 executeUpdate()를 부를 때마다 결과가 바로 DB에 저장됐습니다. 따로 저장 버튼을 누른 적이 없는데도요.

JDBC는 기본값이 자동 커밋(auto commit)이기 때문입니다. 한 줄 실행할 때마다 곧바로 확정 저장합니다.

편하지만 이체에서는 문제가 됩니다. 출금이 이미 확정 저장돼 버려서 되돌릴 방법이 없거든요. 그래서 묶고 싶을 때는 자동 커밋을 먼저 꺼야 합니다.

conn.setAutoCommit(false);   // 이제부터 내가 확정할 때까지 저장 보류

확정은 commit, 취소는 rollback

자동 커밋을 끄면 두 개의 스위치가 내 손에 들어옵니다.

메서드언제
conn.commit()지금까지 한 작업을 확정 저장전부 성공했을 때
conn.rollback()지금까지 한 작업을 전부 취소하나라도 실패했을 때

commit()을 부르기 전까지 변경 내용은 임시 상태입니다. 연필로 써 두었다가 commit()에서 볼펜으로 덧쓰는 셈이고, rollback()은 연필 자국을 지우개로 지우는 것입니다.

트랜잭션 코드 흐름: 자동커밋 끄기 → 작업 → 커밋 또는 롤백

그림 1. 순서만 외우면 됩니다 — 끄고, 하고, 확정하거나 되돌리기.

이체 코드로 보기

계좌이체를 트랜잭션으로 묶으면 이렇게 됩니다.

Connection conn = null;
try {
    conn = DriverManager.getConnection(URL, USER, PW);
    conn.setAutoCommit(false);                    // ① 자동 저장 끄기

    // ② 출금
    PreparedStatement ps1 = conn.prepareStatement(
        "UPDATE account SET balance = balance - ? WHERE id = ?");
    ps1.setInt(1, 10000);
    ps1.setString(2, "나");
    ps1.executeUpdate();

    // ③ 입금
    PreparedStatement ps2 = conn.prepareStatement(
        "UPDATE account SET balance = balance + ? WHERE id = ?");
    ps2.setInt(1, 10000);
    ps2.setString(2, "친구");
    ps2.executeUpdate();

    conn.commit();                                // ④ 둘 다 성공 → 확정
    System.out.println("이체 완료");

} catch (SQLException e) {
    if (conn != null) conn.rollback();            // ⑤ 하나라도 실패 → 전부 취소
    System.out.println("이체 실패, 원상복구했습니다");

} finally {
    if (conn != null) {
        conn.setAutoCommit(true);                 // ⑥ 원래대로 돌려놓기
        conn.close();
    }
}

핵심은 rollback()catch 안에 있다는 점입니다. 예외가 나야 되돌릴 일이 생기니 당연한 자리인데, 처음에는 commit() 옆에 나란히 쓰는 실수가 잦습니다.

직접 확인해 보기

DB 없이도 원리는 그대로 볼 수 있습니다. 아래 코드는 트랜잭션을 흉내 낸 것입니다. 입금 도중 일부러 오류를 내고, 되돌리기 전후의 잔액을 비교합니다.

트랜잭션 흉내내기
public class Main {
  static int 내잔액 = 50000;
  static int 친구잔액 = 10000;

  public static void main(String[] args) {
      // 시작 전 상태를 기억해 둡니다 (이게 rollback 지점 역할)
      int 백업내잔액 = 내잔액;
      int 백업친구잔액 = 친구잔액;

      System.out.println("[시작] 나=" + 내잔액 + " 친구=" + 친구잔액);

      try {
          내잔액 -= 10000;                  // 출금 성공
          System.out.println("출금 완료 → 나=" + 내잔액);

          if (true) throw new RuntimeException("입금 중 오류!");  // 일부러 실패

          친구잔액 += 10000;
      } catch (RuntimeException e) {
          내잔액 = 백업내잔액;               // rollback
          친구잔액 = 백업친구잔액;
          System.out.println("실패: " + e.getMessage() + " → 되돌립니다");
      }

      System.out.println("[끝] 나=" + 내잔액 + " 친구=" + 친구잔액);
  }
}

📱 코드 실행(실습)은 태블릿·PC에서 이용할 수 있어요. 모바일에서는 위 코드를 눈으로 따라가며 확인하세요.

결과 해설 보기

출금으로 잔액이 40000까지 내려갔다가, 되돌린 뒤 다시 50000이 됩니다. 돈이 사라지지 않았죠.

throw new RuntimeException(...) 줄을 지우고 다시 실행해 보세요. 이번엔 되돌리지 않고 끝까지 가서 나=40000, 친구=20000이 됩니다. 이게 commit()까지 간 경우입니다.

실제 DB에서는 이 백업·복구를 우리가 짜지 않아도 rollback() 한 줄이 알아서 해 줍니다.

어디까지 묶어야 할까요

"그럼 다 묶으면 좋은 거 아닌가요?" 싶지만 그렇지 않습니다.

트랜잭션이 열려 있는 동안 DB는 그 데이터를 다른 사람이 못 건드리게 잠급니다. 길게 열어 두면 다른 요청들이 줄을 서서 기다리게 되죠.

기준은 간단합니다. "같이 성공하거나 같이 실패해야 하는 것"만 한 묶음으로. 이체라면 출금과 입금 둘뿐입니다. 그 사이에 이메일 발송이나 오래 걸리는 계산을 끼워 넣지 마세요.

한 장 정리

항목내용
트랜잭션여러 작업을 하나로 묶는 단위
원칙전부 성공 아니면 전부 취소
setAutoCommit(false)자동 저장 끄기 — 묶기의 시작
commit()확정 저장
rollback()전부 취소 — catch 안에서
finallysetAutoCommit(true) 복구 후 close()
범위같이 성패해야 하는 것만 짧게

이것만 기억하면 됩니다. 자동 저장을 끄고, 작업들을 실행하고, 성공하면 commit, 실패하면 rollback. 그리고 되돌리는 코드는 반드시 catch 안에 둡니다.

미니 퀴즈

개념을 제대로 잡았는지 직접 풀어 봅니다. 정답은 눌러야 나옵니다.

미니 퀴즈

OX 2문제 + 4지선다 3문제


포켓코딩(JAVA3) 11편 · 예제 출처: 강사 개인 GitHub 저장소. 다음 편: JAVA3 총정리 — 예외부터 트랜잭션까지 문제로 복습.

PANCO_IT

IT 지식을 정리하는 개발자

관련 글