ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [토비의 스프링 3.1 Vol.1] 5장 서비스 추상화
    Java/Spring Framework 2018. 1. 16. 22:37

      [사족]

      드디어 한 번만 본 챕터가 나왔다. 6장의 AOP는 본 기억이 없으니 아마 5장 중간즈음 보다가 완독을 못했을 것 같다. 이 기세로 쭉쭉 읽어 나가자.

      5장은 내용이 더 재밌어진다. 이때까지 만든 사용자 관리시스템(?)에 기능을 더 추가한다. 활동별 사용자 등급 변경기능과 등급 변경시 메일 안내 발송 기능이다. 해당 기능들을 개발하면서 발생하는 문제점들을 풀어나간다. 어떻게? 당연히 스프링 DI를 활용해서. 그리고 토비 선생님은 정말 테스트를 중요하게 생각 한다는 것을 또 한번 느꼈다.

     

      [내용]

      5장의 목차

    5.1 사용자 레벨 관리 기능 추가

    5.2 트랜잭션 서비스 추상화

    5.3 서비스 추상화와 단일 책임 원칙

    5.4 메일 서비스 추상화

    5.5 정리

     

      사용자 관리시스템에 레벨 기능을 추가한다. 간단히 final static int BASIC = 1과 같은 형식으로 처리해도 될것 같지만 안된다. 타입에 안전하지 못하기 때문이다. 레벨값이 들어와야 하는 곳에 엄한 숫자가 들어와 버리면 안된다. 그래서 자바5에 추가된 ENUM(이늄)을 사용한다. DB에 이늄타입은 없으니 넣을때는 이늄을 숫자로, DB에서 받아올 때는 숫자에서 이늄으로 변환시켜주면 된다.

      

      이제 뭔가 조금씩 비즈니스 로직이 생기고 있는 것 같다. 그래서 UserDao를 사용하는 UserService를 만들어서 사용자 등급 갱신같은 비즈니스 로직은 UserService에서 처리하기로 한다. 이렇게 중간에 추가하는 것도 어렵지 않다. UserService를 만들고 Bean을 조금 수정해주면 된다.

      

      사용자 등급 변경기능을 처음에는 UserService안에서 다 구현한다. 그리고 나서 SRP에 의해 각기 기능들을 User, Level, UserDao, UserService등으로 나눈다. 이렇게 하면 나중에 수정할 때에도 명확하게 고쳐야 할 곳을 파악하기 쉽고 응집도가 높은 프로그래밍이 가능해진다. 객체 설계 원칙에 따라 자기 할일은 자기가 한다!를 잘 지키는 것이 중요하다.


    DI의 가치는 관심, 책임, 성격이 다른 코드를 깔끔하게 분리하는 데 있다. (p. 376 하단)

      

      그런데 만약에 100명의 등급 변경자들의 정보를 업데이트 하다가 중간쯤에 네트워크 오류나 서버 등의 문제로 작업이 중단될 수 있다. 이때, 누구는 승급되있는데 누구는 안되어 있으면 이것도 참 문제다. 그래서 여기에 트랜잭션을 적용해서 100명 모두 적용되거나 아니면 모두 적용 안되거나 하게 해야한다. 그래서 JDBC의 트랜잭션 경계설정을 사용한다. 그런데 또 문제다. 기껏 Service와 Dao를 분리하였는데 코드가 뒤죽박죽이 되어 버리고 데이터 엑세스 기술에 종속되어 버리는 코드가 되어버린다. 그래서 이번에는 스프링이 제공하는 JDBC 트랜잭션 동기화 방식(transaction synchronization)을 사용한다.


      책임을 분리하는 깔끔한 코드가 된것 같으나 문제는 또 발생한다. 한 개 이상의 DB를 사용하는 경우는 JTA를 사용해야하는데 이는 사용 방식이 JDBC와 다르다는 것이다. Hibernate를 사용하는 경우도 마찬가지다. 사용 기술에 따라 코드가 달라지는데 이를 어떻게 해야할까?


      이를 위해서 역시 스프링이 트랜잭션 서비스 추상화를 준비해 두었다. 일관된 방식으로 트랜잭션 처리를 할 수 있게 말이다. PlatformTransactionManager를 사용하면 데이터 엑세스 기술에 상관없이 일관된 방식으로 트랜잭션을 관리할 수 있다. 역시 스프링 최고다.


      이번에는 등급이 올라간 사용자들에게 메일을 보내주는 기능을 추가한다. JavaMail을 사용하면 되는데 테스트 때마다 직접 메일 서버에 접속하고 메일을 실제로 발송하는 것은 번거롭기도 하고 부하도 큰 작업이다. 또한 JavaMail은 테스트 하기도 매우 어렵게 설계가 되어있다. 어떻게 하면 될까?


      그럴줄 알고 스프링에서 또 메일 발송 기능을 추상화해서 준비해 뒀다. MailSender가 그것인데 예외처리도 런타임 예외로 포장해주기 떄문에 try/catch를 작성할 필요도 없다. 메일 기능 테스트용 클래스는 MailSender를 구현해서 입맛에 맞게 구현하면 된다. 이를 DI로 처리하면 개발때는 DummyMailSender를, 서비스 상황에서는 서비스용 MailSender를 사용하면 된다.


    테스트 대역(test double)의 종류와 특징

      • 테스트 스텁(test stub): 테스트 대상 오브젝트의 의존객체로서 존재하면서 테스트 동안에 코드가 정상적으로 수행할 수 있도록 돕는 것
        • 스텁 오브젝트(stub object): 테스트가 수행될 수 있도록 의존 오브젝트에 간접적으로 입력 값을 제공해준다.
        • 목 오브젝트(mock object): 스텁 오브젝트와 비슷한데, 테스트 대상으로부터 받은 정보를 검증하는 기능이 추가되어 있다.

    서비스 추상화

    일관된 API를 가진 추상화 계층을 도입

      

    댓글

Designed by Tistory.