렉시컬 스코프 v 렉시컬 환경
작성일:2025.02.13|조회수:0

렉시컬 스코프라는 용어를 처음 접했을 때, 나는 이것을 별다른 의심 없이 ‘렉시컬 환경에 따른 스코프 체인’ 정도로 이해했다. 두 개념이 밀접하게 연결되어 있다는 인상 때문이었을 것이다. 그 결과, 모 회사의 면접에서 렉시컬 스코프를 설명해 보라는 질문을 받았을 때 스코프 체인에 대한 설명만을 늘어놓고 말았다.
면접이 끝난 뒤, 렉시컬 스코프와 스코프 체인은 다른 개념이라는 피드백을 들었다. 하지만 왜 다른지, 무엇이 다른지, 어떤 관점에서 구분해야 하는지는 명확히 설명할 수 없었다. 이후 _코어 자바스크립트_와 _YDKJSY_를 차례로 읽으며, 이 두 개념이 비슷해 보일 뿐 실제로는 서로 다른 레이어의 개념이라는 사실을 비로소 이해하게 되었다.
렉시컬 스코프는 변수와 함수의 유효 범위가 어디에서 선언되었는지에 의해 결정된다는 원칙을 의미한다. 이는 정적으로 결정되는 규칙이며, 코드가 작성된 위치에 의해 스코프가 고정된다. 다시 말해, 함수가 어느 코드 블록 안에서 선언되었는지가 그 함수가 접근할 수 있는 변수의 범위를 결정하며, 이 결정은 실행 시점의 호출 방식이나 실행 흐름에 의해 바뀌지 않는다.
이러한 이유로 렉시컬 스코프는 흔히 컴파일 타임에 결정된다고 설명된다. 실제로 자바스크립트 엔진은 코드를 실행하기 전에 이미 변수 접근 가능 여부를 구조적으로 확정해 두며, 이후 실행 과정에서는 이 규칙을 변경하지 않는다.
반면 렉시컬 환경은 변수와 함수가 실제로 어떤 값을 가지고 있는지를 저장하고 관리하는 실행 시점의 구조이다. 렉시컬 환경은 **환경 레코드(Environment Record)**를 통해 해당 스코프 내의 식별자와 그에 대응하는 값을 관리한다. 여기에는 변수 선언, 함수 선언, 매개변수, 그리고 this 바인딩과 같은 정보가 포함된다.
즉, 렉시컬 스코프가 “어디까지 접근할 수 있는가”를 정의하는 규칙이라면, 렉시컬 환경은 “그 접근 가능한 식별자들이 현재 어떤 상태를 가지고 있는가”를 관리하는 구체적인 메커니즘이다. 이 관점에서 렉시컬 환경은 렉시컬 스코프가 런타임에 실체화된 결과물이라고 볼 수 있다.
렉시컬 환경은 실행 컨텍스트가 생성될 때마다 동적으로 만들어진다. 각 실행 컨텍스트는 자신만의 렉시컬 환경을 가지며, 동시에 외부 렉시컬 환경에 대한 참조를 유지한다. 이 참조의 연결 구조가 바로 스코프 체인이다. 스코프 체인은 현재 실행 중인 코드가 어떤 렉시컬 환경들에 접근할 수 있는지를 선형적으로 연결한 구조이며, 변수 조회 시 이 체인을 따라 상위 환경으로 탐색을 진행한다. 따라서 스코프 체인은 렉시컬 스코프라는 규칙을 기반으로 하되, 실제 동작은 렉시컬 환경 간의 참조 관계를 통해 이루어진다.
이러한 맥락에서 클로저 역시 렉시컬 스코프 자체보다는 렉시컬 환경에 더 직접적으로 의존한다. 함수가 선언될 당시의 외부 렉시컬 환경에 대한 참조가 유지되기 때문에, 함수 실행이 끝난 이후에도 해당 환경의 값에 접근할 수 있는 것이다. 이는 “스코프 규칙”이 아니라 “환경이 유지되는 방식”의 문제에 가깝다.
정리하면 다음과 같다. 렉시컬 스코프는 컴파일 타임에 결정되는 변수 유효 범위에 대한 규칙이며, 렉시컬 환경은 그 규칙을 바탕으로 자바스크립트 엔진이 런타임에 변수와 값을 관리하는 실제 구조이다. 스코프 체인과 클로저는 렉시컬 스코프 위에 존재하지만, 그 동작의 중심에는 항상 렉시컬 환경이 있다.
더 읽어보기
2026.04.11
Trie 자료구조
문자열 데이터를 다룰 때 단순히 “이 단어가 있나?”만으로는 부족한 순간이 있다. 자동 완성처럼 특정 접두사로 시작하는 후보를 모아야 할 때도 있고, 어떤 키에 값을 두고 빠르게 찾고 싶을 때도 있다. 이럴 때 가장 자연스럽게 떠올릴 수 있는 자료구조가 바로 Trie이다. Trie는 무…
2026.03.19
Streams API 부록 2. 왜 이미지는 위에서 아래로 나타날까
느린 네트워크에서 큰 이미지를 열면 가끔 화면이 위에서 아래로 채워진다. 마치 누군가 아주 성실하게 롤러로 이미지를 칠하는 것처럼 보인다. 물론 브라우저 안에 그런 직원은 없다. 있다면 우리보다 야근을 더 많이 하고 있을 것이다. 이 현상은 단순한 시각 효과가 아니라 네트워크 전송, 브…
2026.03.19
Streams API 부록 1. HTTP 다운로드 진행률은 어떻게 계산될까
다운로드 화면에서 진행 막대가 조금씩 차오르면 이상하게 안심된다. 반대로 스피너만 계속 돌면 파일이 오는 중인지, 서버가 고민 중인지, 내 인생이 잠깐 멈춘 건지 알 수 없다. 사용자는 둘 다 “다운로드 중”이라고 느끼지만, 내부적으로는 꽤 다른 상황일 수 있다. 진행률 계산 자체는 복…
2026.03.13
Streams API 4. 왜 모든 언어에는 Stream API가 존재할까
Streams API를 공부하다 보면 묘한 기시감이 온다. JavaScript에서 ReadableStream, WritableStream, TransformStream을 보고 있는데, Java의 InputStream, Go의 io.Reader, Rust의 Read와 Write가 멀리서…
2026.06.01
React Server Components를 위한 컴포넌트 아키텍처
이 포스트는 Vercel의 Next.js 팀 소속 개발자 Aurora Scharff가 자신의 블로그에 올린 Component Architecture for React Server Components 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는…
2026.05.26
차트는 멈췄는데 윈도우가 움직인다
상황 어느날 서비스를 살펴보시던 팀장님께서 이런 말씀을 slack에 남기셨다. 진호님, 예측 차트에서 zoom을 계속하면 어느 순간 라인 차트가 아니라 단일 스캐터 차트처럼 보이는 데, 이거 수정하면 좋을 거 같아요. 어느정도 zoom을 하면 그 이후로는 zoom이 안 되도록 할 수 없…
2026.05.21
피자가게로 이해하는 디자인 패턴
에이든 피자는 처음부터 복잡한 시스템을 만들 생각이 없었다. 처음에는 메뉴 몇 개만 만들면 됐다. 그런데 손님은 커스텀 주문을 넣기 시작했고, 주방은 상태를 나눠야 했고, 결제와 배달앱과 알림이 하나씩 붙었다. 코드도 가게를 닮는다. 장사가 잘될수록 이상하게 더 쉽게 망가진다. 디자인…
2026.05.21
7. Decorator — 토핑 추가할 때마다 클래스를 새로 만들 수 없다
에이든 피자에서 주문서를 객체로 만들자 취소와 재주문은 한결 편해졌다. 그런데 주문이 편해지자 손님들도 한결 편해졌다. 편해진 손님은 더 많은 요구를 한다. "치즈 추가요", "올리브도 추가요", "소스 많이요", "조금 더 바삭하게 구워주세요" 같은 요청이 주문대 위로 쌓이기 시작했다…
댓글
댓글을 불러오는 중...