작성
·
556
1
강사님 안녕하세요. 이번 강의에서 BookService에 returnBook을 만들어주었는데요, 실행을 하면 반납을 했음에도 불구하고, 같은 이름의 사용자가 이미 반납한 책을 또다시 반납해도 오류가 발생하지 않고, 반납에 성공했다고 결과가 나오는 것을 알게되었습니다.
제 생각에는 UserLoanHistory history = userLoanHistoryRepository.findByUserIdAndBookName(user.getId(), request.getBookName()) .orElseThrow(IllegalArgumentException::new);
해당 코드에서 findby부분에is return도 추가하여 userLoanHistoryRepository.findByUserIdAndBookNameAndIsReturn(user.getId(), request.getBookName(), false)로 해주어야 대출중인 책을 반납하는 동작이 한번 이루어지고, 중복반납이 안될거 같은데 혹시 제가 이해를 잘못한건지 궁금합니다. 감사합니다!
답변 1
1
안녕하세요 인태님!!! 정말 좋은 질문 감사드립니다~~~!!! 👍👍 이 질문을 받게 되어 너무너무 좋네요!! 😊
결론부터 말씀드리자면 기획적으로 정의되어야 하는 부분이지만, 인태님께서 말씀해주신것처럼 검증을 강화하는 것도 한 가지 방법입니다.
상황은 이렇습니다!!
유저 A가 <책 1>을 대출하고 반납한다. (여기까지는 정상입니다)
그런데 유저 A가 <책 1>을 한 번더 반납하는 API가 호출된다.
이때 진작 유저 A는 <책 1>을 반납했는데 API에서 200 OK가 나온다
자 여기서 반납 API가 한 번더 불렸을 때 200 OK가 나오는 것에 대한 관점이 2가지 있을 수 있습니다.
각 관점을 이야기해보겠습니다!!!
[관점 1 - 200 OK가 나오면 안된다]
진작 반납되어 있는 책을 어떻게 다시 한 번 반납할 수 있는가~~ 말이 안된다!
따라서 진작 반납되어 있는 책을 한 번더 반납하려 한다면 예외를 발생시켜 잘못되었다는 것을 알려주어야 한다.
[관점 2 - 200 OK가 나와도 된다]
진작 반납되어 있는 책을 한 번 더 반납하는 것은 물리적으로 어색하지만
최종적으로 데이터를 생각해보았을 때 반납 API가 1번 호출되건~ 2번 호출되건~ 100번 호출되건~ side effect는 없고 유저 A가 <책 1>을 반납했다는 기록이 변경되지는 않는다.
오히려 클라이언트에서 따닥클릭을 했을 때 API가 약간의 텀을 두고 2번 호출되는 일이 생긴다면, 두 API 모두 성공하게 해주는 것도 사용자 경험 측면에서 유리하다.
하나의 API가 실패하면 반납은 정상처리 되었음에도 유저는 "실패 알림"을 보기 때문에 혼란에 빠질 수 있다.
물론, 클라이언트에서 throttle 이나 debounce를 잘 걸어주면, API가 2번 호출되는 일을 막을 수 있습니다.
두 관점 모두 생각해보면 충분히 말이 됩니다. 인태님께서 짚어주신것처럼 예외를 발생시키는 것도 방법이고, 어차피 최종적인 DB는 같으니 굳이 예외 처리를 해주지 않는것도 방법이죠.
유저 이름 변경이나 삭제에 대해서는 관점1을, 도서 대출에 대해서는 관점 2가 반영된 것입니다.
단지 주어진 코드를 타이핑 하는데 그치지 않고, 어떤게 더 맞는 방향인지 어떤 선택지와 장단점이 있는지 고민해주셔서 감사드립니다!! 🙏🙏
혹시나 더 궁금한게 있으시다면 또 편하게 질문 남겨주시기 바랍니다!!
아 추가로, 비슷한 결의 아래 질문글도 한 번 확인해주시면 좋을 것 같습니다.
항상 감사합니다!!! 오늘도 행복한 하루 되세요! 🙏