4. 스프링과 문제 해결 - 트랜잭션
애플리케이션의 구조
프레젠테이션 계층 (@Controller) -> 서비스 계층 (@Service) -> 데이터 접근 계층 (@Repository) -> DB 서버
프레젠테이션 계층
UI와 관련된 처리 담당
웹 요청과 응답
사용자 요청을 검증
주 사용 기술: 서블릿과 HTTP 같은 웹 기술, 스프링 MVC
서비스 계층
비즈니스 로직을 담당
주 사용 기술: 가급적 특정 기술에 의존하지 않고, 순수 자바 코드로 작성
데이터 접근 계층
실제 데이터베이스에 접근하는 코드
주 사용 기술: JDBC, JPA, Refis, Mongo
순수한 서비스 계층
가장 중요한 곳이다 왜? -> 핵심 비즈니스 로직이 들어가 있는 서비스 계층이다. 시간이 흘러서 UI웹와 관련된 부분이 변하고, 데이터 저장 기술을 다른 기술로 변경해도, 비즈니스 로직은 최대한 변경없이 유지되어야 한다.
정리: 서비스 계층은 가급적 비즈니스 로직만 구현하고 특정 구현 기술에 직접 의존해서는 안된다.
@RequiredArgsConstructor
public class MemberServiceV1 {
private final MemberRepositoryV1 memberRepository;
public void accountTransfer(String fromId, String toId, int money) throws
SQLException {
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
memberRepository.update(toId, toMember.getMoney() + money);
}
}
위의 코드의 문제점
SQLException이라는 JDBC기술에 의존한다.
memberRepository에서 올라오는 예외이기 때문에 memberRepository에서 해결해야 한다.
지금까지 우리가 개발한 애플리케이션의 문제점은 크게 3가지이다.
트랜잭션 문제
예외 누수 문제
JDBC 반복 문제
트랜잭션 문제
가장 큰 문제는 트랜잭션을 적용하면서 생긴 다음과 같은 문제들이다.
JDBC구현 기술이 서비스 계층에 누수되는 문제
트랜잭션을 적용하기 위해 JDBC구현 기술이 서비스 계층에 누수되었다.
서비스 계층은 수순해야한다.
트랜잭션 동기화 문제
트랜잭션 적용 반복 문제
예외 누수
데이터 접근 계층의 JDBC 구현 기술 예외가 서비스 계층으로 전파 -> 위에 코드 참고
JDBC 반복 문제
지금 까지 작성한 try catch finally가 이 문제에 속한다.
-> 코드 반복이 너무 많다 ~~~
문제가 JDBC에 너우 의존한다는 것인데 이 문제를 해결하기 위해서는 트랜잭션을 추상화 시키면 된다.
단순히 아래와 같은 코드를 추가
public interface TxManager {
begin();
commit();
rollback();
}
트랜잭션 동기화를 사용하려면 DataSourceUtils를 아래와 같이 사용해야함
private Connection getConnection() throws SQLException {
//주의 트랜잭션 동기화를 사용하라면 DataSourceUtils 를 사용해야한다.
Connection con = DataSourceUtils.getConnection(dataSource);
log.info("get connection={}, class={}", con, con.getClass());
return con;
}
서비스쪽에서 문제가 되는게 DataSource를 직접 가져다 쓰는 것이 문제가 된다.