Home

JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기

Published in javascript
November 30, 2025
2 min read
JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기

안녕하세요, 코딩하는곰입니다! 오늘은 JavaScript에서 let과 const의 핵심 개념인 블록 스코프에 대해 깊이 있게 알아보겠습니다. 많은 자바스크립트 개발자들이 var와 let/const의 차이를 알고는 있지만, 정확한 블록 스코프의 동작 방식과 그 implications을 이해하는 것은 더 안정적이고 예측 가능한 코드를 작성하는 데 중요합니다. 이 글을 통해 {} 안에서 변수가 어떻게 동작하는지 완벽하게掌握하시길 바랍니다.

블록 스코프의 기본 개념 이해하기

블록 스코프(Block Scope)란 간단히 말해 {}(중괄호)로 둘러싸인 코드 블록 내에서 선언된 변수가 해당 블록 안에서만 유효하다는 개념입니다. ES6에서 도입된 let과 const는 바로 이 블록 스코프를 따르는 변수 선언 방식입니다.

블록 스코프의 정의와 동작 방식

블록 스코프의 기본적인 동작을 이해하기 위해 가장 간단한 예제부터 살펴보겠습니다.

{
let blockScopedVariable = "나는 블록 안에서만 살아있어요!";
const alsoBlockScoped = "나도 블록 스코프를 가져요";
console.log(blockScopedVariable); // "나는 블록 안에서만 살아있어요!" 출력
console.log(alsoBlockScoped); // "나도 블록 스코프를 가져요" 출력
}
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
console.log(alsoBlockScoped); // ReferenceError: alsoBlockScoped is not defined

위 예제에서 볼 수 있듯이, letconst로 선언된 변수들은 해당 블록({}) 안에서는 정상적으로 접근할 수 있지만, 블록 밖에서는 완전히 존재하지 않는 변수처럼 동작합니다.

블록 스코프의 다양한 형태

블록 스코프는 단순히 {}만 있는 것이 아니라 여러 가지 형태로 나타납니다:

// 1. 단순 블록
{
let message = "안녕하세요";
console.log(message); // 정상 작동
}
// 2. if문 블록
if (true) {
let conditionVariable = "if문 안의 변수";
console.log(conditionVariable); // 정상 작동
}
// console.log(conditionVariable); // ReferenceError
// 3. for문 블록
for (let i = 0; i < 3; i++) {
let loopVariable = `반복 ${i}`;
console.log(loopVariable); // 매 반복마다 정상 작동
}
// console.log(loopVariable); // ReferenceError
// console.log(i); // ReferenceError
// 4. while문 블록
let count = 0;
while (count < 2) {
let whileVariable = `while ${count}`;
console.log(whileVariable);
count++;
}
// 5. switch문 블록
switch (true) {
case true:
let switchVariable = "switch 안의 변수";
console.log(switchVariable); // 정상 작동
break;
}
// console.log(switchVariable); // ReferenceError

var vs let/const의 스코프 비교

기존의 var와 새로운 let, const의 가장 큰 차이점을 스코프 관점에서 비교해보겠습니다.

// var의 함수 스코프 vs let의 블록 스코프
function varExample() {
if (true) {
var functionScoped = "함수 스코프";
let blockScoped = "블록 스코프";
}
console.log(functionScoped); // "함수 스코프" - 접근 가능!
console.log(blockScoped); // ReferenceError - 접근 불가!
}
// 전역에서의 차이
var globalVar = "나는 전역 var";
let globalLet = "나는 전역 let";
{
var stillGlobal = "나도 전역이야!";
let blockOnly = "나는 블록 안에서만";
}
console.log(globalVar); // 접근 가능
console.log(globalLet); // 접근 가능
console.log(stillGlobal); // 접근 가능 - var는 블록 스코프를 무시!
console.log(blockOnly); // ReferenceError

이러한 차이 때문에 letconst를 사용하면 변수의 유효 범위를 더 명확하게 제어할 수 있고, 의도치 않은 변수 접근이나 값 변경을 방지할 수 있습니다.

JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기
JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기


🛠️ 프로그래밍 팁과 트릭을 찾고 있다면, CSS 적용 방식 3가지 완벽 비교 인라인, 내부, 외부 방식의 모든 것를 참고해보세요.

블록 스코프의 실제 활용과 장점

블록 스코프는 단순한 문법적 차이를 넘어서 실제 개발에서 많은 장점을 제공합니다. 이제 블록 스코프가 어떻게 더 안전하고 명확한 코드 작성을 도와주는지 구체적으로 살펴보겠습니다.

변수 은닉과 네임스페이스 관리

블록 스코프를 활용하면 동일한 변수 이름을 다른 블록에서 안전하게 재사용할 수 있습니다.

function processData(data) {
// 첫 번째 처리 단계
{
let temp = data.preprocess();
console.log("전처리 결과:", temp);
// temp 변수는 이 블록 안에서만 유효
}
// 두 번째 처리 단계
{
let temp = data.transform(); // 같은 이름의 변수 안전하게 재사용
console.log("변환 결과:", temp);
}
// 세 번째 처리 단계
{
let temp = data.finalize();
console.log("최종 결과:", temp);
}
// 각 블록의 temp 변수는 서로 완전히 독립적
}
processData(sampleData);

루프에서의 블록 스코프 활용

전통적인 var를 사용한 for 루프에서 발생하던 클로저 문제를 블록 스코프가 어떻게 해결하는지 확인해보겠습니다.

// 문제가 있는 var 사용 예제
console.log("=== var를 사용한 경우 ===");
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log("var i:", i); // 항상 3 출력
}, 100);
}
// 해결책 1: IIFE 사용 (ES5 방식)
console.log("=== IIFE를 사용한 경우 ===");
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() {
console.log("IIFE j:", j); // 0, 1, 2 출력
}, 100);
})(i);
}
// 해결책 2: let 사용 (ES6 방식 - 더 간단!)
console.log("=== let을 사용한 경우 ===");
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log("let i:", i); // 0, 1, 2 출력
}, 100);
}

블록 스코프와 호이스팅, TDZ(Temporal Dead Zone)

letconst도 호이스팅이 발생하지만, TDZ라는 개념으로 인해 선언 전에 접근할 수 없습니다.

// var의 호이스팅
console.log(varVariable); // undefined (에러 안남)
var varVariable = "var 변수";
// let의 호이스팅 (TDZ)
// console.log(letVariable); // ReferenceError: Cannot access 'letVariable' before initialization
let letVariable = "let 변수";
// const의 호이스팅 (TDZ)
// console.log(constVariable); // ReferenceError: Cannot access 'constVariable' before initialization
const constVariable = "const 변수";
// TDZ의 실제 동작 이해
function demonstrateTDZ() {
// 이 지점부터 letVariable 선언까지가 TDZ
// console.log(example); // ReferenceError
let example = "이제 사용 가능";
console.log(example); // 정상 작동
}
demonstrateTDZ();

조건부 블록 스코프 활용

런타임 조건에 따라 다른 블록 스코프를 생성하는 패턴도 유용하게 사용할 수 있습니다.

function createIsolatedBlock(condition) {
if (condition) {
// 이 블록은 condition이 true일 때만 생성됨
let isolatedVar = "조건부 블록 변수";
const config = {
setting1: "value1",
setting2: "value2"
};
console.log(isolatedVar);
console.log(config);
// 블록이 끝나면 isolatedVar, config는 소멸
} else {
// 다른 블록 - 완전히 분리된 스코프
let isolatedVar = "else 블록 변수"; // 같은 이름 안전하게 사용
console.log(isolatedVar);
}
}
createIsolatedBlock(true);
createIsolatedBlock(false);

JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기
JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기


두뇌 건강을 위한 재미있는 퍼즐 게임이 필요하다면, 크립토 할아버지의 지혜가 담긴 스도쿠 저니를 설치해보세요.

고급 블록 스코프 패턴과 모범 사례

이제 블록 스코프를 활용한 고급 패턴과 실제 프로젝트에서의 모범 사례를 알아보겠습니다.

즉시 실행 블록 표현식(IIBE)

즉시 실행 함수 표현식(IIFE)의 블록 스코프 버전이라고 할 수 있는 즉시 실행 블록 표현식을 소개합니다.

// 기존 IIFE 패턴
(function() {
var privateVar = "IIFE 안의 변수";
console.log(privateVar);
})();
// 블록 스코프를 이용한 즉시 실행 블록
{
let privateVar = "블록 안의 변수";
const helperFunction = () => {
return "도우미 함수";
};
console.log(privateVar);
console.log(helperFunction());
}
// privateVar, helperFunction은 이제 접근 불가
// 조건부 즉시 실행 블록
let shouldExecute = true;
if (shouldExecute) {
let temporaryData = "임시 데이터 처리";
const processData = (data) => data.toUpperCase();
console.log(processData(temporaryData));
// 처리 완료 후 모든 임시 변수 자동 정리
}

모듈 패턴과 블록 스코프

블록 스코프를 이용한 간단한 모듈 패턴 구현을 살펴보겠습니다.

// 데이터 처리 모듈
{
const API_ENDPOINT = "https://api.example.com";
let requestCount = 0;
const fetchData = async (url) => {
requestCount++;
try {
const response = await fetch(`${API_ENDPOINT}${url}`);
return await response.json();
} catch (error) {
console.error("데이터 fetching 실패:", error);
throw error;
}
};
const getRequestCount = () => requestCount;
const resetCounter = () => { requestCount = 0; };
// 외부에 노출할 인터페이스
window.dataModule = {
fetchData,
getRequestCount,
resetCounter
};
}
// 사용 예제
async function useDataModule() {
try {
const data = await window.dataModule.fetchData("/users");
console.log("요청 횟수:", window.dataModule.getRequestCount());
console.log("데이터:", data);
} catch (error) {
console.error("오류 발생:", error);
}
}

에러 처리와 블록 스코프

try-catch 블록과의 조합도 매우 효과적입니다.

function processWithErrorHandling() {
// 첫 번째 시도
{
let attempt = 1;
try {
const result = riskyOperation(attempt);
console.log(`시도 ${attempt} 성공:`, result);
} catch (error) {
console.log(`시도 ${attempt} 실패:`, error.message);
}
// attempt 변수는 블록 종료와 함께 정리
}
// 두 번째 시도 (다른 파라미터)
{
let attempt = 2;
const config = { retry: true, timeout: 5000 };
try {
const result = riskyOperation(attempt, config);
console.log(`시도 ${attempt} 성공:`, result);
} catch (error) {
console.log(`시도 ${attempt} 실패:`, error.message);
}
// attempt, config 변수 정리
}
}
function riskyOperation(attempt, options = {}) {
if (Math.random() > 0.5) {
return `시도 ${attempt}의 결과`;
} else {
throw new Error(`시도 ${attempt}에서 무작위 실패`);
}
}

성능 최적화와 메모리 관리

블록 스코프는 메모리 관리 측면에서도 장점을 가집니다.

function processLargeDataset() {
const largeArray = Array.from({length: 1000}, (_, i) => i);
// 첫 번째 처리 단계 - 대용량 임시 데이터 사용
{
let temporaryData = largeArray.map(x => x * 2);
let processed = temporaryData.filter(x => x % 3 === 0);
console.log("1단계 결과 개수:", processed.length);
// temporaryData는 이 블록 안에서만 필요
// 블록 종료 시 가비지 컬렉션 대상이 됨
}
// 두 번째 처리 단계 - 다른 임시 데이터 사용
{
let temporaryData = largeArray.map(x => x * 3);
let aggregated = temporaryData.reduce((sum, val) => sum + val, 0);
console.log("2단계 집계 결과:", aggregated);
// 첫 번째 temporaryData와는 완전히 별개의 메모리 공간
}
// 대용량 임시 변수들은 블록 종료와 함께 메모리에서 해제
console.log("모든 처리 완료");
}
processLargeDataset();

실전 프로젝트 적용 패턴

마지막으로 실제 프로젝트에서 블록 스코프를 효과적으로 사용하는 패턴들을 정리해보겠습니다.

// 패턴 1: 설정 객체 분리
function initializeApp() {
// 개발 환경 설정
{
const config = {
apiUrl: "http://localhost:3000/api",
debug: true,
features: ["hot-reload", "dev-tools"]
};
console.log("개발 설정 적용:", config);
}
// 프로덕션 환경 설정
{
const config = {
apiUrl: "https://api.myapp.com",
debug: false,
features: ["optimization", "caching"]
};
console.log("프로덕션 설정 적용:", config);
}
}
// 패턴 2: 컴포넌트별 독립 스코프
function renderDashboard() {
// 사용자 정보 컴포넌트
{
const userData = fetchUserData();
const userElement = createUserElement(userData);
document.getElementById('user-section').appendChild(userElement);
// userData, userElement는 이 컴포넌트에서만 사용
}
// 통계 컴포넌트
{
const stats = calculateStatistics();
const chart = renderChart(stats);
document.getElementById('stats-section').appendChild(chart);
// stats, chart는 이 컴포넌트에서만 사용
}
// 각 컴포넌트의 변수들이 서로 간섭하지 않음
}

JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기
JavaScript let, const의 블록 스코프 완벽 가이드 - {} 안에서의 변수 유효 범위 이해하기


두뇌 건강을 위해 매일 스도쿠를 풀고 싶다면, AI 기반 힌트와 스토리 모드를 제공하는 스도쿠 저니를 다운로드해보세요.

블록 스코프는 JavaScript의 let과 const가 가져온 가장 중요한 혁신 중 하나입니다. {} 안에서 변수의 생명주기를 명확하게 제어할 수 있게 해주어 더 안전하고 예측 가능한 코드를 작성할 수 있습니다. 오늘 알아본 내용들을 실제 프로젝트에 적용하면 변수 충돌을 방지하고, 메모리 사용을 최적화하며, 코드의 가독성을 높일 수 있을 것입니다. 항상 let과 const의 블록 스코프特性을 활용하여 더 나은 JavaScript 코드를 작성해보세요! 질문이 있으시면 댓글로 남겨주시면 성심껏 답변드리겠습니다. 다음 포스팅에서 또 만나요!

모바일이나 데스크탑에서 별도 설치 없이 빠르게 사용할 수 있는 온라인 계산기를 이용해보세요.









최상의 건강을 위한 영양가득한 식품과 정보! life-plus.co.kr 바로가기
최상의 건강을 위한 영양가득한 식품과 정보! life-plus.co.kr 바로가기



다채로운 문화축제와 공연 소식을 공유하는 블로그! culturestage.co.kr 바로가기
다채로운 문화축제와 공연 소식을 공유하는 블로그! culturestage.co.kr 바로가기



비트코인 세계로의 첫걸음! 지금 가입하고 거래 수수료 할인 혜택 받으세요! bitget.com 바로가기
비트코인 세계로의 첫걸음! 지금 가입하고 거래 수수료 할인 혜택 받으세요! bitget.com 바로가기




Tags

#developer#coding#javascript

Share

Previous Article
HTML과 XML의 차이점 완벽 정리 - 마크업 언어의 본질적 이해

Table Of Contents

1
블록 스코프의 기본 개념 이해하기
2
블록 스코프의 실제 활용과 장점
3
고급 블록 스코프 패턴과 모범 사례

Related Posts

(실전 프로젝트) localStorage를 활용한 나만의 메모장 웹 앱 만들기 - 데이터 저장부터 불러오기까지 완벽 구현
December 30, 2025
2 min