xuni 인증 도메인 - 회원 가입 로직과 트랜잭션 관리 포스팅에 이어 작성합니다.
목차
1. 회원 가입 로직
2. 1, 2안 테이블 비교
3. 2안을 통한 문제 해결
4. 2안의 단점
회원 가입 로직
앞서 회원 가입 로직에 대해 2가지에 대해 설명드렸는데요. 오늘 포스팅에도 필요한 내용이라 다시 한 번 올리겠습니다.
회원 가입 로직 1안
1안 채택 시
- 회원 가입을 진행했지만 미인증으로 마무리된 회원 레코드는 사용도가 떨어질 것입니다.
- 계정 활성화를 나타내는 속성을 테이블에 추가 되어야 합니다. 또한 로그인마다 활성화 속성을 확인해야 합니다.
회원 가입 로직 2안
2안 채택 시
- 인증 코드가 독자적으로 존재할 수 있어야 합니다. 즉, 인증 코드는 엔티티가 되어야 합니다.
- 인증 코드 엔티티에서 이메일 속성을 테이블에 가지고 있어야 합니다.
결론 : 백앤드 측면만 고려했을 때는 2안이 더 좋은 의사 결정이라고 생각합니다. 2안은 우선 테이블 관점에서 2가지 이점과 애플리케이션 레벨에서 3가지 이점을 누릴 수 있습니다.
테이블 관점
1. 미인증된 사용자의 계정 생성 방지
2. 계정 활성화 플래그 컬럼 불필요
애플리케이션 레벨
1. 사용자 로그인 요청 시, 활성화 플래그를 검증 여부 생략 가능
2. 검증에 따라 활성화 플래그가 거짓일 때 해야하는 예외 처리
3. 트랜잭션 처리
1, 2안 테이블 비교
1안
2안
2안의 관점에서 바라본 1안과의 주요 차이는 다음과 같습니다.
1. MEMBER_AUTH_CODE는 기본키를 가진다. 주체적일 수 있다.
2. is_authenticated 속성이 MEMBER 테이블에서 MEMBER_AUTH_CODE으로 이동한다.
3. email 속성이 양 테이블에 모두 존재한다.
2안을 통한 문제 해결
이 3가지 특징이 앞서 언급한 4가지 문제를 해결하는데 도움을 줍니다. 사실 5가지인데 (계정 활성화 플래그 컬럼 불필요)이 부분은 제가 잘못 생각했더라구요. 아래 4가지 문제를 어떻게 테이블 구조 변경으로 해결했는지 설명하겠습니다.
1. 미인증된 사용자의 계정 생성 방지
2. 사용자 로그인 요청 시, 활성화 플래그를 검증 여부 생략 가능
3. 검증에 따라 활성화 플래그가 거짓일 때 해야하는 예외 처리
4. 트랜잭션 처리
(1) 미인증된 사용자의 계정 생성 방지
2안의 경우, 회원 인증 코드 객체를 먼저 생성합니다. 이후 인증 코드 값 검증을 마치고 인증 여부가 true 값이 되면 회원 객체를 생성합니다. 아래는 AuthCode 엔티티 클래스의 메서드입니다.
(2) 사용자 로그인 요청 시, 활성화 플래그를 검증 여부 생략 가능
1안의 경우, 회원 계정이 인증 여부에 따라 활성화/비활성화로 분류되었기 때문에 로그인 시 활성화 여부를 판단해야 했습니다. 하지만 2안의 경우에는 인증된 이메일으로만 계정을 생성할 수 있게 되었습니다.
정리하면 2안에 MEMBER 테이블에는 인증이 완료된 활성화 계정만 존재하여 활성화 플래그를 두지 않아도 됩니다.
(3) 검증에 따라 활성화 플래그가 거짓일 때 해야하는 예외 처리
2번 문제와 이어지게 되는 문제입니다. 1안의 경우 미인증 계정이 존재할 수 있기 때문에 미인증 계정을 가지고 로그인 요청을 보냈을 때 이와 관련된 예외 처리를 고려해야 합니다.
(4) 트랜잭션 처리
1안에서는 아래와 같이 이메일 회원가입 API를 통해 회원 가입과 인증을 위한 인증 코드 전송이 함께 진행되었습니다.
2안 회원 가입 구조 상 아래와 같이 두 기능이 자연스럽게 분리됩니다. 이에 따라 트랜잭션 처리에 대한 고민을 덜 수 있습니다.
인증 코드 생성 및 이메일 전송
회원 가입
물론 인증 코드 생성 및 인증 코드 이메일 전송은 다시 2개로 기능을 나눌 수 있습니다. 비동기 처리와 이벤트리스너를 활용하면 성능과 코드 상의 유연함을 누릴 수 있습니다.
2안의 단점
(1) 양 테이블 모두 이메일 속성을 가져야 한다.
물론 join을 활용한다면 한쪽에만 이메일 속성을 가지도록 만들 수 있지만 매번 join을 해서 이메일을 찾는 것은 비효율적이라고 판단하였습니다.
(2) 한 도메인 내부에 엔티티가 2개로 증가한다.
이는 구현해야 할 객체가 더 많아지고 서로 의존해야할 클래스가 많아짐을 의미한다. 2안으로 변경되면서
MEMBER, AUTH_CODE 두 개의 엔티티가 생겨났고 각자의 repository 클래스가 생성되어야 한다. 이에 따라 클래스간 의존성이 아주 조금이라도 더 복잡해졌다. 이것은 추후 코드를 해석하는데 더 많은 시간을 소모해야함을 의미한다.
사실 나는 회원 가입 로직에 대해 이렇게 많은 생각을 쏟은 적이 없었는데 이번 1, 2안 구현 및 포스팅 작성을 통해아주 많은 것을 배울 수 있었다.
1. 요구 사항 스펙에 대한 이해력의 중요성
스펙에 대한 이해력에 따라 누군가는 1안을 구상할 것이고 누군가는 2안을 구상할 것이다. 스펙에 대한 이해가 프로젝트 품질에 많은 영향을 미칠 수 있다는 것을 배웠다. 물론 2안 보다 더 좋은 방안도 존재할 것 같다.
2. 문서화/도식화의 중요성
물론 아닐수도 있지만 개발을 하면서 느낀 점은 대부분의 서비스는 단계적이다. 배달의 민족을 통해 음식을 주문할 때 보면
가게 선택 - 메뉴 선택 - 주문 - 결제 - 배달 - 리뷰(선택) 이런 순으로 진행된다. 그리고 각 단계마다 비즈니스 규칙이 존재할 것이다.
내가 진행하는 프로젝트는 위 사례보다는 훨씬 단순하지만 분명한 것은 단계적이라는 것이다. 나는 단계를 잘 표현할 수 있는 것이 도식화라고 생각하고 단계별로 규칙을 잘 정리하기 위해서는 문서화가 효과적이라고 생각한다.
3. 트랜잭션 처리
결과만 놓고 보면 1안은 버려지는 코드이기 때문에 삽질이다. 하지만 이 과정을 통해서 나는 트랜잭션에 대해 고민해볼 수 있어 좋은 경험이었다.