개발자

React 변수 호이스팅

2023년 09월 10일조회 414

아래 react 코드에서 Compoent안에 b는 정상적으로 출력되는데 Component 밖의 b는 "Block-scoped variable 'b' used before its declaration.ts(2448)"에러를 반환합니다. component안의 b도 같은 에러를 반환해야할 것 같은데 왜 정상적으로 될까요? 번들링 과정에서 생기는 현상 같은데 정확한 원인을 모르겠어서 질문 남깁니다. 관련 질문: https://stackoverflow.com/questions/75891792/how-variable-hoisting-works-in-react https://stackoverflow.com/questions/71792930/hoisting-in-react-components-how-does-it-work

1// Component.tsx
2export function Component() {
3  console.log(b);
4
5  return <div></div>;
6}
7
8console.log(b);
9const b = 3;
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

인기 답변

민경배님의 프로필 사진

안녕하세요! 자바스크립트 관련 흥미로운 질문을 주셨네요ㅎㅎ 질문을 주신 현상은 아마 리액트 환경에서 뿐만이 아니라, 콘솔에서 일반 자바스크립트로 실행을 해보셔도 같은 결과를 얻으실 수 있을겁니다! 이는 번들링 과정 때문이라기보다는, 자바스크립트가 일반적으로 가지게 되는 실행 컨텍스트 및 라이프사이클 이슈이기 때문에 그렇습니다. 함수를 살펴보기 이전에, 함수 바깥에 정의된 console.log(b); 케이스를 먼저 살펴보겠습니다. 이 줄의 경우, 스크립트가 웹에 로드됨과 동시에 실행되는 global context의 영역입니다. 따라서 콘솔 로그는 즉시 실행이 되며 내부의 값인 b를 참조하게 될 것이고, 아랫줄에 const로 정의되어 있는 b는 호이스팅이 일어나지 않아 값을 참조하지 못해 ReferenceError를 throw하게 됩니다. (정확히는 const도 호이스팅 자체는 일어나긴 합니다ㅎㅎ - https://yceffort.kr/2020/05/var-let-const-hoisting 참조) 그러나 함수의 경우, 특유의 라이프 사이클로 인해 실행이 되기 이전, 정의 단계에서는 내부 스코프 내의 변수에 접근하지 않습니다. 함수는 foo() 형태로 실행이 된 이후에 실행 컨텍스트를 생성하는데, 이 때 실행에 필요한 환경 정보를 모으게 됩니다. 따라서 함수가 정의된 시점에서는 정의되지 않은 변수를 스코프 내에 가지고 있어도 에러를 내지 않습니다. 따라서 오히려 함수가 정의된 위치보다는, 함수의 실행이 변수의 초기화 이전에 일어나게 된다면, 그 때는 실행 컨텍스트 내부에서 b가 참조되며 ReferenceError를 내게 됩니다. (아래 코드 참조) 결론적으로, 질문을 주신 React 환경에서 컴포넌트 함수들은 모두 렌더링 타이밍에 실행이 되고, global context에 있던 const b = 3; 정의는 함수의 실행 이전 시점에 이루어졌을 확률이 높기 때문에 에러가 나지 않았을 것입니다. 정리하자면 다음과 같은 순서 정도 일 것 같습니다. “function Component()”정의 -> “console.log(b)” 외부 실행(에러) -> “const b = 3” 초기화 및 값 할당 -> 렌더링 시점에서 “Component()” 함수 실행(에러x) 추가적인 질문있으시다면 편하게 대댓글 달아주세요:)

1function myFunc() {
2  console.log(b);
3}
4
5myFunc() // ReferenceError
6const b = 3;
7myFunc() // 3
profile picture

익명

작성자

2023년 09월 11일

함수 라이프 사이클과 실행 컨텍스트와 관련된 내용이군요..! 답변 감사합니다🙇

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2023년 09월 10일

이 문제는 JavaScript의 변수 호이스팅(hoisting)과, `let` 및 `const`의 블록 범위(block scope)에 대한 이해가 필요합니다. JavaScript에서 `var`로 선언된 변수는 함수 단위로 호이스팅되며, 초기화하는 구문이 있더라도 호이스팅 과정에서 초기화가 이루어지지 않습니다. 반면에 `let`과 `const`는 블록 범위를 가지고, 선언 및 초기화가 동일한 줄에서 발생합니다. 따라서 아래와 같은 코드에서 ```javascript console.log(b); // Cannot access 'b' before initialization let b = "Hello World!"; ``` 컴포넌트 내부에 위치한 'b' 변수는 컴포넌트가 호출될 때마다 초기화되므로 정상적으로 사용할 수 있습니다. 하지만 컴포넌트 외부에서 선언된 'b' 변수를 그 전에 접근하려고 하면 위의 오류 메시지가 출력됩니다. 즉 React나 번들링 과정과는 별개로 JavaScript 언어 자체의 특성 때문에 발생하는 현상입니다. 결론적으로, 변수를 사용하기 전에 선언하거나 초기화해야 합니다. 참고로 이러한 현상을 방지하기 위해 ES6(ES2015)에서 도입된 `let`과 `const`는 TDZ(Temporal Dead Zone)라는 개념을 도입하여, 선언 전에 변수에 접근하려고 하면 ReferenceError가 발생하도록 했습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!