1. AccessTokenGuard ์ ์ฉ
post ์์ฑ์ ๋ก๊ทธ์ธ์ ํด์ผ์ง๋ง, ์์ฑํ ์ ์๊ฒ ๋ฐ๊ฟ๋ณด๊ฒ ๋ค.
1// posts.controller.ts ์๋ต2@Post()3@UseGuards(AccessTokenGuard)4postPosts(5@Request() req: any,6@Body('title') title: string, //7@Body('content') content: string,8// ๊ธฐ๋ณธ๊ฐ์ true๋ก ์ค์ ํ๋ ํ์ดํ9// @Body('isPublic', new DefaultValuePipe(true)) isPublic: boolean,10) {11const authorId = req.user.id12return this.postsService.createPost(authorId, title, content)13}
- ๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ง ํฌ์คํธ์์ฑ API๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ฐ๊พธ๋ ค๋ฉด,
- AccessTokenGuard์ ์ ์ฉํด์ฃผ๋ฉด ๋๋ค.
- cf. ์ด๋ฅผ
private route๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๊ทธ๋ฌ๋ฉด ์๋์ ๊ฐ์ด ๋ํ๋์ ์๋ฌ๊ฐ ๋์ฌ ๊ฒ์ด๋ค.
1Nest can't resolve dependencies of the AccessTokenGuard2(?, UsersService). Please make sure that the argument AuthService3at index [0] is available in the PostsModule context.
posts ๋ชจ๋์ AuthService, UsersService์ JwtModule.register(), UsersModel๊น์ง ์ถ๊ฐํด์ค๋ค.
1// posts.module.ts ์๋ต2@Module({3imports: [4JwtModule.register({}), // ์ถ๊ฐ5TypeOrmModule.forFeature([PostsModel, UsersModel]), // ์ถ๊ฐ6],7controllers: [PostsController],8providers: [PostsService, AuthService, UsersService], // ์ถ๊ฐ9})10export class PostsModule {}
2. User ์ปค์คํ ๋ฐ์ฝ๋ ์ดํฐ ์์ฑ
๋ชจ๋ ๋ฐ์ฝ๋ ์ดํฐ๋ ๋๋ฌธ์๋ก ์์ํ๋ค.
users/decorator/user.decorator.ts ํ์ผ์ ๋ง๋ ๋ค.
1import { ExecutionContext, InternalServerErrorException, createParamDecorator } from '@nestjs/common'23export const User = createParamDecorator((data, context: ExecutionContext) => {4const req = context.switchToHttp().getRequest()5const user = req.user67if (!user) {8throw new InternalServerErrorException(9'User ๋ฐ์ฝ๋ ์ดํฐ๋ AccessTokenGuard์ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค. Request์ user ํ๋กํผํฐ๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค!',10)11}1213return user14})
posts ์ปจํธ๋กค๋ฌ์ User ์ปค์คํ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ ์ฉํ๋ค.
1// posts.controller.ts ์๋ต2@Post()3@UseGuards(AccessTokenGuard)4postPosts(5@User() user: UsersModel, // โ User ์ปค์คํ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ ์ฉ6@Body('title') title: string,7@Body('content') content: string,8// ๊ธฐ๋ณธ๊ฐ์ true๋ก ์ค์ ํ๋ ํ์ดํ9// @Body('isPublic', new DefaultValuePipe(true)) isPublic: boolean,10) {11return this.postsService.createPost(user.id, title, content)12}
auth ์๋น์ค์ ํ ํฐ ๊ฒ์ฆ์ try~catch ๋ฌธ์ ์ ์ฉํ๋ค.
1// auth.service.ts ์๋ต2/*** ํ ํฐ ๊ฒ์ฆ3*4*/5verifyToken(token: string) {6try {7return this.jwtService.verify(token, {8secret: JWT_SECRET,9})10} catch (err) {11throw new UnauthorizedException('ํ ํฐ์ด ๋ง๋ฃ๋๊ฑฐ๋ ์๋ชป๋ ํ ํฐ์ ๋๋ค.')12}13}
ํฌ์คํธ๋งจ์์ authorId ์์ด, ํ ํฐ์์ ์ ์ ์ ๋ณด๋ฅผ ๊บผ๋ด ํฌ์คํธ๋ฅผ ์์ฑํ๋ ๊ฑธ ํ์ธํ๋ค.
3. ์ปค์คํ ๋ฐ์ฝ๋ ์ดํฐ์ data ํ๋ผ๋ฏธํฐ ์ฌ์ฉ
data ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํด์, ์ฌ์ฉ์์ ํน์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ด์ฃผ๋ฉด, ํด๋ฑ๋๋ ํ๋กํผํฐ๋ฅผ ๋ฐํํ๊ฒ ํด์ค ์ ์๋ค.
1import { ExecutionContext, InternalServerErrorException, createParamDecorator } from '@nestjs/common'2import { UsersModel } from '../entities/users.entity'34export const User = createParamDecorator(5(6data: keyof UsersModel | undefined, //7context: ExecutionContext,8) => {9const req = context.switchToHttp().getRequest()10const user = req.user as UsersModel1112if (!user) {13throw new InternalServerErrorException(14'User ๋ฐ์ฝ๋ ์ดํฐ๋ AccessTokenGuard์ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค. Request์ user ํ๋กํผํฐ๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค!',15)16}1718if (data) {19return user[data]20}2122return user23},24)
posts ์ปจํธ๋กค๋ฌ์ User ์ปค์คํ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ ์ฉํ๋ค.
1// posts.controller.ts ์๋ต2@Post()3@UseGuards(AccessTokenGuard)4postPosts(5@User('id') userId: number, // โ data ํ๋ผ๋ฏธํฐ๋ฅผ ์ด์ฉํด ํน์ ํ๋ผ๋ฏธํฐ๋ง ๋ฐ์ ์ ์๋ค.6@Body('title') title: string, //7@Body('content') content: string,8// ๊ธฐ๋ณธ๊ฐ์ true๋ก ์ค์ ํ๋ ํ์ดํ9// @Body('isPublic', new DefaultValuePipe(true)) isPublic: boolean,10) {11return this.postsService.createPost(userId, title, content)12}