들어가면서
(임시저장만 해두고 발행을 누르지 않은 것을 반성합니다)
우아한테크코스 레벨2의 마지막 미션은 웹 장바구니 협업 미션이었다. 이번 페어는 키아라와 주드였다. 프론트, 안드로이드 크루들과도 함께 팀을 이루어 미션을 진행하는 방식이었는데 랜덤 배정 결과 프론트 크루들과 함께 미션을 진행하게 되었다. step 0, 1 에서는 서버를 AWS 상에 배포하고 CORS 문제를 해결하는 과정이 핵심이었다. 그리고 step2에서는 장바구니에 담은 물품들을 실제로 주문을 할 수 있도록 기능을 추가 구현하는 것이었다. 이와 더불어 할인 정책과 관련된 기능을 선택해서 추가하는 것 또한 요구사항이었는데 우리는 포인트 적립 및 사용 정책을 구현하는 것을 결정했다.
같이 협업을 하게된 프론트 크루들은 솔로스타와 네이브였다. 다른 팀들을 생각해보면 의사소통하는 과정이나 프론트, 백엔드 간 차이 때문에 힘들어하는 모습이 많이 보였었다. 하지만 같이 협업하게 된 솔로스타와 네이브는 전반적으로 백엔드 분야에 대한 이해도 어느 정도 있었던 크루들이었어서 상대적으로 정말 편하게 협업미션을 진행할 수 있었다.
공부한 개념들
[API 명세]
- 성공 케이스 뿐만 아니라 오류 케이스에 대해서도 작성하고 어떤 케이스에 어떤 응답이 내려가는지도 작성해야 된다.
[Transactional은 Dao와 Service 어디에 작성되어야 하는가]
- 기존에는 Dao의 기능들을 Service에서 사용하기 때문에 비즈니스 로직 상에서 하나의 작업 단위로 묶여야 하는 기능들에 대해서 트랜잭션 선언을 해준다고 생각했다. 그래서 Service 단에서 @Transactional을 붙여줘야 한다고 생각했다.
- 리뷰어 로운은 JPA를 사용하는 관점에서 하나의 엔티티 상태를 수정할 때 내부에 매핑된 여러 엔티티에 대한 update 처리가 같이 이뤄지는 경우 Dao에 트랜잭션 처리를 안해줬을 시 문제가 발생할 수 있다고 했다.
- 이 경우 Service 차원에서만 트랜잭션을 관리한다면 롤백되지 말아야 하는 부분까지 예상치 못한 연산으로 전부 롤백되어 버릴 수도 있을 것이다. 즉 일부분만 트랜잭션으로 관리하는게 불가능해진다.
- 이러한 관점에서 Dao에 기본적으로 `@Transactional`을 붙여야 하고, 추가적으로 비즈니스적으로 묶여야하거나 readOnly처럼 트랜잭션 설정이 따로 필요한 경우에 service에 붙이는 방식에 대한 인사이트를 얻을 수 있었다.
[에러 메세지]
에러 메세지를 응답해줄 때는 어떤 상황에 대한 에러인지 알 수 있도록 공통된 응답 형태를 정하는 것이 좋다. 에러 코드와 에러 메세지를 같이 보내줄 때 클라이언트 입장에서도 어떤 예외상황이 발생했는지 이해하고 대처하기 수월해진다. 다음과 같은 응답 메세지 양식을 활용해보자.
private String code;
private String message;
private T data;
[Service에서 Service를 의존하는 방식]
같은 Service 계층이라고 하더라도 분명히 상위 하위 개념이 존재한다. 예를 들어 주문(Orders) 서비스는 주문상품(OrderItems) 서비스를 하위 서비스로 가질 수 있다. 이는 주문에 주문상품이 종속적이기 때문이다.
- Service 에서 Service를 의존할 때 / Dao를 의존할 때 각각 장단점
- Service를 의존할 때
- 특정 도메인의 영속화 책임을 단일 서비스에게 국한시킬 수 있다.
- 서비스와 서비스 간 비즈니스 로직을 조합해서 요구사항을 수행하는데 집중할 수 있다.
- 서비스 간 순환참조가 발생할 수 있다는 문제가 발생한다.
- Dao를 의존할 때
- 서비스 간 순환 참조 가능성을 배제할 수 있다.
- 여러 서비스에서 영속화된 Entity에 쉽게 접근할 수 있다.
- 특정 Entity에 대한 영속화 관리 포인트를 하나의 서비스에 한정 짓기 쉽지 않다.
- Service를 의존할 때
순환참조가 발생했다는 것은 설계를 잘못했다는 신호로 받아들이고 아키텍처를 어떻게 수정할 지 고민해봐야 한다.
현재 순환참조가 발생한 설계 구조에서 적절하게 역할과 책임이 부여된 것인지 검토하는 것이 중요하다.
[테스트 종류와 목적 그리고 테스트 속도에 관하여]
1. dao는 jdbcTest, jpaTest
2. service는 mock 혹은 의존성 주입, 필요하면 spring boot test
3. controller는 webMvcTest 혹은 spring boot test
4. 인수테스트는 spring boot test
Mock 테스트는 mock으로 적용한 부분은 정상 동작한다는 가정하에 다른 부분들이 잘 동작하는지에 집중하는 방식이다.
Service 계층 테스트에서 Mock 테스트를 진행하는 이유는 dao가 정상 동작한다는 가정하에 service의 역할과 책임인 비즈니스 로직이 정상 동작하는지에 더 집중하기 위해 사용하는 것이다.
이때 중요하게 고려해야 하는 요소는 테스트의 속도이다. 일반적으로 배포를 진행할 때 모든 테스트가 통과되어야 build가 되도록 진행이 된다. 만약 모든 테스트를 springBootTest로 진행했다면 속도가 훨씬 더 오래 걸리게 될텐데 테스트가 5~6배가 된다면 속도는 처참하게 느려질 것이다. Build 하는데에만 20~30분이 걸리는 테스트를 작성하는 것은 효율적인 개발이라고 할 수 없는 것이다.
셀프 회고
화요일부터는 바로 페어 미션을 진행하게 되었다. 시작하기 전에는 마지막 미션이니 할 것이 엄청 많을 거라고 생각했는데 막상 step0, 1에서 백엔드 크루가 구현해야 할 요구사항이 현저하게 적었다. 이 부분은 확실히 예전에 미약하긴 하지만 직접 AWS를 사용하며 배포해본 경험이 있었기 때문이라고 생각한다. 덕분에 나머지 시간에 지하철 미션 리팩토링에 집중할 수 있었던 것 같다. 다만 아쉬웠던 부분은 지하철 미션에 신경이 쏠려서 협업 미션 시작부터 온전히 집중하지 못한 것이었다. 뼈대코드를 좀 더 주의 깊게 살펴보고 페어 미션에 임했다면 좀 더 적극적으로 의견을 피력할 수 있지 않았을까 하는 아쉬움도 남는다.
그래도 무난하게 step0, 1이 마무리 되고 금요일에 프론트 크루들과 처음 만나 회의를 진행하게 되었다. 솔로스타와 네이브가 잠실 캠퍼스로 넘어와 주었는데 회의가 끝날 때까지 거의 3시간이 걸렸던 것 같다. 프론트 크루와 얘기를 하다보니 내가 원래 알고 있다고 생각했던 것들도 기억이 안나고 설명하기 어려웠던 순간이 많았던 것 같다. 지하철 미션 리팩토링에 치여서 이번 미션에 온전히 집중하지 못하고 잠도 몇 주 내내 잘 자지 못해서 그런 것도 분명히 있다. 하지만 그럼에도 불구하고 내가 아는 부분을 프론트엔드 크루에게 잘 설명하면서 API 명세를 해보고 싶었는데 만족스러운 그림은 아니었다고 생각한다. 아쉬웠지만 어쩔 수 없는 Trade-Off였던 걸까…? 그래도 지하철 미션 리팩토링은 스스로의 최소 기준선은 충족할 정도로 진행할 수 있었던 것 같다.
원래대로라면 step2 구현은 개별적으로 진행하게 된다. 하지만 키아라의 제안과 주드의 동의로 우리 페어는 step2 최초 제출까지는 페어로 미션을 진행해보는 것으로 결정했다. 덕분에 일요일, 월요일 연휴에도 캠퍼스에 출근해서 같이 미션을 진행하기로 했다. 지하철 미션에서 진이 많이 빠져서 협업 미션 step2를 혼자서 구현했으면 솔직히 좀 많이 쳐젔을 것 같은데 페어로 진행하게 되어 꾸역꾸역 진행할 수 있었다고 생각한다. 이 순간을 빌어 흔쾌히 페어로 미션을 진행하는 것을 제안하고 동의해준 키아라와 주드에게 감사한다.
'우아한테크코스 > 회고' 카테고리의 다른 글
[우아한테크코스] LV3 - 3차 스프린트 회고 (0) | 2023.08.20 |
---|---|
[우아한테크코스] LV3 - 2차 스프린트 회고 (2) | 2023.08.13 |
[우아한테크코스] LV3 - 1차 스프린트 회고 (2) | 2023.07.09 |
[우아한테크코스] 중간 회고 (2) | 2023.07.02 |
[우아한테크코스] LV2 - 웹 지하철 미션 Step2, 3 회고 (0) | 2023.05.28 |