44,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
nest 에서 혹시 모를 에러 방지
안녕하세요, 제로초님. 좋은강의 정말 감사드립니다. 강의를 듣다가 문득 궁금한 점이 생겼는데요. 저는 express에서 함수를 실행할 때 혹시 에러가 나서 서버가 다운되지 않게 왠만하면 거의 try catch로 묶는 편인데요. nest에서는 혹시모를 에러가 나서 서버가 다운되지 않게하는 방법이 어떤게 있을까요???
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
안녕하세요 질문 있습니다.
QueryFailedError: Field 'createdAt' doesn't have a default value 이런 에러가 계속 떴습니다. 그래서 포스트맨으로 이메일, 비밀번호, 닉네임을 적어서 보내도 저 에러 메시지가 떠서 구글링 해서 찾아보니 createdAt, updatedAt때문에 자꾸 에러나는 것 같았습니다. 그래서 @Column("datetime", { name: "updatedAt" })updatedAt: Date;에서 @CreateDateColumn({ name: 'updatedAt', type: 'datetime' })updatedAt: Date;로 바꿔보니까 잘 되었습니다. (updatedAt도 바꿈)왜이럴까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
안녕하세요 제로초님 질문있습니다.
node express, sleact front 강의를 거쳐 여기까지 오게 되었네요 반갑습니다. redux mobx강의도 구매 해놓아서 또 찾아뵙겠네요ㅋㅋ 질문이 많을 예정입니다 잘 부탁드립니다.. 질문이 있습니다. 현재 sleact 스키마에 테이블이 있는데 다른 스키마에 테이블들을 다시 생성하고 초기 값들 설정해놓은 것들을 다른 스키마에다가 입력해주고 싶어서 각 entity에 @Entity("channelChats", { schema: "nestjs" })이런식으로 "sleact" -> "nestjs" 스키마로 바꿔줬고 app.module.ts에 @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), UsersModule, WorkspacesModule, ChannelsModule, DmsModule, TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, autoLoadEntities: true, entities: [], synchronize: true, }) ], controllers: [AppController], providers: [AppService, ConfigService, UsersService],}) synchronize: true를 해주고 .env에 DB_DATABASE=nestjs로 해주었는데 nestjs스키마에 테이블들이 생성이 안되는데 왜이런거죠?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
chat 감정표현 및 읽음 질문
채팅 좋아요,싫어요등을 추가로 구현해보고싶어서 설계중인데, export class Chat extends CommonEntity { @Column() content: string; @Column('simple-array') readedMembersId: number[]; @Column('simple-array', { nullable: true }) thumbsUpMembersId: number[]; @Column('simple-array', { nullable: true }) thumbsDownMembersId: number[]; @DeleteDateColumn({ nullable: true }) deletedAt: Date | null; @ManyToOne(() => Room, (room) => room.Chats) Room: Room; @ManyToOne(() => User, (user) => user.Chats) User: User; } 읽음처리는 readMembersId 테이블에에 읽은 맴버 Id들을 푸시해주고, 감정표현은 tumbup / down Members Id를 각 테이블에 푸시해주는 식으로 구현해봤는데, 다대다 테이블을 따로 안만들고 이렇게써도 되는지, 실무에선 보통 읽음, 감정표현같은 기능은 어떻게 처리하는지 조언 받고싶습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
mentions 질문
https://github.com/ZeroCho/sleact/blob/master/nest-typeorm/src/entities/ChannelChats.ts 제로초님 소스코드를 보면 channelChats 테이블에 mentions과 관련된 테이블이 없고 mentions테이블 칼럼으로는 그냥 chatId만 해줬는데 (@ManyToOne() 이런것없이) 어떻게 chanelchats과 mentions가 연결될수 있는지 궁금합니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
채팅 백그라운드 흐름 질문
앱이 꺼져있던 켜져있던 항상 소켓상태로 연결하는건 자원낭비이고, ios, android 에서도 백그라운드 소켓연결은 지원안해주기 때문에 불가능하다고 알고있습니다. 그래서 유저가 포그라운드일땐, 소켓으로 연결해서 실시간 채팅을하고. 백그라운드일땐, 서버 db에 저장후 앱 실행 혹은 로그인시 채팅내역들을 받아오면서 소켓 연결. 앱이든 웹이든, 이런 흐름이 최선일것이다라고 이해하고있는데 맞나요? 아니라면 실무에선 어떻게 처리되는지 알수있을까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
도커 사용시 pm2사용
안녕하세요! 현재 docker를 사용해서 nest 앱을 ec2에 배포하고 있습니다. docker사용시에는 pm2 사용할 필요가 없나요?? ec2터미널 껐을때 서버가 죽는 것같아서 질문드립니다 ㅠ
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
데이터 처리 질문드립니다.
개인프로젝트진행중인데, 데이터를 가공하여 프론트에 전달해줘야할것같은데 현업에서는 보통 DB에서 작업을 하나요 백엔드에서 작업을 하나요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
pm2로 계속 켜놨을때 안쓸때는 따로 꺼주는 방법이 있는지 궁금합니다.
터미널에서 실행했을때 피엠투 이용하면 터미널을 꺼도 서버가 안꺼진다는걸 이번 강좌에서 배웠는데요, 아무래도 아직까지는 클라우드에 올려서 쓴다거나 하진 않으니 로컬에서 연습삼아 켜볼까하는데 그럴경우에 안쓸때는 따로 꺼주면서 관리해야하나요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
nest-typeorm npm i 하고 실행 시 cannot add or update a child row
안녕하십니까강의 잘 보고있습니다 nest-typeorm으로 제로초님 깃에 올라온 파일 npm i 한 뒤, 공지에 올라온 대로 typeorm으로 db 생성 해주었습니다. (https://www.inflearn.com/news/292810)지금 상태라면 분명 비어있는 디비에 typeorm이 자동생성해준 것들밖에 없어서 참조할 것도 없을 텐데프론트 npm run dev 하여 회원가입 시도시cannot add or update a child row라는 오류가 납니다. 다음은 NEST.JS 콘솔에 뜬 오류 로그입니다. query failed: INSERT INTO `workspacemembers(`createdAt`,`updatedAt`,`WorkspaceId`,`UserId`,`loggedAt`) VALUES (DEFAULT, DEFAULT,?,?DEFAULT) -- PARAMETERS:[1,1] error:ERROR: Cannot add or update a child row: a foreign key constraint fails (`sleact`.`workspacemembers`,CONSTRAINT `FK_77afc26dfe5a8633e6ce35eaa44` FOREIGN KEY (`WorkspaceId`) REFERENCES `workspaces` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
확장프로그램 뭐쓰시나요
@Post('login)안에 path 같이 hint를 주는 데 어떤 확장프로그램 사용하시나요 또 다른 확장프로그램 추천해주실만한거 있으신가요
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
TypeORM 쿼리빌더 orderBy 질문있습니다.
쿼리빌더를 사용해 데이터를 가져올때 orderby를 두개의 컬럼에 사용하면 데이터를 부족하게 가져오는 경우가 있어서 질문드립니다. const query = await this.reportRepository .createQueryBuilder('report') .select([ 'report', 'content.reportContent', 'hashtag.hashtagName', 'hashtag.id', 'map.createdAt', ]) .innerJoin('report.ReportContent', 'content') .leftJoin('report.Hashtag', 'hashtag') .leftJoin('hashtag.ReportHashtag', 'map', 'map.ReportId =report.id'); const reports = await query .skip(6 * (1 - 1)) .take(6) .orderBy({ 'report.updatedAt': 'DESC', 'map.createdAt': 'ASC' }) .getMany(); return reports; 해당 쿼리문은 데이터를 총 6개를 가져와야하는 쿼리문이지만 2개를 가져옵니다. 하지만 마지막 orderBy에서 'map.createdAt': 'ASC'를 빼면 정상적으로 6개를 가져오게 되네요.. TypeORM의 버그일까요 아니면 쿼리문에 부족한 점이 있을까요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
typeorm, tsconfig 질문드립니다.
typeorm에서 entity 작성시 tsconfig의 strict의 옵션을 true로 하니 아래와 같은 에러가 발생하는데, typeorm사용시에는 strict옵션을 false로 하는게 맞을까요? Property 'id' has no initializer and is not definitely assigned in the constructor.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
typeorm One-to-one 관계설정
제로초님 유저개인정보를 담고있는 User Entity와 그외 기타정보를 담고있는 Profile Entity 를 One - to - One 관계로 연결시켜주고자하는데 /user.entity.ts @OneToOne(() => Profile, (profile) => profile.User, { cascade: true, }) @JoinColumn() Profile: Profile; 유저 엔티티를 이렇게 하고, /profile.entity.ts @OneToOne(() => User, (user) => user.Profile) User: User; 프로파일 엔티티를 이렇게 설정해줬는데, 유저를 생성할때 Profile이 같이 자동생성이 되지않습니다. 혹시나해서 profile에도 cascade:true를 넣어봤는데, 디비 오류가 나네요. OneToOne관계에서 유저를 생성할때 자동으로 profile이 생성되게할려면 어떻게 해야하나요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
dto 중 일부만 사용하고싶을때
제로초님 혹시 Dto중에 일부만 사용하고 싶을경우는 어떻게 쓰면될까요? 예를들어 class Dto { @IsNotEmpty() @IsEmail() email: string; @IsNotEmpty() @IsString() password: string; } 일 경우에 어느 한 라우터에선 이중에 하나만 골라쓰고싶다 하면 @Post() post(@Body() {email}: Dto){} 이럴경우는 어떻게 쓸수있을까요
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
QueryBuilder Mocking 예제를 알 수 있을까요?
구글링을해봐도 도저히 나오지 않아 QueryBuilder를 어떻게 모킹해야할 지 모르겠습니다.. 예) await getConnection() .createQueryBuilder() .update(User) .set({ userId, name, memo }) .where( 'projectId = :projectId and id = :id and authority = :authority', { projectId, id, authority: 0 }, ) .execute(); 를 모킹하려고 하는데 혹시 MockClass 내부에서 어떻게 해당 로직을 구현해야 할까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
소스코드 어디 참고하면 되나요?
강의를 보면서 따라치기는 힘들고 듣고나서 따로 소스코드보고 따라치고 돌려보고싶은데요 강의에서 친 코드랑 똑같은 코드를 강사님 깃에서 찾기가 어렵습니다. 전에도 강의 그대로 쳤다가 세션이 없어서 에러나서 꽤 애먹었는데요 강의를 보고 그 내용을 따로 볼 수 있는 소스코드는 없나요? 나름 제일 비슷한코드 nest-typeorm에서 찾았는데 이 코드도 지금 강사님이 치는 코드랑 달라서 혼란스럽습니다.
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
seed 생성 에러
안녕하세요. npm run seed:run 을하면 🌱 TypeORM Seeding v1.6.1 ✖ Could not load the config file! TypeORMError: No connection options were found in any orm configuration files. 이런 에러가 발생해서 제로초님 깃허브로 전부 복사해도 똑같이 해결이안되는데 이유를 혹시 아시나요? 메세지를 보면 ormconfig.ts를 못찾는거같아요. .env도 입력했고 프론트도 들어서 강의그대로 자동생성 진행했고, entities폴더도 깃허브로 바꿨어요. 그리고 package.json, ormconfig,create-initial-data 이런거 전부 복사해서 다시 해보고 경로도 맞아서 오타문제는 아닌거같은데.. forRoot()부분에 옵션을 직접 넣어보기도 하고 엔티티부분을 entities: ["entities/*.js"] 이거도 해보고 entities: ["dist/**/**.entity{.ts,.js}"] 이렇게 바꿔보기도 package.json의 typeorm부분을 "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config src/ormconfig.ts", 이랗게 바꿔보기도 했는데 에러는 그대로 여서 잘 모르겠네용
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
질문있습니다
const user = await this.usersRepository .createQueryBuilder('user') .where('user.email = :email', { email }) .innerJoin('user.Workspaces', 'workspace', 'workspace.url = :url', { url, }) .getOne(); 해당 코드에서 유저의 email 속성은 unique인데 InnerJoin을 한 이유가 있나요??
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
소셜 로그인 질문
저는 passport-jwt를 사용하여 로그인을 구현하였는데, passport-apple 를 사용하여 소셜 로그인 구현 중에 막혔습니다. 아무리 구글링해봐도 passport-apple + nest.js 조합이 없어 해결이 되지않아 질문드립니다. 우선 제가 이해하고있는 전반적인 큰 흐름부터 맞나 의심됩니다. 1. passport-apple 을 통하여 유저 정보를 받아온 후 2. 유저에게 jwt를 발급 3. 유저는 클라이언트단(or 쿠키)에 jwt 저장 4. 이후 애플서버와는 연계없이 jwt를 이용해 제 서버만을 통하여 유저 정보를 줌. 이게 맞나 모르겠고 틀린 점이 있으면 지적해주시면 감사하겠습니다! 그리고 본 질문은 passport-apple을 통하여 어떻게 유저 정보를 받아오는지를 모르겠습니다. node.js passport-apple 공식문서를 통해 유추하며 해봤습니다 /apple.strategy.ts 파일 import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-apple'; @Injectable() export class AppleStrategy extends PassportStrategy(Strategy,'apple') { constructor() { super({ clientID: process.env.APPLE_CLIENT_ID, teamID: process.env.APPLE_TEAM_ID, callbackURL: process.env.APPLE_CALLBACK_URL, keyID: process.env.APPLE_KEY_ID, privateKeyString: process.env.APPLE_KEY, //참고로 privateKeyLocation로도 해보고 // passReqToCallback: true도 넣어봤습니다. (뭔진 모르겠지만) }); } async validate(req,accessToken, refreshToken, idToken, profile, done) { console.log('req :', req); console.log('idToken :', idToken); console.log('accessToken :', accessToken); console.log('refreshToken :', refreshToken); console.log('profile :', profile); done(null,idToken) } } super에 필요객체를 넣고 validate 인자로 어떤값들이 들어오는지 하나하나 로그를 찍어보려했으나, 아예 저 부분으로 넘어가지않고 에러가 뜹니다. /auth.module.ts 파일 import { JwtStrategy } from './strategies/jwt.strategy'; import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { PassportModule } from '@nestjs/passport'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from 'src/common/entities/user.entity'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; import { AppleStrategy } from './strategies/apple.strategy'; @Module({ imports: [ TypeOrmModule.forFeature([User]), PassportModule.register({ session: false }), JwtModule.register({ secret: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: '60s' }, }), ], providers: [AuthService, JwtStrategy, AppleStrategy], controllers: [AuthController], }) export class AuthModule {} /auth.controller.ts 파일 import { AuthGuard } from '@nestjs/passport'; import { AuthService } from './auth.service'; import { Controller, Get, UseGuards, Req, Post, Body } from '@nestjs/common'; @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) {} @Get('/apple') @UseGuards(AuthGuard('apple')) async appleLogin() {} @Post('/apple/callback') @UseGuards(AuthGuard('apple')) async appleLoginCallback(@Req() req, @Body() body) { console.log("req : ",req) console.log('body : ',body) return 'ok'; } } 전 강의영상의 LocalAuthGuard 같은 클래스 파일을 따로 만들지 않고 바로 AuthGuard('apple')을 데코레이터에 넣어주는 식올 구현했습니다. 여기서 "도메인/auth/apple" 로 접속시 애플 로그인 화면이 뜨는 것까지는 되는데, 로그인을 후 "계속" 버튼을 누르면 서버에 이러한 500에러가 뜹니다 [Nest] 58 - 02/05/2022, 9:56:26 AM ERROR [ExceptionsHandler] Failed to obtain access token InternalOAuthError: Failed to obtain access token at AppleStrategy.OAuth2Strategy._createOAuthError (/usr/src/app/node_modules/passport-oauth2/lib/strategy.js:423:17) at /usr/src/app/node_modules/passport-oauth2/lib/strategy.js:177:45 at /usr/src/app/node_modules/passport-apple/src/strategy.js:101:13 at processTicksAndRejections (node:internal/process/task_queues:96:5) [Nest] 58 - 02/05/2022, 9:56:26 AM LOG [HTTP] 500 POST /api/auth/apple/callback - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 ::ffff:172.18.0.3 도무지 모르겠어서 2번째 (Post부분) @UseGuard데코레이터를 빼서 결과를 봐보니 body에 {state: '2ed****e0ed', code: 'ce23f9c72e7904******d8565b94b4a7.0.r**z.5nDn7h*******RJufk11LWQ'} 이러한 객체가 담겨옵니다. 제 예측으로는 이것이 access 토큰인것같고 이걸 다시 애플에 보내 유저정보를 받아내야하는것같은데, 코드를 어떻게 구현해야하는지 모르겠습니다... 혹시 실무에서 apple login을 어떻게 구현하셨는지, passport-apple이 안되거나 더 편한 다른방법이라도 있다면 알려주시면 정말 감사하겠습니다.