Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 42 additions & 16 deletions study/src/test/java/connectionpool/stage0/Stage0Test.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package connectionpool.stage0;

import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;
import java.util.Properties;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.Test;

class Stage0Test {

private static final String H2_URL = "jdbc:h2:./test";
private static final String USER = "sa";
private static final String PASSWORD = "";
private static final String DB_PROPERTIES = "db.properties";
private static final String PROPERTY_DB_URL = "db.url";
private static final String PROPERTY_DB_USER = "db.user";
private static final String PROPERTY_DB_PASSWORD = "db.password";

/**
* DriverManager
Expand All @@ -27,10 +29,16 @@ class Stage0Test {
* https://docs.oracle.com/javadb/10.8.3.0/ref/rrefjdbc4_0summary.html
*/
@Test
void driverManager() throws SQLException {
void driverManager() throws Exception {
// Class.forName("org.h2.Driver"); // JDBC 4.0 부터 생략 가능
// DriverManager 클래스를 활용하여 static 변수의 정보를 활용하여 h2 db에 연결한다.
try (final Connection connection = DriverManager.getConnection(H2_URL, USER, PASSWORD)) {
final Properties props = loadProps();

final String url = props.getProperty(PROPERTY_DB_URL);
final String user = props.getProperty(PROPERTY_DB_USER);
final String password = props.getProperty(PROPERTY_DB_PASSWORD);

try (final Connection connection = DriverManager.getConnection(url, user, password)) {
assertThat(connection.isValid(1)).isTrue();
}
}
Expand All @@ -42,21 +50,39 @@ void driverManager() throws SQLException {
* 테스트 코드의 JdbcDataSource 클래스는 h2에서 제공하는 클래스다.
*
* DriverManager가 아닌 DataSource를 사용하는 이유
* - 애플리케이션 코드를 직접 수정하지 않고 properties로 디비 연결을 변경할 수 있다.
* - DataSource는 인터페이스이기 때문에 H2, MySQL, PostgreSQL 같은 DB 벤더별 DataSource,
* 혹은 HikariCP/DBCP2 같은 커넥션 풀 구현체를 코드 수정 없이 교체할 수 있다.
* - 커넥션 풀링(Connection pooling) 또는 분산 트랜잭션은 DataSource를 통해서 사용 가능하다.
*
* Using a DataSource Object to Make a Connection
* https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/package-summary.html
*/
@Test
void dataSource() throws SQLException {
final JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(H2_URL);
dataSource.setUser(USER);
dataSource.setPassword(PASSWORD);
void dataSource() throws Exception {
final Properties props = loadProps();

// 구현체 설정(H2)
final JdbcDataSource jdbcDataSource = new JdbcDataSource();
final String url = props.getProperty(PROPERTY_DB_URL);
jdbcDataSource.setURL(url);
final String user = props.getProperty(PROPERTY_DB_USER);
jdbcDataSource.setUser(user);
final String password = props.getProperty(PROPERTY_DB_PASSWORD);
jdbcDataSource.setPassword(password);

// 사용부는 인터페이스만 의존
final DataSource dataSource = jdbcDataSource;

try (final var connection = dataSource.getConnection()) {
assertThat(connection.isValid(1)).isTrue();
}
}

private Properties loadProps() throws Exception {
final Properties props = new Properties();
try (final InputStream in = getClass().getClassLoader().getResourceAsStream(DB_PROPERTIES)) {
props.load(in);
}
return props;
}
Comment on lines +81 to +87
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

리소스 로딩 시 null 체크가 누락되었습니다.

getResourceAsStream()은 리소스를 찾지 못하면 null을 반환합니다. 83번 라인에서 null 체크 없이 84번 라인에서 props.load(in)을 호출하면 NullPointerException이 발생합니다.

🚨 문제 상황:

  • db.properties 파일이 없거나 경로가 잘못된 경우
  • NPE가 발생하여 실제 원인(파일 없음)을 파악하기 어려움

💡 개선 방향:
만약 in이 null이라면 어떻게 처리하는 것이 좋을까요?

  1. 명확한 예외 메시지를 던지는 방법
  2. 파일 존재 여부를 먼저 검증하는 방법

학습 테스트에서 의미 있는 실패 메시지를 제공하는 것도 중요한 부분입니다. 어떤 방식으로 개선할 수 있을지 고민해보세요.

🤖 Prompt for AI Agents
In study/src/test/java/connectionpool/stage0/Stage0Test.java around lines 81 to
87, the InputStream returned by getResourceAsStream(DB_PROPERTIES) is not
null-checked before calling props.load(in), which will throw a
NullPointerException if the resource is missing; update the method to check if
in is null and, when it is, throw a clear Exception (or AssertionError) with a
descriptive message like "db.properties not found on classpath: <DB_PROPERTIES>"
(or fail the test) so failures indicate missing file rather than NPE, and keep
the try-with-resources for non-null streams.

}
3 changes: 3 additions & 0 deletions study/src/test/resources/db.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
db.url=jdbc:h2:mem:testdb
db.user=sa
db.password=