Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

orderForm 유효성 검사 추가 #42

Merged

Conversation

daadaadaah
Copy link
Collaborator

@daadaadaah daadaadaah commented Jun 1, 2023

What

Comment

  • OrderController 테스트 코드 작성을 제외하고 완성시켰습니다!
  • 크게 고민이 2가지 입니다.

🤔 고민 1. 유효성 검사 관련해서 테스트 코드를 어디까지 작성해야 할까?

  • 제가 생각해본 선택지는 3가지 경우인데, @f-lab-TJ 의견은 어떠신지 궁금합니다!
    선택 1. 모든 경우의 수에 대해 다하자 -> 단점 : OrderController 테스트 코드가 어마어마해짐
    선택 2. 정말 유효성 검사가 제대로 되지 않았을 때, 비즈니스적으로 크리티컬하게 문제 생기는 필드들(예 : 돈과 관련된 필드들)만 하자
    선택 3. orderForm에서 주문자 정보는 MySQL에서 가져오고, 상품 정보는 Redis에서 가져오도록 구조 수정하고, 수령자 정보만 유효성 검사하기

🤔 고민 2. 사용자가 PaymentType Enum에 없는 값으로 HTTP 요청한 경우, 유효성 검사 어떻게 해야 할까? 할 필요가 없나?

  • 사용자가 PaymentType Enum에 없는 값으로 HTTP 요청한 경우, 다른 값과 다르게 HttpMessageNotReadableException이 나옵니다.

@daadaadaah daadaadaah mentioned this pull request Jun 1, 2023
10 tasks
@daadaadaah daadaadaah requested a review from f-lab-TJ June 1, 2023 18:06
@jereneal20
Copy link

jereneal20 commented Jun 3, 2023

  1. 테스트 코드가 많아짐 vs 서비스의 퀄리티가 향상됨 (잘못된 주문을 허용할 여지가 낮아짐)
    어떤 것이 더 좋을까요?

  2. Spring에서 알아서 예외를 던져준다면, 그리고 그것이 일반적으로 발생하지 않는 케이스라면 큰 문제가 없지 않을까요?


private void validatePaymentInfoForm(PaymentInfoForm paymentInfoForm, Errors errors) {

if (paymentInfoForm.getDiscountAmount() > paymentInfoForm.getOriginPrice()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래와 같은 예외들은 항상 거짓인 케이스로 예외 처리를 하는데 있어 이점이 있습니다.
하지만, e-commerce 특성상 특정한 유저에게는 x%만큼의 할인율이 들어가거나, 특정한 시간대에 구매한 사람에게 특정한 할인율이 들어가는 등 다양한 할인율이 적용될 수 있는데 (혹은 최소한 상품에 따른 최대 할인율이 있을수도 있음), 이런 것들은 어떻게 처리하면 좋을까요?

e-commerce에서 비즈니스 로직이 중복되는 문제 (duplication/scattering)는 가장 일반적인 문제 중 하나입니다.
커머스 로직이 차후에 복잡해진다는 것을 가정하고 시스템을 설계한다면, 어떤식으로 로직을 공유하는 것이 좋을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하지만, e-commerce 특성상 특정한 유저에게는 x%만큼의 할인율이 들어가거나, 특정한 시간대에 구매한 사람에게 특정한 할인율이 들어가는 등 다양한 할인율이 적용될 수 있는데 (혹은 최소한 상품에 따른 최대 할인율이 있을수도 있음), 이런 것들은 어떻게 처리하면 좋을까요?

  • 네! 저도 정액 할인, 정률 할인, 특정 회원에만 할인 등 다양한 할인 정책이 있을 것을 가정해서,
  • discountAmount를 아예 프론트에서 그런 할인 정책들을 다 계산된 할인 금액을 받는 상황으로 가정하긴 했어요!
  • 그런데, 생각해보니, 그런 할인 정책을 계산하는 로직에 외부로 노출되어서 안되는 로직이 포함될 수 있다는 생각이 드네요.
  • 그러면, 프론트에서 dealProductUuidproductUuid만 던져주고, 그 데이터를 기반으로 DB에서 조회해와서 할인 정책들을 계산하는 클래스를 만드는 것도 방법 중 하나일 것 같아요! 전략 패턴 같은 것을 활용해서요!

e-commerce에서 비즈니스 로직이 중복되는 문제 (duplication/scattering)는 가장 일반적인 문제 중 하나입니다.
커머스 로직이 차후에 복잡해진다는 것을 가정하고 시스템을 설계한다면, 어떤식으로 로직을 공유하는 것이 좋을까요?

  • 어떤 비즈니스 로직이 어떻게 중복되는지에 따라 다를 수 있겠지만, AOP를 활용하거나 도메인 모델을 활용하여 공유할 것 같습니다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

특정 아이템에 대해 가격이 유저나 시간에 따라 다를 가능성이 있나요?
유저가 discountAmount을 보내는 대신, 조작된 discountAmount을 보내준다면 어떻게 되나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

특정 아이템에 대해 가격이 유저나 시간에 따라 다를 가능성이 있나요?

  • 현재 가정해 놓은 상황에는 특정 아이템에 대해 가격이 유저나 시간에 따라 다르지 않지만, 추후에 비즈니스적으로 확장된다는 상황을 가정하면, 가능성이 있다고 생각합니다.

유저가 discountAmount을 보내는 대신, 조작된 discountAmount을 보내준다면 어떻게 되나요?

  • 3번 선택지를 선택한다면, 이런 변조 가능성은 배제될 것 같아요!

@daadaadaah
Copy link
Collaborator Author

  1. 테스트 코드가 많아짐 vs 서비스의 퀄리티가 향상됨 (잘못된 주문을 허용할 여지가 낮아짐)
    어떤 것이 더 좋을까요?
  • 전자가 좋을 것 같아요! 그런데, 정말 기획적 확장성을 고려해서 다양한 상황을 커버하기는 한계가 있을 것 같은데, 혹시, @f-lab-TJ는 3번 선택지에 대해 어떻게 생각하시나요?
  1. Spring에서 알아서 예외를 던져준다면, 그리고 그것이 일반적으로 발생하지 않는 케이스라면 큰 문제가 없지 않을까요?
  • orderForm이 유효하지 않을 때에도 Spring에서 알아서 MethodArgumentNotValidException을 던져줬고, 이 예외에 대해서는 핸들링을 해줬는데, HttpMessageNotReadableException 경우도 해줘야 하지 않나? 라는 생각이 들어서 고민이었습니다.
  • HttpMessageNotReadableException은 클라이언트 요청의 HTTP 메시지를 읽을 수 없는 경우에 발생하는 예외인데, 그 원인이 서버에 있어서 발생한 경우가 있고, 클라이언트에 있어서 발생한 경우가 있더라구요! 그래서, 현재는 스프링에서 500으로 처리하는데, 각각 다르게 상태코드를 내려줘야하나? 라는 생각이 들었습니다.
  • 그런데, 500이든 400이든 이 문제가 비즈니스적으로 또는 기술적으로 큰 문제를 발생시키는 거 아니니, 그냥 스프링이 처리하는 대로 500으로 해도 큰 문제가 없을 것 같네요!ㅎㅎ

@daadaadaah daadaadaah force-pushed the feat/add-validation-for-orderform branch from f0c4867 to 5a1a5cb Compare June 3, 2023 17:33
@f-lab-TJ
Copy link

f-lab-TJ commented Jun 5, 2023

3번 선택지의 이점와 의도가 무엇인지에 따라 다를 것 같네요. 이부분을 좀 더 설명해주실 수 있을까요?

핸들링해서 다른 예외나 메세지를 내리는 것이 의미 있다면, 그렇게 해보는 것도 좋을것 같네요.

@daadaadaah
Copy link
Collaborator Author

daadaadaah commented Jun 5, 2023

3번 선택지의 이점와 의도가 무엇인지에 따라 다를 것 같네요. 이부분을 좀 더 설명해주실 수 있을까요?

3번 선택지의 이점

  1. 변조 가능성을 배제할 수 있어서, 유효성 검사가 필요 없거나 경우의 수가 줄어든다.
  • 왜냐하면, 결제에 필요한 상품 금액, 할인 금액 등의 데이터를 DB에서 가져오기 때문이다.
  • 지금 상황에서 3번 선택지를 선택했다고 했을 때, OrderFormValidator에는 주문 수량에 대해 최대 주문 수량보다 작게 주문했는지에 대한 유효성 검사 정보만 필요하고, 현재 작성해 놓은 나머지 유효성 검사는 필요 없을 것 같아요!
  1. OrderForm이 다음과 같은 구조로 간단해진다.
@Getter
public class OrderForm {
    @Range(min = 1, message = "주문자 ID를 확인해주세요.")
    private final int userId;

    @Valid
    @NotNull(message = "수령자 정보는 필수입니다.")
    private RecipientInfoForm recipientInfoForm;

    @NotNull(message = "딜 상품 UUID를 입력해주세요.")
    private final UUID dealProductUuid;
}

@daadaadaah daadaadaah force-pushed the feat/add-validation-for-orderform branch 4 times, most recently from d392bae to abbf282 Compare June 7, 2023 14:50
@daadaadaah daadaadaah force-pushed the feat/add-validation-for-orderform branch from abbf282 to 60461cc Compare June 7, 2023 14:54
@f-lab-TJ
Copy link

f-lab-TJ commented Jun 8, 2023

멘토링 시간에 이야기했던대로 3번으로 진행해봐도 좋을 것 같네요!

@daadaadaah daadaadaah merged commit ce67d86 into f-lab-edu:develop Jun 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants