JS/TIL(Today I Learned)

2024-11-27

프린스 알리 2024. 11. 27.

내일배움캠프 Node.js 트랙 4일차

사례(1) - 발단

캐릭터 생성 과정에서 에러가 발생했다.

 

 

ReferenceError: Cannot access 'classId' before initialization  
    at prisma.$transaction.isolationLevel (file:///C:/Users/solco/Documents/item_simulator/src/routes/characters.router.js:69:30)  
    at async Proxy._transactionWithCallback (C:\Users\solco\Documents\item_simulator\node_modules\@prisma\client\runtime\library.js:130:8000)  
    at async file:///C:/Users/solco/Documents/item_simulator/src/routes/characters.router.js:52:33

 

classId가 초기화되지 않은 상태에서 접근하려 했다는 것. 아마도 트랜젝션을 하는 과정에서 변수 스코프가 달라진 게 아닐까?

 

 


실제 디버그 터미널을 통해 확인했더니 tx 함수 내부로 classId가 전달되지 않고 있었다. 혹은 변수 자체는 전달되었는데 undefined가 되었을 수도 있겠다.(둘 중 어느 경우인지 콘솔을 찍어봤어야 했는데 중간 과정을 캡쳐하지 못했다.)

사례(1) - 해결방법

(1) 명시적 형변환

정확한 원인은 모르겠지만 형변환의 문제인 것 같아서 아예 숫자형 데이터로 바꿔주기 위해 변수를 새롭게 만들었다.

(2) 클래스ID 유효성 검사를 트랜젝션 내부에서 수행

그리고 변수를 확실하게 전달하게끔, 클래스ID의 유효성 검사를 tx함수의 내부로 옮겨주었다.

(3) Insomnia를 통해 결과 확인해보기

결과는 성공적이었다. 숫자 타입으로 형변환이 된 classIdNumber가 tx 함수 내부에서 정상적으로 작동하였다.

MySQL 확장 프로그램으로 확인한 결과에서도, API가 무사히 작동하고 있음을 알 수 있다.


사례(2) - 발단

이번 과제에서 가장 애를 먹었던 부분은 아이템 상세 조회 API를 만들 때였다. 아래의 조건을 코딩으로 구현하는 게 내가 느끼기엔 꽤나 까다로웠다.

내 캐릭터임을 인증하려면? 당연히 jwt.verify를 이용해 토큰을 검증하면 될 것이다. 그러나 기존에 사용하고 있었던 인증 미들웨어는 사용할 수 없었다. 왜냐하면 예외 상황이 발생할 때 오류 메시지를 바로 반환시켰기 때문이다.

그래서 아래와 같이 함수를 새롭게 작성하였다.

서버에 존재하는 계정은 두 개.

 

세 명의 캐릭터 중 안두인은 첫 번째 계정이 소유하고 있었고, 나머지 둘은 두 번째 계정이 소유하는 중이었다.

 

만약 내가 코드를 정확하게 작성했다면,

 

두 번째 계정으로 로그인했을 때, 안두인의 게임머니는 조회가 되지 않을 것이다. 왜냐하면 첫 번째 계정이 해당 캐릭터를 소유하고 있으니 말이다.

 

그러나 내 기대는 보기 좋게 빗나가 버렸다

 

 

돈이 보인다. 현실 돈이라면 모를까 다른 계정이 보유한 게임 머니가 보여봤자 무슨 보람일까. 이건 그저 버그일 뿐인데 말이다. 패닉에 빠진 채 예외 처리를 이곳저곳 건드려보기도 했고, 레코드의 밸류가 잘못 되진 않았는지 재차 확인도 해보았다.

 

그러나 잘못된 부분은 없었고 남의 돈이 보이는 현상은 변함이 없었다.

사례(2) - 해결방법

이럴 때 가장 도움이 되는 것은 JavaScript Debug Terminal…!

의심이 드는 곳마다 중단점을 찍어 주고 변수에 할당된 값이 제대로 전달되고 있는지 꼼꼼히 확인했다.
그러다 발견하게 된 건, 앞서 작성한 토큰 검증 함수의 리턴값이 전혀 할당되지 않고 있었다는 사실이다.

당황스러웠다. 이유를 짐작하기 어려웠다. 함수의 로직이 잘못 되었다는 의심이 먼저 앞섰다. 그러나 눈을 씻고 쳐다봐도 로직의 문제는 아닌 것 같았고, 라우터 안에서 해당 함수를 읽어올 때 발생한 문제 같았다.

그때, 문득 떠오르는 기억이 있었다.


Node.js 숙련주차 강의를 열심히 듣고 있던 어느 날, 강사님의 실습을 따라하다가 원하는 결과가 나오지 않아서 고생했던 적이 있었더랬다. 그게 시간을 많이 잡아먹었던 터라, 깃헙에 올려둔 실습 파일에도 주석을 달아 놨을 정도였다.

(출처 : my_board/src/routes/users.router.js at b60f7837e2e7b2fbb01833bfc347fbb1b567b1b2 · ppiok-OwO/my_board)

 

과거의 실수를 반추하며 다시 코드를 읽어봤다. 역사는 반복된다고 하지 않았던가. 이번 문제 또한 마찬가지였다.
비동기 함수의 반환값을 할당할 때 await를 빠뜨렸던 것!

// 코드가 제대로 작동하려면 이게 아니라...
const user = verifyToken(authorization);

// 이렇게 썼어야 했다!
const user = await verifyToken(authorization);

코드를 고치고서 insomnia를 다시 실행한 결과, 원하던 결과를 얻을 수 있었다.


느낀 점

두 개의 트러블 슈팅 사례로부터 내가 배운 것은 사람은 언제나 실수를 반복한다는 점이었다. 분명 예전에도 비슷한 실수를 해서 고생을 했음에도, 또 같은 실수를 하고 원인을 찾느라 시간을 낭비해버렸으니 말이다. 그나마 밤을 새며 고민하지 않아도 괜찮았던 것은, 주석으로 메모를 해두었던 습관 덕분일 터다. 그리고 하나 더. 깃헙 레포지토리에 차곡차곡 기록을 해두지 않았더라면, 그걸 들여다볼 생각을 하지 않았더라면 더 많은 시간이 낭비되었을지도 모르겠다. 이번의 경험을 꼭 되새기면서 앞으론 실수를 줄여나갈 수 있게 노력해야겠다.

'JS > TIL(Today I Learned)' 카테고리의 다른 글

2024-11-29  (3) 2024.11.29
2024-11-28  (2) 2024.11.28
2024-11-26(2)  (0) 2024.11.26
2024-11-26  (1) 2024.11.26
2024-11-25  (1) 2024.11.25

댓글