inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

Slack 클론 코딩[백엔드 with NestJS + TypeORM]

인터셉터를 통한 응답의 관련된 질문입니다.

해결된 질문

315

이승훈

작성한 질문수 49

0

 안녕하세요 조현영님. 인터셉터 관련해서 궁금한게 있어 질문드립니다. 아래는 제가 만들어 놓은 인터셉터입니다.

intercept(context: ArgumentsHost, next: CallHandler<any>): Observable<any> {
  // controller 도달 전
  const req = context.switchToHttp().getRequest();
  const res = context.switchToHttp().getResponse();

  console.log(`Receive request from ${req.method} ${req.originalUrl}`);
  const now = Date.now();

  return next.handle().pipe(
    map((data: JSON<null>) => {
      // controller 도달 후
      console.log(
        `Send response from ${req.method} ${
          req.originalUrl
        } :: time taken : ${Date.now() - now}ms`,
      );
      return res.status(data.statusCode).setHeader("X-Powered-By", "").json({ success: true, ...data});
    }),
  );
}

 이전까지는 이런식으로 인터셉터를 구성해서 포스트맨으로 사용할 땐 문제없이 요청과 응답이 오고 갈수 있었습니다. 그런데 시험삼아서 브라우저에 서버 url을 입력후 get메서드를 사용하는 api를 사용해봤는데 응답은 잘 갔었지만 서버 콘솔에 cannot set headers 오류가 났습니다. 이 오류는 꽤나 익숙해서 응답이 두번 보내져서 그런가 싶어 인터셉터 응답을 아래처럼 바꿔보았습니다.

intercept(context: ArgumentsHost, next: CallHandler<any>): Observable<any> {
  // controller 도달 전
  const req = context.switchToHttp().getRequest();
  const res = context.switchToHttp().getResponse();

  console.log(`Receive request from ${req.method} ${req.originalUrl}`);
  const now = Date.now();

  return next.handle().pipe(
    map((data: JSON<null>) => {
      // controller 도달 후
      console.log(
        `Send response from ${req.method} ${
          req.originalUrl
        } :: time taken : ${Date.now() - now}ms`,
      );
      res.status(data.statusCode).setHeader("X-Powered-By", "");

      return { success: true, ...data };
    }),
  );
}

이상한게 get, delete 메서드를 사용하는 api는 return문을 거쳤을 때 응답이 잘 도달되었지만 post,patch등은 응답이 가고 계속 로딩중입니다.

계속 기다려도 이러한 상태여서 디버깅을 통해 문제를 해결하고자 return문에서 부터 계속 디버깅을 시도했습니다. 그리고 문제였던 아래 코드를 발견했습니다.

return async (result, res) => {
            result = await this.responseController.transformToResult(result);
            
             !isResponseHandled &&
                (await this.responseController.apply(result, res, httpStatusCode));
        };

위의 코드는 node_modules/@nestjs/core/router/router-execution-context.js 라는 파일의 174 ~ 177줄의 코드입니다. 아마 result 변수가 인터셉터에서 리턴된 값으로 사용되는 변수 같은데 그 아래 있는 코드 실행 이후 계속 응답이 닿지 않는 모습이었습니다. 그래서 저는 아래처럼 다시 수정해봤습니다.

 return async (result, res) => {
            result = await this.responseController.transformToResult(result);
           
            await this.responseController.apply(result, res, httpStatusCode);
        };

이후에는 post, patch메서드의 응답이 잘 닿았지만 과연 이게 올바른 해결 방법인지는 잘 모르겠습니다. 만약 이 프로젝트를 git에서 pull, clone등을 할 때 node_modules는 .gitignore에 등록해놓아서 위 처럼 변경 사항을 불러올 수가 없어서 git에서 pull, clone하려면 npm i로 모듈들을 받은 후 계속 저런식으로 수정을 해야 되서 이 방법은 좀 아닌거 같지만 일단 임시방편으로 해놓은 상태입니다. 조현영님께서는 이렇게 어떤 문제가 해결이 안될때 node_modules를 건드려서 해결하신적이 있으신가요?

 

nodejs express TypeORM NestJS

답변 1

0

제로초(조현영)

post랑 put일때 컨트롤러랑 인터셉터 handle 부분은 실행되는 거죠? isResponseHandled가 true인게 문제네요. 그게 왜 true가 되는지 파악해봐야할것같습니다.

0

이승훈

네 컨트롤러, 인터셉터 핸들은 실행되는데 리턴 이후가 문제입니다. 혹시 조현영님께서 인터셉터 작성하실 때 이런문제를 겪으신적이 있으신가요?

0

제로초(조현영)

저는 없습니다

0

이승훈

혹시 @nestjs/core버전 몇 쓰시나요?

0

제로초(조현영)

최신버전 씁니다.

0

이승훈

제가 몇가지 테스트 해본 결과 컨트롤러 측에서 매개변수로 @Res() res: Response를 사용하게 될 때 isResponseHandled가 true가 된다는 사실을 알아내었습니다. 그런데 res로 send나 json등을 컨트롤러에서 직접 사용하지는 않고 아래 처럼 쿠키를 생성하는 용도로 사용하고 있습니다.

async login(
    @Body() loginUserDto: LoginUserDto,
    @Res() res: Response,
  ): Promise<JSON<string>> {
    const jwtToken = await this.authService.login(loginUserDto);
    res.cookie("JWT_COOKIE", jwtToken, CookieOption);

    return {
      statusCode: 201,
      message: "로그인을 완료하였습니다. 쿠키를 확인하세요.",
    };
  }

저는 로그인 api를 만들 때 세션 대신 jwt를 주로 사용합니다. 그리고 만들어진 토큰을 쿠키로 보내는 방법을 주로 사용합니다. 그런데 res를 사용하지 않는다면 쿠키를 보낼 수 없어서 결국 로그인이 무용지물이 되어버리게됩니다. 인터셉터를 사용함과 동시에 컨트롤러에서 res객체를 사용할 방법이 없을까요?

0

제로초(조현영)

인터셉터에서 res 작업을 다 하시면 됩니다. 컨트롤러에서 return으로 인터셉터로 데이터를 보낼 수 있으니까요.

0

이승훈

쿠키를 보내는 컨트롤러와 쿠키를 제거하는 컨트롤러, 쿠키와 무관한 컨트롤러 들이 각각 있어서 그런데 그럼 각각 인터셉터들을 만들어 주면 될까요?

0

제로초(조현영)

네네 따로 만드시면 좋습니다. @Req, @Res는 웬만하면 안 쓰시는 게 좋아요.

0

이승훈

감사합니다!

강의자료는 어디서 다운받나요?

0

145

4

질문 있습니다.

0

320

3

코드 편집기 확장 프로그램

0

220

2

(질문)비밀 저장소에 접근하기 위한 인증 정보는 로컬 .env에 저장하는지?

0

165

2

(질문)외부 저장소를 통한 환경변수 불러오기 비동기 질문

0

179

3

로그인을 해도 LoggedInGuard쪽에서 false값이 나옵니다.

0

163

2

로그인방법이 고민됩니다.

0

197

2

yarn seed 명령어 실행 시 데이터 삽입 안됨

0

305

4

yarn run db:create 시에 발생하는 데코레이터 오류

0

249

2

npm run db:create 시에 발생하는 decorating 오류

0

245

2

RxJS 디버깅 질문 있습니다.

0

201

3

CacheManager에 대해 질문 있습니다.

0

185

2

로깅은 어떻게 하는게 효율적일까요?

0

240

1

CORS 질문 있습니다.

0

428

2

쿠키 옵션에 대해서 질문 있습니다.

0

190

2

로그아웃 요청이 403 forbidden 에러가 나는데 왜그런걸까요??

0

458

1

401 unauthorized문제

0

306

1

가드의 장점에 대해서 질문이 있습니다.

0

234

1

로그 관리에 대해 질문 있습니다.

0

256

2

CORS 에러 질문 있습니다.

0

329

2

배포 환경 DB 연결 질문 있습니다.

0

418

2

socket io 미 연결 문제 (nest & flutter)

1

1169

3

no elements in sequence 에러 관해서 질문이 있습니다.

0

466

1

start:dev-backup으로 돌리면 핫 리로딩이 되요 정상인가요?

0

327

1