inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

docker 와 local DB 연결 시 각 폴더는 어떻게 연결되는 건가요?

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요! nestjs 수강생 입니다! docker 부분에서 질문이 있어서 문의 드리게 되었습니다. 현재 local 과 docker postgres image 가 이렇게 연결되어 있습니다. 알고 있는 점 (1) docker-compose up 을 실행하면 두 폴더가 연결되며 docker postgres 의 데이터 폴더를 로컬 폴더와 매핑한다. (2) docker postgres 에서 데이터 손실 시 로컬에서 관리하는 postgres-data 폴더 덕분에 문제 없음 (3) 로컬 폴더를 날리고 docker-compose up을 재 실행하면 모든 데이터 날라감. 궁금한 점 (1) 개발자는 자신의 로컬 폴더에 있는 데이터만 CRUD 하고 그 결과가 docker postgres 에 반영되는 건가요? 그래서 로컬폴더를 삭제하고 docker-compose up 을 재 실행하면 데이터가 모두 날라가는 건가요? (2) docker-compost up 을 실행하면 처음에는 로컬에서 docker postgres 에 데이터를 가져오는데 그럼 ./postgres-data 폴더가 있을때와 없을때가 다르게 동작하는 건가요? 예를들어 있을때는 로컬에서 docker postgres 로 전송, 없을때는 docker postgres에서 로컬로 전송. 아래는 제가 이해하고 있는 점인데 어떤 부분이 맞고 틀린 지를 알 수 없어서 쭉 적어봤습니다!! 처음 docker-compose up 을 실행하면 ./postgres-data 폴더가 없어서 docker postgres의 폴더를 복사해서 가져와 매핑합니다. 매핑 되어있는 폴더 덕분에 우리는 로컬 폴더와 TypeORM 을 사용해서 데이터에 변화를 주고 이러한 CRUD 는 docker postgres 에 반영됩니다. 이러한 매핑 덕분에 docker 가 문제가 되어 docker postgres 의 데이터가 삭제되어도 로컬에서 저장된 데이터를 매핑할 수 있어 데이터를 보존할 수 있습니다. 로컬에서 ./postgres-data 를 삭제하고 docker-compose up 을 실행하면 docker postgres 는 로컬의 CRUD 중 Delete 상황을 docker postgres 에 반영하여 데이터를 모두 삭제하고 폴더가 없어졌으니 다시 받아오는 작업을 한다. 혹시 잘못된 개념 부분이 있을까요?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
jyy0223 댓글 1 좋아요 2 조회수 576

class validation & class transformer

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요. 수강생입니다. 강의 잘보고 있습니다. 한가지 질문이 있습니다. class validation 과 class transformer 도 일종의 pipe 인가요? context를 알고 validation 과 transformer 를 수행하는거 같아서요..

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
정윤근 댓글 1 좋아요 0 조회수 298

debug 문의입니다.

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요 디버그가 잘 안되어서 문의 드립니다. { // IntelliSense를 사용하여 가능한 특성에 대해 알아보세요. // 기존 특성에 대한 설명을 보려면 가리킵니다. // 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요. "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug NestJS", "runtimeExecutable": "yarn", "runtimeArgs": [ "start:debug" ], "console": "integratedTerminal", "restart": true, "port": 9229, "autoAttachChildProcesses": true } ] } 위와 같이 설정을 하고, 실행을 하였는데, 아래 메세지가 뜨면서 실패합니다. source /Users/ik/workspace/full-gpt/venv/bin/activate ➜ workspace source /Users/ik/workspace/full-gpt/venv/bin/activate (venv) ➜ workspace /usr/bin/env 'NODE_OPTIONS= --require "/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/ms-vscode.js-debug/src/bootloader.js" --inspect-publish-uid=http' 'VSCODE_INSPECTOR_OPTIONS=:::{"inspectorIpc":"/var/folders/tz/c_vc4l0n1y5fhzwqv7rphrxm0000gn/T/node-cdp.28589-f5f66828-7.sock","deferredMode":false,"waitForDebugger":"","execPath":"/Users/ik/.nvm/versions/node/v20.10.0/bin/node","onlyEntrypoint":false,"autoAttachMode":"always","fileCallback":"/var/folders/tz/c_vc4l0n1y5fhzwqv7rphrxm0000gn/T/node-debug-callback-8c26c617c10dd13b"}' /Users/ik/.nvm/versions/node/v20.10.0/bin/yarn start:debug Debugger attached. yarn run v1.22.21 error Couldn't find a package.json file in "/Users/ik/workspace" info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. Waiting for the debugger to disconnect... (venv) ➜ workspace 왜 그런지 알 수 있을까요?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
또르빗슈 댓글 2 좋아요 0 조회수 428

docker compose / postgres 부분 질문드려요

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

accept connections 까지 확인 후에도 data 폴더 안에 아무것도 생성되지 않아서요! 질문드립니다!!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
xvds1 댓글 1 좋아요 0 조회수 290

token 재발급문제

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

강의 잘듣고 있습니다. 유투브에서 flutter 영상만 보다가 평소 관심있었던 nest 까지 이어왔습니다(자바스크립트, 타입스크립트 그리고 nestjs까지) 토큰 관련 마지막강의해서 refresh token 이 만료되면 다시 ....refresh end point 로 요청을 보내서 다시 refresh 토큰을 받는다 말씀하셨는데요... 기간 만료된 refresh 토큰을 보내도 되는건가요? 아님 그 기능을 따로 구현해야 하는건가요?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
정윤근 댓글 2 좋아요 0 조회수 405

followeeCount, followerCount 증가, 감소를 위한 메소드 일반화하기 코드 공유

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

increment(conditions: FindOptionsWhere<Entity>, propertyPath: string, value: number | string) 먼저 increment메소드의 propertyPath 부분이 특정 Model의 프로퍼티를 추론 하지 않고 string으로 박혀 있는게 마음에 들지 않아서 대상이 되는 프로퍼티 필드 명을 추론 하게 작성 했습니다. // users.service.ts async incrementFollowerCount( userId: number, fieldName: keyof Pick<UsersModel, 'followerCount' | 'followeeCount'>, incrementCount: number, qr?: QueryRunner, ) { const usersRepository = this.getUsersRepository(qr); await usersRepository.increment( { id: userId, }, fieldName, incrementCount, ); } 1. fieldName: 어떤 프로퍼티를 증가, 감소를 할것인지 특정하는 파라미터 2. incrementCount : 몇 증가 시킬것인지 증가 value // users.service.ts async decrementFollowerCount( userId: number, fieldName: keyof Pick<UsersModel, 'followerCount' | 'followeeCount'>, decrementCount: number, qr?: QueryRunner, ) { const usersRepository = this.getUsersRepository(qr); await usersRepository.decrement( { id: userId, }, fieldName, decrementCount, ); } contoller에서 사용하기 // users.controller.ts @Patch('follow/:id/confirm') @UseInterceptors(TransactionInterceptoer) async patchFollowConfirm( @User() user: UsersModel, @Param('id', ParseIntPipe) followerId: number, @QueryRunnerDecorator() qr: QueryRunner, ) { await this.usersService.confirmFollow(followerId, user.id); await this.usersService.incrementFollowerCount( user.id, 'followerCount', 1, qr, ); await this.usersService.incrementFollowerCount( followerId, 'followeeCount', 1, qr, ); return true; } @Delete('follow/:id') @UseInterceptors(TransactionInterceptoer) async deleteFollow( @User() user: UsersModel, @Param('id', ParseIntPipe) followeeId: number, @QueryRunnerDecorator() qr: QueryRunner, ) { await this.usersService.deleteFollow(user.id, followeeId); await this.usersService.decrementFollowerCount( user.id, 'followerCount', 1, qr, ); await this.usersService.decrementFollowerCount( followeeId, 'followeeCount', 1, qr, ); return true; } filedName 파라미터를 특정 프로퍼티만 올 수 있게 자동완성 잘됩니다. 팔로워 confirm 되면 나의 follower 증가 + 상대방 followee 증가 팔로워 삭제 되면 나의 follower 감소 + 상대방 followee 감소 await this.usersService.incrementFollowerCount( followerId, 'followeeCount', 1, qr, ); userId가 오는 파라미터 자리에 user.id 가 아닌 followerId가 들어간 이유는 followeeCount를 증가 해야 되기 때문이다. 즉, 팔로워를 수락 했으면 나의 followerCount를 증가 시키고 상대방 followeeCount를 증가 시켜야 되기 때문에, 삭제 했을때도 같은 원리 [결과] 2번 사용자가 1번 사용자를 팔로워하고, 1번 사용자가 팔로워를 수락 했을때

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 1 좋아요 0 조회수 290

@IsPublic 어노테이션으로 RefreshTokenGuard에서 RefreshToken 검증을 하기 위한 코드 공유

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

// is-public.const.ts export enum IsPublicEnum { ISPUBLIC = 'ISPUBLIC', ISREFRESHTOKEN = 'ISREFRESHTOKEN', } // is-public.decorator.ts import { SetMetadata } from '@nestjs/common'; import { IsPublicEnum } from '../const/is-public.const'; export const ISPUBLIC_KEY = 'is_public'; export const IsPublic = (status: IsPublicEnum) => SetMetadata(ISPUBLIC_KEY, status); // bearer-token.guard.ts @Injectable() export class BearerTokenGuard implements CanActivate { constructor( private readonly authService: AuthService, private readonly usersService: UsersService, public readonly reflector: Reflector, ) {} async canActivate(context: ExecutionContext): Promise<boolean> { const req = context.switchToHttp().getRequest(); const requiredPublic = this.reflector.getAllAndOverride(ISPUBLIC_KEY, [ context.getHandler(), context.getClass, ]); if (requiredPublic) { req.requiredPublic = requiredPublic; } if (requiredPublic === IsPublicEnum.ISPUBLIC) { return true; } const rawToken = req.headers['authorization']; if (!rawToken) throw new UnauthorizedException('토큰이 없습니다!'); const token = this.authService.extractTokenFromHeader(rawToken, true); const result = await this.authService.verifyToken(token); const user = await this.usersService.getUserByEmail(result.email); req.user = user; req.token = token; req.tokenType = result.type; return true; } } 추가된 코드 if (requiredPublic) { req.requiredPublic = requiredPublic; } requiredPublic 있을때만 req에 담아줌. 추가된 코드 if (requiredPublic === IsPublicEnum.ISPUBLIC) { return true; } IsPublic일때만 return true 즉, ISREFRESHTOKEN 일때는 아래 로직들이 정상적으로 실행됨. // bearer-token.guard.ts @Injectable() export class AccessTokenGuard extends BearerTokenGuard { async canActivate(context: ExecutionContext): Promise<boolean> { await super.canActivate(context); const req = context.switchToHttp().getRequest(); if ( req.requiredPublic === IsPublicEnum.ISPUBLIC || IsPublicEnum.ISREFRESHTOKEN ) { return true; } if (req.tokenType !== 'access') { throw new UnauthorizedException('Access Token이 아닙니다.'); } return true; } } 추가된 코드 if (req.requiredPublic === IsPublicEnum.ISPUBLIC || IsPublicEnum.ISREFRESHTOKEN) { return true; } req.requiredPublic이 ISPUBLIC이거나 ISREFRESHTOKEN이면 return true로 global accessTokenGuard return true로 빠져나옴. // bearer-token-guard.ts @Injectable() export class RefreshTokenGuard extends BearerTokenGuard { async canActivate(context: ExecutionContext): Promise<boolean> { await super.canActivate(context); const req = context.switchToHttp().getRequest(); if (req.tokenType !== 'refresh') { throw new UnauthorizedException('Refresh Token이 아닙니다.'); } return true; } } 변경 사항 없음. 왜냐하면 위에서 정상적으로 refreshToken을 verify하고 req에 값이 담겼기 때문에 RefreshTokenGuard가 정상적으로 실행 되어야함. auth.controller에 적용하기 @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) {} @IsPublic(IsPublicEnum.ISREFRESHTOKEN) @Post('token/access') @UseGuards(RefreshTokenGuard) postTokenAccess(@Headers('authorization') rawToken: string) { ... } @IsPublic(IsPublicEnum.ISREFRESHTOKEN) @Post('token/refresh') @UseGuards(RefreshTokenGuard) postTokenRefresh(@Headers('authorization') rawToken: string) { ... } @IsPublic(IsPublicEnum.ISPUBLIC) @Post('login/email') @UseGuards(BasicTokenGuard) postLoginEmail(@Headers('authorization') rawToken: string) { ... } @IsPublic(IsPublicEnum.ISPUBLIC) @Post('register/email') postRegisterEmail(@Body() body: RegisterUserDto) { ... } }

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 2 좋아요 0 조회수 360

별거 아니긴 한데 nest-cli 로 만들때

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

nest cli로 resource 만들때 경로를 / 넣어주면 아래에 바로 생성 됩니다. nest g resource posts/comments 이렇게 하면 posts폴더 아래에 comments가 생깁니다!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 1 좋아요 1 조회수 420

가드와 미들웨어 질문드립니다.

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요., 강의 잘 보고있습니다. 가드랑 미들웨어 용도를 이렇게 이해하면 좋을까요? 1.가드: -특정 컨트롤러로 들어온 파라매터, 혹은 context데이터를 가공하거나 검증하고 싶을때 2.미들웨어: -특정 규칙을 가진 패쓰 혹은 컨트롤러 전체에 데이터를 검증하고 싶을때 아주 맨 처음에 저는 token 을 검증하는 BearerTokenGuard이 가드보다는 middleware 로 가는것이 맞지 않나 싶었는데요. context.user 데이터를 controller 에 내려주기 위해 IsCommentMine Guard 처럼 다른 가드로 유저데이터를 넘겨줘야하는 경우가 있어서 가드로 사용하는것으로 이해했는데 맞을까요? (그리고 middleware 로는 불가능한걸까요?)

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
닥부 댓글 1 좋아요 1 조회수 288

update comment 관련

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요. update comment 관련 두가지 질문이 있습니다. update(patch) 에서는 query runner를사용하지 않아도 되나요? update 시에repository.update 가 아닌 save 를 사용한 이유가 있을까요? 항상 강의 잘 보고있습니다. 감사합니다!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
닥부 댓글 2 좋아요 0 조회수 345

섹션5의 Post 요청 만들기에서 질문있습니다.

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요. 섹션5의 Post 요청 만들기 영상을 보다가 궁금증이 생겨 질문드립니다. Q1) 새로운 post 생성시 id를 부여할 때 배열의 마지막 인덱스 아이템을 꺼내 해당 아이템의 id에 1을 더하셨습니다. 그런데 배열 안의 아이템 순서가 꼭 id-오름차순으로 정렬되어있을거란 보장이 없기 때문에 배열에서 가장 큰 id를 찾은 후, +1을 하여 새로운 id를 부여해줘야하지 않을까 싶은데 제가 잘못 생각하고 있는걸까요? Q2) 새로운 post를 기존 배열에 push하지 않고, spread 방식으로 추가해주셨는데 특별한 이유가 있는건지도 궁금합니다!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
JB_ 댓글 1 좋아요 0 조회수 269

Transform이 적용이 안됩니다.

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

Transform을 적용해도 path값에 public/posts값이 붙지 않은 채로 계속 나옵니다. main.ts파일에 위와 같이 적용을 해도 안되는데 혹시 원인을 알 수 있나요?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
코린이 댓글 1 좋아요 0 조회수 331

웹에서 포스트 맨 사용하면 파일업로드가 불가능합니다.

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

아무리 찾아봐도 웹에서 해결하는 것이 불가능해서 postman desktop 까는 것을 추천드립니다 ㅎㅎ

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
진수하 댓글 1 좋아요 0 조회수 380

gateway level에서 filter도 잘 작동합니다!

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

@UsePipes( new ValidationPipe({ transform: true, transformOptions: { enableImplicitConversion: true, }, whitelist: true, forbidNonWhitelisted: true, }), ) @UseFilters(SocketCatchHttpExceptionFilter) @WebSocketGateway({ // ws://localhost:3000/chats namespace: 'chats', }) export class ChatsGateway implements OnGatewayConnection { constructor( private readonly chatsService: ChatsService, private readonly messagesService: ChatsMessagesService, ) {} ... } 각각의 메소드마다 넣어주는것보다 나은것 같아서 공유 해보아요!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 1 좋아요 1 조회수 339

ValidationPipe를 좀 더 편하게 쓸 수 없을까해서 찾아보니 controller에서 사용 할 수 있더라고요

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

https://docs.nestjs.com/faq/request-lifecycle 공식 문서에 보니까 controller level에서 사용 할 수 있는것 같아서 controller와 gateway가 비슷하니까 사용 가능하지 않을까 해서 테스트 해보니까 @UsePipes( new ValidationPipe({ transform: true, transformOptions: { enableImplicitConversion: true, }, whitelist: true, forbidNonWhitelisted: true, }), ) @WebSocketGateway({ // ws://localhost:3000/chats namespace: 'chats', }) export class ChatsGateway implements OnGatewayConnection { ... } 해당 gateway에서 usePipes를 설정 할 수 있더라고요! 차선책으로 이것도 괜찮은것 같아서 공유 해봅니다!

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 1 좋아요 3 조회수 395

19:55초정도에 3명의 사용자중 메세지를 보낼려는 사용자가 "enter_room"에 메세지를 보내는데

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

아마 강사님 실수인듯합니다. User 1이 enter_room에 2번 채팅방에 참여 한다고 메세지를 보내는데 "enter_chat"이 맞습니다! 제가 실험 해보니까 결국 enter_chat을 제대로 하지 않은 경우에 다른 사용자가 보낸 message를 제대로 리시브 받지 못하더라고요.

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
rhkdtjd_12 댓글 1 좋아요 0 조회수 241

쿼리러너관련질문

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요 쿼리러너 관련 질문드립니다 코멘트 생성시 Pid 에 일부러 엉뚱한 값을 넣는 경우 QueryRunner를 쓰고 안쓰고에 차이가 있더라구요. 예를들어 this.commentService.ceateComment(dto, pId, user, qr); qr repository 를 일부러 사용하지 않게 조작하면 pid 에 이상한 값을 넣어도 valitation 없이 create 가 되었는데 Qr 을 넘겨주는 순간 아래와 같이 유효하지 않은 pk 에 대해 조작하려고 한다는 validation 을 해주더라구요. { "path": "/posts/{엉뚱한 값}/comments", "statusCode": 500, "message": "insert or update on table \"comment\" violates foreign key constraint \"FK_94a85bb16d24033a2afdd5df060\"", "timestamp": "1/21/2024, 4:06:08 PM" } 이런 차이는 어디서 나는것일지, 이런것들도 Query Runner 의 역할인지도 궁금합니다.

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
닥부 댓글 1 좋아요 0 조회수 335

length에서 min값만 설정하고 싶을 때 max 없이 validationOptions을 어떻게 전달할 수 있나요..?

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

length에서 max값을 전달 안해주고 min만 설정하고 싶을때 if(args.constraints.length===2){ } else}{ } 여기서 else 가 실행되어야 하는데 max 값 없이 validationOptions만을 전달하면 validationOptions가 두번째 인자로 전달되는 것 아닌가요..? 이렇게 하면 에러 나는데.. max 값에 undefined나 null을 넣어도 안되는 것 같습니다. 어떻게 max 값 없이 validationOptions를 실행할 수 있나요..?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
purnsup90 댓글 2 좋아요 0 조회수 360

모델명을 복수로 하는 이유가 따로 있을까요?

미해결

[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core

안녕하세요. 강의내용과는 상관없는 뜬금 질문인데, 모델의 엔티티파일, api path 명 등등에 단어들을 대부분 복수로 표기하시는 이유가 따로 있는지 궁금합니다. MessageModels vs MessagesModel ? /users/:id vs user/:id ?

  • javascript
  • typescript
  • rest-api
  • nestjs
  • backend
닥부 댓글 2 좋아요 0 조회수 445

인기 태그

인프런 TOP Writers

주간 인기글