44,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket io ping pong 클라 상태체크하는법
제로초님 nest js 에서 socket io 통신시 ping / pong 으로 유저 상태 체크하는법을 알고싶습니다. @WebSocketGateway({ namespace: /^\/api\/\w+/, pingInterval: 10000, pingTimeout: 5000, }) 위와 같이 ping / pong 을 설정해주었는데, 딱히 'ping' 이나 'pong' 이벤트가 오지 않아서 용도가 무엇인지 잘모르겠습니다. 따로 클라이언트에 socket.emit('ping') 이런식으로 interval을 만들어줘야하는걸까요? nestjs 에서 클라이언트 상태체크를 하려면 어떻게 해야하는지 알고싶습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
인덱스에 대하여
제로초님 MYSQL에 PK말고 인덱스라는게 있던데, 둘의 차이가 PK에서 중복허용, null허용 해준게 index 인것 맞나요? PK와 index를 둘다거는것도 가능한지 의미있는지 궁금합니다. 사용예로 유저 email과 같은 where에 자주 사용되는것(null일수도있음)에 index걸어주면 되는걸까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket.io 활용중 조언을 얻고싶습니다.
안녕하세요 nest.js수강 후 nest.js로 개인프로젝트 중 궁금한점이 생겨 질문드립니다. socket.io로 카카오톡과 같은 구조의 채팅창을 구현중인데요. 카카오톡 처럼 채팅방에 들어가기 전에 채팅방 목록에서 읽지 않은 메세지를 어떻게 얻을 수 있을까 고민이 되어 조언을 구하고 싶습니다. react를 배우지 않아 정확히는 모르겠지만, 제로초님 sleact 깃헙을 보니 유저가 채팅방에서 나갈 때의 시간을 db에 저장하고, 나간시간부터 마지막에 올라온 채팅까지 갯수를 count해주는 백엔드 api를 만들고, 프론트는 채팅방 목록 하나하나가 백엔드에 요청하여 읽지 않은 채팅 개수를 받아오는거 같았습니다. 혹시 위 방법이 맞다면 사이즈가 커졌을때 db에 큰 무리가 가지는 않을지, 아니라면 다른 좋은 방법이 있을지 궁금합니다. 항상 감사드립니다!!
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
다대다 쿼리시 질문
자신이 속해있는 방들과 그 방에 속한 맴버들을 한꺼번에 구해오려는 쿼리를 짜려고합니다. 그래서 생각해본결과 const myRooms = await this.roomMembersRepository .createQueryBuilder('roomMembers') .innerJoinAndSelect('roomMembers.Room', 'rooms') .innerJoinAndSelect('rooms.RoomMembers', 'members') .innerJoinAndSelect('members.Profile', 'profiles') .where('roomMembers.UserId = :UserId', { UserId }) .getMany(); 이런식으로 innerjoin 3번날리는것 (필요한게 정보가 다오긴하는데 더럽게와서 포멧필요.) 아니면 roomMembers를 그냥 따로 Typeorm Entity를 만들지않고 그냥 ManyToMany로 연결해서 const myRooms = await this.profilesRepository .createQueryBuilder('profile') .innerJoinAndSelect('profile.Rooms', 'rooms') .innerJoinAndSelect('rooms.Members', 'members') .where('profile.UserId = :UserId', {UserId}) .getOne(); 이런식으로하면 inner join 4번날리는것 (정보 깔끔) 그러나 걱정되는게 저런식으로 join 4번해버리면 DB에 부하가 많이 걸리나요?? 사실 3번하는것도 걱정되는데,,,. 실전 경험이 없어서 저런식으로 짜도 될지 모르겠습니다. 너무 개인적인 질문 죄송합니다. 보통 이런경우엔 어떻게 쿼리를 짜는지 알려주시면 정말 감사하겠습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
안녕하세요, 'morgan 모듈 사용하기' 관련 질문이 있습니다.
안녕하세요 제로초님 'morgan 모듈 사용하기' 강좌에서 궁금한게 생겨서 문의드립니다 LoggerMiddleware를 만들고 @Injectable() 데코레이터를 사용했으므로 app.modules.ts 파일에 providers를 넣어줘야하지않나요? 빼고 하니 넣으라는 에러로그가 다음 과같이 나와서 provider 또는 imports 각각에 넣어서 잘 동작합니다 Appmodule 클래스에서 상속받은 NestModule의 configure에서 필요한 클래스이니 constructor (providers) 보다는 불러오는 imports가 맞는 설정법인가요? 제가 뭔가 놓치고있나해서 문의드립니다
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
배포 후 쿠키 전송 문제
기존 로컬 환경에서는 잘 작동하던 passport 로그인이 쿠키가 전송이 되지 않는 문제가 생겼습니다. header에 set cookie가 포함이 되어 있지 않은 상태로 response가 옵니다. 현재 Nginx(Reverse Proxy) + Front Server / Nginx + Backend Server 총 EC2 2개를 사용하고 있습니다. 로컬 환경에서 Front, Backend Server를 키고 했을 때는 작동이 잘 되고 있었는데 로그인 시 쿠키가 전송이 안되고 있어서 질문드립니다. 혹시나 cookie가 전송이 안되는 게 이상해서 제가 response에 cookie를 넣어서 같이 redirect 를 해봤는데 그건 잘 작동되는 걸 확인했습니다. passport login을 제가 잘못한건지 어떤 설정이 잘못됐는지 잘 모르겠습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
Cannot query across one-to-many for property WorkspaceMembers
안녕하세요 typeorm find 에서 서브 쿼리 사용시 다음과 같은 오류가 발생합니다. - 1 ------ return this.workspacesRepository .createQueryBuilder('workspaces') .innerJoin( 'workspaces.WorkspaceMembers', 'workspacemembers', 'workspacemembers.UserId=:id', { id: myId }, ) .getMany(); - 2 -----return this.workspacesRepository.find({ where: { WorkspaceMembers: [{ UserId: myId }], },}); 오타나 다른 해결법이 있나 싶어서 찾아보고 수정해봤는데 안되고 1번 형식으로 하면 정상적으로 받아 오고, 2번 형식은 위에 있는 에러가 발생합니다. 2번 타입으로 사용하는 설정이나 해결법이 따로 있을까요? 소스 코드는 제가 한게 안되서 깃허브에 있는 소스 복사해서 다시 해도 같은 오류가 발생합니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
안녕하세요. e2e 테스트 관련 질문이 있습니다.
e2e 테스트는 꼭 한 파일에 작성해야하나요? api endpoint가 몇 개 없으면 큰 문제가 없을 것 같은데요. 하나의 서버에서 제공하는 모든 API를 하나의 e2e 테스트 파일에서 테스트하면 한 파일에 엄청 많은 e2e 테스트가 생길 것 같습니다. 이는 원하는 테스트 코드를 찾기도 힘들 것 같다는 생각이 들었습니다. 그래서 저는 여러개의 파일로 나눠서 e2e test를 작성해서 실험해봤었는데요. typeorm에서 데드락 에러를 내더라구요. 여러 e2e 테스트 파일에서 아래의 이미지와 같은 app init을 여러번하면서 생긴 에러라고 저는 추측하고 있습니다. 현업에서 어떻게 사용하고 계신지 팁 좀 주실 수 있으실까요? beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ imports: [AppModule], }) app = module.createNestApplication(); bannersRepository = module.get<Repository<Banner>>( getRepositoryToken(Banner), ); await app.init();})
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
NestJS Dockerizing Error loading shared library bcypt 에러
강의의 내용와 조금 동떨어진 질문일 수 있지만 글 올려 봅니다. 무관하시다 생각하시면 답변 달아주지 않으셔도 좋습니다. auth 기능을 로컬에서 구현 후, dockerizing 하는 부분에서 Error: Error loading shared library /gateway/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node: Exec format error 와 같은 에러가 나서 구동되지 않습니다. Dockerfile 은 FROM node:12-alpine RUN apk update && apk add --no-cache curl vim bash WORKDIR /app COPY package*.json ./ RUN npm install COPY . . 이고, bcrypt 는 npm i bcrypt npm i -D @types/bcrypt 로 하여 설치하였습니다. container 안에서 npm i bcrypt npm i -D @types/bcrypt 명령어를 이용해서 bcrypt 를 다시 설치하면, 정상적으로 구동됩니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
다대다 primary key
Primary Key 는 중복될 수 없다 라고 알고있지만,다대다에서는 primary key를 두개로 사용하고 중복이 되는것같은데, 제가 이해하기로 primary key가 2개일 경우 userId | roomId 1 | 1 1 | 2 위는 가능 userId | roomId 1 | 1 1 | 1 위는 불가능 이런식으로 두개 모두 중복일 경우에만 안되는거고 하나중복일경우는 된다고 이해하고있는데 맞나요??만약 PK가 3개면 3개모두, 4개면 4개모두 중복일시에만 안되고요. 정확히 이해했는지 확신이 안들어서 질문드립니다!
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
캐시 사용할때
cache를 사용하려는데 Redis 를 store로 사용하려고합니다. 그래서 아래와 같이 사용하는것은 알겠는데, import { Module, CacheModule } from '@nestjs/common'; import { CacheService } from './cache.service'; import * as redisStore from 'cache-manager-ioredis'; @Module({ imports: [ CacheModule.register({ store: redisStore, host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, ttl: 0, }), ], providers: [CacheService], exports: [CacheService], }) export class RedisCacheModule {} import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common'; import { Cache } from 'cache-manager'; @Injectable() export class CacheService { constructor( @Inject(CACHE_MANAGER) private readonly cache: Cache, ) {} async get({ key }: { key: string }) { return await this.cache.get(key); } async set({ key, value, ttl = 0, }: { key: string; value: any; ttl?: number; }) { await this.cache.set(key, value, { ttl }); return true; } async delete({ key }: { key: string }) { await this.cache.del(key); return true; } } get , set ,del 등 기본적인 명령 외에 redis명령어인 scan 등을 사용하고 싶은데 사용방법이 있을까요? 로우쿼리로라도 날릴수있다면 날리고싶은데,,, 어떻게 방법이 있는지 알고싶습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
음...passport를 사용하는 이유...?
일단 제목만 보고 상당히 "어...?"하셨겠지만, 정말 궁금했던 것 중에 하나입니다. 일단 저는 nodejs교과서를 책으로 읽고, express로 토이프로젝트를 2번 정도 진행을 해본 경험이 있으며, 그 중 한번만 jwt를 이용하여 auth를 구현하였습니다.(passport 없이) [제가 구현한 방식은]: ID,PW를 받아서 PW를 bcrypt로 암호화하여서 DB에 넣고, 후에 로그인 요청이 오면 ID,PW가 맞는지 확인한 후, 맞으면 jwt 토큰을 쿠키 형식으로 부여. 후에 요청하면 token을 verify하여 회원인지 확인. 이었습니다. 개인적으로 토이프로젝트를 제 개인 서버에 올려 24시간 가동되게 하는 것을 선호해서, 트래픽도 없지만 굳이 세션으로 무리를 주고 싶지 않았고, 또한, 굳이 세션이 필요한 서비스가 아니여서 jwt만으로 하였습니다. nodejs 교과서에서는 세션과 쿠키 처리 등 복잡한 작업을 쉽게 처리해줄 검증된 모듈로 passport를 소개하였는데, 만약에 위와 같은 정도의 작업만을 하게되는 경우, passport를 쓰는 것의 이점이 있나요? 제가 passport의 장점을 크게 느끼지 못하고 있는 것이, session을 사용하지 않으면 굳이 passport를 사용해야 하나 라는 생각이 들어서 질문드립니다. 아 그리고, 저 정도의 기능을 구현한다고 하면 passport를 사용하는 것보다 직접 코드를 짜는것이 더 짧아서 passport를 사용하는 것의 장점이 더욱더 궁금하였습니다... session을 이용하지 않는, passport-local의 경우이겠네요.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
AuthGuard에 관한 질문
제로초님 안녕하세요. AuthGuard를 이용해 로그인 처리를 하고있습니다. 세션 쿠키 방식을 사용하고 있구요. 로그인 방식이 1. 리퀘스트에 쿠키가 있으면 => 쿠키로 세션을 불러와서 안에 들어가있는 user id를 가져와서 디비에서 검색후 로그인 2. 리퀘스트에 쿠키가 없으면 => 디비에서 id와 password를 검색하고 있을 시 세션에 저장하고 로그인. 없으면 UnauthorizedException 이렇게 되는 걸로 파악했는데요. 리퀘스트에 쿠키가 있고 세션에도 저장된 게 있지만 디비에서 유저가 지워졌을 경우, 1번 방식에서 user id가 없기 때문에, 그냥 500 에러가 발생하고 끝나는데요. 저는 이 때, 다시 2번 방식으로 돌리는 플로우로 가고 싶습니다.(쿠키 세션으로 불러지는 정보가 없을 경우, 디비에서 id와 password를 가지고 검색 후 처리)그래서 막연히 LocalAuthGuard 에 null 값을 주고 실행해 봤는데, 아무 동작도 하지 않았습니다. 어떻게하면 좋을지 조언을 듣고 싶습니다. ```ts local-auth.guard.ts@Injectable() export class LocalAuthGuard extends AuthGuard('local') { async canActivate(context: ExecutionContext): Promise<boolean> { if (context) { const can = await super.canActivate(context); if (can) { const request = context.switchToHttp().getRequest(); console.log('쿠키 사용해서 로그인 : ', request); await super.logIn(request); } } return true; } } ``````tslocal.strategy.ts @Injectable() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super({ usernameField: 'email', passwordField: 'password' }); } async validate(email: string, password: string, done: CallableFunction) { const user = await this.authService.validateUser(email, password); if (!user) { throw new UnauthorizedException(); } return done(null, user); } } ``` ```ts local.serializer.ts @Injectable() export class LocalSerializer extends PassportSerializer { constructor( private readonly authService: AuthService, private readonly localStrategy: LocalStrategy, private readonly localAuthGuard: LocalAuthGuard, private readonly reLocalAuthGuard: ReLocalAuthGuard, @InjectRepository(HpMasterUserRepository, 'homepage-db') private userRepository: UserRepository, ) { super(); } serializeUser(User: User, done: CallableFunction) { done(null, user.UserId); } async deserializeUser(userId: number, done: CallableFunction) { try { const user = await this.userRepository.selectHpMasterUserById( userId, ); if (hpMasterUser) { done(null, hpMasterUser.userId); // req.user } await this.localAuthGuard.canActivate(null); // this.reLocalAuthGuard.canActivate(null); } catch (err) { // throw new UnauthorizedException(); done(err); } } } ``` ```ts auth.service.ts @Injectable() export class AuthService { constructor(private userService: UserService) {} async validateUser(email: string, password: string) { const user = await this.userService.masterUserLogin(email, password); if (!user) { return null; } else if (user) { const { password, ...userWithOutPassword } = user; return userWithOutPassword; } return null; } } ```
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
채팅 데이터 처리 질문
현재 채팅앱 구현중인데, 경험이없어 조언을 얻고싶어 질문드립니다! 지금까지 나름 조사해본결과, 채팅 데이터 처리방법으로는1. 소켓으로 채팅 하나하나올때마다 MySQL에 저장한다. 클라이언트가 앱 최초 실행시 Local DB에 저장되어있던 마지막 ChatId로 MySQL에서 그 이후 채팅을 조회후 클라이언트에게 보내줌. ---가장 깔끔하고 쉽지만,대규모 채팅앱이 되었을경우 매번 INSERT를 해버리면 MySQL이 감당을 못할것같음.--- 2. 소켓으로 채팅 올때마다 redis에 저장후 일정시간혹은 일정량이차면 한꺼번에 MySQL에 저장한다. 클라가 앱 최초 실행시 Local DB에 있던 마지막 Chat createdAt으로 그시간 뒤의 채팅들은 MySQL에서 조회후, redis에 임시저장된 채팅들이 있다면 그것들을 합처주고 클라이언트에게 보내줌. ---좀 번거롭지만 MySQL INSERT를 한번에 해줌으로서 DB부하를 줄일 수 있을것같음. 다만, 아주 극적인 타이밍으로 클라가 MySQL에 채팅내역을 조회함과 동시에 redis에서 일정량이차서 MySQL에 INSERT 해주고 redis가 비워저버릴경우 해당 클라이언트는 합처줘야할 대화내용이 유실될수있을것같음.(아주 주관적인 이론)--- 이정도가 있는것같은데, "대규모 채팅앱"이라고 가정할경우 1.더 좋은 방법이 있는지, 2.만약 위의 두번째방법이 괜찮지만 제 이론대로 대화내용 유실 문제가 있을수있다면, 해결방법이 있는지. 3.제로초님은 어떤방식을 선호하는지 등 조언을 듣고싶습니다..!
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
configmodule 질문드립니다.
typeorm의 명령들을 사용하기위해서 ormconfig 파일을 외부로 뺀 경우에도 configmodule을 이용하여 환경변수를 받아올수 있나요?
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
스웨거 문서 질문드립니다.
ReseponseDto 작성하여 type에 지정해주는 방식으로 해주는데요, 조인된 테이블이라 조인 데이터가 추가되는경우에는 어떻게 처리해야할까요?
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
socket io Namespace vs Room
채팅앱을 만들고있는데, 단체방이든 일대일방이든 참여방 ID별로 나눠서 분배해주려고합니다. 그래서 namespace와 room 둘중 하나만 써도 될것같은데, 어떤것을 쓰는게 더 나은지, 차이점이 뭔지 모르겠습니다. 그리고 client에서 자신이 포함된 채팅방들을 구독해야하는데, namespace들을 한번에 여러개 구독하기위해서 어떻게 해야할지 모르겠습니다..
- 해결됨Slack 클론 코딩[백엔드 with NestJS + TypeORM]
intercepter 질문드립니다.
intercepter을 이용하여 사용자에게 데이터를 전달하기전에 한번 가공을 해서 전달할 수 있는걸로 아는데요, throw new NotFoundException 이런식으로 에러를 발생시킨부분들은 어떻게 가공을 할수있나요? 공식문서에 import { Injectable, NestInterceptor, ExecutionContext, BadGatewayException, CallHandler, } from '@nestjs/common'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; @Injectable() export class ErrorsInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { return next .handle() .pipe(catchError((err) => throwError(() => new BadGatewayException()))); } } 다음과 같이 되어있어서 해보았는데 catchError에 걸리지않고 바로 넘어가는듯 했었습니다.
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
bcrypt.compare 에러 질문 있습니다.
이런 에러가 발생합니다. 일단 users 테이블에 컬럼은 id, username, password, createdAt, updatedAt이 있습니다. 아무리 찾아봐도 저는 못찾겠습니다. 문제가 뭘까요..? undefined가 나오는 것 같아서 여기저기 찍어봐도 어디서 나오는지도 모르겠습니다. auth.service.ts import { Injectable } from '@nestjs/common';import bcrypt from 'bcrypt';import { InjectRepository } from "@nestjs/typeorm";import { Users } from "../entities/Users";import { Repository } from "typeorm";@Injectable()export class AuthService { constructor( @InjectRepository(Users) private usersRepository: Repository<Users> ) {} async validateUser(username: string, password: string) { const user = await this.usersRepository.findOne({ where: {username}, select: ['id', 'username', 'password' ] }); console.log(username, password, user); if (!user) { return null; } console.log(password, user.password); const result = await bcrypt.compare(user.password, password); if (result) { const { password, ...userWithoutPassword } = user; return userWithoutPassword; } return null; }} local.serializer.ts import { Injectable } from "@nestjs/common";import { PassportSerializer } from "@nestjs/passport";import { AuthService } from "./auth.service";import { InjectRepository } from "@nestjs/typeorm";import { Users } from "../entities/Users";import { Repository } from "typeorm";@Injectable()export class LocalSerializer extends PassportSerializer { constructor( private readonly authService: AuthService, @InjectRepository(Users) private usersRepository: Repository<Users>, ) { super(); } serializeUser(user: Users, done: CallableFunction) { console.log(user); done(null, user.id); } async deserializeUser(userId: string, done: CallableFunction) { return await this.usersRepository .findOneOrFail( { id: +userId, }, { select: ['id', 'username'] }, ) .then((user) => { console.log('user', user); done(null, user); }) .catch((error) => done(error)); }} local.strategy.ts import { Injectable, UnauthorizedException } from "@nestjs/common";import {Strategy} from "passport-local";import { PassportStrategy } from "@nestjs/passport";import { AuthService } from "./auth.service";@Injectable()export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super({ usernameField: 'username', passwordField: 'password' }); } async validate(username: string, password: string, done: CallableFunction) { const user = await this.authService.validateUser(username, password); if (!user) { throw new UnauthorizedException(); } return done(null, user); }} local-auth.guard.ts import { Injectable } from "@nestjs/common";import { AuthGuard } from "@nestjs/passport";@Injectable()export class LocalAuthGuard extends AuthGuard('local') { async canActivate(context): Promise<boolean> { const can = await super.canActivate(context); if (can) { const request = context.switchToHttp().getRequest(); console.log('login for cookie'); await super.logIn(request); } return true; }} users.service.ts import { Injectable } from '@nestjs/common';import { InjectRepository } from "@nestjs/typeorm";import { Users } from "../entities/Users";import { Repository } from "typeorm";import * as bcrypt from 'bcryptjs';@Injectable()export class UsersService { constructor( @InjectRepository(Users) private usersRepository: Repository<Users>, ) { } async findByUserName(username: string) { return this.usersRepository.findOne({ where: { username }, select: ["id", 'username', 'password'], }); } async signUp(username: string, password: string) { console.log("@@ = ", password); const salt = await bcrypt.genSalt(); const hashedPassword = await bcrypt.hash(password, salt); const user = await this.usersRepository.findOne({ where: { username } }); if(user) { throw new Error('이미 존재하는 사용자입니다'); } const returned = await this.usersRepository.save({ username, password: hashedPassword, }); console.log("successed = ", returned); return true; }} users.controller.ts import { Body, Controller, ForbiddenException, NotFoundException, Post, UseGuards, UseInterceptors} from "@nestjs/common";import { UsersService } from "./users.service";import { ApiOperation, ApiTags } from "@nestjs/swagger";import { JoinRequestDto } from "./dto/join.request.dto";import { User } from "../common/decorator/user.decorator";import { LocalAuthGuard } from "../auth/local-auth.guard";import { UndefinedToNullInterceptor } from "../interceptors/undefinedToNull.interceptor";@ApiTags('USERS')@UseInterceptors(UndefinedToNullInterceptor)@Controller('api/users')export class UsersController { constructor(private usersService: UsersService) {} @ApiOperation({ summary: '로그인' }) @UseGuards(LocalAuthGuard) @Post('login') login(@User() user) { return user; } @ApiOperation({ summary: '회원가입' }) @Post('signup') async join(@Body() data: JoinRequestDto) { const user = this.usersService.findByUserName(data.username); if (!user) { throw new NotFoundException(); } const result = await this.usersService.signUp( data.username, data.password, ); if(result) { return 'ok'; } else { throw new ForbiddenException(); } }}
- 미해결Slack 클론 코딩[백엔드 with NestJS + TypeORM]
배포 후 log out 쿠키 삭제
안녕하세요. 현재 제로초님과 같은 코드로 passport-local로 로그인과 로그아웃을 구현하였습니다. 배포 후 https환경에서 log out하였을때 브라우저 상에서 쿠키가 삭제되지 않는것 같아서 질문드립니다 ㅠ 프론트와 백엔드는 같은 도메인을 사용하고 있고 서브도메인만 다른 상황입니다 ! (프론트: dimelo.io, 백엔드: api.dimelo.io) (https://stackoverflow.com/questions/13758207/why-is-passportjs-in-node-not-removing-session-on-logout 여기 글을 보고 req.session.destroy(function() { res.clearCookie('connect.sid'); }); 이렇게 해보았지만 그래도 안됐습니다 ...)