Back-End/JavaSpring

JDBC가 등장한 이유와 JPA로 넘어간 이유

stars_one 2025. 3. 20. 13:15

 

JDBC는 자바 개발자로서 한번 쯤은 들어봤을 단어이다

 

우리는 JDBC의 중요함을 알아야 한다.

우리에게 아주 큰 편의를 제공해주고 있기 때문이다!

 

 

 

서버 개발자로서,

JDBC는 무엇이고, 왜 필요한지, 어디에 사용되고 있는지 알고가자!

JPA가 등장한 이유도 알면 좋겟져?

 


 

JDBC 등장 이유

 

우리는 DB에 접근해서 데이터를 달라는 요청을 보통 아래 그림과 같은 방식으로 한다.

 

 

이런 과정들이 성공적으로 이루어져야, DB로 부터 우리가 원하는 데이터를 받을 수 있다.

(모두 경험해봤겠지만, DB를 수작업으로 연결하는건 어려울 걸..?)

 

 

그런데 만약, MySQL로 개발을 잘 하고 있다가,

갑자기 개발팀장이 "우리 팀은 MySQL에서 postgreSQL로 마이그레이션 하겠습니다" 라고 한다면 어떤 기분이 들까?

 

바로 전쟁 시작이다.

 

왜냐하면,

 

 

MySQL과 PostgreSQL은

커넥션을 연결하는 방법, SQL을 전달하는 방법, 결과를 응답받는 방법 모두 다를 수 있기 때문에,

지금까지 했던 과정들을 처음부터 다시해줘야 하기때문이다.

그래서 WAS에서 작성했던 DB 연결 로직들을 전부 수정해야한다.

 

 

이러한 문제들을 해결하기 위해서 JDBC 표준 인터페이스가 등장한 것이다!

 


 

JDBC

 

JDBC는 Java Database Connectivity로 DB에 접근할 수 있도록 Java에서 제공하는 API 이다.

 

 

 

 

내가 원하는 DB의 JDBC 드라이버를 JDBC 표준 인터페이스에 연결하면,

DB 연결 로직을 변경할 필요없이 손쉽게 DB 변경이 가능하다.

 

그래서 각 DB회사들(MySQL, postgreSQL 등등..)은

자신들의 DB에 맞게 JDBC인터페이스를 구현해서 라이브러리로 제공하는데,

이를 JDBC 드라이버라고 부른다.

 

MySQL -> PostgreSQL 서버로 마이그레이션 할 때,

드라이버만 교체하면 손쉽게 DB 변경이 가능하다는 뜻이다!

(물론 마이그레이션을 하려면 더 많은 작업이 필요하다)

 


 

JdbcTemplate

 

JDBC의 등장으로 손쉽게 DB교체가 가능해졌지만

아직도 DB에 연결하기 위해 여러가지 작업 로직들을 직접 작성해야한다는 남아있다.

 

이러한 불편함을 해결하기 위해 커넥션 연결, statement 준비 및 실행, 커넥션 종료 등의

반복적이고 중복되는 작업들을 대신 처리해주는 JdbcTemplate이 등장했다.

 

 

 

JDBC 의존성을 추가하고, DB 연결이 필요한 부분에서 JdbcTemplate을 주입받아서 사용하면 된다.

 

//jdbc 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'

//JdbcTemplate 주입
private final JdbcTemplate jdbctemplate;
public MemoRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
}

//INSERT SQL을 작성해 String 변수에 저장
//넣고자 하는 데이터 부분에 ?를 사용하면 유동적으로 데이터를 넣어줄 수 있다
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
jdbcTemplate.update(sql, "Robbie", "오늘 하루도 화이팅!");


//SELECT SQL을 작성해 String 변수에 저장한 후 query() 메서드 첫 번째 파라미터에 넣기
//SELECT의 경우 결과가 여러 줄로 넘어오기 때문에 RowMapper를 사용하여 한 줄씩 처리 가능
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
    @Override
    public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
        // SQL 의 결과로 받아온 Memo 데이터들을 MemoResponseDto 타입으로 변환해줄 메서드
        Long id = rs.getLong("id");
        String username = rs.getString("username");
        String contents = rs.getString("contents");
        return new MemoResponseDto(id, username, contents);
    }
});

 

 


 

여전히 느껴지는 불편함

 

 

 

물론 JdbcTemplate이 JDBC를 직접 사용할 때 발생하는 불편함을 해결해 주었지만,

 

JdbcTemplate을 사용하여 DB와 소통하는 방법은 여전히 어렵고 복잡하다.

 

하지만!!

 

다행히도 Java 개발자들을 위해 DB와 객체를 매핑하여 소통할 수 있는 ORM이라는 기술이 등장했는데,

 

spring 개발자들을 위해서,

거기서 발전된 것이 바로 Spring Data JPA 이다!!

 

 


 

JDBC와 비교해서 간편한 JPA

 

ORM(Object-Relational Mapping)이 등장한 배경은, 

특히 데이터베이스와 객체 지향 프로그래밍 사이의 근본적인 불일치를 해결하려는 필요성에서 비롯 되었다.

 

 

이를 흔히 "임피던스 불일치(impedance mismatch)"라고 부르는데,

이는 관계형 데이터베이스(Relational Database)와 객체 지향 프로그래밍 언어(Object-Oriented Programming Language)의

데이터 표현 방식 및 처리 방식이 다르기 때문에 발생한다.

 

 

그런데 위에서 설명한 것 처럼 JDBC를 사용하여 DB와 소통하는 코드도 만만치 않게 복잡했다. 

 

이거 보면 완전 

비즈니스 로직 집중하기 < 데이터베이스 액세스 코드 작성

아닌가?

 

옛 개발자들은 간단한 CRUD 작업조차도 수십줄을 작성해야 하는 끔찍한 상황을 겪었다는 것!!

 

JDBC는 유저를 조회하는 코드를 이렇게 작성해야 하는데,

public class JdbcExample {
    // 데이터베이스 연결 정보
    private static final String URL = "jdbc:mysql://localhost:3306/mydb";
    private static final String USER = "root";
    private static final String PASSWORD = "password";

    // ID로 사용자 조회 메서드
    public User findById(int id) {
        User user = null;
        String sql = "SELECT * FROM users WHERE id = ?";

        // 데이터베이스 연결 및 쿼리 실행
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            // 파라미터 설정
            pstmt.setInt(1, id);
            
            // 쿼리 실행 및 결과 처리
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setName(rs.getString("name"));
                    user.setEmail(rs.getString("email"));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }
    
   ......생략 
  
  }

 

 

JPA는 이렇게 한줄만 작성해주면 된다!

User user = exampleRepo.findById(1);

 

 

한잔해~

 

728x90