[JDBC] JDBC 이해

dondonee·2023년 12월 7일
1
post-thumbnail

JDBC 이해

JDBC(Java Database Connectivity)는 애플리케이션과 데이터베이스 연결 동작을 표준화한 자바 API 인터페이스이다. 개발자들은 수많은 데이터베이스의 사용법을 따로 공부할 필요 없이 JDBC 기술 하나만 익히면 자바 애플리케이션에 어떤 데이터베이스든 연결하여 사용할 수 있게 되었다.

요즘에는 순수 JDBC를 사용하는 일은 드물고 MyBatis 등의 SQL Mapper를 통해 편리하게 사용한다. 심지어 최근에 점유율이 높아지고 있는 JPA 등의 ORM 기술을 사용하면 개발자는 쿼리조차 작성할 필요가 없다.

그러나 SQL Mapper든 ORM이든 그 기반에는 JDBC를 통해 동작하고 있기 때문에 JDBC에 대한 이해는 필수이다.


JDBC란?


JDBC 이전

대부분의 애플리케이션은 중요한 정보를 데이터베이스에 저장한다. 일반적으로 서버는 세 단계를 거쳐 DB에 데이터를 저장한다.

  1. 커넥션 확보 : TCP/IP를 이용해 서버와 DB를 연결한다.
  2. SQL 쿼리 전달 : 서버는 커넥션을 통해 쿼리를 DB에 전달한다.
  3. 결과 응답 : DB는 쿼리를 수행하고 그 결과를 서버에게 응답한다.

초기에는 DB마다 이 세가지 단계를 수행하는 방법이 달랐기 때문에 개발에 어려움이 많았다. 자바는 이 사용법을 표준화하였고, 이것이 JDBC(Java DataBase Connectivity)이다.


JDBC의 탄생

JDBC는 대표적으로 다음 세 가지 기능을 인터페이스로 제공한다 :

  • java.sql.Connection - 연결
  • java.sql.Statement - SQL을 담은 내용
  • java.sql.ResultSet - SQL 요청 응답

인터페이스는 틀만 정해져 있을 뿐 세부 동작까지 자세히 정해져있지는 않다. 따라서 각 DB 벤더(제조사)마다 자신의 DB에 맞게 JDBC 인터페이스를 구현한 JDBC 드라이버를 제공한다. 개발자는 DB마다 다른 사용법을 익힐 필요없이 적절한 드라이버만 설치하면 된다.

한계점

JDBC의 등장으로 데이터베이스 연결이 편리해졌지만 여전히 한계는 존재한다. DB마다 SQL 문법이 다르기 때문이다. 개발 도중 다른 DB로 변경하고 싶다면 애플리케이션 코드는 변경하지 않아도 되지만 쿼리는 변경해야 한다.

  • ANSI SQL이라는 표준이 있기는 하지만 일반적인 일부 기능에 대해서만 표준화되었고, 대부분의 기능은 벤더마다 사용법이 다르다.
  • ORM 기술을 사용하면 개발자가 직접 쿼리를 작성하는 것이 아니라 ORM이 자동으로 쿼리를 생성해준다. 따라서 DB를 변경해도 쿼리를 변경할 필요가 없다.

JDBC와 현재

JDBC는 1997년에 출시된 오래된 기술이다. 사용법이 복잡하기 때문에 최근에는 JDBC를 직접 사용하기 보다는 SQL Mapper, ORM 등을 통해 보다 편리하게 사용하고 있다. 하지만 어떤 기술을 사용하든 그 기반에는 JDBC로 동작한다는 것을 기억하자.

  • SQL Mapper :
    • 응답 결과를 객체로 편리하게 변환해주고 중복 코드를 줄여준다.
    • 대표 기술: JdbcTemplate, MyBatis
  • ORM(Object–relational mapping) :
    • 객체를 관계형 데이터베이스 테이블과 매핑해주는 기술이다. ORM 기술이 개발자 대신에 SQL을 동적으로 만들어 실행해주기 때문에 개발자는 직접 쿼리를 작성할 필요가 없다. 추가로 각각의 데이터베이스마다 다른 SQL을 사용하는 문제도 중간에서 해결해준다.
    • 대표 기술: JPA Hibernate


JDBC 사용법


일반적으로 JDBC를 통한 SQL 쿼리 실행은 다음 다섯 단계로 이루어진다 :

  1. Conncection 생성 (DB 연결 확보)
  2. Statement 생성 (쿼리문 준비)
  3. Statement 실행 (쿼리 실행)
  4. ResultSet 처리 (결과 처리)
  5. Conncection 종료 (DB 연결 종료)

(1) Conncection 생성

Connection 객체를 생성하여 데이터베이스와의 연결을 확보한다.

JDBC가 제공하는 DriverManager는 DB 드라이버를 관리하고 커넥션을 획득하는 기능을 제공한다. 라이브러리에 등록된 드라이버 목록을 자동으로 인식해서 자신이 전달받은 DB URL 정보에 해당하는 DB를 찾아 연결해준다.

  • DriverManager.getConnection(url, user, password)
  • DriverManager를 직접 사용하는 것보다 DataSource 클래스를 사용하여 커넥션 확보를 추상화 하는 것이 더 좋다.

(2) Statement 생성

SQL statement에 대응하는 객체인 statement 객체를 생성한다. connection 객체로부터 생성할 수 있다. 문자열로 된 쿼리(sql)를 인자로 전달한다.

  • stmt = con.createStatement(sql)

(3) Statement 실행

쿼리를 실행하기 위해서는 Statement의 실행 메서드를 목적에 맞게 호출하면 된다 :

  1. execute() :
    • 반환 타입: boolean
    • 모든 쿼리에서 사용 가능
  2. executeQuery() :
    • 반환 타입: ResultSet
    • 조회(SELECT) 쿼리에 사용. ResultSet 객체는 여러 row 값을 저장할 수 있다.
  3. executeUpdate() :
    • 반환 타입: int
    • 조회를 제외한 다른 쿼리에서 사용 가능
    • INSERT, UPDATE, DELETE의 경우 쿼리 실행으로 영향을 받은 row의 수를 반환한다. CREATE, DROP에서는 -1을 반환한다.

(4) ResultSet 처리

ResultSet에 값을 가져왔다면 next() 메서드를 이용해 결과 값을 차례대로 가져올 수 있다.

ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
 String name = rs.getString("NAME");
 ...
}

ResultSet 객체는 여러 개의 결과 row 값을 저장할 수 있으며, 내부에 커서가 존재한다. next() 메서드를 이용해 커서를 한 단계씩 이동할 수 있다. 커서는 최초에 가장 앞부분을 가리키고 있으므로 처음 next()를 실행하면 첫 번째 값을 가리키게 된다.

next() 메서드는 값이 있는 경우 true를 반환한다. 값을 가져오고 싶다면 데이터 타입에 맞게 getXXX() 메서드를 사용하면 된다.

  • 담긴 값이 여러 개인 경우 위와 같이 while을, 담긴 값이 분명하게 한 개라면 if (rs.next())를 사용할 수 있다.

(5) Connection 종료

쿼리를 실행하고 나면 커넥션을 종료해야 한다. 리소스 정리는 예외가 발생하든 하지 않든 상관 없이 반드시 해주어야 한다. 만료된 커넥션이 닫히지 않고 남아있는 것을 리소스 누수라고 하며, 커넥션 부족 장애로 이어질 수 있다.

리소스를 정리할 때는 얻을 때와 반대 순서로 정리해야 한다. Statemente부터 닫고 마지막으로 Connection을 닫는다(close() 메서드 사용).




🔗 References

0개의 댓글