- ···
- 10.
[멀티캠퍼스] 풀스택 개발자 아카데미 (10) - SQL - 11.[멀티캠퍼스] 풀스택 개발자 아카데미 (11) - JDBC현재
- 12.
[멀티캠퍼스] 풀스택 개발자 아카데미 (12) - Algorithm(1) - ···
1. JDBC
JDBC는 Java Database Connectivity의 약자로, Java Application이 다양한 종류의 DB와 통신할 수 있도록 표준화된 방법을 제공하는 API 규격이다.
한마디로, JDBC는 Oracle DB, PostgreSQL 등 수많은 DB와 Java 사이의 통역사와 같다. Java 개발자는 어떤 DB를 사용하던지 무관하게 API가 제공하는 규격에 맞게 사용하면 된다.
JDBC 아키텍처는 크게 두 가지 계층으로 나뉜다.
- JDBC API: 개발자가 직접 사용하는 Interface와 Class 들의 집합 (
java.sql,javax.sql). 이후 내용의Connection,Statement,ResultSet등이 여기에 속하며, 개발자는 이 표준 API를 사용하여 코드를 작성한다. - JDBC Driver Manager: JDBC Driver를 관리하는 역할을 하며, Application의 요청에 맞는 적절한 드라이버를 찾아 DB와의 연결을 수립해준다. 각 DB 벤더(Oracle, MySQL, PostgreSQL 등)는 자신의 DB와 통신할 수 있는 드라이버를 구현해 제공한다.
이에 따라 우리는 Oracle용 드라이버를 OracleDB와 통신할 수 있고, PostgreSQL용 드라이버를 사용하면 PostgreSQL DB와 통신할 수 있게 된다. 코드의 변경 없이 드라이버의 변경으로 다른 DB와 통신 가능하다는 점이 JDBC의 매우 큰 장점이다.
2. Oracle JDBC 프로그래밍
멀티캠퍼스에서는 Oracle Database XE 21c를 기준으로 수업을 진행했다. Oracle XE DB를 사용하기 위해 앞서 설명했던 Oracle JDBC 드라이버를 추가해야 한다.
2.1. OJDBC (Oracle JDBC) 추가
Oracle JDBC 드라이버를 추가하는 방법은 Java 프로젝트에 따라 세 가지로 나뉜다.
2.1.1. .jar 파일 직접 다운로드 및 추가
빌드 관리 도구가 없는 바닐라 Java 프로젝트나, 특정 환경에서 중앙 저장소에 접근할 수 없는 경우, 공식 홈페이지에서 .jar 파일을 직접 다운로드하여 추가할 수 있다. 멀티캠퍼스에서는 해당 방식으로 수업을 진행했다.
- Oracle JDBC 드라이버 다운로드 페이지에 접속
- 사용하려는 JDK 버전과, DB버전을 확인하여 버전에 맞는 드라이버를 다운로드 (예:
ojdbc17.jar,ojdbc11.jar등) - 프로젝트 내에
lib폴더 등을 생성하고.jar파일을 복사 - 사용하는 IDE(IntelliJ IDE, Eclipse 등)에서 프로젝트 설정으로 이동해 추가한
.jar파일을 라이블리 또는 Classpath에 직접 추가
2.1.2. Maven 프로젝트
최근 Java는 Maven이나 Gradle과 간은 도구가 의존성, 빌드, 배포를 자동화해주기 때문에, 이와 같은 빌드 관리 도구를 사용하는 것이 일반적이다.
Maven 프로젝트의 경우, 의존성을 pom.xml에서 관리하기 때문에, 다음과 같이 내용을 추가해준다.
2.1.3. Gradle 프로젝트
Gradle의 경우 의존성은 build.gradle(Kotlin Gradle의 경우 build.gradle.kts)에서 관리한다. 다음과 같이 추가해 준다.
- Gradle
- Kotlin Gradle
2.2. 핵심 인터페이스
JDBC를 이용한 DB 프로그래밍은 일반적으로 6단계를 거치며, 핵심적인 3가지의 인터페이스를 사용한다. 프로그래밍 단계 흐름 이전에, 3가지 인터페이스는 다음과 같다.
Connection은 데이터베이스와의 연결(세션) 자체를 나타낸다. 모든 DB 작업은 작업에 앞서Connection객체를 얻는 것부터 시작한다. DB에 대한 메타데이터 조회, 트랜잭션관리 등 연결과 관려된 모든 기능을 담당하며, SQL을 실행할Statement객체 또한Connection객체로부터 생성된다. 즉, DB와의 전용 통신 회선이라고 할 수 있다.Statement: SQL 문을 실행하는 역할.Connection객체를 통해 얻어진 연결 위에서, 우리가 작성한 SQL 쿼리를 데이터베이스로 보내고 실행하는 '전달자'이다.Statement인터페이스는executeQuery()(SELECT),executeUpdate()(INSERT, UPDATE, DELETE)와 같은 메소드를 제공하여 다양한 종류의 SQL을 처리한다.ResultSet:Statement를 통해 SELECT 쿼리를 실행했을 때, **데이터베이스로부터 반환된 결과(데이터 집합)**를 담는 객체이다.ResultSet은 데이터 테이블의 형태를 하고 있으며, 내부에 커서(Cursor)를 가지고 있어next()메소드를 통해 한 행(row)씩 이동하며 데이터를 추출할 수 있다.getString(),getInt()등 데이터 타입에 맞는 메소드로 각 컬럼의 값을 가져올 수 있다.
2.3. OJDBC 프로그래밍 단계
JDBC를 이용한 DB 프로그래밍은 일반적으로 다음과 같은 흐름을 가진다.
- 데이터베이스 연결(Connection):
DriverManager.getConnection()메소드를 사용하여 URL, 사용자 이름, 비밀번호를 전달하고 데이터베이스와의Connection객체 생성 - SQL 실행을 위한 객체 생성(Statement 또는 PreparedStatement): 작성된 SQL 쿼리를 실행하기 위한
Statement또는PreparedStatement객체를Connection객체로부터 생성 - SQL 쿼리 실행:
executeQuery()또는executeUpdate()메소드를 호출하여 SQL을 실행 - 결과 처리(ResultSet): SELECT 쿼리의 경우, 반환된
ResultSet객체를 순회하며 데이터를 읽어옴 - 자원 해제: 사용이 끝난
ResultSet,Statement,Connection객체를close()메소드를 호출하여 반드시 해제 (매우 중요)
3. 개선된 JDBC 코드
위의 예제는 DBC의 기본 흐름을 보여주지만, 실제로 사용하기에는 문제가 있다. 바로 SQL Injection 공격에 취약하고, 코드가 장황하다는 점이다.
3.1. PreparedStatement
PreparedStatement 객체는 SQL 쿼리의 템플릿을 미리 만들어 컴파일해두고, 실행 시점에 필요한 값만 ? (파라미터 바인더)를 통해 전달하는 방식이다. 이를 통해 다음과 같은 이점을 얻는다.
- 보안 강화: 입력값이 SQL 문법이 아닌 순수한 데이터로 처리되어 SQL 삽입 공격을 원천적으로 방어한다.
- 성능 향상: 동일한 구조의 쿼리가 반복 실행될 경우, 미리 컴파일된 쿼리를 재사용하므로 실행 속도가 빠르다.
다음 예시를 통해 PreparedStatement 사용 방법을 확인해본다.
3.2. try-with-resource
Java 7부터 도입된 try-with-resources 구문을 사용하면 finally 블록에서 close()를 명시적으로 호출하지 않아도, try 블록이 끝날 때 자동으로 자원을 해제해 준다. 코드가 훨씬 깔끔하고 안전해진다.
이전 코드에 비해 확연히 간결해진 모습이 보인다.
4. JDBC의 고질적인 문제점과 해결 방안
순수 JDBC는 강력하지만 실제 대규모 애플리케이션에 그대로 적용하기에는 몇 가지 문제점이 있다.
- 반복적인 코드(Boilerplate Code): 드라이버 로딩, 연결, 자원 해제 등 모든 과정에 반복적인 코드가 너무 많이 필요함
- 자원 관리의 어려움: 개발자가 실수로
close()를 누락하면 **자원 누수(Resource Leak)**가 발생하여 시스템 장애로 이어질 수 있음 (try-with-resources로 어느정도 해결 가능) - 비효율적인 커넥션 관리: 매번 요청이 있을 때마다 데이터베이스 연결을 새로 맺고 끊는 것은 상당한 비용이 드는 작업임
- HikariCP, Apache DBCP2 등이 널리 사용되는 커넥션 풀 라이브러리이다.
5. 최신 Java 개발 경향과 JDBC
요즘 Java, 특히 Spring Boot를 이용한 웹 개발에서는 개발자가 직접 JDBC 코드를 작성하는 경우는 드물다. 대부분 더 추상화된 기술을 사용한다.
- Spring
JdbcTemplate: Spring 프레임워크에서 제공하는 클래스로, 커넥션 풀과의 연동, 자원 해제, 예외 처리 등 JDBC의 반복적인 작업을 내부적으로 모두 처리해 준다. 개발자는 SQL 쿼리와 결과 매핑에만 집중하면 되어 생산성이 크게 향상된다. ORM (Object-Relational Mapping): 객체-관계 매핑 기술은 한 단계 더 나아가, SQL 쿼리마저도 직접 작성하지 않고 자바 객체(Object)를 다루는 것만으로 데이터베이스 작업을 처리할 수 있게 해준다.
- JPA (Java Persistence API): Java의 ORM 표준 명세
- Hibernate: JPA의 가장 대표적인 구현체
6. 결론
지금까지 JDBC의 기본 개념부터 핵심 인터페이스의 역할, Oracle XE를 이용한 실습, 그리고 현대적인 개발 방식과의 관계까지 폭넓게 알아보았다.
- JDBC는 자바와 데이터베이스를 잇는 표준 기술이다.
- Connection, Statement, ResultSet 은 JDBC 프로그래밍의 가장 중요한 3대 구성 요소이다.
- 보안과 성능을 위해 항상 PreparedStatement를 사용해야 한다.
- try-with-resources를 통해 자원 관리를 안전하고 간결하게 할 수 있다.
- 대규모 애플리케이션에서는 커넥션 풀 사용이 필수적이다.
- Spring JdbcTemplate이나 JPA와 같은 현대적인 기술은 JDBC를 더 편리하게 - 사용하기 위해 만들어졌으며, 그 근간에는 여전히 JDBC가 있다.