DAY14

yejichoi·2022년 11월 18일
0
post-thumbnail
  1. Algorithm Self Study
  1. Backend Class

Utility Types

Utility Type은 기존에 있던 Type들을 변형해서 변형된 타입을 새로 만들어주는 역할을 하며,

코드의 가독성을 높이기 위해(같은 코드를 여러번 작성하지 않기 위해) 많이 사용

Partial Type

: 모든 속성을 선택사항으로 바꿔주는 역할

Required Type

모든 속성을 필수사항으로 바꿔주는 역할 ( Partial Type과 반대 )

Pick Type

: 원하는 속성만을 뽑아서 사용

// index.ts

interface IProfile {
  name: string;
  age: number;
  school: string;
  hobby?: string;
}


// 3. Pick 타입
type MyType3 = Pick<IProfile, "name" | "age">;

Omit Type

원하는 속성만 제거하여 사용

// index.ts

interface IProfile {
  name: string;
  age: number;
  school: string;
  hobby?: string;
}

// 4. Omit 타입
type MyType4 = Omit<IProfile, "school">;

Record Type

: Utility Type 속성을 다른 Type으로 매핑 시키고자 할 때 사용
Record<Key, Type> 으로 사용하며, Key로 들어온 타입을 Type 값을 가지는 타입으로 만들 수 있음

// index.ts

interface IProfile {
  name: string;
  age: number;
  school: string;
  hobby?: string;
}

// 5. Record 타입
type MyUnion = "철수" | "영희" | "훈이"; // Union 타입
type MyType5 = Record<MyUnion, IProfile>; 

Union Type
: Javascript의 OR 연산자( || )와 같이 ‘A’ 이거나 ‘B’이다 라는 의미의 타입으로,
**|** 연산자를 이용하여 타입 또는 값을 여러 개 연결할 때 사용할 수 있습니다.

Keyof Type
: 해당 객체 내 key값을 Union 형태로 반환시켜 주는 역할
즉, IProfile의 key만을 뽑아서 새로운 타입을 만들고 싶을때 사용

type과 interface의 차이
interface는 type과 달리 선언병합이 가능
즉, IProfile을 만들어 주었는데, 또다시 IProfile을 만들어 주게 된다면
두 IProfile이 합쳐진 하나의 IProfile이 생성
=> 선언병합은 type에서 사용할 수 없음

Generic Types

C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징
특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 생성하는데 사용

❓Any Type
여러 가지 타입을 허용하고 싶다면 any를 사용할 수 있음
다만, 함수의 인자로 어떤 타입이 들어갔고 어떤 값이 반환되는지는 알 수가 없음.
왜냐하면 any타입은 타입 검사를 하지 않기 때문임 => 제네릭으로 해결 가능

TypeORM을 활용한 mysql 연결

MongoDB 를 사용할 때는 model 파일 로 표현하여 사용하는 반면,

표 형태의 SQL DB 같은 경우에는 Entity 파일 로 표현

mysql과 연결시켜주기 위해서 TypeOrmModule 의 옵션을 설정 => app.module.ts 파일 작성

// app.module.ts

import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardModule } from './apis/boards/boards.module';
import { Board } from './apis/boards/entities/board.entity';

@Module({
  imports: [
    BoardModule,
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: 'src/commons/graphql/schema.gql',
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',            // 데이터 베이스 타입
      host: 'localhost',        // local 환경으로 진행
      port: 3306,               // mysql은 기본 port는 3306
      username: 'root',         // mysql은 기본 user는 root로 지정
      password: 'root',         // 본인의 mysql password 
      database: 'mysql',        // 연결할 데이터 베이스명
      entities: [Board],        // 데이터 베이스와 연결할 entity
      synchronize: true,        // entity 테이블을 데이터베이스와 동기화할 것인지
      logging: true,            // 콘솔 창에 log를 표시할 것인지
    }),
  ],
})
export class AppModule {}
// board.entity.ts

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Board {
  @PrimaryGeneratedColumn('increment')
  number: number;

  @Column()
  writer: string;

  @Column()
  title: string;

  @Column()
  contents: string;
}
  • @Entity : Board class가 실행될 때, typeorm에 의해 Entity 테이블을 만들어줌
  • @PrimaryGeneratedColumn : 자동으로 생성될 값의 컬럼
    • increment : 데이터가 한 줄씩 쌓일 때마다 자동으로 숫자가 1씩 증가하여 값이 생성
    • uuid : 중복되지 않는 문자열 ID가 자동으로 생성
  • @Column : 표 형태에서 에 해당. 실제 들어갈 데이터의 값의 컬럼

    ODM & ORM

    • ODM ( Object Document Mapping )
      : NoSQL에서 Document Database를 지원하기 위해 데이터를 변환하는 프로그래밍 기법
      i.e) MongoDB 에서는 Board.save() 등을 통해 데이터 저장 기능 뿐 아니라, 데이터를 만들거나 꺼내오는 것들이 가능
    • ORM ( Object Relational Mapping )
      : 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법

DTO (data transfer object)
: 데이터 전송 객체. 즉, 네트워크 간에 데이터를 어떤 식으로 보낼지를 정의한 객체
i.e) input

// createBoard.input.ts


import { InputType, Field } from '@nestjs/graphql';

@InputType()
export class CreateBoardInput {
  @Field(() => String)
  writer: string;

  @Field(() => String)
  title: string;

  @Field(() => String)
  contents: string;
}
//board.resolver.ts


import { Query, Resolver, Mutation, Args } from '@nestjs/graphql';
import { BoardService } from './board.service';
import { CreateBoardInput } from './dto/createBoard.input';
import { Board } from './entities/board.entity';

@Resolver()
export class BoardResolver {
  constructor(private readonly boardService: BoardService) {}

  @Query(() => [Board])
  fetchBoards(){
    return this.boardService.findAll();
  }

  @Mutation(() => String)
  createBoard(
  //  @Args('writer') writer: string,
  //  @Args('title') title: string,
   // @Args('contents') contents: string,
  //input으로 묶어서 대신 사용 
    @Args('createBoardInput') createBoardInput: CreateBoardInput,
  ){
    return this.boardService.create({
     // writer,
     // title,
     // contents,
      createBoardInput,
    });
  }
}

.env 사용을 위해 Nest에서 제공하는 ConfigModule을 사용

  • type : type 은 무조건 mysql 을 사용한다는 의미로 as mysql 을 통해 강제 지정
  • port : Number()을 사용하여 string 타입을 number 타입으로 바꿔줌
  • .env파일은 local 전용 파일, docker 전용 .env.docker
// app.module.ts

import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { GraphQLModule } from '@nestjs/graphql';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardsModule } from './apis/boards/boards.module';
import { Board } from './apis/boards/entities/board.entity';

@Module({
  imports: [
    BoardsModule,
    ConfigModule.forRoot(),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: 'src/commons/graphql/schema.gql',
    }),
    TypeOrmModule.forRoot({ //.env 파일 사용하여 기밀 유지 
      type: process.env.DATABASE_TYPE as 'mysql',
      host: process.env.DATABASE_HOST,
      port: Number(process.env.DATABASE_PORT),
      username: process.env.DATABASE_USERNAME,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE_DATABASE,
      entities: [Board],
      synchronize: true,
      logging: true,
    }),
  ],
})
export class AppModule {}

Docker로 서버를 올리기 위해선, Docker를 위한 설정 파일 3개 필요

  • .dockerigonre, docker-compose.yaml, Dockefile
// .dockerignore

node_modules
dist
# docker-compose.yaml

version: '3.7'

services:
  my-backend:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./src:/myfolder/src
    ports:
      - 3000:3000
    env_file:
      - ./.env.docker

  my-database:
    image: mysql:latest
		platform: linux/x86_64
    environment:
      MYSQL_DATABASE: 'mydocker'
      MYSQL_ROOT_PASSWORD: 'root'
    ports:
      - 3306:3306
  • my-database
    • platform: linux/x86_64 : 맥북 M1 칩을 사용하시는 분이라면 추가 설정
    • image : mysql 최신버전으로 설정
    • environment : MySQL 설치 시, 초기 셋팅을 위한 곳으로 DB 이름과 DB 비밀번호롤 작성
      • DB 이름.env.docker 파일의 DATABASE_DATABASE 와 동일해야 하며,
        DB 비밀번호.env.docker 파일의 DATABASE_PASSWOR 와 동일

0개의 댓글