Replies: 1 comment
|
고생하셨습니다. ! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
4. 스프링과 문제 해결 - 트랜잭션 (1)
#️⃣ 목차
문제점들
애플리케이션 구조
여러가지 애플리케이션 구조가 있지만, 가장 단순하면서 많이 사용하는 방법은 역할에 따라 3가지 계층으로 나누는 것임

순수한 서비스 계층
문제점들
서비스 계층을 순수하게 유지하려면 어떻게 해야할까?
MemberServiceV1
MemberServiceV1은 특정 기술에 종속적이지 않고, 순수한 비즈니스 로직만 존재함MemberServiceV2
트랜잭션을 적용한
MemberServiceV2코드를 살펴보자javax.sql.DataSource,java.sql.Connection,java.sql.SQLException과 같은 JDBC 기술에 의존해야한다는 점임문제 정리
지금까지 우리가 개발한 애플리케이션의 문제점은 크게 3가지
트랜잭션 문제
가장 큰 문제는 트랜잭션을 적용하면서 생긴 다음과 같은 문제들
예외 누수
SQLException은 체크 예외이기 때문에 데이터 접근 계층을 호출한 서비스 계층에서 해당 예외를 잡아서 처리하거나 명시적으로throws를 통해서 다시 밖으로 던져야 함SQLException은 JDBC 전용 기술임. 향후 JPA나 다른 데이터 접근 기술을 사용하면, 그에 맞는 다른 예외로 변경해야 하고, 결국 서비스 코드도 수정해야 함JDBC 반복 문제
MemberRepository코드는 순수한 JDBC를 사용함트랜잭션 추상화
현재 서비스 계층은 트랜잭션을 사용하기 위해 JDBC 기술에 의존하고 있음
구현 기술에 따른 트랜잭션 사용법
con.setAutoCommit(false)transaction.begin()JDBC 트랜잭션 코드 예시
JPA 트랜잭션 코드 예시
JDBC 트랜잭션 의존
JDBC 기술 -> JPA 기술로 변경
트랜잭션 추상화
이 문제를 해결하려면, 트랜잭션 기능을 추상화하면 됨 !
트랜잭션 추상화 인터페이스
TxManager인터페이스를 기반으로 각각의 기술에 맞는 구현체를 만들면 됨JdbcTxManager: JDBC 트랜잭션 기능을 제공하는 구현체JpaTxManager: JPA 트랜잭션 기능을 제공하는 구현체트랜잭션 추상화와 의존관계
TxManager라는 추상화된 인터페이스에 의존함JdbcTxManager를 서비스에 주입하고, JPA 트랜잭션 기능으로 변경해야 하면JpaTxManager를 주입하면 됨스프링의 트랜잭션 추상화
PlatformTransactionManager인터페이스임PlatformTransactionManager 인터페이스
getTransaction(): 트랜잭션을 시작getTransaction()인 이유 : 기존에 이미 진행중인 트랜잭션이 있는 경우 해당 트랜잭션에 참여할 수 있기 때문commit(): 트랜잭션 커밋rollback(): 트랜잭션 롤백앞으로
platformTransactionManager인터페이스와 구현체를 포함해서 트랜잭션 매니저로 이야기 함트랜잭션 동기화
스프링이 제공하는 트랜잭션 매니저는 크게 2가지 역할을 함
트랜잭션 추상화
앞에서 설명함
리소스 동기화
트랜잭션을 유지하려면 시작부터 끝까지 같은 데이터베이스 커넥션을 유지해야 함
커넥션과 세션
트랜잭션 매니저와 트랜잭션 동기화 매니저
ThreadLocal)을 사용해서 커넥션을 동기화해줌동작방식 설명
정리
트랜잭션 문제 해결 - 트랜잭션 매니저1
본격적으로 애플리케이션 코드에 트랜잭션 매니저를 적용해보자
MemberRepositoryV3
DataSourceUtils.getConnection()
getConnection()에서DataSourceUtils.getConnection()를 사용하도록 변경된 부분을 특히 주의해야 함DataSourceUtils.getConnection()는 다음과 같이 동작함DataSourceUtils.releaseConnection()
close()에서DataSourceUtils.releaseConnection()를 사용하도록 바뀐 부분을 특히 주의하기con.close()를 사용해서 직접 닫아버리면 커넥션이 유지되지 않는 문제가 발생함DataSourceUtils.releaseConnection()을 사용하면 커넥션을 바로 닫는 것이 아님MemberServiceV3_1
트랜잭션 매니저를 사용하는 서비스 코드
private final PlatformTransactionManager transactionManagerDataSourceTransactionManager구현체를 주입받아야 함JpaTransactionManager를 주입받으면 됨transactionManager.getTransaction()TransactionStatus status를 반환함. 현재 트랜잭션의 상태 정보가 포함되어 있음. 이후 트랜잭션을 커밋, 롤백할 때 필요함new DefaultTransactionDefinition()transactionManager.commit(status)transactionManager.rollback(status)MemberServiceV3_1Test
new DataSourceTransactionManager(dataSource)DataSourceTransactionManager)를 선택해서 서비스에 주입함DataSource가 필요함트랜잭션 문제 해결 - 트랜잭션 매니저2
트랜잭션 매니저의 전체 동작 흐름을 살펴보자
트랜잭션 매니저1 - 트랜잭션 시작
클라이언트의 요청으로 서비스 로직 실행
transactionManager.getTransaction()을 호출해서 트랜잭션을 시작트랜잭션 매니저2 - 로직 실행
DataSourceUtils.getConnection()을 사용해서 트랜잭션 동기화 매니저에 보관된 커넥션을 꺼내서 사용함. 이 과정을 통해서 자연스럽게 같은 커넥션을 사용하고, 트랜잭션도 유지함트랜잭션 매니저3 - 트랜잭션 종료
con.setAutoCommit(true)로 되돌림. 커넥션 풀을 고려해야 함con.close()를 호출해셔 커넥션을 종료. 커넥션 풀을 사용하는 경우con.close()를 호출하면 커넥션 풀에 반환🔗 출처
All reactions