공부했던 것들에 대해서 계속 복습 중이다.
여기서는 서버 APP에서 DB의 데이터에 엑세스하는 접근 방식에 대해서 설명하고 있다. 주로 2가지의 패턴이 보이게 되는데, 이에 대한 차이점을 정리해 볼려고 한다.
Active Record Pattern
모델 내에서 모든 쿼리(접근자) 메서드를 정의하고 모델 메서드를 통해서 객체의 CRUD를 한다.
이렇게 작성하게 되면 개발이 빨라진다. 하지만 DB와 애플리케이션 로직의 결합으로 인해서 단위 테스트를 하기가 어려워지고, 단일 책임 원칙에 위배된다는 문제도 생긴다. 단위 테스트의 경우에는 테스트를 위한 새로운 계층의 생성으로 해결이 가능할 수도 있으나, 단일 책임 원칙에 위배되는 점은 해결하기 힘들어 보인다.
아래의 예시를 보면 User라는 엔티티에 직접 findByName이라는 쿼리 메서드를 지정하고 있다.
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()
}
}
Data Mapper Pattern
전형적인 서버 애플리케이션에서 데이터는 컨트롤러 -> 서비스 -> 리포지토리 -> DB의 계층으로 나뉘어 있다. 여기서 리포지토리는 DB와 프로그램 내 데이터 표현 계층을 연결하는 데이터 엑세스 계층이다. 이 패턴은 여러 서버 애플리케이션에서 정석처럼 사용되고 있으며, 단일 책임 원칙에 위배되지도 않으면서 테스트도 비교적 쉽다는 장점이 있다.
사용 예시는 아래와 같다.
const userRepository = dataSource.getRepository(User)
// example how to save DM entity
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await userRepository.save(user)
// example how to remove DM entity
await userRepository.remove(user)
// example how to load DM entities
const users = await userRepository.find({ skip: 2, take: 5 })
const newUsers = await userRepository.findBy({ isActive: true })
const timber = await userRepository.findOneBy({
firstName: "Timber",
lastName: "Saw",
})
차이점
Active Record는 직관적이고 비교적 빠르게 앱을 제작할 수 있다. 그래서 소규모 앱에 자주 쓰인다. 반대로 Data Mapper는 Model과 역할을 분리하여 사용하므로, 비교적 확장성이 좋고 큰 앱에서 주로 사용한다. 하지만 빠르게 앱을 제작하기에는 약간의 제한이 있다.
참고자료
https://orkhan.gitbook.io/typeorm/docs/active-record-data-mapper
https://en.wikipedia.org/wiki/Active_record_pattern
https://en.wikipedia.org/wiki/Data_mapper_pattern
'프레임워크 > NestJS' 카테고리의 다른 글
Typeorm querybuilder에서 bigint number로 받기 (0) | 2023.11.12 |
---|---|
NestJS Graceful shutdown (0) | 2023.08.13 |
[NestJS] JWT 인증과 Role 적용하기 (0) | 2022.12.10 |
[NestJS] 데이터 요청과 응답 사이의 Request lifecycle (0) | 2022.11.06 |
[NestJS] Dependency Injection과 NestJS (2) | 2022.11.05 |