Controller에서 중복되는 부분을 처리하려면?
- 별도의 객체로 분리
- 별도의 메소드로 분리
- 쇼핑몰에서 게시판에서도 회원 정보를 보여주고, 상품 목록 보기에서도 회원 정보를 보여줘야 한다면 회원 정보를 읽어오는 코드는 어떻게 해야 할까?
-> 회원 정보를 읽는 코드를 분리시킨다. (회원 정보 = 비즈니스 메서드)
컨트롤러와 서비스
- 비지니스 메소드를 별도의 Service객체에서 구현하도록 하고 컨트롤러는 Service객체를 사용하도록 한다.
서비스(Service)객체란?
- 비지니스 로직(Business logic)을 수행하는 메소드를 가지고 있는 객체를 서비스 객체라고 한다.
- 보통 하나의 비지니스 로직은 하나의 트랜잭션으로 동작한다.
트랜잭션(Transaction)
원자성 (Atomicity)
예를 들어 "출금"이라는 기능의 흐름이 다음과 같다고 생각해보자
- 잔액이 얼마인지 조회한다.
- 출금하려는 금액이 잔액보다 작은지 검사한다.
- 출금하려는 금액이 잔액보다 작다면 (잔액 - 출금액)으로 수정한다.
- 언제, 어디서 출금했는지 정보를 기록한다.
- 사용자에게 출금한다.
위의 작업이 4번에서 오류가 발생했다면 어떻게 될까?
- 4번에서 오류가 발생했다면, 앞의 작업을 모두 원래대로 복원을 시켜야 한다.(rollback)
- 5번까지 모두 성공했을 때만 정보를 모두 반영해야 한다.(commit)
- rollback 하거나 commit을 하게 되면 하나의 트랜잭션 처리가 완료된다.
일관성 (Consistency)
- 일관성은 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것이다.
- 트랜잭션이 진행되는 동안에 데이터가 변경되더라도 업데이트된 데이터로 트랜잭션이 진행되는 것이 아니라, 처음에 트랜잭션을 진행하기 위해 참조한 데이터로 진행된다.
- 이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있다.
독립성 (Isolation)
- 독립성은 둘 이상의 트랜잭션이 동시에 병행 실행되고 있을 경우에 어느 하나의 트랜잭션이라도 다른 트랜잭션의 연산을 끼어들 수 없다.
- 하나의 특정 트랜잭션이 완료될 때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없다.
지속성 (Durability)
- 지속성은 트랜잭션이 성공적으로 완료됐을 경우, 결과는 영구적으로 반영되어야 한다는 것이다.
JDBC 프로그래밍에서 트랜잭션 처리 방법
- DB에 연결된 후 Connection객체의 setAutoCommit메소드에 false를 파라미터로 지정한다.
- 입력, 수정, 삭제 SQL이 실행을 한 후 모두 성공했을 경우 Connection이 가지고 있는 commit()메소드를 호출한다.
@EnableTransactionManagement
- Spring Java Config파일에서 트랜잭션을 활성화 할 때 사용하는 애노테이션이다.
- Java Config를 사용하게 되면 PlatformTransactionManager 구현체를 모두 찾아서 그 중에 하나를 mapping하여 사용한다.
- 특정 트랜잭션 메니저를 사용하고자 한다면 TransactionManagementConfigurer를 Java Config파일에서 구현하고 원하는 트랜잭션 메니저를 리턴하도록 한다.
- 아니면, 특정 트랜잭션 메니저 객체를 생성시 @Primary 애노테이션을 지정한다.
서비스 객체에서 중복으로 호출되는 코드의 처리
- 데이터 엑세스 메소드를 별도의 Repository(Dao) 객체에서 구현하도록 하고 Service는 Repository객체를 사용하도록 한다.
레이어드 아키텍처(Layered Architecture)
Presentation Layer : Controller
Service Layer : business service
Repository Layer : DAO
재사용 측면이나 유지 보수적인 면에서 봤을 때, Presentation Layer와 나머지 부분은 아예 설정파일도 분리하는게 좋다. 그래야 언제든지 따로 떼서 떼서 변경하기 용이하다.
(ex. Presentation Layer만 Window 프로그래밍, 앱으로 바꿀 수 있다.)
설정의 분리
- Spring 설정 파일을 프리젠테이션 레이어쪽과 나머지를 분리할 수 있다.
- web.xml 파일에서 프리젠테이션 레이어에 대한 스프링 설정은 DispatcherServlet이 읽도록 하고, 그 외의 설정은 ContextLoaderListener를 통해서 읽도록 한다.
- DispatcherServlet을 경우에 따라서 2개 이상 설정할 수 있는데 이 경우에는 각각의 DispathcerServlet의 ApplicationContext가 각각 독립적이기 때문에 각각의 설정 파일에서 생성한 빈을 서로 사용할 수 없다.
- 위의 경우와 같이 동시에 필요한 빈은 ContextLoaderListener를 사용함으로써 공통으로 사용하게 할 수 있다.
- ContextLoaderListener와 DispatcherServlet은 각각 ApplicationContext를 생성하는데, ContextLoaderListener가 생성하는 ApplicationContext가 root 컨텍스트가 되고 DispatcherServlet이 생성한 인스턴스는 root 컨텍스트를 부모로 하는 자식 컨텍스트가 된다.
- 자식 컨텍스트들은 root 컨텍스트의 설정 빈을 사용할 수 있다.