src/
├── config/ # 설정 파일들
├── database/ # DB 관련 설정, 마이그레이션, 시드 파일
├── entity/ # TypeORM 엔티티 정의
├── board/ # 게시판 모듈
├── middleware/ # 미들웨어
├── exceptions/ # 예외 처리
├── decorators/ # 커스텀 데코레이터
├── app.module.ts # 루트 모듈
├── app.controller.ts # 루트 컨트롤러
└── main.ts # 애플리케이션 시작점
TypeORM은 NodeJS에서 실행되는 ORM(Object-Relational Mapping)으로, 데이터베이스를 객체지향적으로 관리할 수 있게 해주는 도구입니다.
npm install @nestjs/typeorm typeorm pg @nestjs/config
import { DataSource } from 'typeorm';
import { config } from 'dotenv';
config({ path: '.env.local' });
export default new DataSource({
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432'),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
entities: ['src/**/*.entity.{js,ts}'],
synchronize: false,
migrations: ['src/database/migrations/*.ts'],
migrationsTableName: 'migrations',
});
# chocolatey를 통한 설치
choco install postgresql
# homebrew를 통한 설치
brew install postgresql
CREATE DATABASE simple_board;
CREATE USER myuser WITH PASSWORD 'mypassword';
GRANT ALL PRIVILEGES ON DATABASE simple_board TO myuser;
npm install dotenv
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=myuser
DB_PASSWORD=mypassword
DB_NAME=simple_board
Entity는 데이터베이스 테이블과 매핑되는 클래스입니다. 각 프로퍼티는 테이블의 컬럼을 나타냅니다.
src/entity/user.entity.ts:
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100 })
username: string;
@Column({ unique: true })
email: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
@OneToOne(() => Profile)
@JoinColumn()
profile: Profile;
@OneToMany(() => Board, board => board.user)
boards: Board[];
@ManyToOne(() => User, user => user.boards)
user: User;
데이터베이스 스키마의 버전 관리 시스템입니다. 데이터베이스 구조 변경사항을 코드로 관리합니다.
npm run migration:generate
npm run migration:run
package.json:
{
"scripts": {
"migration:create": "typeorm migration:create ./src/database/migrations/Migration",
"migration:generate": "typeorm-ts-node-commonjs migration:generate ./src/database/migrations/Migration -d ./src/database/data-source.ts",
"migration:run": "typeorm-ts-node-commonjs migration:run -d ./src/database/data-source.ts",
"migration:revert": "typeorm-ts-node-commonjs migration:revert -d ./src/database/data-source.ts"
}
}
import { MigrationInterface, QueryRunner } from "typeorm";
export class CreateUserTable1234567890123 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE user (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE user`);
}
}
초기 데이터를 데이터베이스에 삽입하는 프로세스입니다.
npm install --save-dev typeorm-extension
"scripts": {
...
"seed": "ts-node -r tsconfig-paths/register src/database/seeds/run-seed.ts",
}
import { DataSource } from 'typeorm';
import { Seeder, SeederFactoryManager } from 'typeorm-extension';
import { User } from '../../entity/user.entity';
export default class InitialSeeder implements Seeder {
public async run(
dataSource: DataSource,
factoryManager: SeederFactoryManager
): Promise<void> {
const userRepository = dataSource.getRepository(User);
const users = [
{
username: 'admin',
email: 'admin@example.com',
},
{
username: 'user',
email: 'user@example.com',
}
];
for (const user of users) {
await userRepository.save(userRepository.create(user));
}
}
}
import { config } from 'dotenv';
import { runSeeders } from 'typeorm-extension';
import dataSource from '../data-source';
// 환경변수 로드
config({ path: '.env.local' });
const runSeeder = async () => {
try {
// 데이터베이스 연결 초기화
await dataSource.initialize();
// 시더 실행
await runSeeders(dataSource, {
seeds: ['src/database/seeds/*.seed.ts'],
});
} catch (error) {
process.exit(1);
} finally {
// 연결 종료
if (dataSource.isInitialized) {
await dataSource.destroy();
}
}
};
runSeeder();
npm run seed