1. SQL ๊ด๊ณ
- foreign key๋ฅผ ์๊ณ ์์ผ๋ฉด, ํด๋น ํค์ ๋ฐ์ดํฐ๋ฅผ ๊ตณ์ด ๊ฐ์ง ํ์๊ฐ ์๋ค.
2. UserModel ์์ฑ
์ด์ ๋ค์ typeorm์ฉ ํด๋๊ฐ ์๋ ๊ธฐ์กด rest-server๋ก ์ค์ต์ ์งํํ๋ค. ๊ทธ ๋ค์ user ๋ชจ๋ธ์ nest cli ๋ช ๋ น์ด๋ก ์์ฑํ๋ค.
1nest g resource2? What name would you like to use for this resource? users3? What transport layer do you use? REST API4? Would you like to generate CRUD entry points? No
๊ทธ๋ฆฌ๊ณ cli๋ก ๋ง๋ค๋ฉด, ์๋์ผ๋ก app ๋ชจ๋์ ๋ฐฉ๊ธ ์์ฑํ ๋ชจ๋์ ์ถ๊ฐํด์ค๋ค.
src/users/entities/users.entity.ts ํ์ผ์ ๋ง๋ ๋ค.
1import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'23@Entity()4export class UsersModel {5@PrimaryGeneratedColumn()6id: number78@Column()9nickname: string1011@Column()12email: string1314@Column()15password: string16}
app ๋ชจ๋์ UsersModel์ ์ถ๊ฐํ๋ค.
1@Module({2imports: [3PostsModule,4TypeOrmModule.forRoot({5// ์๋ต6// entitiesํด๋์ ์์ฑํ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ7entities: [PostsModel, UsersModel],8synchronize: true,9}),10UsersModule,11],12controllers: [AppController],13providers: [AppService],14})
3. Column ์ต์ ์ข ๋ฅ
@Column์ Cmd + ๋ง์ฐ์ค ์ผ์ชฝ ๋ก ํด๋ฆญํ๋ฉด, ๋ช
์ธ์๊ฐ ๋์จ๋ค.
1import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'23@Entity()4export class UsersModel {5@PrimaryGeneratedColumn()6id: number78/*** ๋๋ค์ ํน์ฑ9* 1) ๊ธธ์ด๊ฐ 20์ ๋์ง ์์ ๊ฒ10* 2) ์ ์ผ๋ฌด์ดํ ๊ฐ์ด ๋ ๊ฒ11*/12@Column({13length: 20,14unique: true,15})16nickname: string1718/*** ์ด๋ฉ์ผ ํน์ฑ19* 1) ์ ์ผ๋ฌด์ดํ ๊ฐ์ด ๋ ๊ฒ20*/21@Column({22unique: true,23})24email: string2526@Column()27password: string28}
4. Enum Column ์์ฑ
users/const/roles.const.ts ํ์ผ์ ๋ง๋ญ๋๋ค.
1export enum RolesEnum {2ADMIN = 'ADMIN',3USER = 'USER',4}
cf, enum ํ์ ์ TS์์ ์ ๊ณตํ๋ ๋ช ๋ช ๋ ์์์ ์งํฉ์ ๋ํ๋ด๋ ๋ฐ์ดํฐ ํ์
1@Entity()2export class UsersModel {3// ์๋ต45@Column({6// role ํน์ฑ์ ํ์ ์ RolesEnum์ ๋ชจ๋ ๊ฐ๋ค๋ก ์ง์ 7enum: Object.values(RolesEnum),8default: RolesEnum.USER,9})10role: RolesEnum11}
5. User ๊ด๋ จ ์๋น์ค ๋ฐ ์ปจํธ๋กค๋ฌ ์์ฑ
1// ์๋ต23@Module({4// ์ด ๋ชจ๋ ์์์ UsersModel์ ์ด๋์๋ ์ฌ์ฉ ๊ฐ๋ฅ5imports: [TypeOrmModule.forFeature([UsersModel])],6controllers: [UsersController],7providers: [UsersService],8})9export class UsersModule {}
์ ์ ์๋น์ค๋ฅผ ๋ง๋ ๋ค.
1import { Injectable } from '@nestjs/common'2import { InjectRepository } from '@nestjs/typeorm'3import { UsersModel } from './entities/users.entity'4import { Repository } from 'typeorm'56@Injectable()7export class UsersService {8constructor(9@InjectRepository(UsersModel)10private readonly userRepository: Repository<UsersModel>,11) {}1213async createUser(nickname: string, email: string, password: string) {14const user = this.userRepository.create({15nickname,16email,17password,18})19const newUser = await this.userRepository.save(user)20return newUser21}2223async getAllUsers() {24return this.userRepository.find()25}26}
์์์ ๋ง๋ ์๋น์ค ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ ๋ค.
1import { Body, Controller, Get, Post } from '@nestjs/common'2import { UsersService } from './users.service'34@Controller('users')5export class UsersController {6constructor(private readonly usersService: UsersService) {}78@Get()9getUsers() {10return this.usersService.getAllUsers()11}1213@Post()14postUser(15@Body('nickname') nickname: string, //16@Body('email') email: string,17@Body('password') password: string,18) {19return this.usersService.createUser(nickname, email, password)20}21}
6. Author ๊ด๊ณ ์์ฑ
ํฌ์คํธ ์ํฐํฐ์ ๋ค๋์ผ ๊ด๊ณ๋ฅผ ๋ฃ์ด์ค๋ค.
1@Entity()2export class PostsModel {3@PrimaryGeneratedColumn()4id: number56/*** ์์ฑ์ 1๋ช ์ด ์ฌ๋ฌ ๊ฐ์ ํฌ์คํธ๋ฅผ ์์ฑ7* 1) UserModel๊ณผ ์ฐ๋ํ๋ค (Foreign Key๋ฅผ ์ฌ์ฉํด์)8* 2) null์ด ๋ ์ ์๋ค9*/10// one์ ํด๋นํ๋ ํด๋์ค ํ์ ์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค11// ์ด ํด๋์ค ํ์ ์ ๋ ๋ฒ์จฐ ํจ์์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ์ ์๋ค.12// ์ด๋ค ํ๋ผ๋ฏธํฐ์ ์ฐ๋์ํฌ์ง ์ ํ13@ManyToOne(() => UsersModel, user => user.posts, {14nullable: false,15})16author: UsersModel1718// ์๋ต19}
์ ์ ์ํฐํฐ์ ์ผ๋๋ค ๊ด๊ณ๋ฅผ ๋ฃ์ด์ค๋ค.
1@Entity()2export class UsersModel {3// ์๋ต45@OneToMany(() => PostsModel, post => post.author)6posts: PostsModel[]7}
7. ์๋ฌ ํด๊ฒฐ ๋ฐ DB ์ด๊ธฐํ
posts ์๋น์ค์ ๋ณด๋ฉด author ๋ถ๋ถ์ ์๋ฌ๊ฐ ๋ ๊ฒ๋๋ค. author๊ฐ string์ด์๋ค๊ฐ, UsersModel๋ก ๋ณ๊ฒฝ๋์ด์ ์๊ธด๊ฒ๋๋ค.
1// posts.service.ts2/**3* 1) create : ์ ์ฅํ ๊ฐ์ฒด๋ฅผ ์์ฑ4* 2) save : ๊ฐ์ฒด๋ฅผ ์ ์ฅ (create aใ ์๋์์ ์์ฑํ ๊ฐ์ฒด๋ก)5*/6async createPost(authorId: number, title: string, content: string) {7const post = this.postsRepository.create({8author: {9id: authorId,10},11title,12content,13likeCount: 0,14commentCount: 0,15})1617const newPost = await this.postsRepository.save(post)1819return newPost20}2122/** save์ 2๊ฐ์ง ๊ธฐ๋ฅ23* 1) ๋ง์ฝ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์๋๋ค๋ฉด(id ๊ธฐ์ค) ์๋ก ์์ฑํ๋ค.24* 2) ๋ง์ฝ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ค๋ฉด(๊ฐ์ id์ ๊ฐ์ด ์กด์ฌํ๋ค๋ฉด) ์กด์ฌํ๋ ๊ฐ์ ์ ๋ฐ์ดํธํ๋ค.25*/26async updatePost(postId: number, title: string, content: string) {27const post = await this.postsRepository.findOne({28where: { id: postId },29})3031if (!post) throw new NotFoundException()32if (title) post.title = title33if (content) post.content = content3435const newPost = await this.postsRepository.save(post)36return newPost37}
1// posts.controller.ts ์๋ต2/*** 3) POST /posts3* post๋ฅผ ์์ฑํ๋ค4*/5@Post()6postPosts(7@Body('authorId') authorId: number, //8@Body('title') title: string,9@Body('content') content: string,10) {11return this.postsService.createPost(authorId, title, content)12}1314/*** 4) PATCH /posts/:id15* id์ ํด๋นํ๋ post๋ฅผ ๋ถ๋ถ ๋ณ๊ฒฝํ๋ค16*/17@Patch(':id')18putPost(19@Param('id') id: string, //20@Body('title') title?: string,21@Body('content') content?: string,22) {23return this.postsService.updatePost(+id, title, content)24}
๋ฃ์ ๋ฐ์ดํฐ๋ค ๋๋ฌธ์ author๊ฐ null์ธ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๊ธฐ์, DB ์ด๊ธฐํํด์ค๋๋ค.
8. ๊ด๊ณ๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ ์์ฑ
- posts์ users์ ๊ด๊ณ๋ฅผ PostMan์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ค.
9. ๊ด๊ณ ํฌํจํ ์ฟผ๋ฆฌ ์์ฑ
1// posts.service.ts ์๋ต2async getAllPosts() {3return this.postsRepository.find({ relations: ['author'] })4}56async getPostById(id: number) {7const post = await this.postsRepository.findOne({8// PostsModel์ id๊ฐ ์ ๋ ฅ๋ฐ์ id์ ๊ฐ์์ง ํํฐ๋ง9where: {10id,11},12relations: ['author'],13})14if (!post) {15throw new NotFoundException()16}17return post18}