해결됨
토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
28. 회원 애플리케이션... / 이메일 중복 검사를 도메인 서비스로 수행하는 방식에 대해서
안녕하세요, 토비님.강의 유익하게 듣고 있습니다. 🔵수업:28. 회원 애플리케이션 서비스 테스트 (2) / 13:00~ : 이메일 중복 검사는 도메인모델에서 처리할 수 없음 🔵질문:이메일 중복 여부의 검사는 도메인 규칙으로 생각됩니다. 이메일 중복 여부 검사를 도메인 계층 대신 애플리케이션 계층에 두신 점에 대해 토비님의 시각이 궁금합니다.회원 도메인의 email 속성을 자연키로 삼아 유일성을 부여했고, 이는 도메인 규칙이라 생각됩니다.이메일 중복 여부 검사는 외부 액터와의 상호작용이 필요하니 말씀하신 것처럼 도메인 모델 내부에서 직접 수행할 수 없지만, PasswordEncoder처럼 도메인 서비스를 통해 검사를 수행하여 '이메일은 중복될 수 없다'는 도메인 규칙을 도메인 계층에 잡아두는 것도 아키텍처 구조 상 문제는 없을 것 같습니다. 🔵코드:수업 버전 - 애플리케이션 서비스에서 이메일 중복 검사(코드 블럭을 java 코드로 설정했고, 글 작성/수정 페이지에서는 코드 색상이 제대로 표시되는데 수정을 완료하면 흑백으로 돌아옵니다.)@Service
@RequiredArgsConstructor
public class MemberService implements MemberRegister {
private final MemberRepository memberRepository;
private final EmailSender emailSender;
private final PasswordEncoder passwordEncoder;
@Override
public Member register(Member.MemberRegisterRequest registerRequest) {
// 이메일 중복 검사
checkDuplicateEmail(registerRequest);
Member member = Member.register(registerRequest, passwordEncoder);
memberRepository.save(member);
sendWelcomeEmail(member);
return member;
}
...
} 회원 도메인 객체에서 이메일 중복 검사도메인 서비스 EmailDuplicationChecker를 추가하고 Member.register(...)에서 EmailDuplicationChecker를 이용해 이메일 중복 검사 수행domain.EmailDuplicationCheckerpackage tobyspring.splearn.domain;
/**
* 이메일 중복 검사를 수행하는 도메인 서비스
*/
public interface EmailDuplicationChecker {
boolean isDuplicated(String email);
}domain/Member@Entity
...
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
public static Member register(
MemberRegisterRequest registerRequest,
PasswordEncoder passwordEncoder,
EmailDuplicationChecker emailDuplicationChecker
) {
Member member = new Member();
// 🔻이메일 중복 검사
if (emailDuplicationChecker.isDuplicated(registerRequest.email())) {
throw new DuplicateEmailException("Duplicated email: " + registerRequest.email());
}
...
return member;
}
...
} 레포지터리와 협력하기위해 EmailDuplicationChecker 구현하는 어댑터 추가adapter.persistence.EmailDuplicationCheckerImpl@Component
@RequiredArgsConstructor
public class EmailDuplicationCheckerImpl implements EmailDuplicationChecker {
private final MemberRepository memberRepository;
@Override
public boolean isDuplicated(String email) {
return memberRepository.findByEmail(new Email(email)).isPresent();
}
} 기존 애플리케이션 서비스에 포함된 이메일 중복 검사 제거application.MemberService@Service
...
public class MemberService implements MemberRegister {
private final MemberRepository memberRepository;
private final EmailSender emailSender;
private final PasswordEncoder passwordEncoder;
private final EmailDuplicationChecker emailDuplicationChecker;
@Override
public Member register(Member.MemberRegisterRequest registerRequest) {
// 🔻이메일 중복 검사 호출 제거
Member member = Member.register(registerRequest, passwordEncoder, emailDuplicationChecker);
memberRepository.save(member);
sendWelcomeEmail(member);
return member;
}
...
} 🔵 제가 생각해본 장단점수업 버전 - 애플리케이션 서비스에서 이메일 중복 검사장점회원 등록 과정 절차에 이메일 중복 검사가 표현되어 회원 등록 과정 절차를 명시적으로 표현'중복 검사는 안하나?' 같은 의문을 방지단점-회원 도메인 객체에서 이메일 중복 검사장점이메일 중복 불가 규칙을 도메인 계층 내부에 표현하여 도메인 모델을 코드에 자세히 표현여러 지점에서 중복 검사가 필요한 경우, 반복되는 중복 검사 메서드(레포지터리 조회 후 예외 생성)를 어댑터에 위임할 수 있음단점액터와의 협력이 필요한 도메인 규칙마다 도메인서비스&어댑터가 추가되어 유지보수 포인트가 추가되고, 이를 이용하는 객체에도 의존성이 추가되어 DI해야할 파라미터가 늘어남.만약 제가 개발을 진행 한다면 도메인 규칙마다 도메인서비스&어댑터를 추가하는 비용이 크다고 생각하는 점, 도메인 계층까지 내려가지 않고도 로직의 큰 흐름을 이해할 수 있는 점에서 수업 내용대로 애플리케이션 서비스에 로직을 구현하는 방식을 사용할 것 같습니다. 그럼에도 도메인 규칙을 도메인 계층에 두는 것에 대해서 토비님이 의견이 궁금합니다. 감사합니다.