사용자 정의 TypeORM 저장소
복잡한 데이터베이스 쿼리를 캡슐화하고 코드 구성과 재사용성을 향상하는 사용자 정의 저장소를 만듭니다.
사용자 정의 TypeORM 저장소은(는) CoddyKit의 무료 NestJS Enterprise Backend APIs 강의입니다. 이것은 3개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 NestJS Enterprise Backend APIs 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. NestJS Enterprise Backend APIs 강의에는 총 3개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Beyond Basic CRUD
TypeORM's default Repository offers basic operations like save, find, and delete. These are great for simple tasks.
However, real-world applications often need more complex queries or domain-specific data retrieval logic.
Encapsulating Complex Queries
Without custom repositories, complex database queries might end up directly in your service layer. This can make services bloated and harder to maintain.
- Cleaner Services: Services focus on business logic, not database specifics.
- Reusability: Complex queries can be reused across different parts of your application.
- Testability: Easier to test database interactions in isolation.
Creating a Custom Repository
To create a custom repository, you define a class that extends TypeORM's Repository<Entity>. You must also decorate it with @EntityRepository(Entity) to link it to a specific entity.
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@Column({ default: true })
isActive: boolean;
}
// src/user/user.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
// Custom methods will go here
}Injecting the Custom Repository
Once defined, you can inject your custom repository into NestJS services or controllers using the @InjectRepository() decorator.
Remember to pass your custom repository class as an argument to @InjectRepository().
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
) {}
async findAllActive(): Promise<User[]> {
// This method will be defined in the custom repo
return this.userRepository.findActiveUsers();
}
}Adding a Custom Method
Inside your custom repository, you can add methods that encapsulate specific query logic. These methods can use the default Repository methods or TypeORM's Query Builder.
Let's add methods to find all active users and find a user by email.
// src/user/user.repository.ts (updated)
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
async findByEmail(email: string): Promise<User | undefined> {
return this.findOne({ email });
}
}Custom Repo Workflow
Here's the typical flow: you define your Entity, then your Custom Repository extending Repository<Entity>, and finally inject it into your Service.
// 1. user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity() export class User {
@PrimaryGeneratedColumn() id: number;
@Column() name: string;
@Column({ unique: true }) email: string;
@Column({ default: true }) isActive: boolean;
}
// 2. user.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
}
// 3. user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
) {}
async getAllActive(): Promise<User[]> {
return this.userRepository.findActiveUsers();
}
}Module Configuration
For NestJS to properly manage the TypeORM repositories, your module needs to import TypeOrmModule.forFeature() with your entities. The @EntityRepository decorator handles the TypeORM-side registration, allowing injection.
// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
imports: [
TypeOrmModule.forFeature([User]) // Only entities here
],
providers: [UserService, UserController],
exports: [UserService] // Export service if used elsewhere
})
export class UserModule {}Leveraging Query Builder
For more complex queries, custom repositories often use TypeORM's powerful Query Builder. This allows you to construct dynamic queries with joins, conditions, and more.
Let's add a method to find users who are active and have a specific name pattern.
// src/user/user.repository.ts (extended)
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
import { MoreThan } from 'typeorm'; // Example for complex query
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
async findByNamePattern(pattern: string): Promise<User[]> {
return this.createQueryBuilder('user')
.where('user.name LIKE :pattern', { pattern: `%${pattern}%` })
.andWhere('user.isActive = :isActive', { isActive: true })
.getMany();
}
}Check Your Understanding
Consider the following custom repository and service:
// product.repository.ts
import { EntityRepository, Repository, MoreThan } from 'typeorm';
import { Product } from './product.entity'; // Assume Product entity exists
@EntityRepository(Product)
export class ProductRepository extends Repository<Product> {
async findAvailableProducts(): Promise<Product[]> {
return this.find({ where: { stock: MoreThan(0), isActive: true } });
}
}
// product.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ProductRepository } from './product.repository';
import { Product } from './product.entity'; // Assume Product entity exists
@Injectable()
export class ProductService {
constructor(
@InjectRepository(ProductRepository)
private productRepo: ProductRepository,
) {}
async getProducts(): Promise<Product[]> {
return this.productRepo.findAvailableProducts();
}
}Custom Repositories Summary
In this lesson, we explored custom TypeORM repositories. We learned that they are a powerful pattern to:
- Encapsulate complex, reusable database query logic.
- Keep your NestJS services clean and focused on business rules.
- Improve code organization, reusability, and testability.
By extending TypeORM's Repository and using @EntityRepository, you can define domain-specific methods that make your data access layer much more robust.
자주 묻는 질문
“사용자 정의 TypeORM 저장소” 강의는 무료인가요?
네 — “사용자 정의 TypeORM 저장소” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 NestJS Enterprise Backend APIs 강의 전체를 잠금 해제할 수 있습니다. NestJS Enterprise Backend APIs 강의에는 총 3개의 강의가 포함되어 있습니다.
“사용자 정의 TypeORM 저장소”에서 뭘 배우나요?
복잡한 데이터베이스 쿼리를 캡슐화하고 코드 구성과 재사용성을 향상하는 사용자 정의 저장소를 만듭니다. 브라우저에서 직접 실행하는 실습 코드로 NestJS Enterprise Backend APIs을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
NestJS Enterprise Backend APIs을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 NestJS Enterprise Backend APIs은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 1번째 강의입니다.
“사용자 정의 TypeORM 저장소” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 NestJS Enterprise Backend APIs 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 NestJS Enterprise Backend APIs 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 사용자 정의 TypeORM 저장소
- 트랜잭션과 마이그레이션
- 데이터베이스 시딩과 테스트