Framework/Spring

[Spring] DB 접근 방법

검은 까마귀 2024. 4. 10. 23:57

사족을 먼저 달고 하겠다.

Spring을 공부하면서 DB에 Query를 날리는 많은 방법이 있지만, 인강을 통해서 JPA를 학습하는데, "김영한 선생님" 께서 말씀하셨다시피 Query를 못짜면 JPA를 쓸 필요가 없다는 것이다. 그리고 무조건 JPA가 좋은 것도 아니다. 👏

 

취업을 준비하는 분들과 취업을 준비하는 나에게 Spring에서 DB로 쿼리를 날릴때, 어떤 점들이 좋고 어떤 것들을 선택하는게 좋은 것인지 알아볼 수 있도록 정리해보겠다.  

# JdbcTemplate

먼저, JdbcTemplate를 알기 전에, Jdbc를 알고가자.

 

Jdbc란? Java Database Connectivity의 약자로써 Java가 데이터베이스와 통신하기 위한 API이다.  Jdbc를 활용하여 DB연결, SQL 실행과 같은 기능을 수행한다.

 

JdbcTemplate는 Jdbc의 추상화 계층중 하나로 Jdbc를 보다 간편하게 사용해둘 수 있도록 템플릿화를 해둔 것이다.

장점 단점
간단하고 직관적인 사용법 파라미터화가 되어있지 않아 복잡한 쿼리 작성이 어렵다.
ORM 기능을 지원하지 않아 객체와 DB간의 맵핑처리를 해야한다.

  

@Autowired
private JdbcTemplate jdbcTemplate;

public void getData() {
    String sql = "SELECT * FROM table_name";
    List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
    for (Map<String, Object> row : rows) {
        // 처리 로직
    }
}

# NamedParameterJdbcTemplate

JdbcTemplate에서 파라미터화를 지원했다. 그렇기 때문에 유연하게 DB에 접근할 수 있다. 가독성이 좋아진다고 볼 수 있다.

장점 단점
파라미터화 된 쿼리로 유연하게 쿼리를 작성할 수 있다.
가독성 상승
ORM 기능을 지원하지 않아 객체와 DB간의 맵핑처리를 해야한다.
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void getData(int id) {
    String sql = "SELECT * FROM table_name WHERE id = :id";
    Map<String, Object> params = new HashMap<>();
    params.put("id", id);
    List<Map<String, Object>> rows = namedParameterJdbcTemplate.queryForList(sql, params);
    for (Map<String, Object> row : rows) {
        // 처리 로직
    }
}

# Spring Data JPA

JPA는 사실상 혁신이긴 하다. DB와 객체는 서로 대척점에 서 있지만 이를 자동으로 맵핑해준다는 것이다. 또한 기본적인 ORM에 CRUD를 제공한다.

장점 단점
객체와 데이터베이스간 매핑을 자동처리
객체지향적인 개발 가능
복잡한 쿼리 작성이 어렵다 ➡️ Querydsl로 극복한다고 하지만, 현재 오픈소스에서 업데이트를 진행하지 않는다.
러닝커브가 높다 ➡️ JPA를 이해하지 못하면 안쓰느니만 못하다.
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByLastName(String lastName);
}

# MyBatis

다른 API이런것과는 다르게 SQL 매핑 프레임워크이다. SQL쿼리와 Java 쿼리를 분리한다.(장점인지, 단점인지는 때에 따라 다르겠다)

장점 단점
복잡한 쿼리 작성이 용이하다. 뭐 작성해야될 코드가 많다. 맵핑코드, 어노테이션 설정 등등
객체와 DB를 직접처리해야한다.
@Mapper
public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(@Param("id") int id);
}

위에 4가지로 DB에 접근하는 방법을 모두 사용해보았다. 

Jdbc➡️MyBatis 마이그레이션

MyBatis ➡️JPA, Querydsl 마이그레이션 도 해보았다.

 

사실 나는 개인적으로 DB에서 복잡한 쿼리를 던지지 않는다. 그 이유는 내가 사용했던 DBMS들이 대게 오픈소스였고, 상용제품이 아니기 때문이다. 그래서 대게 간단하게 가져오고 어플리케이션 단에서 처리를 한다.(Oracle DB유저들은 다르긴하더라)

 

그래서 JPA를 사용했을때 장점은 객체를 자동으로 맵핑해준다는 것인데 이를 복잡하게 Querydsl을 활용해서 할 것까지는 없다. 그렇다면 성능이슈에 빠지고 코드가 뭔가 기분나쁘게 지저분했다. 적당히 라는 말보다는 잘 활용해야한다.

 

Mybatis를 사용했을때는 Jdbc의 코드를 분리해서 쿼리가 문제가 생겼을때 맵퍼를 통해 바로 사용할 수 있었지만, 문제는 코드의 중복이 많이 발생한다는 것이다. 또한 Mapper 생성도 해줄때마다 넣어야한다. 이게 익숙하지 않으면 까먹고 안해서 애러를 일으키는데 에러 메시지도 그닥 친절한 프레임워크가 아니다.

 

그래서 결론적으로 하고싶은 말은, "JPA 조와요~, Querydsl 조와요"가 아니라는 것이다. Querydsl은 이미 오픈소스인데 몇년동안 commit이 이루어지지 않았다. 다 적확한 방식으로 사용해야한다. 필요하면 JPA, Mybatis, Jdbc템플릿 세개 다 써야지 뭐....! 

반응형