본문 바로가기

nestJS - MySQL과의 연동 본문

개발/nest.js

nestJS - MySQL과의 연동

자전하는명왕성 2023. 2. 1. 12:29

오늘은 어제 과제로 진행했던 내용을 복기해본다.

  • NestJS와 docker 내 MySQL 과의 연동
  • dto / entity / interface 작성
  • API 틀 작성

 

NestJS와 docker 내 MySQL 과의 연동

Docker 를 통해 MongoDB 와 연동을 했던 기억이 있어서 그리 어렵진 않았다.

MySQL 을 이용할 것이기 때문에, docker Database 이미지를 mysql 가장 최근 버전으로 설정해주고,

MySQL 부팅 시 필요한 데이터 베이스 이름 / 비밀번호를 입력해준다. 

* mongoDB 가 포트번호를 27017 을 사용했던 것처럼, MySQL 포트번호인 3306 을 입력해준다.

 

추가적으로 환경변수로 모아놨던 데이터들을

MySQL을 다루기 위한 TypeORM 에 아래와 같이 작성해주면 거의 완성되었다고 볼 수 있다.

 

dto / entity / interface 작성

dto는 데이터 이동 객체로, 데이터 타입에 대한 룰을 작성하는 것을 의미한다.

해당 데이터가 어떤 성격을 가지고 있는지 제시하기 때문에

'데이터 이동 객체'라는 그 말마따나 typescript 내에서 데이터 교환할 때 유용한 역할을 한다.

해당 dto 클래스는 input-type 이기는 하나, 

graphQL 에서 docs 로 제공되면서도, interface 형식 등으로 타 파일에 제공될 수 있다.

@Field() 데코레이터를 추가하여 GraphQL Field 임을 알려주었고, 타입을 지정해주었음.

 

entity는 DB와 매핑되는 핵심적인 클래스이며, DB 테이블에 나타날 형식을 정의한다.

이때의 Column 은 각각의 테이블의 필드가 되는데, 엑셀에서의 '열'로 이해하면 좋다.

당연하게도 entity 또한 TypeORM 을 통해 연결을 시켜주어야 한다.

@primaryGeneragtedColumn = 자동으로 생성될 값의 컬럼. ('increment' = 데이터 쌓일 시 자동으로 숫자 증가)

 

interface

인터페이스는 타입 체크를 위해 사용되는 것으로, 아래 이미지에서는 dto 에서 작성한 것을 그대로 활용했고,

이를 service 에서 원하는 산출 값으로 반환하도록 설정했다.

위와 같이 dto를 활용하면, 같은 코드를 두번 작성할 필요가 없어진다.

 

API 틀 작성

과제에서 핵심적인 API 틀 구현은 '커피 목록 조회 & 커피 목록 추가' 두 가지였다.

따라서, query / mutation API 각각 하나씩 작성해줄 필요가 있었다.

resolver.ts

// resolver.ts

import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { CreateStarbucksInput } from './dto/create-starbucks.input';
import { StarBucks } from './entities/starbucks.entity';
import { StarsbucksService } from './starbucks.service';

@Resolver()
export class StarbucksResolver {
  constructor(private readonly starbucksService: StarsbucksService) {}
  
  // 커피 목록 조회
  @Query(() => [StarBucks], { nullable: true })	// 엔티티에서 가져온 형식 활용으로
  					// 플레이그라운드에서 보여주기 위함
  fetchStarbucks(): StarBucks[] {	// fetchStarbucks = 조회 API 이름
    return this.starbucksService.findAll();		// API 실행 시 실행될 함수 findAll()
  }
  
  // 커피 목록 추가
  @Mutation(() => String)
  createStarbucks( // createStarbucks = 추가 API 이름
    @Args('createStarbucksInput') createStarbucksInput: CreateStarbucksInput, 
  ): string {	// @Args() 데코레이터를 사용해서 객체 value값의 타입을 지정
  			// @Args() 안은 gql 타입이고, 그 뒤는 스크립트 타입을 의미
    return this.starbucksService.createStarbucks({ createStarbucksInput });
  } // API 실행 시 createStarbucks({ createStarbucksInput }) 실행
}

services.ts 

// Service.ts

import { Injectable, Scope } from '@nestjs/common';
import { StarBucks } from './entities/starbucks.entity';
import { IStarbucksServiceCreate } from './interfaces/starbucs-service.interface';

@Injectable({ scope: Scope.DEFAULT })	// Injectable 주입
export class StarsbucksService {
  findAll(): StarBucks[] {	// entity의 starbucks를 배열 형식으로 가져올 것 지시
    const result = [{
        number: 1, name: '아메리카노', kcal: 10,
        caffeine: 10, fat: 10, price: 10,
        protein: 10, sodium: 10, sugar: 10,},
//	... 중략 
    ];
    return result; // 결괏값 반환
  }

  //
  //
  createStarbucks({ createStarbucksInput }: IStarbucksServiceCreate): string {
  	// interface 내 IStarbucksServiceCreate 값으로 형식을 저장하여 생성 지시
    return '게시물 등록에 성공하였습니다.';
  }
}

module.ts

import { Module } from '@nestjs/common';
import { StarbucksResolver } from './starbucks.resolver';
import { StarsbucksService } from './starbucks.service';

@Module({
  imports: [],
  providers: [
    StarbucksResolver, // 
    StarsbucksService, // DI
  ],
})
export class StarbucksModule {}

마지막으로 하위 module 에서 각각의 데이터를 종합해준 뒤,

app.module에서 API / graphQL / TypeORM 을 조립해주면 잘 실행이 되는 것을 확인할 수 있다.

 

Comments