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

렉시컬 스코프라는 용어를 처음 접했을 때, 나는 이것을 별다른 의심 없이 ‘렉시컬 환경에 따른 스코프 체인’ 정도로 이해했다. 두 개념이 밀접하게 연결되어 있다는 인상 때문이었을 것이다. 그 결과, 모 회사의 면접에서 렉시컬 스코프를 설명해 보라는 질문을 받았을 때 스코프 체인에 대한 설명만을 늘어놓고 말았다.
면접이 끝난 뒤, 렉시컬 스코프와 스코프 체인은 다른 개념이라는 피드백을 들었다. 하지만 왜 다른지, 무엇이 다른지, 어떤 관점에서 구분해야 하는지는 명확히 설명할 수 없었다. 이후 _코어 자바스크립트_와 _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.10
:empty로 비어 있는 wrapper 다루기
UI를 만들다 보면 내용은 없는데 wrapper만 남는 경우가 있다. 카드의 보조 설명 영역, 필터 결과 안내 영역, 혹은 children을 받아서 그리는 작은 레이아웃 컴포넌트가 그렇다. 실제로 보여줄 내용은 없는데 padding이나 border가 적용된 부모 요소만 화면에 남으면,…
2026.06.07
AI 에이전트의 비밀값을 macOS Keychain에 맡기기
AI 에이전트나 스킬을 만들다보면 비밀값을 어떻게 관리하면 좋을지 하는 생각을 자주 하게 된다. API를 호출하려면 API Key가 필요하고, 특정 기능을 자동화하는 과정에서 아이디와 비밀번호가 필요할 수도 있다. 그런데 그 값을 프롬프트에 박아버리면 대화 기록에 남고, 명령어 인자로…
2026.06.01
React Server Components를 위한 컴포넌트 아키텍처
이 포스트는 Vercel의 Next.js 팀 소속 개발자 Aurora Scharff가 자신의 블로그에 올린 Component Architecture for React Server Components 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는…
2026.05.26
차트는 멈췄는데 윈도우가 움직인다
상황 어느날 서비스를 살펴보시던 팀장님께서 이런 말씀을 slack에 남기셨다. 진호님, 예측 차트에서 zoom을 계속하면 어느 순간 라인 차트가 아니라 단일 스캐터 차트처럼 보이는 데, 이거 수정하면 좋을 거 같아요. 어느정도 zoom을 하면 그 이후로는 zoom이 안 되도록 할 수 없…
댓글
댓글을 불러오는 중...