ABOUT ME

Today
Yesterday
Total
  • 캐싱 (NEST
    카테고리 없음 2023. 12. 22. 15:11

    캐싱

     

    야 이거 했던 요청을 또해??

     

    동일한 요청이  지속적으로 들어오는 경우에 대해서는 캐싱기능을 사용할 수 있다면 성능이 상승하겠지?

     

     


     

     

    //cache-manager 설치

     

    npm i @nestjs/cache-manager cache-manager

     

     

     


     

     

     

    // APP.MODULE 수정

     

    import Joi from 'joi';

    import { CacheModule } from '@nestjs/cache-manager';
    import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import { JwtModule } from '@nestjs/jwt';
    import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';

    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { AuthMiddleware } from './auth/auth.middleware';
    import { Post } from './post/entities/post.entity';
    import { PostModule } from './post/post.module';
    import { User } from './user/entities/user.entity';
    import { UserModule } from './user/user.module';

    const typeOrmModuleOptions = {
      useFactory: async (
        configService: ConfigService,
      ): Promise<TypeOrmModuleOptions> => ({
        type: 'mysql',
        host: configService.get('DB_HOST'),
        port: configService.get('DB_PORT'),
        username: configService.get('DB_USERNAME'),
        password: configService.get('DB_PASSWORD'),
        database: configService.get('DB_NAME'),
        entities: [Post, User],
        synchronize: configService.get('DB_SYNC'),
        logging: true,
      }),
      inject: [ConfigService],
    };
    @Module({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          validationSchema: Joi.object({
            DB_HOST: Joi.string().required(),
            DB_PORT: Joi.number().required(),
            DB_USERNAME: Joi.string().required(),
            DB_PASSWORD: Joi.string().required(),
            DB_NAME: Joi.string().required(),
            DB_SYNC: Joi.boolean().required(),
          }),
        }),
        TypeOrmModule.forRootAsync(typeOrmModuleOptions),
        JwtModule.registerAsync({
          useFactory: (config: ConfigService) => ({
            secret: config.get<string>('JWT_SECRET_KEY'), // .env 파일에 JWT_SECRET_KEY라는 키로 비밀키를 저장해두고 사용합니다.
          }),
          inject: [ConfigService],
        }),
        CacheModule.register({
          ttl: 60000, // 데이터 캐싱 시간(밀리 초 단위, 1000 = 1초)
          max: 100, // 최대 캐싱 개수
          isGlobal: true,
        }),
        PostModule,
        UserModule,
      ],
      controllers: [AppController],
      providers: [AppService, AuthMiddleware],
    })
    export class AppModule implements NestModule {
      configure(consumer: MiddlewareConsumer) {
        consumer
          .apply(AuthMiddleware) // 미들웨어 적용!
          .forRoutes({ path: 'user/check', method: RequestMethod.GET }); // user/check 엔드포인트에만 적용
      }
    }

     


     

    POST.SERVICE.TS 수정 

     

    import { Cache } from 'cache-manager';
    import _ from 'lodash';
    import { Repository } from 'typeorm';

    import { CACHE_MANAGER } from '@nestjs/cache-manager';
    import {
      BadRequestException, Inject, Injectable, NotFoundException, UnauthorizedException
    } from '@nestjs/common';
    import { InjectRepository } from '@nestjs/typeorm';

    import { CreatePostDto } from './dto/create-post.dto';
    import { RemovePostDTO } from './dto/remove-post.dto';
    import { UpdatePostDto } from './dto/update-post.dto';
    import { Post } from './entities/post.entity';

    @Injectable()
    export class PostService {
      constructor(
        @InjectRepository(Post) private postRepository: Repository<Post>,
        @Inject(CACHE_MANAGER) private cacheManager: Cache,
      ) {}

      async create(createPostDto: CreatePostDto) {
        return (await this.postRepository.save(createPostDto)).id;
      }

      async findAll() {
        const cachedArticles = await this.cacheManager.get('articles');
        if (!_.isNil(cachedArticles)) {
          return cachedArticles;
        }

        const articles = await this.postRepository.find({
          where: { deletedAt: null },
          select: ['id', 'title', 'updatedAt'],
        });
        await this.cacheManager.set('articles', articles);
        return articles;
      }

      async findOne(id: number) {
        if (_.isNaN(id)) {
          throw new BadRequestException('게시물 ID가 잘못되었습니다.');
        }

        return await this.postRepository.findOne({
          where: { id, deletedAt: null },
          select: ['title', 'content', 'updatedAt'],
        });
      }

      async update(id: number, updatePostDto: UpdatePostDto) {
        if (_.isNaN(id)) {
          throw new BadRequestException('게시물 ID가 잘못되었습니다.');
        }

        const { content, password } = updatePostDto;
        const post = await this.postRepository.findOne({
          select: ['password'],
          where: { id },
        });

        if (_.isNil(post)) {
          throw new NotFoundException('게시물을 찾을 수 없습니다.');
        }

        if (!_.isNil(post.password) && post.password !== password) {
          throw new UnauthorizedException('비밀번호가 일치하지 않습니다.');
        }

        await this.postRepository.update({ id }, { content });
      }

      async remove(id: number, removePostDto: RemovePostDTO) {
        if (_.isNaN(id)) {
          throw new BadRequestException('게시물 ID가 잘못되었습니다.');
        }

        const { password } = removePostDto;

        const post = await this.postRepository.findOne({
          select: ['password'],
          where: { id },
        });

        if (_.isNil(post)) {
          throw new NotFoundException('게시물을 찾을 수 없습니다.');
        }

        if (!_.isNil(post.password) && post.password !== password) {
          throw new UnauthorizedException('비밀번호가 일치하지 않습니다.');
        }

        await this.postRepository.softDelete({ id });
      }
    }

Designed by Tistory.