ActiveRecord 사용자가 알아야 할 세상: 다른 ORM과의 비교를 통한 이해

ActiveRecord使いが知るべき世界:Java/Go/TypeScriptのORMアプローチ比較 / 河野裕隆 - Kaigi on Rails 2025

작성자
Kaigi on Rails
발행일
2025년 11월 25일

핵심 요약

  • 1 ActiveRecord는 컨벤션 기반의 올인원 ORM으로, 직관적인 데이터 조작과 유연한 DSL을 통해 SQL 지식 없이도 개발 가능한 강력한 장점을 가집니다.
  • 2 다른 언어의 ORM(Prisma, JPA, MyBatis, SQLC)은 타입 안정성, SQL 분리, 선언적 마이그레이션 등 ActiveRecord와 다른 접근 방식으로 다양한 개발 환경과 요구사항에 대응합니다.
  • 3 ORM의 설계 철학과 책임 분리는 언어 특성 및 문화에 따라 다르며, 각 접근 방식은 안전성, 유연성, 개발 편의성 사이의 트레이드오프를 반영합니다.

도입

본 발표는 ActiveRecord 사용자들이 쿼리 작성 시 겪는 어려움(인덱스 사용, 복잡한 WHERE 절, 집계 함수 등)을 배경으로, 다른 언어의 ORM 매퍼들과 ActiveRecord를 비교하여 설계 관점과 사상을 확장하는 것을 목표로 합니다. 특정 라이브러리의 우월성을 논하기보다는 각 언어의 특성과 문화를 이해하고, 라이브러리가 어떤 사상으로 만들어졌는지 고찰하는 데 중점을 둡니다. 이를 통해 ActiveRecord의 강점과 한계를 객관적으로 파악할 수 있는 시야를 제공하고자 합니다.

ORM의 정의 및 역할

ORM(Object-Relational Mapping)은 프로그램 객체와 RDB 레코드 간의 변환을 간략화하는 라이브러리입니다. 주요 역할은 다음과 같습니다.

  • DB 결과와 프로그래밍 언어 타입 간의 매핑

  • 쿼리 발행 간략화 (DSL을 통한 쉬운 쿼리, CRUD 작업)

  • 객체 생성 노력 해소 및 라이프사이클 관리

  • 임피던스 불일치 해소 (타입 매핑, 데이터 구조 불일치 처리)

ORM의 유형

ORM은 크게 두 가지 패턴으로 나뉩니다.

  • Active Record 패턴: 엔티티와 리포지토리가 결합된 형태로, Rails의 ActiveRecord, Laravel의 Eloquent 등이 해당됩니다.

  • Data Mapper 패턴: 엔티티(데이터 구조)와 리포지토리(DB 접근 계층)가 분리된 형태로, Java의 Hibernate, PHP의 Doctrine 등이 있습니다. Ruby에서는 Hanami 프레임워크의 ruby-object-mapper가 이 패턴을 따릅니다.

  • SQL Builder: 쿼리 발행에 중점을 두며, 객체 라이프사이클 관리는 SQL을 통해 이루어집니다. Java의 MyBatis, Ruby의 Sequel 등이 있습니다.

ActiveRecord의 특징 및 강점

ActiveRecord는 DB 마이그레이션, 유효성 검사, 커넥션 풀링 등 ORM 외의 다양한 기능을 포함하는 ‘올인원’ 라이브러리입니다. 주요 강점은 다음과 같습니다.

  • 설정보다 규약(Convention over Configuration): 명시적인 매핑 없이 직관적인 데이터 조작이 가능합니다.

  • 통합된 데이터 처리: 유효성 검사 및 스키마 관리를 통합하여 올인원 패키지로 제공합니다.

  • 유연한 DSL: SQL을 몰라도 다양한 쿼리 발행이 가능하여 개발 생산성을 높입니다.

다른 ORM과의 비교

## 1. 쿼리 발행

  • ActiveRecord (Ruby): Model.where.select와 같은 DSL로 직관적이고 쉬운 쿼리 발행이 가능하며, 연관관계 및 Enum 처리가 용이합니다.

  • Prisma (TypeScript): ActiveRecord와 유사한 DSL을 제공하지만, 스키마 정의와 밀접하게 연동되어 타입 안전성을 보장합니다. 컴파일 시점에 타입 오류를 감지할 수 있습니다.

  • JPA (Java): 메소드 이름(findByUserCreatedAtGreaterThanAndStatusOrderByCreatedAtAsc)을 통해 SQL을 발행하는 독특한 방식을 사용합니다. JPQL을 통해 SQL과 유사한 형태로 쿼리를 작성할 수도 있어 DSL의 한계를 벗어날 수 있습니다.

  • MyBatis (Java, 2SQL): SQL 파일을 코드와 분리하여 관리하며, SQL 파일 내 주석을 통해 파라미터 바인딩을 처리하는 2SQL 방식을 사용합니다. DAO 인터페이스와 SQL 간의 컴파일 시점 검사를 통해 타입 안전성을 확보합니다.

2. 스키마 관리

  • ActiveRecord: db:migrate 명령어를 통해 DSL로 테이블 정의를 관리하고, 스키마 마이그레이션 테이블을 통해 버전 관리를 수행합니다. 모델의 프로퍼티는 DB 메타 정보를 통해 동적으로 매핑됩니다.

  • Prisma: prisma migrate dev 명령어로 스키마 파일을 읽어 마이그레이션을 수행합니다. 특히, 선언적 마이그레이션(Declarative Migration)을 지원하여 스키마 변경 시 Prisma가 자동으로 ALTER TABLE 문을 생성해줍니다. 또한, prisma generate를 통해 스키마로부터 타입 정의를 자동 생성하여 타입 안전성을 높입니다.

  • SQLC (Go): DB 스키마 변경과 애플리케이션 코드를 분리합니다. schema.sql에서 구조체 타입을, .sql 파일에서 리포지토리 인터페이스와 SQL을 생성하여 유연한 SQL 작성 및 타입 안전한 실행을 가능하게 합니다.

3. 다기능성 (All-in-one vs. Specialized)

  • ActiveRecord: 쿼리 DSL, 커넥션 풀, 스키마 관리 등 다양한 기능을 내장한 올인원 솔루션입니다.

  • Java: 커넥션 풀(HikariCP) 등 각 기능별로 전문화된 서드파티 라이브러리를 조합하여 사용하는 경우가 많습니다. 이는 유연한 커스터마이징이 가능하지만, 초기 설정의 복잡성이 증가하는 트레이드오프가 존재합니다.

결론

결론적으로, ORM 라이브러리들의 다양한 접근 방식과 책임 분리는 무엇을 보장하고 싶은지에 대한 설계 철학의 차이에서 비롯됩니다. 이는 언어의 특성과 문화에 크게 의존하며, 라이브러리의 좋고 나쁨을 판단하는 기준이 될 수 없습니다. Java는 대규모 엔터프라이즈 개발에서 안전성을 중시하여 라이브러리 조합을 선호하며, Go는 숙련된 팀을 위한 유연한 접근 방식을, TypeScript의 Prisma는 Rails의 장점을 흡수하여 친절하고 현대적인 개발 경험을 제공합니다. ActiveRecord는 규약 기반의 직관적인 개발 경험을 제공하지만, 때로는 유연성 측면에서 한계를 가질 수 있습니다. 팀의 특성과 프로젝트 요구사항에 맞춰 최적의 ORM 및 접근 방식을 선택하는 것이 중요하며, 다른 언어의 기술 동향을 주시하며 변화에 적응하고 미리 대비하는 자세가 필요합니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!