0Pricing
Java Academy · 강의

트랜잭션

커밋과 롤백을 알아봅니다

트랜잭션은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

트랜잭션이란 무엇인가요

트랜잭션은 여러 SQL 작업을 하나의 전부 성공하거나 전부 실패하는 단위로 묶습니다.

모든 문이 성공하면 변경 사항을 영구 반영하고(commit), 무언가 실패하면 모든 변경 사항을 취소합니다(rollback). 이렇게 하면 데이터베이스의 일관성을 유지할 수 있습니다.

1분 만에 이해하는 ACID

트랜잭션은 다음과 같은 ACID 보장을 제공합니다.

  • 원자성 — 전부 반영되거나 전혀 반영되지 않습니다.
  • 일관성 — 데이터베이스를 유효한 한 상태에서 다른 유효한 상태로 이동시킵니다.
  • 격리성 — 동시에 실행되는 트랜잭션이 서로의 데이터를 손상시키지 않습니다.
  • 지속성 — 한 번 commit되면 장애가 발생해도 변경 사항이 유지됩니다.

자동 커밋 모드

기본적으로 JDBC 연결은 자동 커밋 모드로 실행됩니다. 즉, 각 문이 독립적인 트랜잭션이 되어 즉시 commit됩니다.

단일 문만 실행할 때는 괜찮지만, 여러 쓰기 작업이 함께 성공해야 할 때는 쓸모가 없습니다. 트랜잭션을 직접 제어하려면 자동 커밋을 끄세요.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            System.out.println("Default auto-commit: " + conn.getAutoCommit());
            conn.setAutoCommit(false);
            System.out.println("Now manual: " + conn.getAutoCommit());
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

commit 및 rollback

자동 커밋을 끄면 트랜잭션의 경계를 직접 정합니다.

  • conn.commit()은 보류 중인 모든 변경 사항을 영구 반영합니다.
  • conn.rollback()은 보류 중인 변경 사항을 폐기합니다.

대표적인 예는 송금입니다. 한 계좌에서 금액을 인출하고 다른 계좌에 입금해야 합니다. 두 작업 모두 수행되거나, 둘 다 수행되지 않아야 합니다.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        String debit = "UPDATE account SET balance = balance - ? WHERE id = ?";
        String credit = "UPDATE account SET balance = balance + ? WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            conn.setAutoCommit(false);
            try (PreparedStatement d = conn.prepareStatement(debit);
                 PreparedStatement c = conn.prepareStatement(credit)) {
                d.setInt(1, 100); d.setInt(2, 1); d.executeUpdate();
                c.setInt(1, 100); c.setInt(2, 2); c.executeUpdate();
                conn.commit();
                System.out.println("Transfer committed");
            } catch (SQLException ex) {
                conn.rollback();
                System.out.println("Rolled back: " + ex.getMessage());
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

실패 시 rollback 패턴

기억해 둘 구조는 다음과 같습니다.

  • 자동 커밋을 끕니다.
  • 내부 try 블록 안에서 작업을 수행합니다.
  • 성공하면 commit()을 호출합니다.
  • catch에서 rollback()을 호출한 다음 예외를 다시 발생시키거나 기록합니다.

rollback이 없으면 실패로 인해 데이터베이스가 일부만 업데이트된 상태로 남을 수 있습니다.

원자성 시뮬레이션

다음은 독립적으로 실행할 수 있도록 일반 Java로 구현한 전부 성공하거나 전부 실패하는 방식의 예입니다. 스냅샷에 두 가지 업데이트를 적용하고, 둘 중 하나라도 실패하면 스냅샷을 복원합니다.

public class Main {
    public static void main(String[] args) {
        int[] balances = {500, 300};
        int[] backup = balances.clone();
        try {
            balances[0] -= 200;
            if (balances[0] < 0) throw new IllegalStateException("insufficient funds");
            balances[1] += 200;
            System.out.println("Commit: " + balances[0] + ", " + balances[1]);
        } catch (RuntimeException e) {
            balances = backup;
            System.out.println("Rollback: " + balances[0] + ", " + balances[1]);
        }
    }
}

저장 지점

저장 지점은 트랜잭션 내부에 설정하는 표시입니다. 전체 트랜잭션을 폐기하지 않고 저장 지점까지 rollback할 수 있습니다.

  • Savepoint sp = conn.setSavepoint()
  • conn.rollback(sp)은 해당 지점 이후의 작업만 취소합니다.

긴 트랜잭션에서 일부 작업을 복구할 때 유용합니다.

격리 수준

격리는 한 트랜잭션이 다른 트랜잭션의 commit되지 않은 작업을 어디까지 볼 수 있는지를 제어합니다. JDBC에서는 conn.setTransactionIsolation(...)을 통해 수준을 정의합니다.

  • TRANSACTION_READ_COMMITTED — 일반적인 기본값입니다.
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE — 가장 강력하지만 가장 느립니다.

격리 수준이 높을수록 이상 현상을 방지할 수 있지만 동시성은 낮아집니다.

읽기 이상 현상

격리 수준이 낮으면 다음과 같은 현상이 발생할 수 있습니다.

  • 오염된 읽기 — 다른 트랜잭션의 commit되지 않은 변경 사항을 봅니다.
  • 반복 불가능 읽기 — 두 번 읽는 사이에 행의 내용이 바뀝니다.
  • 유령 읽기 — 이전 쿼리와 일치하는 새 행이 나타납니다.

애플리케이션의 로직이 허용할 수 없는 이상 현상을 막는 가장 낮은 수준을 선택하세요.

자동 커밋 복원

연결 풀에서 연결을 빌려 왔다면 반환하기 전에 원래 상태로 복원하세요.

수동 트랜잭션을 실행한 후에는 conn.setAutoCommit(true)를 다시 설정하거나, 빌릴 때 확인한 값으로 되돌리세요. 그래야 다음 사용자가 여러분의 설정 때문에 예상하지 못한 동작을 겪지 않습니다.

트랜잭션을 짧게 유지하세요

트랜잭션은 commit하거나 rollback할 때까지 잠금을 유지합니다. 트랜잭션이 길어지면 다른 작업이 차단되고 교착 상태가 발생할 위험이 커집니다.

  • 열린 트랜잭션 안에서 느린 네트워크 호출이나 사용자 입력 요청을 수행하지 마세요.
  • 먼저 데이터를 수집한 다음 연결을 열고, 데이터를 쓰고, 신속하게 commit하세요.

짧고 집중된 트랜잭션이 훨씬 더 잘 확장됩니다.

빠른 확인

connection.rollback()을 호출하면 어떤 효과가 있나요?

복습

트랜잭션은 전부 성공하거나 전부 실패하는 안전성을 제공합니다.

  • setAutoCommit(false)로 자동 커밋을 끕니다.
  • 성공하면 commit()하고, 실패하면 rollback()합니다.
  • 일부 작업만 rollback하려면 저장 지점을 사용합니다.
  • 정확성과 동시성 사이의 균형을 맞추도록 격리 수준을 조정합니다.
  • 연결 풀의 연결을 반환하기 전에 자동 커밋을 복원합니다.

자주 묻는 질문

“트랜잭션” 강의는 무료인가요?

네 — “트랜잭션” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“트랜잭션”에서 뭘 배우나요?

커밋과 롤백을 알아봅니다 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“트랜잭션” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. JDBC 기초
  2. PreparedStatement
  3. 트랜잭션
  4. HikariCP를 사용한 연결 풀링
← Java Academy(으)로 돌아가기