-
[리팩토링 보고서] API와 Repository 의존성 제거하기 (DTO-Repository 의존성 제거)Back End/리팩토링 보고서 2022. 3. 4. 17:06
리팩토링 진행마다 계속 업데이트 됩니다.
* 버전 표기는 프로젝트 실제 버전이 아닌 의존성의 변화과정을 담기 위해 편의상 표기하였습니다.
* v1.0 은 배포된 버전 입니다. (PocketMark)
API 변경 시 DTO 만 수정해도 되도록 리팩토링 완료했습니다.
API -> DTO -> Repository 에서 API -> DTO 로의 리팩토링 여행기입니다.
> v1.0 바로가기
v1.0 의 장점
1.
DTO->Repository 의존성
이 제거되어 API 스펙변경에도 끄떡없다. (코드 재사용성 매우 우수)
2. Spring Data JPA가 제공하는Query Method
를 마음껏 편리하게 사용할 수 있어 신속한 쿼리작성이 가능하다.
3. Projection 이기 때문에성능적으로도 우수
하다.
4. Class-Based 는 개발자가 마음만 먹으면 내부에 비지니스 로직을 넣을 수 있지만 Interface-Based는 넣을 수 없게 강제하기 때문에 협업시코드안정성(불변성)
에도 큰 기여를 할 수 있다.* API 스펙변경으로 인해 엔티티에 새로운필드를 추가해야하는 상황은 설명하고자 하는 부분과 관련이 없음.
PocketMark v0.1
API 스펙변경으로 인해 엔티티에 새로운필드를 추가해야하는 상황은 제외한다.
특징
엔티티 객체에서 Dto로 변환이 가능했었음 (ex_Entity.toDto())(v0.2에서 삭제)Summary. 개판 5분전
Spring Data JPA Repository
// Query Method (반환형은 User 이지만 Entity.toDto()가 있으므로 수정할 필요가 없음) List<User> findByName(String name); // Native Query @Query(value = "SELECT u.name, u.email FROM user u", nativeQuery=true) List<UserDto> findUserDto();
문제점
1. Entity-DTO 양방향 의존성
2. DB의 특수한 기능을 사용하는 것도 아닌데 쓸모없는 NativeQuery
API 스펙변경 시
Native Query
- SQL 문자열 수정필요
PocketMark v0.2
API 스펙변경으로 인해 엔티티에 새로운필드를 추가해야하는 상황은 제외한다.
특징
1. ClassBased-DTO-Proejction 적용으로 Entity-DTO 양방향 의존성 삭제
2. 단순조회에서 필요없어진 NativeQuery
Summary. 엔티티(도메인) 변경 없음
Spring Data JPA Repository & QueryDSL
// Class-Based Projection List<UserDto> findAllUserDto(){ em.createQeury("select new xx.xx.xx.ClassBasedUserDTO(u.name, u.email) " + "from User u", User.class) .getResultList(); } //Query-DSL public List<UserDto> findAllUserDto(){ return queryFactory .select(new QUserDTO(qUser.name, qUser.email)) .from(qUser) .fetch() .stream().......collect(Collectors.toList()); }
문제점
DTO-Repository 의존성으로 인한 API-Repository 의존성 문제
API 스펙변경 시
JPQL & QueryDSL
- 수정필요 (ex_ x.name-> x.userName)
PocketMark v1.0
API 스펙변경으로 인해 엔티티에 새로운필드를 추가해야하는 상황은 제외한다.
Summary. DTO만 수정하면 끝
Spring Data JPA Repository
// Interface-Based DTO Projection List<UserDtoNameAndItemsOnly> findByNameIn(Collection<String> nameList);
DTO Side
class UserDto{ public interface UserDtoNameOnly{ String getName(); } public interface UserDtoNameAndItemsOnly{ String getName(); List<Item> getItems(); } }
장점
1.
DTO->Repository 의존성
이 제거되어 API 스펙변경에도 끄떡없다. (코드 재사용성 매우 우수)
2. Spring Data JPA가 제공하는 Query Method 를 마음껏 편리하게 사용할 수 있다.
3. Projection 이기 때문에 성능적으로도 우수하다.
4. Class-Based 는 개발자가 마음만 먹으면 내부에 비지니스 로직을 넣을 수 있지만 Interface-Based는 넣을 수 없게 강제하기 때문에 협업시코드안정성(불변성)
에도 큰 기여를 할 수 있다.728x90'Back End > 리팩토링 보고서' 카테고리의 다른 글
[리팩토링 보고서] JPA 쿼리 성능 최적화 (0) 2022.03.05 [리팩토링 보고서] 서버과부하 방지를 위한 Batch 처리 (0) 2022.03.05 [리팩토링 보고서] 일급 컬렉션의 적용 (0) 2022.03.04 [리팩토링 보고서] 레이어간 의존성 개선 (0) 2022.03.04 [개발노트] PocketMark 개발노트 (0) 2022.03.03