[ TIL ] 02.17(금) 68일차

2023. 2. 17. 21:00· 코딩캠프/내일배움캠프
728x90

TypeORM

 

1. 데이터베이스 연결

 

Nest.js에서 데이터베이스 연동은 TypeORM을 사용한다.

 

TypeORM 설치

npm i typeorm@0.3.0 @nestjs/typeorm mysql

 

TypeORM을 모듈에 임포트!

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BoardModule } from './board/board.module';
@Module({
imports: [
TypeOrmModule.forRoot({
//데이터베이스 설정
type: 'mysql',
host: 'localhost',
port: 3306,
username: '데이터베이스 아이디',
password: '데이터베이스 비밀번호',
database: 'board',
entities: [],
synchronize: true,
}),
BoardModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

 

기본적인 데이터베이스 설정은 위와 같이한다

하지만 데이터베이스의 정보가 코드에 노출이 된다.

 

 

.env를 사용했던 것 처럼 @nestjs/config 패키지를 사용한다

npm i @nestjs/config

 

config/typeorm.config.service.ts 파일생성

import { Injectable } from '@nestjs/common';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
// 생성자를 통해서 DI
constructor(private readonly configService: ConfigService) {}
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'mysql',
host: this.configService.get<string>('DATABASE_HOST'),
port: this.configService.get<number>('DATABASE_PORT'),
username: this.configService.get<string>('DATABASE_USERNAME'),
password: this.configService.get<string>('DATABASE_PASSWORD'),
database: this.configService.get<string>('DATABASE_NAME'),
entities: [],
synchronize: this.configService.get<boolean>('DATABASE_SYNCHRONIZE'),
};
}
}

 

.env 파일생성

DATABASE_HOST="localhost"
DATABASE_PORT=3306
DATABASE_USERNAME="데이터베이스 아이디"
DATABASE_PASSWORD="데이터베이스 비밀번호"
DATABASE_NAME="board"
DATABASE_SYNCHRONIZE=true

 

app.module.ts 수정

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config/dist';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BoardModule } from './board/board.module';
import { TypeOrmConfigService } from './config/typeorm.config.service';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRootAsync({
useClass: TypeOrmConfigService,
}),
BoardModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

 

 

2. 엔티티 & 리포지토리 생성

 

엔티티 : 데이터테이블의 스키마를 정의를 하는것

 

article.entity.ts

import {
Column,
CreateDateColumn,
DeleteDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from "typeorm";
@Entity({ schema: "board", name: "articles" })
export class Article {
@PrimaryGeneratedColumn({ type: "int", name: "id" })
id: number;
@Column("varchar", { length: 10 })
author: string;
@Column("varchar", { length: 50 })
title: string;
@Column("varchar", { length: 1000 })
content: string;
@Column("varchar", { select: false })
password: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn()
deletedAt: Date | null;
}

 

패스워드에 select: false 가 되어있는데 특별한 경우 아니고는 셀렉트를 할 필요가 없다

그래서 기본적으로 false로 한다.

(필요에 따라 셀렉트 할수있다.)

 

deletedAt 에 null 이 있는건

해당 엔티티가 삭제되는 순간 실제로 삭제(Hard Delete) 되는게 아니라

논리적으로 삭제(soft Delete)가 되는걸 목적으로 할 경우 사용한다.

 

 

리포지토리 : 엔티티와 서비스코드 사이에서 데이터베이스 관련된 기능을 실행

일반 리포지토리와 커스텀 리포지토리가 있다

일반 리포지토리 명세는 TypeORM의 Repository 문서를 참고
데이터베이스 연산이 부족하면 일반 리포지토리를 상속한 커스텀 지포지토리를 작성한다.

 

일반 리포지토리 사용 예시)

constructor(
@InjectRepository(Article) private articleRepository: Repository<Article>
) {}

를

 

board.service.ts 에 추가

import {
Injectable,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import _ from 'lodash';
import { Repository } from 'typeorm';
import { Article } from './article.entity';
@Injectable()
export class BoardService {
constructor(
@InjectRepository(Article) private articleRepository: Repository<Article>,
) {}
private articles = [];
// 게시글 비밀번호를 저장하기 위한 Map 객체입니다.
private articlePasswords = new Map();
getArticles() {
return this.articles;
}
getArticleById(id: number) {
return this.articles.find((article) => {
return article.id === id;
});
}
createArticle(title: string, content: string, password: number) {
// id 먼저 할당
// 1번부터 시작 => 현재 배열의 크기 + 1
const articleId = this.articles.length + 1;
this.articles.push({ id: articleId, title, content });
this.articlePasswords.set(articleId, password);
return articleId;
}
updateArticle(id: number, title: string, content: string, password: number) {
if (this.articlePasswords.get(id) !== password) {
throw new UnauthorizedException(
`Article password is not correct. id: ${id}`,
);
}
const article = this.getArticleById(id);
if (_.isNil(article)) {
throw new NotFoundException(`Article not found. id: ${id}`);
}
article.title = title;
article.content = content;
}
deleteArticle(id: number, password: number) {
if (this.articlePasswords.get(id) !== password) {
throw new UnauthorizedException(
`Article password is not correct. id: ${id}`,
);
}
this.articles = this.articles.filter((article) => {
return article.id !== id;
});
}
}

 

 

 

 

board.module.ts

import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Article } from "./article.entity";
import { BoardController } from "./board.controller";
import { BoardService } from "./board.service";
@Module({
// 매우 중요: 서비스에서 사용할 리포지토리 사용을 imports에 명시!
imports: [TypeOrmModule.forFeature([Article])],
controllers: [BoardController],
providers: [BoardService],
})
export class BoardModule {}

 

typeorm.config.service.ts

import { Injectable } from '@nestjs/common';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
import { Article } from 'src/board/article.entity';
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
constructor(private readonly configService: ConfigService) {}
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: 'mysql',
host: this.configService.get<string>('DATABASE_HOST'),
port: this.configService.get<number>('DATABASE_PORT'),
username: this.configService.get<string>('DATABASE_USERNAME'),
password: this.configService.get<string>('DATABASE_PASSWORD'),
database: this.configService.get<string>('DATABASE_NAME'),
entities: [Article],
// 엔티티에 Article 추가!
synchronize: this.configService.get<boolean>('DATABASE_SYNCHRONIZE'),
};
}
}
저작자표시 비영리 변경금지

'코딩캠프 > 내일배움캠프' 카테고리의 다른 글

[ TIL ] 02.20(월) 69일차  (0) 2023.02.20
[ WIL ] 02.13~17 14주차  (0) 2023.02.19
[ TIL ] 02.16(목) 67일차  (0) 2023.02.16
[ TIL ] 02.15(수) 66일차  (0) 2023.02.15
[ TIL ] 02.14(화) 65일차  (0) 2023.02.14
'코딩캠프/내일배움캠프' 카테고리의 다른 글
  • [ TIL ] 02.20(월) 69일차
  • [ WIL ] 02.13~17 14주차
  • [ TIL ] 02.16(목) 67일차
  • [ TIL ] 02.15(수) 66일차
고랑E
고랑E
300x250
고랑E
고랑의 개발일지
고랑E
전체
오늘
어제
  • 분류 전체보기 (209)
    • Project (18)
      • [팀] Color On Me (18)
      • [팀] Eats Finder (0)
    • Dev (14)
      • 네이버 클라우드 플랫폼(NCP) (3)
      • DB (3)
      • AWS (4)
      • GitHub (0)
    • Etc. (6)
      • 마인크래프트(Minecraft) (1)
      • 팰월드(PalWorld) (5)
    • 코딩캠프 (171)
      • 내일배움캠프 (99)
      • AI 웹개발 취업캠프 (72)

블로그 메뉴

  • 홈
  • 방명록
  • 글쓰기
  • 관리

공지사항

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
고랑E
[ TIL ] 02.17(금) 68일차
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.