본문 바로가기
카테고리 없음

[Spring] DAO (MyBatis) vs Repository (JPA)

by wook99 2024. 11. 6.

이전에 진행했던 spring 프로젝트 중에, DAO - MyBatis 프로젝트 하나 있다.

요즘 학습하면서 JPA를 많이 사용하는데, DAO랑 분명히 비슷한 효과를 내는 것을 느꼈다.

구글링을 하는데 가려운 부분을 제대로 긁지 못한 것 같아서,
블로그 포스팅들과 AI를 참고하여 한번 포스팅 해봐야겠다.

 

DAO vs Repository

Spring 에서 DAO와 Repository는 데이터 접근을 담당한다. 하지만 사용하는 방식에는 약간의 차이점이 있다.

일단 이 둘의 개념부터 알아보자.

 


개념

DAO

  • 역할 : 데이터베이스 접근 로직을 캡슐화하고, CRUD와 같은 데이터 작업을 수행하는 인터페이스를 제공한다.
  • 사용방식 : 보통 JDBC 코드와 함께 사용되며, 명시적인 SQL 쿼리를 사용하는 경우가 많다.
    Mybatis와 사용하기도 한다. 
  • 구현 방식 : 보통 @Repository 어노테이션을 붙여 Spring Bean으로 관리할 수 있도록 만든다.
  • 장점 : 데이터 접근 로직을 분리함으로써 비즈니스 로직과 분리되어 재사용 및 유지보수가 용이하다.

Repository

  • 역할 : JPA에서는 Repository 인터페이스를 통해 데이터 접근 계층을 더 높은 수준의 추상화로 제공한다. JpaRepository, CrudRepository와 같은 기본 인터페이스를 상속하면서 CRUD 메서드를 자동으로 제공한다.
  • 사용방식 : Repository는 보통 JPA, Hibernate와 같은 ORM 툴과 함께 사용하며, SQL을 직접 작성할 필요가 없다.
  • 구현 방식 : @Repository 어노테이션을 사용할 필요 없이 인터페이스를 상속받기만 하면 Spring이 자동으로 구현체를 만들어 준다.
  • 장점 : ORM 프레임워크와 결합하여 객체 지향적인 방식으로 데이터베이스를 처리할 수 있고, 코드 작성이 간결해진다.

 

이제 DAO와 Repository는 데이터베이스 접근을 가능하게 해준다(Data Access Layer)는 공통점이 있다는 점을 알게 되었다.

그렇다면 언제? 어떤걸? 어떻게 사용해야하나?

일단 코드 예시를 먼저 보면서 차이점을 알아보자.


DAO - MyBatis

  • UserDAO
public interface UserDAO {
    void insertUser(User user);
    User selectUserById(Long id);
    List<User> selectAllUsers();
}
  • UserDAOImpl
@Repository
public class UserDAOImpl implements UserDAO {

    @Autowired
    private SqlSession sqlSession;

    private static final String NAMESPACE = "com.example.dao.UserDAO.";

    @Override
    public void insertUser(User user) {
        sqlSession.insert(NAMESPACE + "insertUser", user);
    }

    @Override
    public User selectUserById(Long id) {
        return sqlSession.selectOne(NAMESPACE + "selectUserById", id);
    }

    @Override
    public List<User> selectAllUsers() {
        return sqlSession.selectList(NAMESPACE + "selectAllUsers");
    }
}
  • UserMapper.xml
<mapper namespace="com.example.dao.UserDAO">
    <insert id="insertUser">
        INSERT INTO users (name, email) VALUES (#{name}, #{email})
    </insert>

    <select id="selectUserById" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>

    <select id="selectAllUsers" resultType="com.example.model.User">
        SELECT * FROM users
    </select>
</mapper>
  • UserService
@Service
public class UserService {
    
    @Autowired
    private UserDAO userDAO;

    public void saveUser(User user) {
        userDAO.insertUser(user);
    }

    public User getUserById(Long id) {
        return userDAO.selectUserById(id);
    }

    public List<User> getAllUsers() {
        return userDAO.selectAllUsers();
    }
}

 

MyBatis와 함께 사용할 때는 DAO 인터페이스를 직접 구현하는 대신, MyBatis가 자동으로 구현체를 생성하도록 설정하는 것이 일반적이긴 하다. 위와 같이 Impl이라는 구현 클래스를 직접 작성하고자 한다면, SqlSession을 이용하여 작성할 수 있다. 위의 코드들이 DAO를 작성하여 MyBatis와 상호작용하는 방법의 예이다.

 


Repository - JPA

  • UserRepository
// UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
    // 기본적인 CRUD 메서드는 JpaRepository에 의해 자동으로 제공됩니다.
    // 필요 시 커스텀 쿼리 메서드도 작성 가능
    List<User> findByEmail(String email);
}
  • UserService
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void saveUser(User user) {
        userRepository.save(user); // 기본 제공되는 save 메서드 사용
    }

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null); // 기본 제공되는 findById 메서드 사용
    }

    public List<User> getUsersByEmail(String email) {
        return userRepository.findByEmail(email); // 커스텀 메서드
    }
}

 

JPA는 JpaRepository를 상속받아 UserRepository의 구현체를 자동으로 생성한다. 따로 SQL을 작성할 필요 없이, 메서드 이름을 통해 쿼리를 생성할 수도 있다.

 


차이점

그렇다면 어떤 차이점이 있을까?

  • DAO : SQL을 직접 작성해 데이터베이스에 접근
  • Repository : Spring Data JPA의 추상화된 메서드를 사용해 SQL 없이 데이터 접근 가능

이정도가 있겠다.

이제 DAO와 Repository는 데이터베이스 접근을 가능하게 해준다는 공통점과,
SQL 직접 작성의 유무의 차이가 있다는 것을 알았다. 기본적인 사용법은 알게 된 것이다.

 

그렇다면 언제 사용해야 할까?

 


선택기준

기준 DAO - MyBatis Repository - JPA
쿼리 제어 SQL 직접 제어가 필요할 때 적합 JPA 추상화를 통한 데이터 조작
개발 속도 명시적 SQL 작성 필요, 유지보수성 낮음 CRUD 자동화로 속도 및 유지보수성 높음
성능 최적화 대량 데이터 처리와 튜닝에 적합 기본 캐싱 제공, 복잡 쿼리엔 부적합
이식성 특정 DB에 종속적 DB 변경에 강한 이식성
적합한 프로젝트 복잡한 쿼리가 많은 기업용, ERP 시스템 CRUD 중심의 애플리케이션, 객체 모델링 중심

 

복잡한 쿼리와 성능 최적화가 필요하면 DAO-MyBatis를,
객체 중심 설계와 유지보수성이 중요하다면 Repository-JPA를 선택하는 것이 일반적이다.

 

만약 JPA를 사용할 때에 복잡한 쿼리를 다루고 싶다면, JPQL, QueryDSL 라는 개념들이 있다고 한다.

나는 JPA를 자주 사용하고, 공부하고 있으므로 이 부분도 학습해서 추후에 꼭 포스팅 해야겠다.