잘못된 리팩토링, OOP와 순수 함수
이전에 올렸던 포스트가 잘못된 부분이 있었다.
순수 함수를 사용하면서 테스트가 더 쉬워진 것은 분명히 맞는 사실이다.
하지만 JPA와 엔티티, 객체지향의 관점에서는 좋은 코드가 아니었다.
사진으로 살펴보자.
이전 글에서 이런 코드를 보여주며 테스트하기 어려운 코드를 분리하고 순수 함수를 사용하자는 의견을 냈었다.
이런 패턴을 가질 때 좋은 점은 비즈니스 레이어의 코드를 쉽게 테스트할 수 있다는 것이다.
테스트 코드를 쉽게 작성할 수 있고 스프링부트 테스트 혹은 JPA 테스트처럼 스프링 컨텍스트를 활용하지 않고도 테스트할 수 있어 속도가 매우 빠르다.
이제 단점에 대해 살펴보자.
순수 함수에서의 객체
순수 함수에서는 객체의 값이 변경되면 새로운 객체를 생성해서 반환한다.
그래서 나는 주황색 표시와 같이 새로운 객체를 빌더 패턴으로 생성하고 반환하는 로직을 추가했다.
하지만 JPA와 OOP에서의 객체는 느낌이 다르다.
모든 엔티티는 누군가가 자신에게 업데이트 요청을 보내주면 그것을 수행하는 것이다.
외부의 누군가는 그 로직에 대해 알 필요가 없다.
이런 관점에 저런 패턴은 좋지 않은 것이다. 업데이트를 하는 것은 엔티티에게 맡기고 외부 로직은 그걸 몰라도 된다. 이런 개념이 JPA에 구현된 것이 더티 체킹이다. 엔티티의 데이터가 업데이트 되었을 때, 영속성 컨텍스트에서 데이터가 바뀌었는지 확인하고 UPDATE 쿼리를 JPA레벨에서 날려버리는 것이다.
객체의 의존성과 코드의 복잡도 그리고 단위 테스트
위 exisitingSearch라는 객체는 결국 Repository의 조회 결과에 의존한다.
복잡하게 생각할 것 없이 나는 단위 테스트를 위해서 억지로 코드를 분리하고 있었던 것이다.
그 과정에서 existingSearch를 입력받아 처리하는 코드가 한 줄 더 늘어났고, 업데이트 혹은 생성하는 코드가 쓸데없이 늘어난 것이다.
exisitingSearch는 Repository의 결과에 의존하기 때문에 통합 테스트의 개념으로 비즈니스 로직을 테스팅해야 하는데, 굳이 단위 테스트를 하겠다고 코드의 복잡성을 늘리고 줄 수를 늘렸던 것이다.
정리하면 단위 테스트를 위한 함수 분리 및 코드 늘리기라고 볼 수 있겠다.
이 파트를 리팩토링하면서 비즈니스 로직이 단위 테스트를 할 수도 있지만 통합 테스트의 시나리오 비중이 더 크다는 것을 느꼈다.
개선 결과
위의 두 가지 단점을 개선하고자 아래와 같이 코드를 수정했다.
상태를 변경하는 코드는 엔티티에 위임했다.
여전히 테스트하기 어려운 코드가 남아있지만 이 부분은 통합 테스트의 개념으로 테스트 DB가 돌아가는 환경에서 검증을 할 수 있도록 통합 테스트의 성격을 띄게 작성하고 있다.
3줄 정리
- 지난 번의 포스트의 코드는 JPA와 OOP를 고려하지 않은 안티 패턴이다.
- 순수 함수와 OOP의 특성을 고려하자.
- 만약 어떤 데이터가 Repository를 의존하지 않고 순수 비즈니스 로직에 기여한다면, 그 로직을 추출해서 순수 함수로 만들 수도 있을 것이다.
'개발 > 개발 공부' 카테고리의 다른 글
[MySQL] 검색 조회 쿼리 성능 개선 - 1편 (2) | 2025.07.03 |
---|---|
[AWS] RDS로 데이터 삽입 삽질 (0) | 2025.07.03 |
테스트 코드는 왜 작성하기 어려울까? (0) | 2025.05.31 |
검색 구현을 위한 기초 공부 (0) | 2025.05.05 |
[밑바닥부터] 8일차 - 2장 불 연산: ALU 구현 및 테스트 (0) | 2025.04.13 |