1차 프로젝트에서 Mybatis를 적용한 아키텍쳐는 단순히 Service에서 MybatisRepository를 의존한 것이다. JPA를 변환하고자 했을때 단순하게 생각하면 아래 아키텍쳐를 가질 수 있다.
하지만 위 설계는 DIP를 위반한 것이다. 왜냐면 고수준 Service가 저수준 MybatisRepository와 JpaRepository를 직접 의존하기 때문이다.
MybatisRepository를 지우지 않고 JPA 기능을 추가한 이유는 언제든지 수정중인 소스를 운영에 반영할수 있도록 하기 위함이다. JPA기능을 추가하고 테스트코드도 작성되지 않은 상태에서 Mybatis 기능을 삭제해버리면 이 소스를 운영에 반영 할 수 없다. 그래서 언제든지 운영에 반영할 필요가 있을때 빠르게 수정중인 소스에서 Mybatis 기능으로 적용하고 운영에 반영할 수 있도록 할 수 있다.
[DIP 원칙]
DIP(Dependency Inversion Principle)는 의존관계 역전 원칙으로 SOLID 개발원칙에서 D에 해당된다. 특징은 아래와 같다.
- 고수준 모듈은 저수준 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 된다.
- 추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.
Service는 고수준이고 MybatisRepository, JpaRespository는 저수준이다. 만약 위대로 설계를 가져가면 문제점은 Service에서 Jpa와 Mybatis의 로직 변경이 쉽지가 않아 코드 변경이 잦아지고, 요구사항 변경에 대한 유지보수가 힘들어진다.
DIP 지키지 않은 아키텍쳐
예를 들어 아래 소스를 보면 member도메인에 대한 MybatisRepository와 JpaRepository가 있는데 findAll()로 memberList를 가져온다고 했을때 Service의 비즈니스 로직이 바뀌어 버린다. 또 반환타입도 달라서 밑에 MemberResponse List로 변환해주는 로직도 변경해야 한다. 고수준 Service가 저수준 MybatisRepository, JpaRepository를 직접 의존하고 있기 때문에 코드 변경과 전환이 힘들것이다. 좋은 설계는 Mybatis와 Jpa의 변경이 쉽게 이루어져야 한다.
DIP 원칙 지킨 아키텍쳐
하지만 DIP를 지키면 아래와 같은 아키텍쳐를 가지게 된다.
Adapter가 낀 이유는 MybatisRepository와 반환타입이 다르기 때문이다. 반환타입을 맞춰주기 위해서 어댑터 패턴을 적용하였다. 위처럼 적용하면 Service가 Repository를 의존하여 고수준이 고수준을 의존하도록 변경하였고 MybatisRepository, JpaRepository도 추상화 된 Repository를 의존하게 하여 DIP 원칙을 지켰다.
수정된 아래 코드를 보면 @Qualifier를 변경해서 Repository 구현체의 변경만 해주면 아래 서비스 로직들이 한번에 변경이 된다. 이러면 Mybatis와 Jpa의 변경이 쉽게 이루어져 유지보수가 편해졌다.
DIP 원칙을 지켜가며 JPA 기능을 추가하였다. 그리고 테스트코드를 작성해야 한다.
테스트코드 통과와 테스트 커버리지 충족
테스트코드는 기능마다 단위테스트를 작성하고 통과시키고 마지막으로 통합테스트를 작성하여 전체적인 흐름을 통과시켜야 한다.
테스트코드는 모두 통과하는것은 기본이 되어야 한다.
테스트 커버리지는 단순히 테스트코드에서 메서드가 사용되거나 필드가 사용된다. 옳바른 테스트 코드 로직을 작성하는것이 더 중요해서 커버리지 %가 꼭 높다고 좋은것이 아니다. 그래도 기본적으로 최소 70% 이상은 넘겨야된다.
마지막으로 Mybatis 로직을 도려내면 JPA 기능으로 변경이 완료된다.
참고
- 도메인주도 개발 시작하기 / 최범균
'Project > B2C-Side-Project(second)' 카테고리의 다른 글
[SpringBoot] 스프링 시큐리티 활용한 회원가입 이메일 인증 방법(개선전) (0) | 2024.06.29 |
---|---|
[SpringBoot] Github Actions 이용한 AWS EC2(ubuntu)에 자동배포와 디스코드 알림 설정 서버다운 해결 (0) | 2024.06.11 |
[SpringBoot] GlobalException 활용한 파라미터 유효성 검증 리팩토링 (0) | 2024.06.10 |
[프로젝트] 스프링시큐리티 5->6, JWT 버전 업그레이드 하고 error와 warning 수정 (0) | 2024.06.10 |
[Github] 깃허브에서 애자일 방식 프로젝트 문서 관리 방법 (0) | 2024.06.05 |