이번주도 역시 정신없이 한주가 지나갔다. 그리고 이번주는 특이하게 체력적으로 많이 힘들었던 한주였던 것 같다. 자꾸만 일정들이 한 두개씩 딜레이되면서 잠자는 시간이 줄어들고, 이것이 체력적으로 회복이 잘 안되서 그랬던 것 같다. 그런데 힘들지만 여전히 재밌다. 하루의 모든것을 쏟고서 기절하는 느낌이 좋다. 근데 이에대한 부작용(?)인 것인지, 어제 하루는 정말 많이 늘어졌던 것 같다. 시작만하면 괜찮은데, 어젠 그 시작이 정말 힘들었다.
동적쿼리 개발: 제품을 좀 더 다양한 조건을 가지고 검색한다. #4
(어제) 오늘은 "제품을 좀 더 다양한 조건을 가지고 검색한다. #4" 이슈를 작업했다. (가장 초창기에 등록한 이슈인데 이제서야 이 이슈를 처리하는 내 자신 반성한다..)
제품을 좀 더 다양한 조건을 가지고 검색한다. · Issue #4 · KEEMSY/shoes-ordering-system
설명 기존 시스템 분석에서 식별한 기능이었던 상품 검색 및 필터링의 대한 개발로, 제품카테고리(ProductCategory)를 통한 검색 기능을 개발했으나, 더 다양한 Product의 속성이 존재하며, 해당 속성
github.com
이번 이슈의 핵심은 동적쿼리이다. 원래 제품 검색을 ProductCategory 를 통해서만 가능하도록 개발했었는데, Product의 속성은 ProductCategory 외에도 다양했기에, 다양한 조건으로 Product 를 검색하는 기능이 필요할 것이라고 생각이 들어 개발의 필요성을 인지하게 되었다.
하지만 이번 기능 개발은 완벽하지 않다. 개발하면서 이게 무슨말인가 싶지만.. 지난 친구의 조언때문이다.
그렇다. 문자열 검색을 하는데 MySQL을 사용한다면, 인덱스를 타는 것이 아니라 풀 스캔을 하기에.. 만약 검색이 몰릴 경우 장애가 발생할 수 있다. 하지만 나는 검색엔진까지는 아직 공부해보지 못했다.. 해당 부분도 호기심의 영역이라 분명 공부를하겠지만, 지금은 시간적인 여유가 너무 부족하다. 그래서 나는 이를 해결(?)하기위해 name 필드 값에 값이 있을경우, 다른 필드의 값을 반드시 포함하도록 하는 방법을 생각했다. 하지만 지금은 이를 반영하지 않았다. 이번 개발 이 후, 조회기능을 부하테스트 해보려는데, 실제 어느정도 수준에서 문제가 되는지를 직접 보고 싶어서하지 않았다. 지금까지는 데이터의 수가 적었어서 그런지, 조회, 데이터 삽입을 함께 테스트(Thread 1000, 10번 반복)할 때 문제가 없었다.
무튼 나는 지금은 검색엔진을 사용할 수 없기에, 반쪽짜리(?) 개발을 시작했다. 작업의 분류는 크게 두 종류이다. Application 계층에서 유스케이스를 추가하고, DataAccess 계층에서 해당 유스케이스를 위한 영속성 계층의 상호작용 API를 추가하는 것이다.
Product-Domain-Application 유스케이스 추가
나는 먼저 유스케이스를 처리하는 Product-Domain-Application 계층을 개발했다. 이 계층에서 다뤄야할 핵심 내용은, DTO를 추가하고, 이를 활용한 유스케이스를 추가하는 것이다. 그런데 이 작업을 다 끝내고 나서 문제점을 알게된 부분이 있다. 이 작업을 시작하기 전에 공통으로 사용되는 인터페이스를 Product(기준브랜치)에서 정의를 했었어야 했다. 하지만 이를 몰랐기에, 첫 작업 이후, 두번째 작업을 진행할 때, 같은 코드를 두번 작성하는 불편함이 발생했다. 앞으로는 인터페이스를 먼저 정의 하고서, 작업을 진행하도록하자!
변경사항 1. DTO 추가
이 작업을 진행하면서 가장 고민이 됬던 부분은 "입력 유효성 조건을 어떻게 줄것이며, 어떻게 검증할 것인가" 였다. 이를 고민하면서, 초기에 고민했던 name에 대한 제한조건은 나중에 하기로했고, 다른 유효성 검사를 추가했다.
입력 유효성을 검증하면서, 고민이 됬던 부분이 있다. 바로 "default value 를 지정할 것인가" 에 대한 부분이다. 나는 기본적으로 검색 시, 입력에 null 값을 허용하지 않는 것을 원칙으로 하였었다. 왜냐하면 값을 입력하지 않은건 잠재적으로 잘못된 것 이라 생각했기 때문이다. 그래서 일단은 없는 것 보다는 낫다는 생각으로 값이 없을 경우, default value 를 지정하였다.
name 필드의 경우, default value 를 지정할 수 없었다. 그래서 해당 DTO 를 개발하면서, 잠재적 문제를 내포하는 친구는 name 필드가 되겠군.. 이라는 생각을 갖고서 개발을 했는데, 근데 DataAccess 를 개발하면서, 내가 틀렸다는 생각이 들었다. 그리고 굳이 default value 를 지정하지 않았어도 될듯하다.
변경사항 2. ProductQueryService 내 API 추가
DTO를 개발하고 해당 DTO를 사용하여 신규 유스케이스를 특성에 맞게 올바른 Service 내에 추가하였다. 이번 유스케이스의 경우 Query 이므로 QueryService 내에 추가를 진행했다. 그리고 추가를 진행하면서, 테스트는 ProductQueryService 에서 진행하는 것이 아니라, Handler 에서 진행을 했다. 그리고 지금 이렇게 적으면서 보니 나 완전 짬뽕이다.. 어느곳에선 Service에서 하고 어느곳에선 Handler 에서 하고있다.. 둘다하거나 아니면 분명하게 정해서 진행해야겠다.
변경사항 3. ProductRepository 인터페이스 내 API 추가
이번 작업 간, 가장 잘못했다 생각을 하게 된 부분이다. 이번 작업은 Application 계층과 DataAccess 계층의 작업이 필요한데, 공통으로 사용되는 ProductRepository 인터페이스(Port) 를 미리 정의하지 않았다는 것과, 영속성 계층에서 바로 DTO 객체를 사용하는 부분이 아주 잘못됬었다.
- DTO 를 영속성 계층에서 사용한다는 것은 영속성 계층의 변경의 원인이 늘어나게 된다.(SRP 미준수), DTO 가 변경되면 전혀 상관 없는 영속성 계층의 기능에 장애가 발생한다.
- 공통으로 사용되는 인터페이스를 미리 정의하지 않으면 작업이 함께(병렬적)으로 이뤄질 수 없다.
이 부분은 스스로 셀프 리뷰를 하기 전까지는 전혀 인지하지 못했다. 그래도 스스로 돌아보면서 이 문제를 인지해서 다행이다.
Feature/41 product search(Product Domain-Application 계층 내, 다양한 Product 의 속성 값을 가지고 조회할 수 있
관련 이슈 #4 #41 변경 사항 신규 DTO 추가 신규 기능(다양한 Product 의 속성 값을 가지고 조회) 를 위해 사용할 DTO(DynamicSerachProductQuery) 를 추가했습니다. 검색 시, 조건 값을 입력하지 않을 경우, 기
github.com
Optional 와 [[]] 에 관하여
Application 계층 개발 이후, DataAccess 계층에 대한 개발을 바로 이어서 진행하였다. 그런데 DataAccess 계층을 개발하면서, 내가 잘못알고 있는 부분을 알 수 있었다.
나는 Optional 을 null 에 대한 안정성을 위해 사용한다 알고 있었고, 이를 위해 Optional 을 사용했다. 그리고 Optional.of 는 null 을 허용하지 않고, ofNullable 은 null 을 허용하는 것으로 알았고 있고, 사실도 그러하다.
나는 사실 Optional 에 대한 완벽한 이해를 하지 않고 사용했다. 그래서 나는 이런 경고문을 테스트 코드를 작성하면서 볼 수있었는데, 나는 "Optional 은 isPresent()를 통해 값이 있는지 없는지 확인하고 사용해야하는구나" 를 알 수 있었다. 그리고 나는 다음 사진의 테스트는 당연히 실패하는 테스트라고 생각했다.
하지만 테스트는 성공했다. 빈 리스트의 값이 들어있으므로, null 이 아니었기 때문이다. 나는 잘못알고있었다. isPresent() 는 빈값을 갖고 있는지 확인하는 것이 아니라 null 인지를 확인하는 것이었다.
뿐만아니라, 내가 완전히 착각을 한 부분도 새롭게 알게되었다. 나는 테스트를 진행하면서, Optional[[]] 맞이했고, 이전 isPresent() 의 경험을 통해 다음과 같이 테스트 코드를 작성했었다.
나는 실패한 테스트 코드가 실패 할 것이라고 생각했고 실패했다. 그리고 성공한 테스트 코드는 실패할 것이라고 생각했다. 하지만 성공했다. 그런데 나는 왜 실패한다고 생각했을까? 다음 테스트 코드 때문이다.
원래 당연히 [[]] 의 isEmpty()는 성공해야한다. 그런데 다음 테스트 코드를 실행 및 결과는 실패였고, 이를 보고선 optional 의 테스트 코드가 실패할 것이라고 생각했다. 그런데 왠걸... Optional 이 성공하니.. 조금 복잡하다.. 내가 뭘 잘못알고 있는 것일까..?
이 부분때문에 오늘 개발을 전부다 끝마지치는 못했다. 내일은 이 이슈를 모두 마치고, 내 지식 정리에 초점을 많이 맞출 생각이다. 면접 준비한다고, 공부했던 내용들을 다시 보는데.. 내용이 조금 많이 뒤죽박죽인것 같더라...ㅎㅎ 그리고 또 내 생각들이 조리있게 정리가 되어있지 않더라... 면접 전에 분명하게 다 정리를하고 숙지를 할 수 있도록 해야겠다.
다음주도 화이팅!
'회고 > TIL' 카테고리의 다른 글
Optional 정리, Product DataAccess 계층 내, 다양한 Product 의 속성 값을 가지고 조회할 수 있는 유스케이스를 추가한다. PR 작성, 독서 (0) | 2023.09.19 |
---|---|
기술면접 준비, Product DataAccess 계층 내 유스케이스 추가, 육각형개발자 독서: 아키텍처 (0) | 2023.09.18 |
이력서 지원 시작, 독서: 소프트웨어 가치와 비용, 기존 이슈 작업 시작 및 신규 이슈 (0) | 2023.09.13 |
특정(한정판) 상품에 대한 계정 당 1회 주문 제한 기능추가 마무리, 인프라 구축, yml 분리의 필요성 (0) | 2023.09.11 |
TestContainers 사용을 통한 Redis 테스트 및 기능 개발 (0) | 2023.09.08 |