JPA

yeolyeol·2024년 12월 11일
0

til

목록 보기
24/27
post-thumbnail

JPA는 백엔드 개발하는 사람이라면 다들 써봤을 것이다.
그럼, 다른 사람이 JPA가 뭔가요? 왜 쓰나요? 라는 질문을 받았다면 잘 설명할 수 있을까?

실제로 동기가 JPA에 대해 물어봤는데, 나 역시 사용하는 법만 알지 JPA가 정확히 무엇이고 왜 사용하는지 몰랐다.


ORM

JPA를 알기 전 ORM에 대해 알아보자.

ORM이란 Object-Relational Mapping의 약자로 직역을 해보자면, 객체 관계 맵핑이라는 뜻이 있다. 이는 객체는 객체대로 설계하고 RDB는 RDB대로 설계할 수 있게 맵핑시켜주는 것을 말한다.

JPA

JPA는 현재 자바 진영의 ORM 기술 표준, 인터페이스의 모음이다.
인터페이스의 모음이기 때문에 구현체가 필요하며 이를 구현한 오픈소스는 Hibernate가 대표적이다. 그 외에도 EclipseLink, DataNucleus가 있는데 이 중 하나를 사용해서 개발하면 된다.

그리고 JPA는 인터페이스이기 때문에, 개발자가 직접 JPA 구현체를 만들어서 사용할 수 있다.

동작 과정

JPA는 ORM 역할을 하기 때문에 애플리케이션과 JDBC 사이에 동작한다.
그래서 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하고 DB와 통신을 대신 해준다.

개발자가 직접 JDBC API로 통신

// DBUtil.java - DB 연결하는 코드
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBUtil {
    private static final String URL = "jdbc:mysql://localhost:3306/database_name";
    private static final String USER = "username";
    private static final String PASSWORD = "password";
    
    public static Connection getConnection() throws SQLException {
        try {
            // MySQL JDBC 드라이버 로딩
            Class.forName("com.mysql.cj.jdbc.Driver");
            return DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (ClassNotFoundException e) {
            throw new SQLException("JDBC 드라이버를 찾을 수 없습니다.", e);
        }
    }
}
// DAO.java
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class UserDAO {

    // 사용자 목록 조회
    public List<User> getAllUsers() {
        List<User> users = new ArrayList<>();
        String sql = "SELECT * FROM users";
        
        try (Connection connection = DBUtil.getConnection();
             PreparedStatement statement = connection.prepareStatement(sql);
             ResultSet resultSet = statement.executeQuery()) {
            
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String email = resultSet.getString("email");

                users.add(new User(id, username, email));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return users;
    }

    // 특정 사용자 조회 (ID로)
    public User getUserById(int id) {
        User user = null;
        String sql = "SELECT * FROM users WHERE id = ?";
        
        try (Connection connection = DBUtil.getConnection();
             PreparedStatement statement = connection.prepareStatement(sql)) {
            
            statement.setInt(1, id);
            ResultSet resultSet = statement.executeQuery();
            
            if (resultSet.next()) {
                String username = resultSet.getString("username");
                String email = resultSet.getString("email");
                user = new User(id, username, email);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return user;
    }
}

JPA를 사용하기 전에는 이런 식으로 DB와 연결을 해주고 DAO(Data Access Object)를 만들어서 원하는 쿼리를 실행한다.
나는 개인적으로 Java코드에는 Java만 있어야 마음이 편하기 때문에 조금 불편한 감이 없이 않아 있다.

JPA로 통신하기

# MySQL 데이터베이스 연결 설정 == DBUtil.java
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
// Repository.java
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Integer> {
    // 사용자 조회를 위한 추가적인 메서드를 정의할 수 있습니다.
    User findByUsername(String username);
}
// Service.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;

    // 모든 사용자 조회
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    // 사용자 ID로 조회
    public User getUserById(int id) {
        return userRepository.findById(id).orElse(null);
    }

    // 사용자 이름으로 조회
    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username);
    }
}

JPA로 변경된 코드를 보면 DBUtil.java는 properties에 설정을 하고 따로 객체를 만들지 않는다. 그리고 쿼리문이 포함되어 있던 DAO역시 JpaRepository를 상속받는 인터페이스로 대체된다.
그리고 사용하는 방법은 보통 Service 단에서 인터페이스 메서드를 실행해서 사용한다.

JPA를 왜 사용할까?

  1. 객체 중심적인 개발이 가능하다.
    코드를 비교해보면 바로 알 수 있 듯, Java 개발자가 SQL을 사용하지 않고도 개발이 가능하다.
  2. 생산성이 증가한다.
  • DDL문을 자동으로 생성하게 해주기 때문에 빠른 개발과 오타로 인한 오류를 줄일 수 있다.
  • SQL을 작성하고 JDBC API를 사용하는 반복적인 일을 대신 처리해준다.
  1. 유지보수가 쉽다.
    기존에는 필드를 변경하게 되면 모든 SQL 문을 수정해야 했다. 즉, 결합도가 높았는데, 반면 JPA를 사용하게 되면 필드만 바꿔도 정상적으로 수행하기 때문에 결합도가 느슨한 개발을 할 수 있다.

이러한 이유로 JPA를 사용하는 편이다. 특히, 느슨한 결합도가 코드 유지보수의 핵심이라고 생각한다.

단점

사용하는 이유와 내포된 장점을 알아봤는데, 마냥 좋은 것만 있는 것은 아니다.

  • 개발자가 의도하지 않은 자동으로 생성된 Query로 인해 성능이 저하된다.
  • 복잡하고 무거운 Query문은 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 쓰는게 나은 상황이 발생할 수도 있다.
  • 학습비용이 비싸고 시간이 오래걸린다.

요즘에 크게 와 닿는 점은, 결국 SQL문을 쓰는게 더 편한거 같은데? 라는 생각이 종종 든다.
이유는 정말로 SQL문이 편한 것도 있지만, 아직 JPA를 완벽하게 알지 못하기 때문인 것 같다.

profile
한 걸음씩 꾸준히

0개의 댓글

관련 채용 정보