스프링 트랜잭션 전파 - 기본

도서관 대출 카드로 비유하기

  • 물리적 커넥션 (conn0): 도서관에 있는 실물 책 (예: "JPA 프로그래밍")

  • 커넥션 풀 (HikariCP): 책들이 꽂혀있는 도서관 서가

  • 애플리케이션의 트랜잭션 (트랜잭션1, 트랜잭션2): 도서관 이용자 (A, B)

  • 프록시 커넥션 (HikariProxyConnection): 책을 빌릴 때마다 발급되는 대출 카드 (또는 대출 기록)

시나리오:

  1. 트랜잭션 1 (이용자 A):

    • 이용자 A가 "JPA 프로그래밍" 책이 필요해서 도서관에 요청합니다.

    • 도서관(커넥션 풀)은 서가에서 "JPA 프로그래밍" 실물 책(conn0)을 꺼냅니다.

    • 그냥 책을 주지 않고, "A가 빌려감"이라고 기록된 대출 카드(HikariProxyConnection@1000000)와 함께 책을 빌려줍니다. 이 대출 카드에는 반납 예정일, 대출 상태 등의 정보가 기록됩니다.

    • 이용자 A는 이 대출 카드를 통해 책을 읽고(DB 작업 수행) 다 읽으면 책을 반납합니다.

    • 반납 시 대출 카드는 파기되고, 실물 책(conn0)은 다시 서가에 꽂힙니다.

  2. 트랜잭션 2 (이용자 B):

    • 잠시 후, 이용자 B가 "JPA 프로그래밍" 책이 필요해서 도서관에 요청합니다.

    • 도서관(커넥션 풀)은 서가에서 아까 A가 반납했던 바로 그 "JPA 프로그래밍" 실물 책(conn0)을 다시 꺼냅니다.

    • 이번에는 "B가 빌려감"이라고 기록된 새로운 대출 카드(HikariProxyConnection@2000000)와 함께 책을 빌려줍니다.

    • 이용자 B는 이 새로운 대출 카드를 통해 책을 읽고 반납합니다.

핵심 정리:

  • 커넥션은 같은데 (conn0): 이용자 A와 B는 결국 동일한 실물 책을 읽었습니다. 즉, 데이터베이스와 연결되는 물리적인 통로(TCP/IP 소켓)는 재사용된 것이 맞습니다. 커넥션을 새로 맺는 과정은 비용이 비싸기 때문에 이렇게 재사용하는 것이 커넥션 풀의 핵심 목적입니다.

  • 내부는 다르다 (HikariProxyConnection@...): 하지만 이용자 A와 B가 책을 빌릴 때 받은 대출 카드는 서로 다릅니다. 이 대출 카드는 히카리 커넥션 풀이 커넥션을 관리하기 위해 사용하는 "포장지" 또는 "대리인(Proxy)"입니다.

왜 프록시(Proxy) 객체로 감싸서 사용할까요?

히카리 커넥션 풀은 이 프록시 객체를 통해 다음과 같은 중요한 관리 작업을 수행합니다.

  1. 반납 관리: 애플리케이션이 커넥션 사용을 마친 후 close()를 호출하면, 프록시 객체는 실제 물리 커넥션을 닫는 대신 커넥션 풀에 반납하는 작업을 가로채서 수행합니다. 만약 프록시가 없다면 애플리케이션이 실수로 실제 커넥션을 닫아버려 재사용이 불가능해질 수 있습니다.

  2. 상태 추적: 커넥션이 대여된 시간, 마지막 사용 시간 등을 추적하여 너무 오랫동안 반납되지 않는 커넥션(Connection Leak)을 감지하거나, 유효성 검사(is-alive check)를 수행합니다.

  3. 오버헤드 최소화: 매번 물리적인 커넥션을 생성하고 해제하는 비싼 비용을 피하고, 가벼운 프록시 객체만 생성/소멸시키면서 효율적으로 커넥션을 재사용합니다.

결론:

로그에서 conn0이 동일하게 나타나는 것은 물리적 커넥션의 재사용을 의미하며, 이는 커넥션 풀이 정상적으로 동작하고 있다는 증거입니다. 그리고 HikariProxyConnection의 주소값이 다른 것은 각 트랜잭션이 커넥션 풀로부터 독립적인 커넥션 대여(논리적 세션)를 받았다는 것을 의미합니다.

따라서 "같은 물리적 자원(conn0)을 사용하지만, 논리적으로는 격리되고 독립적인 작업 단위(트랜잭션)로 관리된다"고 이해하시면 정확합니다.

Last updated