What happend?

puppeteer 기반의 크롤러 기능 중 loop를 돌며 화면 내의 '다음' 이동 버튼을 클릭하며 데이터를 수집하는 부분을 개발하고 있었다.

 

클릭 후 자체적으로 setTimeOut을 활용해 만든 delay 함수를 호출시켜 대기 후 루프를 돌게 했는데도 자꾸만 몇개 데이터가 중복으로 들어가서 원인을 찾느라 몇 시간을 썼다.

 

수집할 데이터 - FOTMOB 사이트의 슈팅 상황

 

 

 

What went wrong?

루프를 도는 함수 내에서 click에 await를 걸어주지 않았다.

 

수정 후, 원래는 await가 빠져 있었다.

 

 

 

여기서 주의할 점이, puppeteer에서 제공하는 $를 사용해 가져온 객체는 ElementHandle로 반환되고, querySelector를 사용해 가져온 객체는 그냥 Element로 반환된다는 점이다.

 

다른 로직에서는 eval 함수 내부에서 특정 버튼을 querySelector로 가져왔다. 

그렇게 가져온 요소는 Element이므로 click 시에도 Promise를 반환하지 않으므로 그냥 await 없이 동기 호출했다.

 

이 기억때문에 오류가 난 부분에도 동일하게 await를 걸어주지 않았고, 따라서 click 이후 await 대기한 뒤 후속 작업을 진행해야 하는데 대기 없이 비동기 로직들은 남겨두고 루프가 추가로 돌아버렸고, 그래서 몇번의 중복 루프가 추가적으로 수행 & 중복 데이터가 입력된 것으로 보인다.

 

해당 matchLink는 Element이므로 click 시에도 Promise를 반환하지 않는다.

 

 

 

Lesson & Learned

따라서 puppeteer $ 함수로 가져온 객체를 click시, async 함수 내에서는 반드시 await로 호출해 대기하자.

 

 

 

끝.

 

반응형

멍청한 에러들을 기록한다.

 

 

What happend?

NestJS로 백엔드 개발을 하던 중, 기존 Array에 push하는 부분에서 자꾸만 'ERROR [ExceptionsHandler] XXX is not a function' 에러가 발생했다.

 

ERROR [ExceptionsHandler] XXX is not a function

 

 

로직도 수차례 변경해 보고, push 함수가 아니라 새로운 Array를 만들어 slice로 깊은 복사 후 재 할당도 해보고 온갖 짓을 다 했으나 해결이 안 됐다.

 

자고 일어난 다음날, 테스트를 하다가 해결했다.

역시 졸린 상태에서는 개발하는 거 아니다.

 

 

 

What went wrong?

Movie 정보를 담고 있는 this.movie는 Array인데, update시 호출하는 deleteMovie 로직에서 delete 후 Array가 아닌 List로 담는 바람에 오류가 발생했다.

 

List에는 당연히 push function이 없으니까 위와 같은 에러가 발생한다.

 

휴...

 

 

 

 Lesson & Learned

  • API 테스트 결과 확실히 살피기 - 자료형이나 Depth 등이 변하진 않았는지
  • TypeScript 맹신하지 않기 - movies를 Movie[]로 선언하였으나 로직 중에 해당 변수에 List를 할당해도 에러가 발생하지 않는다.
    (그러나 다이렉트로 movies = {}; 따위를 넣어버리면 오류가 발생한다.)

 

 

 

 

끝.

반응형

+ Recent posts