본문 바로가기
Spring|Spring-boot

스프링 DB (1)

by oncerun 2022. 8. 15.
반응형

오랫동안 기다리던 김영한님의 스프링 DB 강의가 열렸다. 이론과 실전까지 기다려 한번에 구매했다. 

이번 강의로 내가 확실히 알고 있는 것과 두리뭉실하게 알고 있던 것을 확실히 구분하는 좋은 기회가 됐으면 한다.

다시 복습한다는 느낌으로 이론 공부를 시작해보자. 내가 공부를 헛하지 않았다면 빠르게 이해해야 한다. 

 

 

과거의 데이터베이스는 서로 많은 차이점을 가지고 있다.

만약 애플리케이션 서버가 A라는 데이터베이스와 연결할 때와 B라는 데이터베이스와 연결할 때 차이점이 존재하기 때문에 변경이 일어나면 그 영향이 애플리케이션 코드 영역까지 침범한다. 

따라서 추상화를 통해 데이터베이스 벤더사에 영향을 받지 않고 하나의 표준으로 데이터베이스를 이용하기 위해 만든 자바 API이다. 

즉 자바 진영에서는 데이터베이스를 위한 표준 인터페이스를 발표하였고 이를 실제로 구현하는 것은 데이터베이스의 벤더 사들이다. 벤더사들이 인터페이스의 구현체를 만들어 라이브러리 형태로 제공하는데 이를 JDBC 드라이버라고 한다.

 

JDBC를 통해 문제는 어느 정도 해결된 것 같지만 SQL, 데이터 타입, 전용 키워드로 인해 일부 사용법이 다르다. 

페이징 쿼리를 비교해보면 그 차이가 명확해지는데 오라클인 경우 ROWNUM을 사용하고 mariaDB, mySQL은 LIMIT, OFFSET을 통해 처리하는 걸 볼 수 있다.

이는 애플리케이션 코드의 변경은 없지만 SQL 문의 변경은 그대로 존재하고 있다는 것을 의미한다.  

 

사실 JDBC를 직접적으로 사용해보았다면 사용방법이 매우 복잡하다고 느낀다. 그래서 최근에는 JDBC를 직접 사용하는 것보다는 JDBC를 편리하게 사용하는 다양한 기술이 존재한다.

 

크게 두 가지로 SQL Mapper와 ORM 기술이 존재한다. 

SQL Mapper는 SQL문만 개발자가 작성하면 나머지 번거로운 일은 SQL Mapper가 처리해준다. 또한 진입 장벽이 그리 높지 않다. SQL문만 작성할 줄 알면 쉽게 사용할 수 있다. 예시로 스프링의 JdbcTemplate, MyBatis가 있다.

 

ORM 기술은 객체를 관계형 데이터베이스 테이블과 매핑해주는 기술로 데이터베이스 코드를 작성하다 보면 객체지향의 괴리감이 느껴질 때가 있는데, 그 부분을 해결해 주기 위한 기술이다. 보통 JPA 인터페이스에 하이버네이트 구현체를 자바 진영에선 많이 사용한다.  다만 JPA를 실제 실무에 적용하기 위해선 JPA가 어떻게 캐싱하고 어떻게 영속성을 관리하는지 등 깊은 지식이 요구된다. 즉 진입장벽이 높다. 

 

중요한 것은 이 두 기술은 JDBC를 편리하게 사용하기 위해 감싸 놓은 것이지 사용하지 않는 것은 아니다. 따라서 JDBC가 어떻게 동작하는지 기본 원리부터 깨닫고 앞의 기술로 들어가야 한다. 

 

나도 사실 이 강의를 구매한 이유도 JDBC의 깊은 이해가 된다면 관련 문제를 직면했을 때 자연스러운 디버깅 스토리텔링이 될 것 같아서 구매한 의도가 크다.

 

실제 JDBC를 활용해 데이터베이스에 연결까지만 하는 과정은 다음과 같다.

public static Connection getConnection() {
    try {
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        log.info("get connection = {}, class = {}", connection, connection.getClass());
        return connection;
    } catch (SQLException e) {
        throw new IllegalStateException(e);
    }

}

 

여기서 주목해야 하는 점은 DriverManager의 작동방식이다.

DriverManager 클래스에는 클래스 로더를 통해 JDBC 구현체들의 클래스를 찾아 등록하는 과정이 들어가 있다.

만약 여러 데이터베이스의 드라이버가 라이브러리 폴더에 존재한다면, DriverManager.getConnection의 인수로 넣어준 정보를 토대로 각각의 드라이버가 자신이 처리할 수 있는 요청인지 확인 후 커넥션을 획득하여 클라이언트에게 반환한다. 

 

그럼 JDBC를 간단히 사용해보자.

public Member save(Member member) throws SQLException {
        String sql = "insert into member(member_id, money) values (?, ?)";

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, member.getMemberId());
            pstmt.setInt(2,member.getMoney());
            int result = pstmt.executeUpdate();
            return member;
        } catch (SQLException e) {
            log.error("db error", e);
            throw e;
        } finally {
            close(conn, pstmt, null);
        }
    }

    public Member findById(String memberId) throws SQLException {
        String sql = "select * from Member where member_id = ? ";

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, memberId);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                Member member = new Member();
                member.setMemberId(rs.getString("member_id"));
                member.setMoney(rs.getInt("money"));
                return member;
            } else {
                throw new NoSuchElementException("not find member_id = " + memberId);
            }
        } catch (SQLException e) {
            log.error("db error", e);
            throw e;
        } finally {
            close(conn, pstmt, rs);
        }

    }

 

복사- 붙여넣기 수준으로 처리가 된다. 이 말은 메서드 내부에 많은 공통점이 있기 때문에 반복되는 코드가 많고 메서드의 양도 상당히 길다. 

따라서 SQL Mapper, ORM 기술들은 이를 포함하여 자신들의 목적에 따라 더 높은 추상화 기술을 선보인 것이다.

 

간단하게 JDBC의 사용법을 보았고 누군가는 처음, 누군가는 힘들었던 과거를 떠올린다. 사실 데이터베이스와 어플리케이션의 연동이라는 주제는 매우 방대하다.

그 중 기초에 대해 생각할 때 알고있으면 좋다고 생각했던 부분이 있는데 바로 커넥션풀과 데이터소스이다. 

 

다음 장은 커넥션풀이 필요한 이유와 동작원리, 데이터소스에 대해 알아보자.

 

반응형

'Spring|Spring-boot' 카테고리의 다른 글

스프링 DB (3)  (0) 2022.09.05
스프링 DB (2)  (0) 2022.08.15
파일 업로드 및 다운로드  (0) 2022.01.26
Spring-boot ExceptionResolver  (0) 2022.01.15
Spring-boot Error Page  (0) 2022.01.13

댓글