강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

yunsoo0510님의 프로필 이미지
yunsoo0510

작성한 질문수

토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1

회원 애플리케이션 서비스 테스트 (2)

checkDuplicateEmail 메서드와 동시 요청에 관한 질문

작성

·

23

·

수정됨

0

안녕하세요 토비님! 좋은 강의 만들어주셔서 잘 듣고 있습니다.

작은 질문이 하나 있는데요. checkDuplicateEmail 메서드와 동시 요청에 관한 질문이 있습니다.

섹션 5. 28강 회원 애플리케이션 서비스 테스트(2) 20:47초 경에 email 중복 체크를 위하여 checkDuplicateEmail 메서드 코드를 작성하였고, 같은 email로 가입하려고 하면 DuplicateEmailException이 발생하는 것을 확인하였습니다.

 

그런데 여기서 다른 가정을 해보고 그런 상황에서 토비님이라면 어떻게 하셨을지 궁금합니다.

만약 email이 아닌 id로 회원가입을 하는 상황을 가정한다면,

email과 다르게 id는 여러 사람이 같은 id로 회원가입하려고 시도할 수 있습니다.

따라서 동시에 2개의 요청이 들어오게 된다면 checkDuplicateEmail는 둘 다 통과하고 DataIntegrityViolationException이 발생하게 될 것입니다. (DB에서 유니크 제한을 걸었기 때문에)

규칙인 id는 중복되지 않는다는 지켜지겠지만,

사용자가 보게 될 예외는 우리가 의도했던 DuplicateEmailException가 아니게 되겠죠.

 

여기서 궁금한 점은 이런 상황까지 고려하여 코드를 작성하여야 하는 것인지

아니면 그냥 넘어갈 것인지 궁금합니다.

 

저라면,

드물게 발생할 것이라고 예상을 했다면 로깅만 잘 해놓고, 해당 예외가 많이 발생했거나 관련 cs문의가 많이 들어온다면 추가로 코드를 작성할 것 같습니다.

처음부터 만약 많이 발생할 것이라고 예상했다면 try-catch를 통해 예외를 변경해줬을 것 같습니다.

아마 다음과 같은 코드가 될 것 같습니다.

@Override
public Member register(MemberRegisterRequest registerRequest) {
    try {
        checkDuplicateEmail(registerRequest);

        Member member = Member.register(registerRequest, passwordEncoder);

        memberRepository.save(member);

        emailSender.send(member.getEmail(), "등록을 완료해주세요", "아래 링크를 클릭해서 등록을 완료해주세요");

        return member;
    } catch (DataIntegrityViolationException e) {
        if (/*e를 통해 유니크 키 예외를 확인했다면*/) {
            throw new DuplicateEmailException();
        }
        throw e;
    }
}

서비스의 코드가 현재보다는 보기 지저분해진다고 생각했습니다. (아니면 이 방법이 아닌 다른 방법이 있을까요?)

 

토비님은 어떻게 생각하시는지 궁금합니다.

답변 1

0

토비님의 프로필 이미지
토비
지식공유자

id로 가입하면 email에 unique 조건이 걸려있는데도 checkDuplicatedEmail을 통과한다는게 잘 이해는 안 됩니다. id로 가입한다는 것은 어떤 것인지도요.

그와 상관없이 이렇게 조회를 통해서 중복을 체크하는 것이 아주 많은 동시 접속자가 있을 때 우연히 거의 동시에 두 개의 같은 이메일로 가입 신청이 들어왔을 경우 체크를 통과할 수 있습니다. 트랜잭션의 고립도 설정에 따라 달라지겠죠. 일반적으로 그럴 일은 없겠지만 그래도 있다고 가정한다면 그때는 말씀하신 대로 DB가 최종적으로 중복을 막아줄 겁니다. 그러면 그렇게 발생한 에러는 어떻게 처리해야 할지에 대해서는 여러가지 방법이 있을 듯한데요.

저라면 정말 우연히 1년에 한번 발생할까 말까한 수준이라면 그냥 에러가 나게 하고 클라이언트는 지금 일시적인 문제가 있으니 다시 시도해달라고 요청하게 할 겁니다. 다시 하면 중복 이메일 메시지자 확실하게 나오겠죠.

그런데 뭔가 동시에 많이 몰리는 상황이고 이런 에러가 많이 발생할 수 있다면, 예외가 발생했을 때 재시도를 통해서 이메일 중복 체크에 먼저 걸리도록 하는 방법과 지금 작성하신 것처럼 try/catch로 처리하는 방법이 있을 겁니다. 둘 다 가능하긴한데 DataIntegrityViolationException는 꼭 unique 조건 때문에만 발생하는 게 아닐 수 있어서 자칫 다른 DB 데이터 문제가 이메일 중복 문제로 잘못 해석될 가능성도 있습니다. 가능성이.. 아주 희박하겠지만요.

저는 가능하면 깔끔하게 코드를 만들고, DB가 잘 막아줄테니 에러가 그대로 나도록 하는걸 선호합니다. 비단 중복 데이터 문제 뿐 아니라, 네트워크와 시스템의 각종 예외들이 종종 발생하는데 그걸 매번 다 체크하도록 코드를 만들면 정말 복잡해질 것 같아요.

yunsoo0510님의 프로필 이미지
yunsoo0510

작성한 질문수

질문하기