💻문제점
MemberService, PostService, CommentService, LikeService 클래스마다 클래스 내부에서 사용하는 유효성 검사 메서드가 존재한다. 각 클래스에서 사용하는 유효성 검사 메서드는 다음과 같다.
MemberService 클래스
// ==== 유효성 검사 ====
private void tokenNullCheck(String token) {
if (token == null) {
throw new NullPointerException(ExceptionMessage.HAS_NO_TOKEN.getMessage());
}
}
private void tokenValidateCheck(String token) {
if (!jwtUtil.validateToken(token)) {
throw new IllegalArgumentException(ExceptionMessage.EXPIRED_TOKEN.getMessage());
}
}
private Member findMemberByToken(String token) {
String userInfo = jwtUtil.getUserInfoFromToken(token);
return memberRepository.findByEmail(userInfo).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.EXPIRED_TOKEN.getMessage())
);
}
private void validateMemberByEmail(String email) {
memberRepository.findByEmail(email).ifPresent(member -> {
throw new IllegalArgumentException(ExceptionMessage.DUPLICATED_MEMBER.getMessage());
});
}
private void validateMemberByNickname(String nickname) {
memberRepository.findByNickname(nickname).ifPresent(member -> {
throw new IllegalArgumentException(ExceptionMessage.DUPLICATED_NICKNAME.getMessage());
});
}
private Member validateMember(String email) {
return memberRepository.findByEmail(email).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_MEMBER.getMessage())
);
}
private void validatePassword(String password, Member member) {
if (!passwordEncoder.matches(password, member.getPassword())) {
throw new IllegalArgumentException(ExceptionMessage.NO_MATCH_PASSWORD.getMessage());
}
}
PostService 클래스
// ==== 유효성 검증 ====
private void validatePostAuthor(Member member, Post post) {
if (!member.getNickname().equals(post.getNickname())) {
throw new IllegalArgumentException(ExceptionMessage.NO_AUTHORIZATION.getMessage());
}
}
private Post ValidateExistPost(Long id) {
return postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_POST.getMessage())
);
}
CommentService 클래스
// ==== 유효성 검증 ====
private void validateCommentAuthor(Member member, Comment comment) {
if (!member.getId().equals(comment.getMember().getId())) {
throw new IllegalArgumentException(ExceptionMessage.NO_AUTHORIZATION.getMessage());
}
}
private Post ValidateExistPost(Long id) {
return postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_POST.getMessage())
);
}
private Comment ValidateExistComment(Long id) {
return commentRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_COMMENT.getMessage())
);
}
LikeService 클래스
// 게시글 여부확인
private Post validatePost(Long id) {
return postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_POST.getMessage())
);
}
메서드들을 보면, CommentService에서 PostService에 있는 유효성 검사 메서드와 같은 로직을 또 다시 사용한다. LikeService에서도 게시글 존재 여부에 대한 유효성 검사 메서드를 만들어 사용한다.
이런 식으로 중복되는 유효성 검사 메서드들을 효율적으로 처리할 수 있는 방법을 고민했다.
📃시도
MemberValidator, PostValidator와 같은 공통 모듈 클래스를 만들어서 해당 클래스 안에 유효성 검사 메서드를 작성하고, 전역적으로 사용하고자 하였다. 싱글톤 패턴을 적용하여 작성하려 했으나, 각 메서드 안에 있는 MemberRepository나 PostRepository가 필요했다. 단순한 java 클래스이기 때문에 @Autowired는 당연히 동작하지 않는다.
🔍해결
클래스에 @Component 애노테이션을 사용하여 빈 객체로 관리하도록 했다. 빈 객체는 기본적으로 싱글톤으로 생성되고 관리되기 때문에 의존성 주입을 통해 어디서든 사용할 수 있었고, 빈 객체이기 때문에 MemberRepository 와 같은 클래스를 @Autowired나 lombok의 @RequiredArgsConstructor를 통해 주입 받을 수 있었다.
이로써 CommentService나 PostService에서 게시글 존재 여부를 검사한다고 해도, 공통적으로 PostValidator의 검증 메서드를 사용할 수 있다.
MemberValidator 클래스
@Component
@RequiredArgsConstructor
public class MemberValidator {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
public void validateMemberByEmail(String email) {
memberRepository.findByEmail(email).ifPresent(member -> {
throw new IllegalArgumentException(ExceptionMessage.DUPLICATED_MEMBER.getMessage());
});
}
public void validateMemberByNickname(String nickname) {
memberRepository.findByNickname(nickname).ifPresent(member -> {
throw new IllegalArgumentException(ExceptionMessage.DUPLICATED_NICKNAME.getMessage());
});
}
public Member validateMember(String email) {
return memberRepository.findByEmail(email).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_MEMBER.getMessage())
);
}
public void validatePassword(String password, Member member) {
if (!passwordEncoder.matches(password, member.getPassword())) {
throw new IllegalArgumentException(ExceptionMessage.NO_MATCH_PASSWORD.getMessage());
}
}
}
TokenValidator 클래스
@Component
@RequiredArgsConstructor
public class TokenValidator {
private final JwtUtil jwtUtil;
private final MemberRepository memberRepository;
public void tokenNullCheck(String token) {
if (token == null) {
throw new NullPointerException(ExceptionMessage.HAS_NO_TOKEN.getMessage());
}
}
public void tokenValidateCheck(String token) {
if (!jwtUtil.validateToken(token)) {
throw new IllegalArgumentException(ExceptionMessage.EXPIRED_TOKEN.getMessage());
}
}
public Member findMemberByToken(String token) {
String userInfo = jwtUtil.getUserInfoFromToken(token);
return memberRepository.findByEmail(userInfo).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.EXPIRED_TOKEN.getMessage())
);
}
}
PostValidator 클래스
@Component
@RequiredArgsConstructor
public class PostValidator {
private final PostRepository postRepository;
public void validatePostAuthor(Member member, Post post) {
if (!member.getNickname().equals(post.getNickname())) {
throw new IllegalArgumentException(ExceptionMessage.NO_AUTHORIZATION.getMessage());
}
}
public Post validateExistPost(Long id) {
return postRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_POST.getMessage())
);
}
}
CommentValidator 클래스
@Component
@RequiredArgsConstructor
public class CommentValidator {
private final CommentRepository commentRepository;
public void validateCommentAuthor(Member member, Comment comment) {
if (!member.getId().equals(comment.getMember().getId())) {
throw new IllegalArgumentException(ExceptionMessage.NO_AUTHORIZATION.getMessage());
}
}
public Comment validateExistComment(Long id) {
return commentRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException(ExceptionMessage.NO_EXIST_COMMENT.getMessage())
);
}
}
'TIL' 카테고리의 다른 글
[TIL - 20230515] @ReqeustParam enum 타입 받기 (0) | 2023.05.15 |
---|---|
[TIL - 20230513] 게시글 수정(썸네일 변경 포함)을 위한 MutipartFile과 Dto 함께 받기 (0) | 2023.05.14 |
[TIL - 20230506] 회원/비회원 전체 게시글 조회 처리 (0) | 2023.05.06 |
[TIL - 202030504] WebSocket+Stomp 채팅방에 직접 참여하지 않은 사용자 구독시키기2 + 자잘한 문제점 해결 (0) | 2023.05.04 |
[TIL - 20230503] WebSocket+Stomp 채팅방에 직접 참여하지 않은 사용자 구독시키기1 (0) | 2023.05.04 |