ORM(Object-Relation Mapping)은 이름 그대로 객체와 관계형 데이터베이스를 연결해주는 기술으로, 쿼리를 객체지향 언어처럼 작성할 수 있게 해준다. Java의 Hibernate, Node.js의 Sequelize 등이 ORM 프레임워크이다.
var orm = require('generic-orm-library');
var user = orm("users").where({ email: 'test@test.com' });
가상의 ORM 라이브러리로 쿼리를 실행하는 예시.
자바스크립트뿐 아니라 다른 여러 언어에서 위와 같이 쿼리를 SQL이 아닌 익숙한 언어로 작성하여 사용할 수 있다.
타입스크립트와 자바스크립트 ES5~ES8에서 사용가능한 ORM 프레임워크로 Active Record와 Data Mapper 패턴을 모두 지원한다.
모델 자체에 쿼리 메소드를 정의해서 모델의 메소드를 사용하여 객체를 조작하는 패턴.
import {BaseEntity, Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
isActive: boolean;
static findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
}
}
모델을 정의한 클래스에 스태틱 메소드형태로 쿼리를 작성해 객체를 조작한다.
분리된 클래스에 쿼리 메소드를 정의하고 Repository를 이용하여 객체를 조작하는 패턴.
import {EntityRepository, Repository} from "typeorm";
import {User} from "../entity/User";
@EntityRepository()
export class UserRepository extends Repository<User> {
findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
}
}
모델을 정의한 클래스와 분리하여 리포지토리 클래스를 만들어 리포지토리에서 객체를 조작한다.
공식 문서에 따르면 Data Mapper 패턴은 유지보수성이 좋고 대규모 앱에서 효과적으로 사용할 수 있다고 하며, Active Record 패턴은 구현이 간단하여 소규모 앱에서 사용하기 좋다고 한다.
https://dev.solita.fi/2021/06/01/why-avoid-an-orm.html
https://axiomq.com/blog/comparing-orm-vs-sql-what-to-know/
https://blog.bitsrc.io/what-is-an-orm-and-why-you-should-use-it-b2b6f75f5e2a
https://www.freecodecamp.org/news/a-comparison-of-the-top-orms-for-2018-19c4feeaa5f/