리액트 딥다이브 (클로저, 비동기 함수)

뇽뇽·2025년 7월 12일

클로저

  • 함수와 함수가 선언된 어휘적 환경의 조합
  • 함수가 어디서 선언되었는지를 의미하게 된다
    • 함수 안에 내부 함수가 존재하기 되면 외부 함수의 변수에 접근할 수 있게 됨

함수 스코프

  • 스코프 : 변수의 유효 범위

  • 전역 스코프: 전역 레벨에 선언하는 것 (window, global 같은 것들이 선언됨)

    • 전역 스코프는 어디서든 원하는 값 수정할 수 있다는 점에서 단점 이 있다
  • 함수 스코프: 함수 레벨에서 선언하는 것 (함수 내부 변수)

  • 우리는 클로저 라는 개념을 통해서 내부 함수에서 외부 함수의 변수의 접근 가능하다는 것을 이용해 전역 스코프의 사용을 막고 원하는 정보에 대해서 원하는 방식으로 노출 (ex, react 에서 상태를 관리했던 거 처럼)

리액트에서의 클로저

  • setState 를 통해서 최신 상태값을 확인할 수 있는 방법은 useState (라는 외부 함수) 의 호출이 끝나더라도 setState (라는 내부 함수) 는 자신이 선언된 외부 함수가 선언된 환경에 기억할 수 있어서 내부적으로 state 를 활용할 수 있게된다.

주의할 점

for 문에서 setTimeout 넣고 var 로 선언한 idx 값으로 출력을 찍으면 함수 레벨 스코프라고 간주하고 일정한 값만 출력된다. 그러나 let 으로 선언해주면 블록 레벨 스코프를 가지게 되어 일정하게 증가하는 idx 값을 가지게 된다.

또한 클로저는 생성되었을 떄의 그 선언적 환경에 대해서 기억해주기 위해 비용이 든다. 내부 함수는 외부 함수의 선언적인 환경에 대해 기억해주기 위해 큰 메모리 비용이 든다.

비동기 통신

  • js 는 기본적으로 싱글 스레드 언어 이기 때문에 하나의 작업만 동기적인 방식으로 처리할 수 있다. 비동기 방식은 작업의 응답이 돌아올 떄까지 기다리는 것이 아니라 그 다음 작업에 대해 실행을 이어가는 것이다.
  • 프로세스 : 프로그램이 실행되는 단위, 스레드: 프로세스 내에서 더 작은 작업 단위로 처리하는 거

이벤트 루프

  • 싱글 스레드로 동작하는 자바스크립트의 단점을 보완해내기 위해 비동기 로직을 처리하기 위해 도입
  • 콜 스택, 태스크 큐: 호출되는 함수들은 콜 스택에 쌓이고 실행되면 빠져나가게됨, 여기서 이벤트 루프는 콜 스택이 비어있다면 태스크 큐에 담겨있는 비동기 함수의 콜백 함수를 넣어서 실행한다.
    • 비동기 함수는 일단 콜 스택에 들어가긴 함. 하지만 비동기 함수라면 바로 태스크 큐로 이동
    • 태스크 큐는 실행 가능한 가장 오래된 태스크를 가져온다.
    • 비동기 함수는 js 를 동기적으로 실행하는 메인 스레드 가 아니라 태스크 큐에 할당된 별도의 스레드에서 실행됨1! ( 온전히 모든 역할 js 의 메인 스레드만이 하는 것은 아님)

마이크로 태스크큐 & 매크로태스크큐

마이크로태스크큐: Promise 객체, MutationObserver 와 같이 비동기 함수의 중요도 가 높은 애들
매크로태스크큐: setTimeout, setInterval 과 같이 중요도 낮은 비동기 함수

  • 렌더링이 일어나는 것은 각 마이크로태스크큐의 작업이 끝날 때마다, 매크로태스크큐의 작업이 모두 끝난 이후 렌더링 됨
  • requestAnimationFrame 작업과 비교했을 떄에는 raf 는 브라우저에서 다음 리페인트(화면에 그려내는 작업) 가 일어나기 전에 실행된다.
    즉 마이크로 태스크 큐의 콜백 함수 -> 렌더링 직전에 호출되는 raf 의 콜백함 수 실행 -> 렌더링 -> 매크로태스크큐의 콜백 함수 실행 -> 다음 이벤트 루프
profile
https://github.com/SeieunYoo

0개의 댓글