Hyunseok
프로그래밍/환율 앱 실시간 환율 데스크톱 앱 - nestjs로 스케쥴러를 사용해보자
2023. 8. 21. 08:48

싸랑해요 TS, 싸랑해요 Nestjs

이번 프로젝트의 핵심은

재사용 가능한 데이터의 활용으로 점진적인 기능추가

ㄴ 이것이 이번 프로젝트의 주목적이다 

그러기 위해서는 첫 이니셜라이즈가 제일 중요하다 생각했다

 

초반에는 어차피 USD와 JPY만 긁어올텐데.. 하면서

그냥 냅다 불러온 데이터에서 USD와 JPY만 파싱 해서

DB에 저장하고 있었는데, 생각해 보니 fetch 한 데이터가 아까워서

다른 데이터도 다 db에 넣기로 결정했다 

 

1. nestjs에서 task폴더 작성 후 task.service.ts파일 작성

import { Inject, Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import axios from 'axios';
import { AppService } from 'src/app/app.service';
import { ContriesList, parseHTML } from './parseUtil';

export interface currencyAxios {
    meta: { last_updated_at: string };
    data: {
        [key: string]: {
            code: string;
            value: number;
        };
    };
}

@Injectable()
export class TasksService {
    private readonly logger = new Logger(TasksService.name);

    @Inject(AppService)
    private readonly appService: AppService;

    @Cron(CronExpression.EVERY_MINUTE)
    async handleCron() {
        try {
            const { data } = await axios.get('https://finance.naver.com/marketindex/exchangeList.naver')
            this.appService.create('SUCCESS', parseHTML(data))
        } catch (error) {
            const result = await this.appService.findLastOne()
            this.appService.create('ERROR', result[0] as ContriesList)
        }
    }
}

(지금 보니 조금이라도 프로젝트가 커지면 그냥 axios interceptor를 하나 작성해서 쓰는 게 나아 보인다)

 

nestjs가 참 좋은 게.. 스프링부트도 그렇지만 일단 모든 것을 다 만들어 두었다

오히려 nestjs가 더 편하게 느껴지는 이유는 변수명을 좀 더 쉽게 만들어뒀다던가..

저런 식으로(@Cron) 아예 리눅스의 크론탭... 을연상시키는, 심지어 사용법도 더 간단한 기능들을 다 만들어두었다

 

사실.. 이렇게 느끼는 데는 Typescript의 문법을 그대로 써서여서일 수도 있다 

개인적으로는 너무 편하다..

 

아,  여하튼 긁어오는 대상은 홈페이지 환율에서 긁어온다 

굳이 다른 api 쓸 필요도 없어 보이고

내가 이걸 상업적으로 쓰지도 않고.. 그냥 내 생각에는 혼자 쓸 듯하다

 

만약에.. 진짜 만약에 star가 50개.. 100개가 넘어간다면

로직을 바꾸던 API키를 사용하던 그땐 다른 방법을 모색해 보자 

 

그리고 task.service에 보면 AppService가 injection 되어있다

그럼 모듈에서도 사용한다고 명시해줘야 하지 task.moudle에도 넣어주자

 

import { Module } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { AppService } from 'src/app/app.service';
import { CurrencyEntity } from 'src/app/entity/currency.entity';

@Module({
    imports: [CurrencyEntity],
    providers: [TasksService, AppService],
})
export class TasksModule { }

 

이러면.. 사실 일이 끝난다 

parseHTML은 자신이 가져올 페이지의 데이터를 parsing 할 데이터를 가져와서 로직을 짜고 넣어준다 

 

아, main.module에도 넣어주는 것을 잊지 말자 

import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppModule } from './app/app.module';
import SqlConfig from './sql/sqlconfig';
import { TasksModule } from './task/tasks.module';
@Module({
    imports: [
        ScheduleModule.forRoot(),
        TasksModule,
        AppModule,
        SqlConfig()
    ]
})
export class MainModule { }

 

TasksModule과 스케쥴러를 사용하기 위한 ScheduleModule.forRoto()을 추가해 주자

 

그러고 나서 서버를 실행시키면..

 

 

크론탭이 발생할 때마다

조합된 데이터를 appService를 이용하여

sqlite에 저장할 수 있는 것을볼 수 있다 

 

개인적으로는 테이블 구조를 조금 더 정규화시켜야 한다 생각하는데 

지금은 귀찮고, 어차피 데이터는 JSON형태로 한방오브젝트가 뜨기도 하고..

이 테이블 자체가 INSERT, SELECT두 개만 치는 테이블이라 그리 많은 정규화도 필요 없어 보이고..

궁극적으로는 누구든 테이블을 딱 1초만 봐도 이게 어떤 테이블인지 알기에.. 

 

그냥 이대로 놔두려 한다 (진짜 만약에 규모가 커지면 그때해도 문제없을 것 같다)

 

여하튼 이렇게 nestjs로 스케쥴러를 사용해 보았다

스프링 스케쥴러도 있다던데 .. 이건 스프링으로 백엔드 만들 때..

쓸 기회가 오면 한 번 도전해 봐야겠다 


프로그래밍/환율 앱의 다른 글