본문 바로가기

프로젝트

SpringBoot로 그룹캘린더 만들기 시즌2 - 스프링 데이터 JPA를 활용

기존의 프로젝트는 순수 jpa와 QueryDSL을 사용하여 레파지토리를 구현했다.

그러다보니 간단한 CRUD도 직접 구현해야하는데..! 영한쌤의 스프링 데이터 JPA 강의를 완독한 후 아 ..! 바꿔야겠다 싶었다.

그래서 바꿨다!

 

 

UserJpaRespository.java -> 기존의 순수 jpa 를 사용한 코드
@Repository
@RequiredArgsConstructor
public class UserJpaRepository {
    private final EntityManager em;
    private final JPAQueryFactory queryFactory;

    public Optional<User> findByUserId(String userId){
        return em.createQuery("select u from User u where u.user_id = :user_id", User.class)
                .setParameter("user_id", userId)
                .getResultList()
                .stream().findAny();
    }

    public User findUserById(String id){
        return em.find(User.class, id);
    }
    public void saveUser(User user) {
        em.persist(user);
    }

    public Optional<User> findUserByCoupleCode(String coupleCode) {
        return em.createQuery("select u from User u where u.coupleCode = :coupleCode", User.class)
                .setParameter("coupleCode", coupleCode)
                .getResultList()
                .stream().findAny();
    }
}​

 

UserRepository.java -> 스프링 데이터 JPA
public interface UserRepository extends JpaRepository<User, String> {
    Optional<User> findUserByCoupleCode(String coupleCode);
}​

 

와훙... ㅋㅋㅋ 기존 코드가 사실 많은 편이 아니긴 했지만 그래도 완전 대박 간결하게 줄었다.

UserRepository 를 보면 findUserByCoupleCode 그냥 메소드명으로 쿼리를 뽑아낼 수 있다! 기존에 em.createQuery... 해서 직접 쿼리 작성하고 하던 귀찮던 (?) 작업들을 그냥 한 줄로 요약시켜버린 것이다.

 

UserService.java
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
    
    public User findUserByCoupleCode(String coupleCode) {
        return userRepository.findUserByCoupleCode(coupleCode).orElse(null);
    }
}​

서비스에서는 반환 타입이 Optional 이므로 orElse(null)로 처리해주는 방식을 택했다.

값이 없다면 그냥 null로 처리할 생각이기 때문에 ~

 

 

방식이 바뀌는 건 그렇게 어렵지는 않았고 그냥 오류가 없는지, 내가 정한 규칙과 잘 들어맞는지를 따져가며 리팩토링에 신경 써봤다.

 

 

이쯤에서 리팩토링할 부분에 대해 풀어보자면

내가 지켜야 할 원칙

1. Controller는 웹 전달만 하는 계층
    비즈니스 로직은 서비스에서 처리할 수 있도록 하자.

2. Service 에서 DTO <-> Entity 변환의 역할을 맡도록 하자.
    그렇지 않으면 LazyInitializationException 노출 위험이 커짐
    트랜잭션 안에서 하이버네이트의 명령이 이루어질 수 있도록 하자.

3. 서비스 안에서 다른 서비스 호출 가능
    캘린더에서 그룹조회를 원한다면 당연히 그룹서비스를 불러 호출
	-> 이렇게 된다면 Service에서 중복코드가 사용될 가능성도 있다.

 4. RequestDTO / ResponseDto 구분
    요청과 응답 그리고 엔티티의 경계는 확실히 해두자.

암튼 수정했고 차근차근 올리도록 하겠다.