본문 바로가기
Spring

Spring Day 26 : 코드 리팩토링 (팔로우 기능)

by 우 석 2024. 3. 4.

지난 블로그의 팔로우 기능 구현 코드에서 리팩토링 할 부분을 발견했다.

바로 followService의 user 검증 부분이다.

FollowService

 @Transactional
    public void createFollow(User fromUser, Long toUserId) {
        authService.findUser(toUserId);  --> 수정할 부분
        Follow follow = Follow.builder()
                .fromUserId(fromUser.getId())
                .toUserId(toUserId)
                .build();
        followRepository.save(follow);
    }

authService

public User findUser(Long userId) {
        return userRepository.findById(userId).orElseThrow(
                () -> new InvalidInputException("해당 User는 존재하지 않습니다.")
        );

 

코드를 읽어보면 authService.findUser(toUserId); 는 사용이 되지 않고 있다고 보일 수 있다. 하지만 이 코드의 내부 로직은 아래와 같은 형식으로,  userId를 받아 DB에서 해당 유저가 존재하는지 찾고, 존재한다면 입력받은 userId로 follow 객체를 생성한다. 즉, authService.findUser(toUserId); 한 줄로 유저가 존재하지 않으면 exception을 던지고,  존재한다면 다음 로직을 이어나간다.

 

 

followService에서 authService를 주입받아 사용한 이유는 도메인을 나누었기 때문이다. followService는 followRepository만 주입을 받아야 하지, user의 정보를 찾기 위해 userRepository를 주입받으면 도메인을 나눈 이유가 없다.

따라서 authService.findUser(toUserId); 를 사용했지만 문제가 발생한다.

 

 

authService.findUser(toUserId); 의 반환값은 User이다.

followService에서 User 객체를 사용하지 않기 위해 authService에 public으로 선언한 메서드를 만들어 주입받아 사용했다. 하지만 결국 반환값이 User인 객체를 사용하고 있다. 좀전에 언급했듯, 도메인을 나눈 이유가 사라진다.

 

해결방법 1.

1) authService의 findUser 메서드의 반환값을 void로 선언하여 User 객체를 반환하지 않는다.

2) findUser라는 모호한 메서드명 대신, user의 존재를 검증한다는 의미에서 checkUser 메서드명을 사용한다.

// FollowService    
@Transactional
   public void createFollow(User fromUser, Long toUserId) {
       authService.checkUser(toUserId);  --> 수정 완료
     ...
   }

// AuthService
public void checkUser(Long userId) {
        userRepository.findById(userId)
            .orElseThrow(() -> new InvalidInputException("해당 User는 존재하지 않습니다."));
    }

 

방법 2.

validator 서비스를 생성하여, user의 검증 로직만을 담은 클래스 생성한다.

이렇게 되면, UserValidator.checkUser 라는 함수의 이름으로, 메서드의 명과 클래스의 명만으로도 동작을 이해할 수 있다.

 

현재 UserValidator 클래스에 checkUser 메서드 하나만 가지고 있지만, validatePassword, validateNewPassword 등 검증 메서드를 모아서 관리하는 데 사용할 수 있다.

@Service //(= @Component) 같은 동작
public class UserValidator {

    private UserRepository userRepository;

    public void checkUser(Long userId) {
        userRepository.findById(userId)
            .orElseThrow(() -> new InvalidInputException("해당 User는 존재하지 않습니다."));
    }
}