[3주차] 예약API, 비관 락, 낙관 락, 분산 락 구현 및 테스트#84
Conversation
3rdweek to dev
| private LocalDateTime updatedAt; | ||
|
|
||
| private LocalDateTime deletedAt; | ||
| } |
There was a problem hiding this comment.
system properties 에 작성자, 수정자도 추가하면 좋을 것 같아요.
| @RequestParam(required = false) Genre genre | ||
| ) { | ||
|
|
||
| return ResponseEntity.ok(movieService.findMoviesPlayingWithFilters(title, genre)); |
There was a problem hiding this comment.
불필요한 줄바꿈 혹은 괄호 등의 기본적인 컨벤션을 조금만 더 신경 써주시면 좋을 것 같아요 !
There was a problem hiding this comment.
기본적으로 파라미터 구간은 닫힌 괄호를 기준으로 블록을 쉽게 구별할 수 있도록 줄 바꿈을 하고,
블록 내부 줄바꿈은 의미 단위로 구분하기 위해 사용하는데,
두 원칙 외에 무의식적으로 줄바꿈 해버리는 부분들이 있네요ㅠㅠ
이부분 조심하겠습니다!
| } | ||
| } | ||
|
|
||
| private void checkReservationPolicy(Reservation reservation, List<ReservationSeat> reservationSeats, int limit) { |
There was a problem hiding this comment.
전체적으로 함수들이 SRP 가 지켜진 모습이네요 👍🏿
| } | ||
|
|
||
| private boolean isAbusing(List<ReservationSeat> reservationSeats, int limit) { | ||
| if (reservationSeats.size() == limit) { |
There was a problem hiding this comment.
이런 함수들은 Service 에 있어야 하는건지 혹은 Domain 에 있어야 하는 건지
고민을 해주시면 좋을 것 같습니다 ~
There was a problem hiding this comment.
앗 그러네요! 도메인에 두는 게 훨씬 더 직관적일 것 같아요. 리팩토링하겠습니다!
| checkDoubleBooking(scheduleSeats); | ||
|
|
||
| List<ReservationSeat> reservationSeats = toReservationSeats(reservation, seats); | ||
| checkReservationPolicy(reservation, reservationSeats, 5); |
There was a problem hiding this comment.
매직넘버(5) 는 상수로 관리하면 좋을 것 같아요.
| @DistributedLock( | ||
| key = "#{#request.scheduleId}", | ||
| waitTime = 1, // second | ||
| leaseTime = 2 // second |
There was a problem hiding this comment.
변수명을 waitSec 등으로 설정하면 주석이 필요 없겠네요 !
| return point.proceed(); | ||
| } finally { | ||
| lock.unlock(); | ||
| } |
There was a problem hiding this comment.
finally 구문에서 lock.unlock 은 현재 스레드가 자신의 락만을 해제함을 보장할 수 있나요 ?
There was a problem hiding this comment.
추가로 GC Stop the world 현상이 길어지는 경우 tryLock 만으로 동시성 이슈를 해결하기 충분한지 deep dive 해보시는 것도 좋을 것 같습니다.
There was a problem hiding this comment.
finally 구문에서 lock.unlock 은 현재 스레드가 자신의 락만을 해제함을 보장할 수 있나요 ?
아 내부적으로 자신의 스레드인지 체크해서 본인이 획득한 락만 해제해야 할 것 같습니다.
놓쳤던 부분인 것 같습니다. 수정하겠습니다.
There was a problem hiding this comment.
추가로 GC Stop the world 현상이 길어지는 경우 tryLock 만으로 동시성 이슈를 해결하기 충분한지 deep dive 해보시는 것도 좋을 것 같습니다.
이 부분이 어렵네요. leaseTime 을 늘리려고 하니 적정선을 모르겠고,
구글링을 하니 자동 연장 기능이 있다는데, 한 번 활용해보겠습니다.
There was a problem hiding this comment.
@orkrj 👍🏿 fencing token 이라는 개념으로 찾아보시는 것도 좋을 것 같습니다 ~
There was a problem hiding this comment.
@orkrj 👍🏿 fencing token 이라는 개념으로 찾아보시는 것도 좋을 것 같습니다 ~
오오 분산 락에 토큰을 또 적용할 수 있네요. 정합성 유지하는데 많이 도움이 될 것 같아요.
흥미로운 주제라 계속 찾아보고 있습니다 감사합니다!
|
|
||
| @Repository | ||
| @RequiredArgsConstructor | ||
| public class JpaScheduleSeatRepositoryAdapter implements ScheduleSeatRepository { |
There was a problem hiding this comment.
port & adapter 패턴을 잘 적용해주셨네요 👍🏿
| private final MemberService memberService; | ||
| private final ScheduleService scheduleService; | ||
| private final SeatService seatService; | ||
| private final ScheduleSeatService scheduleSeatService; |
There was a problem hiding this comment.
현재 Service 는 도메인 서비스가 아닌 애플리케이션 서비스로서, 다양한 도메인 로직을 오케스트레이션 하는 역할 인것 같아요. 하지만 실상 Service 내부의 로직에는 도메인 로직이 포함되어있네요.
이 경우 지금처럼 애플리케이션 Service 들이 여러 애플리케이션 Service 를 의존하게 되는 경우,
서비스 규모가 커질 수록 Service Dependency Graph 가 추적하기 되게 힘들 정도로 복잡해집니다.
경우에 따라 개발자들이 나중에는 의존성에 대해서 신경 쓰는 것을 포기하는 수준까지 올 수 있습니다.
이런 문제를 해결하기 위해서 애플리케이션 Service 들이 다른 애플리케이션 Service 를 의존하지 않도록� 하는 방법도 실무에서 자주 사용됩니다.
There was a problem hiding this comment.
기존에 ‘하나의 서비스에 하나의 레포지토리’라는 원칙을 고수했는데,
생각해보니 이를 지키려다 보니 포트-어댑터 패턴을 충분히 활용하지 못했던 것 같습니다.
다른 애플리케이션 서비스가 아닌, 레포지토리를 직접 활용하여 도메인 객체를 조회하고 조작하는 방식으로
오케스트레이션하도록 리팩토링을 진행하겠습니다.
DDD를 적용하는 게 생각보다 어렵네요ㅜㅜ
There was a problem hiding this comment.
넵 도메인로직과 애플리케이션 로직을 명확히 분리하고, 이 과정에서 도메인서비스가 별도로 필요하진 않은지
필요 없다면 말씀 주신 것 처럼, 애플리케이션 서비스가 다른 애플리케이션 서비스를 참조하지 않게 Repository 를 호출해서 로직을 작성하는 방식으로 개선해도 좋을 것 같습니다 !
There was a problem hiding this comment.
넵 도메인로직과 애플리케이션 로직을 명확히 분리하고, 이 과정에서 도메인서비스가 별도로 필요하진 않은지 필요 없다면 말씀 주신 것 처럼, 애플리케이션 서비스가 다른 애플리케이션 서비스를 참조하지 않게 Repository 를 호출해서 로직을 작성하는 방식으로 개선해도 좋을 것 같습니다 !
넵 조언주신 방향으로 리팩토링 완료하였습니다!
설계.. 익숙해지면 뚝딱 뚝딱 해낼 수 있겠죠..?
|
@orkrj 님, 구조 및 코드 전반적으로 많이 신경써주신 모습이 보입니다 👍🏿 고생하셨습니다 ~ 좋았던 점
아쉬웠던 점
리뷰 포인트 및 추가 질문에 대한 답변
일반적으로 동시성 테스트라는 것을 별도의 시나리오로 빼서 진행하진 않습니다. 개발자들이 직접 검증을 하는 정도가 대부분입니다. |
3주차 과제
개인 사정으로 늦게 제출한 점 다시 한 번 죄송합니다.
프로젝트를 재설계한 부분은 커밋 볼륨을 크게 가져갔고,
3주차 과제 커밋은 이모지를 활용하여 강조하였습니다.
작업 내용
이번 주차에서 고민되었던 지점이나, 어려웠던 점을 알려 주세요.
기타 질문