angular에서 타이머 스크립트 사용시 this 오류

앵귤러에 일반적인 자바스크립트 타이머 스크립트를 적용하던 중 다음과 같은 오류가 발생했다.

TypeError: Cannot read properties of undefined (reading ‘split’)

타이머 시작 부분에서 setInterval로 1초 간격으로 callback펑션을 호출하여 callback펑션 안에서 시간을 1초씩 줄이는 스크립트였는데 해당 기능을 angular에 맞게 클래스 내부 변수 및 메소드로 분리하고 남은시간 변수(interval)를 클래스의 변수로 빼두고 테스를 하니 callback펑션 안에서 남은시간 변수(this.interval)를 참조하지 못했다.

기존 자바스크립트에서 타이머 시작부분

let interval = setInterval(callback, 1000);

기존 자바스크립트에서 시간을 1초씩 빼는 콜백 펑션

  function callback() {
    let timer = timer2.split(":");
    let minutes = parseInt(timer[0], 10);
    let seconds = parseInt(timer[1], 10);

    --seconds;
    minutes = seconds < 0 ? --minutes : minutes;
    if (minutes === 0 && seconds === 0) clearInterval(interval);
    seconds = seconds < 0 ? 59 : seconds;
    seconds = seconds < 10 ? "0" + seconds : seconds;
    $(".count-number").html(minutes + ":" + seconds);
    timer2 = minutes + ":" + seconds;
  }

원인

왜냐하면 interval로 함수를 호출한 이후의 this는 앵귤러 클래스의 this가 아니라 호출한 펑션 그 자체를 뜻하기 때문이다.
풀어서 얘기하자면 callback펑션 안에서 this.interval로 앵귤러 클래스의 interval변수를 참조시키려 했으나 this가 호출된 앵귤러 클래스가 아닌 callback펑션 그 자체를 의미하므로 interval이라는 변수가 undefined가 되어 에러메세지가 발생한 것이다.
원래 자바스크립트에서는 함수호출시 인자 및 this가 암묵적으로 함수 내부로 전달되는데 경우에 따라 this는 자기참조변수이기도 해서 문제가 발생하는 것이다.
this가 가리키는 값은 함수 호출 방식에 의해 동적으로 결정된다는 것을 이해하는 것이 핵심이다.


해결방법

이 문제를 해결하는 가장 쉬운 방법은 setInterval에서 펑션을 바로 호출하지 말고 () => 화살표 함수로 호출하면 된다.
화살표 함수로 함수를 선언하면 this가 상위 스코프의 this를 가리키므로 의도했던 대로 현재 class의 interval변수를 가리키게 된다.

setInterval(callback, 1000); 이 부분을 다음과 같이 변경한다.

setInterval( () => { this.callback() }, 1000);

아울러 개발자라면 자바스크립트의 this개념은 한번 정리해두고 넘어갈 필요가 있다. 특히 참조 링크의 마지막 게시물을 추천한다.
(초급때는 의외로 이 부분을 이해하지 못해 삽질을 많이 하게 됨 ^^;)

참조 링크

영어에 익숙치 않다면 다음 포스팅도 추천한다.

생계형 특급 개발자이자 아들 하나 있는 평범한 아빠. 취미는 요리, 캠핑, 뮤직 페스티발 다니기 등이지만 이 블로그에는 주로 개발관련된 내용만 올릴 예정입니다. 워드프레스를 시작한지 얼마 되지않아 사이트가 허전하지만 좋은 내용으로 채우도록 노력하겠습니다. 자주 놀러오세요 ^^
Posts created 54

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top