연의 기록 🪁
[Typescript] Property 'session' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.ts(2339) 에러 본문
[Typescript] Property 'session' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.ts(2339) 에러
kite707 2023. 5. 7. 20:40📌 문제 상황
require문을 import로 바꾸는 작업을 하던 도중 const express = require(’express’)를 import express from ‘express’로 바꿨더니 아래 부분에서 Property 'session' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.ts(2339) 에러가 발생했다.
💡 해결 방안
이를 해결하기 위해서는 먼저 @types/express-session을 설치해줘야 한다. 아래 명령어를 실행하도록 하자.
npm install -D @types/express-session@1.17.0
이후 그러고나면 req.logout과 req.session.destroy가 각각 콜백함수를 요구하기 때문에 req.logout이 되면 req.session.destroy를 하도록 함수를 짜주었다. 이후 성공했다는 값을 리턴해주는 success 함수(커스텀 함수)를 호출해주었다.
import { Request, Response } from 'express';
import { responseMessage, statusCode } from '../modules/constants';
import { success } from '../modules/util';
const logout = async (req: Request, res: Response) => {
req.logout(() => {
req.session.destroy(() => {
success(res, statusCode.OK, responseMessage.SUCCESS, {
session: req.session,
});
});
});
};
export { logout };
위와 같이 하면 에러는 해결된다.
⭐️ req.logout vs req.session.destroy
req.logout과 req.session.destroy의 차이가 궁금해져서 아래와 같이 콘솔에 값을 찍어봤다.
import { Request, Response } from 'express';
import { responseMessage, statusCode } from '../modules/constants';
import { success } from '../modules/util';
const logout = async (req: Request, res: Response) => {
console.log(`session before logout ${JSON.stringify(req.session, null, 4)}`);
req.logout(() => {
console.log(`session after logout ${JSON.stringify(req.session, null, 4)}`);
req.session.destroy(() => {
console.log(
`session after destroy ${JSON.stringify(req.session, null, 4)}`,
);
success(res, statusCode.OK, responseMessage.SUCCESS, {
session: req.session,
});
});
});
};
export { logout };
그 결과는 아래와 같다.
그런데 사실 로그아웃을 안하고 바로 req.session.destroy를 해도 session은 undefined가 찍힌다. logout을 생략한 코드와 그 실행 결과는 각각 다음과 같다.
import { Request, Response } from 'express';
import { responseMessage, statusCode } from '../modules/constants';
import { success } from '../modules/util';
const logout = async (req: Request, res: Response) => {
console.log(`session before logout ${JSON.stringify(req.session, null, 4)}`);
req.session.destroy(() => {
console.log(
`session after destroy ${JSON.stringify(req.session, null, 4)}`,
);
success(res, statusCode.OK, responseMessage.SUCCESS, {
session: req.session,
});
});
};
export { logout };
그래서 챗GPT에게 물어본 결과 결론은 아래와 같다.
session.logout은 단순히 Passport에 의해 추가된 req.user property를 지우는 것이다. 그러나 servier-side session에 유저와 관련된 정보가 남아있을 것을 대비하여 session.destroy까지 해주는 것이라고 한다. 그렇지 않으면 연이어 오는 다른 요청(Request)이 유저가 로그아웃을 한 상태임에도 불구하고 유저 관련 정보에 접근할 수 있기 때문이다.