ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›…์˜ ํšจ์šฉ๊ณผ ํ™œ์šฉ ๋ฐฉ์•ˆ (w/ NodeJS + TypeORM)

2025. 4. 28. 21:26ใ†Backend/NestJS

์„œ๋ก 

๋ฐฑ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ํ•ต์‹ฌ ์š”์†Œ์ž…๋‹ˆ๋‹ค. Node.js ํ™˜๊ฒฝ์—์„œ TypeORM์„ ์‚ฌ์šฉํ•  ๋•Œ, ์šฐ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์ธ ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก, ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŠธ๋žœ์žญ์…˜ ์ด์ƒ์˜ ๊ฒƒ์ด ํ•„์š”ํ•ด์ง‘๋‹ˆ๋‹ค.

ํ˜„๋Œ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…๊ณผ ํ•จ๊ป˜ ์›น์†Œ์ผ“ ํ†ต์‹ , ํ‘ธ์‹œ ์•Œ๋ฆผ, ์™ธ๋ถ€ API ํ˜ธ์ถœ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ€๊ฐ€ ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ž‘์—…๋“ค์€ DB ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์‹คํ–‰ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. TypeORM์˜ ๊ธฐ๋ณธ ํŠธ๋žœ์žญ์…˜ API๋งŒ์œผ๋กœ๋Š” ์ด๋Ÿฌํ•œ ๋ณต์žกํ•œ ํ๋ฆ„์„ ์šฐ์•„ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” TypeORM ํ™˜๊ฒฝ์—์„œ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›…์„ ํ™œ์šฉํ•ด ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด์™€ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ ํ›…๊ณผ ๋น„๊ตํ•˜๊ณ , Node.js + TypeORM ํ™˜๊ฒฝ์—์„œ ์ด๋ฅผ ์ ์šฉํ•ด๋ณด๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ณธ๋ก 

1. ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ์˜ ๋„์ „ ๊ณผ์ œ

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ํŠธ๋žœ์žญ์…˜ ๋กœ์ง์˜ ๊ฒฐํ•ฉ

TypeORM์—์„œ ๊ธฐ๋ณธ์ ์ธ ํŠธ๋žœ์žญ์…˜ ์‚ฌ์šฉ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค:

await dataSource.transaction(async transactionalEntityManager => {
  await transactionalEntityManager.save(user);
  await transactionalEntityManager.save(userProfile);
});

์ด ํŒจํ„ด์€ ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ์—๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:

  1. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ๋กœ์ง์ด ๊ฒฐํ•ฉ๋จ: ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ์ฝ”๋“œ๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ์„ž์—ฌ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ €ํ•˜๋ฉ๋‹ˆ๋‹ค.

  2. ์ฝ”๋“œ ์ค‘๋ณต: ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์—์„œ ์œ ์‚ฌํ•œ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ํŒจํ„ด์ด ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค.

  3. ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ ์ฒ˜๋ฆฌ์˜ ์–ด๋ ค์›€: ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต/์‹คํŒจ ์‹œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ถ”๊ฐ€ ๋กœ์ง์„ ์ผ๊ด€๋˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์‹ค์ œ NestJS์—์„œ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚ฉ๋‹ˆ๋‹ค:

// ๊ธฐ๋ณธ์ ์ธ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ๋ฐฉ์‹
async createOrder({ itemsToOrder }: CreateOrderRequestDto): Promise<Order> {
  const queryRunner = this.dataSource.createQueryRunner();
  await queryRunner.connect();
  await queryRunner.startTransaction();

  try {
    const order = await queryRunner.manager.save(Order.create({...}));
    await queryRunner.manager.save(itemsToOrder.map(item => OrderItem.create({...})));
    await queryRunner.commitTransaction();

    // ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต ํ›„ ์•Œ๋ฆผ ๋ฐœ์†ก (DB ์™ธ ๋กœ์ง)
    await this.notificationService.sendOrderCreatedNotification(order);

    return order;
  } catch (e) {
    await queryRunner.rollbackTransaction();
    throw new InternalServerErrorException();
  } finally {
    await queryRunner.release();
  }
}

์ด ์ฝ”๋“œ์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณตํ•œ ํ›„์—๋งŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋Š” ๋กœ์ง์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŒจํ„ด์ด ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์— ๊ฑธ์ณ ๋ฐ˜๋ณต๋˜๋ฉด ์ฝ”๋“œ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์ง€๊ณ , ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต/์‹คํŒจ์— ๋”ฐ๋ฅธ ๋ถ€๊ฐ€ ๋กœ์ง ์ฒ˜๋ฆฌ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์„ ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

DB ์™ธ ๋กœ์ง ์ฒ˜๋ฆฌ์˜ ๋„์ „

ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณตํ•œ ํ›„์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ๋กœ์ง๋“ค์„ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”:

  • ์ด๋ฉ”์ผ ๋˜๋Š” ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก

  • ์›น์†Œ์ผ“์„ ํ†ตํ•œ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ

  • ์บ์‹œ ๋ฌดํšจํ™”

  • ์™ธ๋ถ€ ์„œ๋น„์Šค API ํ˜ธ์ถœ

  • ๋กœ๊น… ๋ฐ ๊ฐ์‚ฌ

์ด๋Ÿฐ ๋กœ์ง๋“ค์€ ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต ํ›„์—๋งŒ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋ฉฐ, ํŠธ๋žœ์žญ์…˜์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ ์‹คํ–‰๋˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ TypeORM ํŠธ๋žœ์žญ์…˜ API๋งŒ์œผ๋กœ๋Š” ์ด๋Ÿฐ ํŒจํ„ด์„ ์šฐ์•„ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

2. ๋‹ค๋ฅธ ํ™˜๊ฒฝ์˜ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›…

๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ORM์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ์„๊นŒ์š”?

Java Spring์˜ ํŠธ๋žœ์žญ์…˜ ๋™๊ธฐํ™”

Spring ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” TransactionSynchronizationManager๋ฅผ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

@Transactional
public void createUser(User user) {
    userRepository.save(user);

    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
        @Override
        public void afterCommit() {
            emailService.sendWelcomeEmail(user.getEmail());
        }
    });
}

์ด ์ฝ”๋“œ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ปค๋ฐ‹๋œ ํ›„์—๋งŒ ์ด๋ฉ”์ผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. Spring 4.2๋ถ€ํ„ฐ๋Š” ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

Sequelize์˜ ํŠธ๋žœ์žญ์…˜ ํ›…

Sequelize๋Š” ํŠธ๋žœ์žญ์…˜ ํ›…์„ ์ง์ ‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:

const transaction = await sequelize.transaction({
  hooks: {
    afterCommit: async (tx) => {
      await notificationService.send('Transaction completed');
    },
    afterRollback: async (tx) => {
      console.log('Transaction rolled back');
    }
  }
});

์ด๋Ÿฌํ•œ ํ›…์€ ํŠธ๋žœ์žญ์…˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์–ด ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ์˜ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ์–ธ์–ด์™€ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

3. TypeORM์—์„œ์˜ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›… ๊ตฌํ˜„

TypeORM์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›…์„ ์ œ๊ณตํ•˜์ง€ ์•Š์ง€๋งŒ, ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๊ฐœ๋ฐœํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

typeorm-transactional ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

typeorm-transactional์€ TypeORM์—์„œ ํŠธ๋žœ์žญ์…˜์„ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” @Transactional() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ํŠธ๋žœ์žญ์…˜ ์ฝœ๋ฐฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

ํŠธ๋žœ์žญ์…˜ ํ›… ์‚ฌ์šฉ:

import { Transactional, runOnTransactionCommit, runOnTransactionRollback } from 'typeorm-transactional';

export class UserService {
  constructor(
    private userRepository: UserRepository,
    private emailService: EmailService,
    private logService: LogService
  ) {}

  @Transactional()
  async createUser(userData: CreateUserDto): Promise<User> {
    const user = await this.userRepository.save(userData);

    // ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ํ›„ ์‹คํ–‰๋  ๋กœ์ง ๋“ฑ๋ก
    runOnTransactionCommit(async () => {
      await this.emailService.sendWelcomeEmail(user.email);
      console.log('User created successfully');
    });

    // ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ ์‹œ ์‹คํ–‰๋  ๋กœ์ง ๋“ฑ๋ก
    runOnTransactionRollback(async () => {
      await this.logService.logFailure('User creation failed');
    });

    return user;
  }
}

์ด ์ฝ”๋“œ์—์„œ๋Š” @Transactional() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์‹ธ๊ณ , runOnTransactionCommit๊ณผ runOnTransactionRollback ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

4. ์‹ค์ „ ์˜ˆ์ œ: ๋ฉ€ํ‹ฐ ๋„๋ฉ”์ธ ์„œ๋น„์Šค์—์„œ์˜ ํŠธ๋žœ์žญ์…˜ ํ›… ํ™œ์šฉ (w/ typeorm-transactional)

๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ฐ€์ง„ ์ฃผ๋ฌธ ์ƒ์„ฑ API๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:

@Injectable()
export class OrderService {
  constructor(
    private orderRepository: OrderRepository,
    private paymentService: PaymentService,
    private inventoryService: InventoryService,
    private notificationService: NotificationService,
    private socketService: SocketService
  ) {}

  @Transactional()
  async createOrder(orderData: CreateOrderDto): Promise<Order> {
    // 1. ์ฃผ๋ฌธ ์ƒ์„ฑ
    const order = await this.orderRepository.save(new Order(orderData));

    // 2. ๊ฒฐ์ œ ์ฒ˜๋ฆฌ
    await this.paymentService.processPayment(order.id, orderData.paymentInfo);

    // 3. ์žฌ๊ณ  ๊ฐ์†Œ
    await this.inventoryService.decreaseStock(orderData.items);

    // ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ ํ›„ ์‹คํ–‰๋  ๋กœ์ง ๋“ฑ๋ก
    runOnTransactionCommit(async () => {
      // ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก
      await this.notificationService.sendOrderConfirmation(order);

      // ์›น์†Œ์ผ“์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
      this.socketService.emitOrderCreated(order.userId, order);

      // ์™ธ๋ถ€ ๋ฌผ๋ฅ˜ ์‹œ์Šคํ…œ API ํ˜ธ์ถœ
      await this.logisticsService.requestShipment(order);
    });

    // ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ ์‹œ ์‹คํ–‰๋  ๋กœ์ง ๋“ฑ๋ก
    runOnTransactionRollback(async () => {
      // ์‹คํŒจ ๋กœ๊น…
      await this.logService.logOrderFailure(orderData, 'Transaction failed');

      // ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹คํŒจ ์•Œ๋ฆผ
      await this.notificationService.sendOrderFailureNotice(orderData.userId);
    });

    return order;
  }
}

์ด ์˜ˆ์ œ์—์„œ๋Š”:

  1. ์ฃผ๋ฌธ ์ƒ์„ฑ, ๊ฒฐ์ œ ์ฒ˜๋ฆฌ, ์žฌ๊ณ  ๊ฐ์†Œ๊ฐ€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  2. ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ปค๋ฐ‹๋œ ํ›„์—๋งŒ ์•Œ๋ฆผ ๋ฐœ์†ก, ์›น์†Œ์ผ“ ๋ฉ”์‹œ์ง€ ์ „์†ก, ์™ธ๋ถ€ API ํ˜ธ์ถœ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  3. ํŠธ๋žœ์žญ์…˜์ด ์‹คํŒจํ•˜๋ฉด ๋กค๋ฐฑ ํ›„ ์‹คํŒจ ๋กœ๊น…๊ณผ ์‹คํŒจ ์•Œ๋ฆผ์ด ๋ฐœ์†ก๋ฉ๋‹ˆ๋‹ค.

์ด ๋ฐฉ์‹์€ ์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ ์„œ๋น„์Šค์— ๊ฑธ์นœ ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ๋„, DB ํŠธ๋žœ์žญ์…˜๊ณผ DB ์™ธ ๋กœ์ง์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

TypeORM ํ™˜๊ฒฝ์—์„œ ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›…์„ ํ™œ์šฉํ•œ ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ ์ฒ˜๋ฆฌ๋Š” ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ, ์žฌ์‚ฌ์šฉ์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ: DB ํŠธ๋žœ์žญ์…˜ ๋กœ์ง๊ณผ DB ์™ธ ๋กœ์ง(์›น์†Œ์ผ“, ์•Œ๋ฆผ ๋“ฑ)์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ: ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต/์‹คํŒจ์— ๋”ฐ๋ฅธ ๋กœ์ง์„ ์ผ๊ด€๋˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ: ๋ณต์žกํ•œ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ์ฝ”๋“œ๊ฐ€ @Transactional() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ๊ฐ„์†Œํ™”๋ฉ๋‹ˆ๋‹ค.

  4. ์œ ์ง€๋ณด์ˆ˜์„ฑ ๊ฐœ์„ : ํŠธ๋žœ์žญ์…˜ ๊ด€๋ จ ๋กœ์ง์ด ์ค‘์•™ํ™”๋˜์–ด ๋ณ€๊ฒฝ์ด ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.

Spring, Sequelize ๋“ฑ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ด๋ฏธ ์ œ๊ณตํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ›… ๊ธฐ๋Šฅ์„ TypeORM ํ™˜๊ฒฝ์—์„œ๋„ typeorm-transactional ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜๋‚˜ ๋ณต์žกํ•œ ๋„๋ฉ”์ธ ๋กœ์ง์„ ๊ฐ€์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํฐ ๊ฐ€์น˜๋ฅผ ๋ฐœํœ˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋งŒ์•ฝ ์ด๋ฏธ ํŠธ๋žœ์žญ์…˜ ํ›…์„ ์ง€์›ํ•œ๋‹ค๋ฉด ์œ„์™€ ๊ฐ™์ด ์ ์šฉํ•ด๋ณด๋Š” ๊ฒƒ์„, ์ง€์›ํ•˜์ง€ ์•Š๋Š” ํ™˜๊ฒฝ์ด๋ผ๋ฉด ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

'Backend > NestJS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

NestJS Request Lifecycle (5) - Exception Filter  (0) 2023.01.13
NestJS Request Lifecycle (4) - Pipe  (0) 2022.12.29
NestJS Request Lifecycle (3) - Interceptor  (0) 2022.12.26
NestJS Request Lifecycle (2) - Guard  (0) 2022.12.23
NestJS Request Lifecycle (1) - Middleware  (0) 2022.12.22