오늘 DB 처음 써보는 사람 나야나~~
설치하는 것부터 막혔지만 NestJS 공식문서와 똑똑하신 분들의 기술블로그들을 참고해서 하나씩 차근차근 해결한 덕분에 DB로 옮겨올 수 있었다!
Algorithm이 왜 3번이나 저장되었지?
창을 새로 클릭할 때마다 save 함수가 호출되어서 그런 듯하다.
더 이상 중복 저장되지 않도록 save 함수는 잠시 주석 처리하였다.
곧 삭제 구현도 해보자!
여튼 DB는 여태 이론만 훑어봤지 직접 사용해본 적이 없어서 미지의 영역이었는데 새로 시도하고 옮기니까 뿌듯하다!
감격의 순간을 캡처~
이제 vscode에 배열로 저장 안해도된다 ㅋㅋㅋㅋ
그렇다면 이제 지금까지의 과정을 정리하자.
오늘 의도치 않게 TypeOrm도 사용하게 되었다. Docs에서 권장하길래 뭔지도 제대로 모르고 사용해봤는데, 이번 기회에 오늘 사용해본 지식들도 더 공부해서 정리를 좀 해봐야겠다.
MySQL과 MySQL WorkBench를 설치한다.
❯ mysql --version
mysql Ver 8.0.37 for macos14 on arm64 (MySQL Community Server - GPL)
최신 버전을 받았었는데 Workbench가 자꾸 종료되어서 버전 버그 문제인지 낮은 버전으로 다시 받았다. 8.0.37 버전으로 받았더니 connection되지 않고 종료되는 문제가 사라졌다.
Test Connection 버튼을 클릭하고 OK를 클릭하니 연결이 되었다. 버전 문제인지 Test Connection을 클릭하지 않아서인지는 허둥지둥 했어서 확실히 잘 모르겠다. Test Connection은 말 그대로 연결을 테스트 하는 버튼일테니 버전 문제일 것 같긴하다.
$ pnpm install --save @nestjs/typeorm typeorm mysql2
TypeOrm이 무엇인지 간단히 공부를 해보았다.
✏️ Orm이란?
Object-relational mapping이란 뜻. 객체 관계형 매핑? 객체지향 프로그래밍 언어를 사용하여 관계형 데이터베이스와 상호작용할 수 있도록 해주는 기술이다. SQL 쿼리를 직접 작성하지 않고 데이터베이스 작업을 대신 사용할 수 있는 기술이다.
https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping
✏️ TypeOrm이란?
javascript와 Typescript로 nodeJS에서 사용할 수 있는 Orm이다. 나는 NestJS를 사용하고 있으니 TypeOrm을 사용해서 객체지향적으로 데이터를 관리하면 딱이다.
https://typeorm.io/
정적 모듈과 동적 모듈의 차이에 대해 저번 시간에 기록했었다.
https://velog.io/@jasmine0714/nestJS-jwt-secretorprivatekey-must-have-a-value
...
import { TypeOrmModule } from '@nestjs/typeorm';
import { Category } from './category/category.entity';
@Module({
imports: [
AuthModule,
UsersModule,
CategoryModule,
ConfigModule.forRoot({
isGlobal: true,
}),
TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
entities: [Category],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
DB 관련 정보는 .env에 저장해두었다.
port는 Number type이어야 하므로 +를 붙여주었다.
synchronize: true로 설정하면 앱이 실행될 때마다 엔티티 정의를 기반으로 DB 스키마를 자동으로 동기화해준다. 단, production 모드에서는 엔티티 모델을 변경했을 때 기존 데이터를 덮어쓸 위험이 있기 때문에 false로 지정하라고 docs에 나와있다.
✏️ entity란?
데이터 베이스 테이블에 매핑되는 클래스를 의미한다. @Entity라는 데코레이터를 사용하여 entity를 정의할 수 있다. 모든 테이블에 primary key가 있어야 하므로, entity에는 primary column이 있어야 한다.
https://typeorm.io/entities#what-is-entity
처음으로 간단하게 만들어본 entity는 아래와 같다.
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity({ name: 'category' }) // 생성될 테이블 이름
export class Category {
@PrimaryGeneratedColumn() // 자동생성되며, 1씩 증가하는 Primary key
id: number;
@Column()
title: string;
}
children도 곧 추가해서 2 depth로 만들 예정!
// category.module.ts
@Module({
imports: [TypeOrmModule.forFeature([Category])],
controllers: [CategoryController],
providers: [CategoryService],
})
export class CategoryModule {}
// category.service.ts
@Injectable()
export class CategoryService {
constructor(
@InjectRepository(Category)
private categoryRepository: Repository<Category>,
) {}
..
async saveCategories(): Promise<void> {
for (const categoryData of categoryList) {
await this.saveCategory(categoryData);
}
}
private async saveCategory(categoryData: Category): Promise<void> {
const category = new Category();
category.id = categoryData.id;
category.title = categoryData.title;
await this.categoryRepository.save(category);
}
// main.ts
const app = await NestFactory.create(AppModule);
const categoryService = app.get(CategoryService);
await categoryService.saveCategories();
저장 완료!
이제 소항목 카테고리도 저장해보자.
근데 children table을 따로 만들어야 해? 어떻게 해야해?
다음 이 시간에 2 depth 항목을 다룰 때 entity 간의 참조를 어떻게 구성해야할지 다뤄보겠다.