11. Nest.js 광부왕 게임 서버 Log 저장 모듈 생성

2023. 3. 13. 17:09프로젝트/게임 서버 - Nest.js

로그 저장은 account, stage, item, company 분류

account : 계정 로그인 관련 로그

stage : 진행 게임 관련 로그

item : 아이탬 관련 로그

company : 회사 (길드) 관련 로그


1. 모듈 생성 ( Mongoose 설정 ), dayjs 설치

 

명령어 작성

nest g mo logs
npm i dayjs

 

 

 

src/logs/logs.module.ts 파일에서 MongooseModule 의존성 주입한다. 

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { Logs, LogsSchema } from '../model/logs.model';

@Module({
  imports: [
    MongooseModule.forFeature([
      {
        name: Logs.name,
        schema: LogsSchema,
      },
    ]),
  ],
  providers: [],
  controllers: [],
  exports: [],
})
export class LogsModule {}

2. DTO 생성

 

logs.dto.ts 파일에 두개의 DTO를 작성한다.

 

  • 로그 찾기 DTO 
import { ApiProperty } from '@nestjs/swagger';
import { IsIn } from 'class-validator';
import { IsNotEmpty, IsString, Matches } from 'class-validator';

export class FindLogDto {
  @ApiProperty({
    example: 'stage',
    description: 'type',
    required: true,
  })
  @IsIn(['account', 'stage', 'item', 'company'])
  @IsNotEmpty()
  type: 'account' | 'stage' | 'item' | 'company';

  @ApiProperty({
    example: '2022-01-01',
    description: 'startDate',
    required: true,
  })
  @IsString()
  @IsNotEmpty()
  @Matches(/^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/)
  startDate: string;

  @ApiProperty({
    example: '2022-01-10',
    description: 'endDate',
    required: true,
  })
  @IsString()
  @IsNotEmpty()
  @Matches(/^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/)
  endDate: string;
}

 

  • 로그 저장 DTO
export class SaveLogDto {
  @IsIn(['account', 'stage', 'item', 'company'])
  @IsNotEmpty()
  type: 'account' | 'stage' | 'item' | 'company';

  log: any;
}

3. Controller 생성

 

명령어 작성

nest g co logs

 

src/logs/logs.controller.ts 파일 수정

 

* 로그 저장은 따로 API통신으로 저장 되지 않고 서버에서 저장하기 때문에 findLog() 함수만 있다.

import { Controller } from '@nestjs/common';
import { Get, Param } from '@nestjs/common';
import { FindLogDto } from './dto/logs.dto';
import { LogsService } from './logs.service';
@Controller('logs')
export class LogsController {
  constructor(private readonly logsService: LogsService) {}

  @Get('/:type/:startDate/:endDate')
  async findLog(@Param() param: FindLogDto) {
    return await this.logsService.findLog(param);
  }
}

4. Service 생성

 

명령어 작성

nest g s logs

 

src/logs/logs.service.ts 파일 수정

 

* 서버 시간 (UTC + 0)을 한국시간(UTC + 9)으로 시간을 맞추었다.

import { Injectable } from '@nestjs/common';
import dayjs from 'dayjs';
import { FindLogDto, SaveLogDto } from './dto/logs.dto';
import { LogRepository } from './logs.repository';

@Injectable()
export class LogsService {
  constructor(private readonly logRepository: LogRepository) {}
  async findLog(data: FindLogDto) {
    const { type, startDate, endDate } = data;
    const start = dayjs(new Date(startDate))
      .subtract(1, 'day')
      .set('hours', 5)
      .set('minutes', 0)
      .set('seconds', 0)
      .toDate();

    const end = dayjs(new Date(endDate))
      .set('hours', 15)
      .set('minutes', 0)
      .set('seconds', 0)
      .toDate();

    const log = await this.logRepository.findLog({ type, start, end });
    return log;
  }

  async saveLog(user: string, data: SaveLogDto) {
    await this.logRepository.saveLog(user, data);
  }
}

5. Repository 생성

src/logs/logs.repository.ts 파일 생성 후 작성

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import dayjs from 'dayjs';
import { Model } from 'mongoose';
import { Logs } from '../model/logs.model';
import { SaveLogDto } from './dto/logs.dto';

@Injectable()
export class LogRepository {
  constructor(@InjectModel(Logs.name) private readonly logModel: Model<Logs>) {}
  async findLog(data: { type: string; start: Date; end: Date }) {
    const { type, start, end } = data;
    return await this.logModel
      .find()
      .select({ [`${type}Log`]: 1, user: 1 })
      .gte('createdAt', start)
      .lte('createdAt', end);
  }

  async saveLog(user: string, data: SaveLogDto) {
    const { type, log } = data;
    const now = new Date();
    const date = dayjs(now).format('YYYY-MM-DD');
    const savedLog = await this.logModel.findOne({ user, date });
    log.time = new Date();

    if (savedLog) {
      await this.logModel.findOneAndUpdate(
        { _id: savedLog._id },
        { $push: { [`${type}Log`]: log } },
      );
    } else {
      await this.logModel.create({ user, date, [`${type}Log`]: [log] });
    }
  }
}

6. 모듈 설정

* 로그 저장을 다른 모듈에서 재사용 하기 위해  LogsService은 exports에 넣는다.

import { Module } from '@nestjs/common';
import { LogRepository } from './logs.repository';
import { LogsService } from './logs.service';
import { LogsController } from './logs.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Logs, LogsSchema } from '../model/logs.model';

@Module({
  imports: [
    MongooseModule.forFeature([
      {
        name: Logs.name,
        schema: LogsSchema,
      },
    ]),
  ],
  providers: [LogsService, LogRepository],
  controllers: [LogsController],
  exports: [LogsService],
})
export class LogsModule {}
728x90
반응형