44,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
이전 질문에 이어서 질문드립니다.
이전에 findEmail 과 같은 함수에서 promise allSettled를 사용해야 할지 질문했었는데 findEmail에 allSettled를 적용시키려고 시도해봤습니다. 이전 질문의 코드를 아래 처럼 재구성하였습니다. await Promise.allSettled([ this.authRepositry.isExistUserWithRealName(realName), this.authRepositry.isExistUserWithPhoneNumber(phoneNumber), ]).then((data) => { const errors = data.map((idx) => idx.status === "rejected" ? idx.reason : false, ); if (errors.includes(false)) { const foundWithRealName = data[0].value; } throw new BadRequestException(errors, "Find Email Error"); }); allSettled 인자의 함수들에는 실명과 전화번호가 없을 시 에러를 내는 코드가 있고 에러가 있을시 rejected 상태의 인덱스를 errors 배열에 담고 아닐 시 false를 담습니다. 그리고 errors에 false값이 포함되어있다면 실명과 전화번호를 매치시켜 일치한다면 email을 리턴하게끔 하려 했습니다. 그런데 data변수가 PromiseRejectedResult라서 value속성이 없다 합니다. data[idx].value를 해야 value 안에 있는 id를 서로 비교 시킬수가 있는데 value를 사용할 수가 없습니다. 만약 콘솔로 찍어보면 "fullfiled" 라고 뜨기는 하는데 말이죠. 제가 디버그 콘솔을 자주 사용하는데 const foundWithRealName이 있는 라인에서 data[0].value를 찍어보면 정상적으로 User Entity값을 얻어올 수가 있습니다. 어떻게 좋은 방법이 없을까요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
이런 경우에 promise allSettled를 사용해야 할지 궁금합니다.
nest 강좌와 관련된 부분은 아니지만 조현영님께서 await을 연달아 사용하지 말라고 언급하신것이 생각나서 질문드립니다. 아래 함수는 사용자가 회원가입을 했을 때 입력했던 실명과 전화번호를 매치 시켜 email을 찾아내는 코드입니다. async findEmail(findEmailDto: FindEmailDto): Promise<string> { const { realName, phoneNumber } = findEmailDto; const foundWithRealName = await this.authRepositry.isExistUserWithRealName( realName, ); const foundWithPhoneNumber = await this.authRepositry.isExistUserWithPhoneNumber(phoneNumber); if (!foundWithRealName || !foundWithPhoneNumber) { throw new UnauthorizedException("올바르지 않은 정보입니다."); } if (!(foundWithRealName.id === foundWithPhoneNumber.id)) { throw new UnauthorizedException("올바르지 않은 정보입니다."); } return foundWithRealName.email; } 실명과 전화번호로 유저 엔티티를 찾아내고 각 정보가 존재하는지 그리고 각 정보가 한 유저의 아이디에서 나온 것인지 확인 한뒤 email을 리턴해줍니다. await이 두번 사용되긴 하였는데 이런 경우에도 await을 연달아 사용하지 않고 promise allSettled로 묶어야 하는지 궁금합니다. 제 생각에는 코드가 하는 작업이 별로 없어서 await을 써도 될거같긴해요.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
요청 & 응답 Body 데이터 snake case
제로초님 안녕하세요! 최근 nestjs에 입문해 많은 도움을 받고 있는 백엔드 개발자 입니다. 강의 내용을 바탕으로 별도로 공부하며 서버를 하나 구축하고 있는데요! API 요청 & 응답 Body 데이터를 구성할 때, 필드명(key값)을 snake case로 유지시키고 싶은데요! 뭔가 배운 지식으로는 Interceptor나 Pipe를 잘 활용하면 구현이 가능할 것 같은데, 질문은 아래와 같습니다! 1. snake case로 요청 & 응답 데이터를 만드는 것이 현명할지 제로초님의 조언을 구하고 싶습니다 1. camel case의 DTO를 snake case 형태의 Body 데이터로 변환하는 기능은 nestjs에서 따로 제공하고 있지 않은 것 같은데요. 제가 밑바닥부터 구현을 해야할지 조언을 구하고 싶습니다 (구글링을 여러번 했는데 관련 라이브러리나 코드를 찾지 못했습니다..) 항상 좋은 강의 감사합니다 :)
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
관계 설정 질문 드립니다.
조현영님 안녕하세요. 얼마 전에 nestjs에 관심이 생겨서 nestjs로 프로젝트 진행중에 mongodb를 쓰다가 typeorm 한 번 써볼까 해서 강의 결제하게 되었습니다. 제가 현재 4가지 entity들을 만들었습니다. // product.entity.ts import { float } from "aws-sdk/clients/lightsail"; import { IsNotEmpty, IsNumber, IsString } from "class-validator"; import { CommonEntity } from "src/common/entities/common.entity"; import { Column, Entity } from "typeorm"; @Entity("products") export class ProductEntity extends CommonEntity { @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 20, unique: true, nullable: false }) name: string; @IsNumber() @IsNotEmpty() @Column({ type: "int", unsigned: true, nullable: false }) price: number; @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 20, nullable: false }) origin: string; @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 20, nullable: false }) type: string; @IsString() @IsNotEmpty() @Column({ type: "text", nullable: true }) description: string; @Column({ type: "varchar", default: "no image yet" }) imgUrl?: string; @Column({ type: "int", default: 50 }) quantity: number; @Column({ type: "float", default: 0.0 }) rating: float; } // user.entity.ts import { Exclude } from "class-transformer"; import { IsNotEmpty, IsString, IsEmail } from "class-validator"; import { CommonEntity } from "src/common/entities/common.entity"; import { Column, Entity } from "typeorm"; @Entity("users") export class UserEntity extends CommonEntity { @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 20, nullable: false }) realName: string; @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 20, unique: true, nullable: false }) nickName: string; @IsString() @IsNotEmpty() @Column({ type: "date", nullable: false }) birth: string; @IsString() @IsNotEmpty() @Column({ type: "enum", enum: ["male", "female"] }) gender: string; @IsEmail() @IsNotEmpty() @Column({ type: "varchar", length: 60, unique: true, nullable: false }) email: string; @Exclude() @Column({ type: "varchar", nullable: false }) password: string; @IsString() @IsNotEmpty() @Column({ type: "varchar", length: 15, unique: true, nullable: false }) phoneNumber: string; @Column({ type: "smallint", default: 0 }) point: number; @Column({ type: "enum", enum: ["general", "special", "admin"], default: "general", }) userType: string; } // upload.entity.ts import { IsNotEmpty, IsString } from "class-validator"; import { CommonEntity } from "src/common/entities/common.entity"; import { Column, Entity } from "typeorm"; @Entity("images") export class ImagesEntity extends CommonEntity { @IsString() @IsNotEmpty() @Column({ type: "varchar", nullable: false, unique: true }) imageFileName: string; @IsString() @IsNotEmpty() @Column({ type: "varchar", nullable: false }) uploader: string; } @Entity("videos") export class VideosEntity extends CommonEntity { @IsString() @IsNotEmpty() @Column({ type: "varchar", nullable: false, unique: true }) videoFileName: string; @IsString() @IsNotEmpty() @Column({ type: "varchar", nullable: false }) uploader: string; } // common.entity.ts import { IsUUID } from "class-validator"; import { CreateDateColumn, DeleteDateColumn, PrimaryGeneratedColumn, UpdateDateColumn, } from "typeorm"; export abstract class CommonEntity { @IsUUID() @PrimaryGeneratedColumn("uuid") id: string; @CreateDateColumn({ type: "timestamp", }) createdAt: Date; @UpdateDateColumn({ type: "timestamp", }) updatedAt: Date; @DeleteDateColumn({ type: "timestamp", }) deletedAt: Date; } product user upload common 4개의 entity가 있습니다. id, createdAt, updatedAt, deletedAt등을 common entity에서 각각 다른 entity들에게 상속 시켜서 사용합니다. 아직 관계 설정은 적용하지 않았습니다. 질문이 무엇이냐면 1. product entity에서 imgUrl이라는 컬럼이 있는데 이 컬럼을 upload entity에 있는 images entity의 imageFileName라는 컬럼과 매치 시키려 하는데 햇갈리는 부분이 상품한개에 이미지한개 이니까 OneToOne이 맞는지 아니면 상품 여러개가 이미지 여러개를 가질 수 있으니 ManyToMany가 맞는지 궁금합니다. 2. user entity에서 nickName이라는 컬럼이 있는데 이 컬럼을 images entity의 uploader컬럼과 매치 시키려 하는데 사용자 한명이 이미지를 한개만 업로드 하는것이 아니니까 user entity의 nickName컬럼에 OneToMany를 적용시키고 image entity의 uploader컬럼에 ManyToOne을 적용시키는것이 맞는지 궁금합니다. 3. 위의 2가지 방법이 아니라면 image entity를 product entity와 user entity가 서로 ManyToMany 관계를 거쳐서 나온 중간 테이블(엔티티)로 만들어서 사용해야 할까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
@Param
제로초님 오랜만에 복습겸 다시 듣습니다. 혹시 @Param 설정하실때 main.ts 에서 transform : true 설정하면 되지만 하나하나 ParseIntPipe 설정하신게 그냥 단순히 고집이 맞으신건가용 ?? 어떠한 다른 이유가있을까요 ?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket.io와 gateway에 대한 질문입니다!
Nest.JS document를 읽어보면 클라이언트에서 보내준 메세지를 @subscribeMessage()에서 받아와서 gateway에 주입된 service를 이용해 로직을 수행하는 걸로 이해했는데 강의에서는 client -> controller -> service에서 gateway 의존성 주입 후 client로 emit 하는 순서로 진행이 되는데 client에서 바로 gateway로 진입하지 않은 이유를 알고 싶습니다.
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
기능 확장시 폴더 파일 관리
기능을 확장할 때 폴더, 파일구분을 어떻게 하는게 효율적이고 직관적인지 궁금합니다. 예를 들어서 유저부분에 컨트롤러, 서비스 기능이 많이 생겨 확장하는 부분에서 어떻게 처리하는지에 대한건데 제 생각은 users 내부 폴더에서 두개의 컨트롤러, 서비스를 만들어 주는게 맞나요?? 아니면 users에서 하위 폴더를 만들어 트리 형식으로 이어주기도 하나요??
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
typeorm 과 Aurora serverless v2 연결
제로초님 Aurora serverless v2 가 나와서 사용하려는데, 엔드포인트가 라이트 인스턴스, 리드 인스턴스 이렇게 두개있어서, Typeorm 에 두개의 엔드포인트를 연결하고싶은데 가능한가요?? 혹시 아신다면 방법을 알려주시면 정말 감사하겠습니다!
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
ec2 micro 사용중인데 적절한 배포 순서가 알고 싶네요.
안녕하세요, nest.js 에 대해 처음 공부하고 dev 서버에서 막 API 들을 만들고 곧 Prod 서버에 올릴 예정에 있습니다. 현제는 제가 지금 어떤 작업을 해서 dev 에 수정사항을 반영할때 [ 로컬에서 수정 -> 깃 푸쉬 -> ec2 에서 forever stop -> ec2 재가동 -> ec2 에서 git pull -> forever start ] 로 하고있는데 이번 강의를 듣고 저도 제 package.json 에 아래와 같이 넣었다면 아래에 쓴 배포 순서가 맞나요? ["start:prod":"sudo cross-env NODE_ENV=prod PORT=8000 forever start dist/main.js",] Prod 서버를 만일 제가 만들게 될 시에는, [ 로컬 수정 -> npm run build -> 깃 푸쉬 -> ec2 에서 forever stop -> ec2 재가동 -> ec2 에서 git pull -> 로컬 에서 start:prod] 를 하는 인식이 맞나요 ㅠㅠ
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
TS2307: Cannot find module 'typeorm-seeding' or its corresponding type declarations.
이 부분이 올바르게 안되서 질문드립니다.제로초님 같은 경우에는 implements 후 Seeder을 사용하니까 자동 리포트가 되었는데, 저는 자동리포트가 안되어서 수동으로 직접 쳤는데도 import가 안되네요. 혹시 어떠한 이유로 안되는 지 알 수 있을까요? 이것과 같은 증상으로는 Connection 또한 마찬가지입니다. 패키지 설치는 다 한 것 같은데 이유를 모르겠습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socketIO room 관련 질문
io.of(`/ws-${workspace.url}`) .to(`/ws-${workspace.url}-${channel.id}`) .emit("message", chatWithUser); this.eventsGateway.server // .of(`/ws-${url}`) .to(`/ws-${url}-${chatWithUser.ChannelId}`) .emit('message', chatWithUser); } 깃허브를 참조해서 위 둘이 같은 코드라는 것은 알겠는데, io.of(namespace).to(room).emit(~); 의 형태이니까, 예를들어 제가 typescript 워크스페이스에 error 채널에서 채팅을 한다고 하면 namespace는 ws-typescript이고, room은 ws-typescript-error인건가요...? 그리고 of는 왜 주석처리가 되어있는 건가요? event-gateway에서 namespace를 이미 처리해서 그렇게 된건가요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
강의가 검은화면에 소리만 나오는게 있어요
확인 부탁드려요
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
응답 관련 문의드립니다.
안녕하세요, 강의를 보고 프로젝트를 진행하던 도중 도저히 풀리지 않는 문제가 있어 질문드립니다. 프로젝트에서 인터셉터를 사용하여 response의 형식을 조작하고 있습니다. 예를 들어, { id: 1, title: '123', } 이런 데이터가 있다면 { success: true, data: { id: 1, title: '123', } } 이런 식으로 response를 감싸서 내려주고 있는데요, 단순히 생각했을 땐 data를 generic으로 만들어 사용하면 될 줄 알았는데 swagger에서 generic 타입을 지원하지 않는다고 합니다. 저 data의 자료형이 어떤 dto가 될 수도 있고, 어떤 배열이 될 수도 있는데 혹시 이럴 땐 어떤 방법으로 해결할 수 있을까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
sessionOption.cookie.proxy = true 설정에 대해서 질문입니다.
강사님 안녕하세요 아래 설정에 대해서 궁금해서 문의글 남깁니다. sessionOption.cookie.proxy = true 배포시 위 설정이 실행되는거 같은데요. 강사님이 책에서 https적용을 위해 노드 서버 앞에 다른 서버를 두었을 때 true를 설정한다고 써있는데 구체적으로 어떤 상황인지 알려주실 수 있나여
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
리다이렉팅에 대하여...
제로초님 현재 채팅앱 구현중인데, aws s3에 이미지들을 저장하고있습니다. s3 이미지 url을 그대로 프론트에서 Get날리게두면 뭔가 보안상으로 안좋을것같아서 프론트에선 제 서버로 Get 요청하고 그 요청을 s3 주소로 리다이렉팅 시켜주는 방법을 쓰려고하는데 여기서 질문이있습니다. 리다이렉팅 시키는건 제 서버와 아무 관계가 없는것맞나요?? 제 서버에서 그 이미지들을 다운로드 하거나 부하가 되는 작업이 들어가는지 궁금합니다. 한줄 요약하면 프론트에서 s3에 그대로 요청하는것과 똑같은 효과인지 궁금합니다. (서버가 꺼지지 않는다는 가정하에)
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
핫 리로딩 질문
제로초님의 강의를 듣고 혼자 nestjs 개인 프로젝트를 해보려고 개발환경을 세팅하였습니다. 좋은강의 너무 감사드립니다. 세팅을 하던 중 핫 리로딩이 되지 않아 질문드립니다. nestjs 공식문서를 보고 핫 리로딩을 설정하였고, 파일을 수정하면 Error: No such label 'emitAssets' for WebpackLogger.timeEnd() 위와같은 에러가 나오며 실행이 종료됩니다. \Desktop\projects\github_visualization\backend\node_modules\webpack\lib\logging\Logger.js:123 throw new Error(`No such label '${label}' for WebpackLogger.timeEnd()`); 검색을 해보니 webpack 플러그인 문제라고 하는데, 해결 방법을 모르겠어서 질문드립니다.
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
로깅된 sql 관련해서 문의드립니다.
안녕하세요 제로초님, 강의를 보고 개인 프로젝트를 진행하다 궁금한 점이 있어서 질문 남깁니다. 현재 다음과 같은 typeorm 코드로 질의를 날리고 있습니다. const post = await this.postsRepository.findOne({ where: { id }, relations: ['author'] }); 그랬더니 다음과 같은 두 개의 쿼리가 나가는 것을 확인 할 수 있었습니다. 제 생각에는 첫 번째 select distinct ~ 쿼리는 필요 없는 쿼리인 듯 한데 혹시 의미가 있는 쿼리인지 궁금합니다!
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket.io 관련 질문있습니다..!
안녕하세요! 강의 정말 잘 듣고 있습니다! ㅎㅎ 다름이 아니라 강의를 듣고 응용하여 배포까지 진행하는 과정에서 궁금한 점이 생겼습니다. socket은 서버에 client socket이 연결되면 tcp 세션이 생성돼 데이터를 주고 받는 것으로 알고 있습니다. 만약 배포 과정에서 로드 밸런싱을 하여 각 서버 인스턴스끼리 세션을 공유하지 못하는 상황이라면 namespace 또한 공유하지 못하는건가요? 만약 공유하지 못한다면 namespace를 공유할 수 있는 다른 방법은 없나요..?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
코드 저장 시 address already in use :::3000에러가 발생합니다
안녕하세요! 강의 잘 듣고 있습니다 코드를 작성하고 저장을 하면 address already in use 에러가 뜹니다. 맨 처음 실행할때는 문제없이 실행이 되는데, 코드를 작성하고 저장하면 3030포트를 사용하고 있다는 에러가 뜹니다. lsof -i :포트번호 로 열려진 파일 목록을 보면 아래 사진처럼 실행중인 프로세스가 확인이 됩니다. sudo lsof -i :3030 kill -9 PID 인터넷에 쳐보니 해당 프로세스를 죽이는 법은 나오는데 반복적으로 이런 현상이 나오는것에 대해서는 해결방법을 아직 못찾았습니다. 어떻게 하면 이런 현상을 해결할 수 있을까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
map관련 궁금한게 있습니다.
map안에 함수를 전달하겠거니 해서 map((data) => { return { data, code: 'SUCCESS' } } 이런 식으로 작성해야 할 줄 알았는데, map((data) => ( 라고 하시더라구요. 화살표 다음에 일반 함수처럼 {로 시작되는게 아니라 이해가 잘 안되는데요. javascript가 아닌 rxjs의 OperatorFunction문법이라 생각하고 넘어가면 될까요?