백엔드 개발을 하다 보면 반드시 데이터베이스와 연동해야 하는 순간이 온다. 이때 등장하는 것이 바로 ORM(Object-Relational Mapping)이다. ORM이 무엇인지, 왜 필요한지, 어떤 장단점이 있는지 차근차근 알아보자.
영속성(Persistence)은 프로그램이 종료되어도 데이터가 사라지지 않는 특성을 말한다.
예를 들어, 메모리에 저장된 변수는 프로그램이 끝나면 사라지지만, 데이터베이스에 저장된 데이터는 프로그램이 종료되어도 계속 남아있다. 이처럼 데이터를 영구적으로 보존하는 것이 영속성이다.
Java에서 데이터베이스에 접근하는 방법은 다음과 같이 발전해왔다
ORM(Object-Relational Mapping)은 객체와 관계형 데이터베이스를 자동으로 연결해주는 기술이다.
// 기존 SQL 방식
String sql = "SELECT * FROM users";
// 복잡한 JDBC 코드...
// ORM 방식
List<User> users = userRepository.findAll();
ORM을 사용하면 SQL을 직접 작성하지 않고도 데이터베이스 작업을 할 수 있다.
객체지향 프로그래밍은 클래스와 상속, 다형성을 사용하지만, 관계형 데이터베이스는 테이블과 외래키를 사용한다. 이 두 모델 간에는 근본적인 차이가 있다.
기존 JDBC 방식에서는 매번 동일한 패턴의 코드를 반복해서 작성해야 했다:
// JDBC 방식 - 반복적인 코드
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setLong(1, userId);
ResultSet rs = pstmt.executeQuery();
// ResultSet을 User 객체로 변환하는 코드...
테이블 구조가 변경되면 관련된 모든 SQL을 수정해야 하는 문제가 있었다.
// ORM 방식 - 간단한 메서드 호출
User user = userRepository.findById(userId);
List<User> users = userRepository.findAll();
userRepository.save(user);
userRepository.delete(user);
복잡한 SQL 작성 없이 간단한 메서드 호출만으로 데이터베이스 작업이 가능하다.
// Sequelize 예시
const users = await User.findAll();
const user = await User.findByPk(1);
await User.create({ name: 'John', email: 'john@example.com' });
# Django ORM 예시
users = User.objects.all()
user = User.objects.get(id=1)
User.objects.create(name='John', email='john@example.com')