Velog Dashboard (V.D.) 4주차 회고

최하온·2024년 12월 9일
2

velog-dashboard

목록 보기
5/6

들어가며

전체적으로 리펙토링을 하면서 보낸 더딘 한 주였으며, 근본적인 문제 원인을 빠르게 캐치하지 못하여 시간을 많이 허비한 한 주 였다. 덤으로 이력서 작성과 아르바이트를 진행하게 되어 많은 시간을 할애하지 못하였다.

그래 이게 다 거짓말이었으면 좋겟다..

Express

Nest만 사용하던 나에게 찾아온 Express.. 더구나 한 번도 안 써본 TypeScript + Express 조합이라 생각도 못했던 에러를 마추쳤다.
Error-handling middleware에서 인자는 꼭 4개여야하는 것도 까먹어 버릴 만큼 사용하지 않았던 8개월은 길었나보다. 코딩 중 나를 괴롭힌 문제를 정리해 보겠다!

1. 문제 개요

오류 상황: router에서 호출 오버로드 오류 방생
발생 배경: 인증 미들웨어 작성 중 유효성 검사에 return을 입력하니 생김

2. 오류 코드 및 메시지

오류 코드: typescript 2769
오류 메시지:

이 호출과 일치하는 오버로드가 없습니다.
  마지막 오버로드에서 다음 오류가 발생했습니다.
    '(req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' 형식의 인수는 'RequestHandlerParams<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' 형식의 매개 변수에 할당될 수 없습니다.
      '(req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' 형식은 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' 형식에 할당할 수 없습니다.
        'Promise<Response<any, Record<string, any>> | undefined>' 형식은 'void | Promise<void>' 형식에 할당할 수 없습니다.
          'Promise<Response<any, Record<string, any>> | undefined>' 형식은 'Promise<void>' 형식에 할당할 수 없습니다.
            'Response<any, Record<string, any>> | undefined' 형식은 'void' 형식에 할당할 수 없습니다.
              'Response<any, Record<string, any>>' 형식은 'void' 형식에 할당할 수 없습니다.

관련 로그:

[{
	"resource": "/Users/choi/Desktop/velog-dashboard/src/routes/user.router.ts",
	"owner": "typescript",
	"code": "2769",
	"severity": 8,
	"message": "이 호출과 일치하는 오버로드가 없습니다.\n  마지막 오버로드에서 다음 오류가 발생했습니다.\n    '(req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' 형식의 인수는 'RequestHandlerParams<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' 형식의 매개 변수에 할당될 수 없습니다.\n      '(req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' 형식은 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' 형식에 할당할 수 없습니다.\n        'Promise<Response<any, Record<string, any>> | undefined>' 형식은 'void | Promise<void>' 형식에 할당할 수 없습니다.\n          'Promise<Response<any, Record<string, any>> | undefined>' 형식은 'Promise<void>' 형식에 할당할 수 없습니다.\n            'Response<any, Record<string, any>> | undefined' 형식은 'void' 형식에 할당할 수 없습니다.\n              'Response<any, Record<string, any>>' 형식은 'void' 형식에 할당할 수 없습니다.",
	"source": "ts",
	"startLineNumber": 19,
	"startColumn": 23,
	"endLineNumber": 19,
	"endColumn": 43,
	"relatedInformation": [
		{
			"startLineNumber": 153,
			"startColumn": 5,
			"endLineNumber": 163,
			"endColumn": 10,
			"message": "여기서 마지막 오버로드가 선언됩니다.",
			"resource": "/Users/choi/Desktop/velog-dashboard/node_modules/.pnpm/@types+express-serve-static-core@5.0.1/node_modules/@types/express-serve-static-core/index.d.ts"
		}
	]
}]

3. 원인 분석

오류 원인: Express의 RequestHandler는 void | Promise<void> 반환 타입을 요구하는 반면 현재 코드는 Response객체 반환 중이라 타입 에러가 남 (return res.status().json({message: ''})

에러 로그 해석: typescript가 owner인 점을 확인하여 typescrpit + express 조합에서 생긴 에러이며 @types/express-serve-static-core/index.d.ts에서 발생하였음

4. 해결책

해결 방법: return문 제거 or as RequestHandler 로 타입 단언해주기
코드 예시:

  1. return문 제거 : Express의 일반적인 패턴을 따르나 함수가 계속 실행 될 수 있다.
  if (!accessToken || !refreshToken) {
        res.status(401).json({ message: 'accessToken과 refreshToken의 입력이 올바르지 않습니다' });
    - return
      }

2.as RequestHandler 로 타입 단언 : 타입 안정성 유지할 수 있으나 타입 단언은 TypeScript의 타입 체크를 우회 할 수 있다.

export const validateResponse = <T extends object>(dtoClass: new (...args: any) => T) => {
  return (...) + as RequestHandler;

🤔 두 가지 장점을 다 살린다면 이렇게 작성하면 될까? 이것또한 내일!

const validateToken: RequestHandler = (req, res, next) => {
  if (!accessToken || !refreshToken) {
    res.status(401).json({ message: '토큰이 올바르지 않습니다' });
    return next(new TokenError('Invalid tokens'));
  }
  ...
  next();
};

참고 자료: DefinitelyTyped Github , Express Middleware 공식문서

KPT

KPT

  • 트러블 슈팅 문서로 제작
  • 타입스크립트 이해도 향상

Problem

  • TS + Express 타입 체크 에러에 많은 시간을 할애한 점
  • ChatGTP한테 1차 코드리뷰를 받을 때 옳게 된 피드백인지, 과하지는 않은지 확인 안 해보고 덥썩 수정한 점

Try

  • 이번 주까지 내배캠 Express 강의 복기
  • 실제 프로젝트 요구사항과 적합한지 분별하여 적용하기

마무리

목요일 부터는 꽤 널널하니 진짜 꼮 빡집중해서 다 해벌인다.

3개의 댓글

comment-user-thumbnail
2024년 12월 10일

"내배캠 Express 강의 복기" 가 인상깊은데요 ㅋㅋㅋㅋ
"목요일 부터는 꽤 널널하니 진짜 꼮 빡집중해서 다 해벌인다." 가 글로 안끝나면 정말 멋있을 것 같아요! 화이팅! 연말 전 까지 무조건! 무조건!! 아자아자!

답글 달기
comment-user-thumbnail
2024년 12월 10일

GPT한테 받는 첨삭이라.. 뭔가 애가 쓸만은 한데 주변 환경이나 배경을 정말 대략적으로만 알려주다 보니까 이상한 코드를 주는 경우가 많더군요;
어떻게 잘 쓰면 정말 유용한 친구긴 합니다! 저도 커스텀 오류 핸들링 적용할 때 애용해서 썼답니다~

아무튼 지금 있는 Problem들 다 잘 해결하고, 크리스마스 전까지 열심히 달려봅시다!

답글 달기
comment-user-thumbnail
2024년 12월 11일

이력서도 쓰시고 아르바이트도 하시고 플젝도 하시고… 몸이 두 개여도 바쁘시겠습니다ㅜㅠㅠ 그래도 에러를 마주치고 해결하는 만큼 성장하실테니까 크리스마스까지 파이팅해봅시다💪🏻💪🏻

답글 달기