01. const로 변하지 않는 값을 표현해라
과거 변수를 할당할 수 있는 방법이 var를 사용하는 것밖에 없었지만 지금은 let과 const를 사용하면서 선택지가 늘었다.
그중 대부분의 경우에는 const를 선택하는 게 좋다고 한다.
나도 평소에 const를 많이 쓰긴 했지만 이유는 딱히 없었는데 책에서 나온 이유는 const로 많은 것을 할 수 있는 게 아니라 가장 적은 것을 할 수 있기 때문이라고 한다.
이게 무슨 소리인가 했지만 const가 가장 코드를 읽기 쉽게 만드는 제약사항이 있다고 한다.
const의 장점: 명확한 의도 전달
재할당을 할 수 없는 const를 기본적으로 선택하면 좋은 이유는 값을 할당하고 변경하지 않을 것이라는 점을 표시하면 추후 그 코드를 볼때 이것은 걸러도 되는 코드다 아니다를 명확할수 있게 알수 있기 때문이다.
무슨 소리인가 싶지만 아래의 코드를 보면 쉽게 이해 할수 있다.
// const를 사용할 경우
const taxRate = 0.1;
const total = 100 + ( 100 * taxRate );
return `구매 금액은 ${total} 입니다.`;
// var를 사용할 경우
var taxRate = 0.1;
var total = 100 + ( 100 * taxRate );
return `구매 금액은 ${total} 입니다.`;
두 코드가 단순히 위처럼 3줄짜리가 아니라 100줄짜리 코드라고 생각을 해보면 알기 쉬울꺼같다.
첫번째 코드에서는 재할당을 할수 없다는것을 알수 있기때문에 구매 금액이 명확히 110원이라는 것을 알수 있었고 두번째 코드에서는 재할당이 가능 한 코드라서 반복문 조건문 재할당 처럼 값을 변경할수 있는 코드가 있는지 100줄의 코드를 직접 분석을 해야되서 명확히 구매 금액이 얼마 인지 알기 쉽지 않다.
결론은 대부분의 코드는 const를 기본으로 사용하고 재할당이 필요하다면 그때 다른 선언 방식을 사용하는게 나도 좋고 이코드를 보는 다른사람도 편하다는것을 알수 있었다.
왜 대부분의 경우 const를 써야 할까?
- 코드 가독성 향상: 코드를 읽는 사람이 어떤 변수가 변경될 수 있고 어떤 변수가 변경되지 않는지 쉽게 파악할 수 있다.
- 버그 예방: 의도치 않은 변수 재할당으로 인한 버그를 예방할 수 있다.
- 코드 최적화: JavaScript 엔진이 const로 선언된 변수를 최적화할 수 있는 여지가 더 많다.
결론
const의 제약은 오히려 코드의 의도를 명확하게 하고 예측 가능성을 높이는 장점이 된다는것을 알수 있었다.
"가장 적은 것을 할 수 있다"는 말은 제약이 많을수록 코드의 동작이 예측 가능해지고, 이는 결국 더 안정적인 프로그램으로 이어진다는 것이다.
따라서, 기본적으로 const를 사용하고, 변수의 값을 변경해야 할 필요가 있을 때만 let을 사용하는 것이 좋은 전략임을 알수 있었다.
02. let과 const로 유효 범위 충돌을 줄여라
const에 대해 알아보면서 변수를 다룰때는 재할당을 피하는것이 낫다 라는것을 배웠다. 그렇지만 변수를 반드시 재할당 하는 경우라면 let이라는 친구를 사용해야한다. 왜 var라는 선택지도 있는데 하필이면 let일까를 지켜 보았다.
블록 유효범위 vs 어휘적 유효범위
var와 let의 가장 큰 차이점은 유효범위(스코프)에 있다.
- 어휘적 유효범위(var): 함수 단위로 스코프가 생성됨
- 블록 유효범위(let, const): 중괄호({}) 단위로 스코프가 생성됨
코드로 보면 이해가 쉽다:
// var사용 - 어휘적 유효범위
function lowestPrice(item) {
var count = item.inventory;
var price = item.price;
if(item.salePrice) {
var count = item.seleInventory // 이전 count를 덮어씀
if(count > 0) {
price = item.salePrice;
}
}
if(count){ // 여기서 count는 item.seleInventory임
return price;
}
return 0
}
// let 사용 - 블록 유효범위
function lowestPrice(item) {
let count = item.inventory;
let price = item.price;
if(item.salePrice) {
let count = item.seleInventory // 블록 내에서만 유효한 새로운 변수
if(count > 0) {
price = item.salePrice;
}
}
if(count){ // 여기서 count는 여전히 item.inventory임
return price;
}
return 0
}
var를 사용하면 if 블록 안에서 선언한 변수도 함수 전체에서 접근 가능해서 밖에서 선언한 같은 이름의 변수를 덮어쓰게 된다. 근데 let은 블록 안에서 선언한 변수는 그 블록 안에서만 살아있고, 블록 바깥에서는 접근할 수 없다.
변수 재선언 문제
한가지 더 큰 차이점이 있는데, var는 같은 이름의 변수를 몇 번이고 다시 선언할 수 있지만, let과 const는 같은 이름으로 재선언하면 에러가 난다:
// var는 재선언 가능
var x = 1;
var x = 2; // 문제 없음
// let은 재선언 불가능
let y = 1;
let y = 2; // SyntaxError: Identifier 'y' has already been declared
이런 특성 때문에 var는 의도치 않게 변수 이름을 재사용했을 때 기존 값이 덮어씌워져도 에러가 안 나서 버그 찾기가 어려울 수 있다.
결론적으로, 변수를 재할당해야 하는 상황이라면 var 대신 let을 쓰는 게 훨씬 안전하다. let은 블록 단위로 변수가 관리되고, 같은 이름의 변수를 실수로 재선언하면 에러를 내서 버그를 미리 잡아준다. 그래서 재할당이 필요하다면 var보다는 let을 쓰자!
03. 블록 유효범위 변수로 정보를 격리하라
for문 같은 반복문에서 let을 사용해서 유효범위 충돌을 방지하는 방법을 살펴보려고 한다.
블록 유효범위 변수 선언을 사용하면 변수는 블록 내에서만 접근 할수 있다.
for문과 if블록 내부에 변수를 선언하면 중괄호 밖에서는 접근 할수 없다.
반대로 함수 외부에 선언한 변수는 블록 내부에 접근할수 있다.
반면 어휘적 유효범위를 따르는 변수를 선언한 경우에는 함수 내부 어디서든 접근 할수 있다.
for 루프에서의 변수 유효범위 비교
var와 let의 유효범위 차이를 for 루프에서 살펴보자:
// var를 사용한 경우 (어휘적 유효범위)
function processItems(items) {
var result = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
result.push(item);
}
console.log("마지막 처리된 아이템:", item); // 접근 가능 - item은 함수 전체에서 유효
console.log("루프 카운터:", i); // 접근 가능 - i는 함수 전체에서 유효
return result;
}
// let을 사용한 경우 (블록 유효범위)
function processItems(items) {
let result = [];
for (let i = 0; i < items.length; i++) {
let item = items[i];
result.push(item);
}
// console.log("마지막 처리된 아이템:", item); // 에러! - item은 for 블록 내에서만 유효
// console.log("루프 카운터:", i); // 에러! - i는 for 블록 내에서만 유효
return result;
}
위 코드에서 var를 사용하면 for 루프 안에서 선언한 item과 루프 카운터 i가 함수 전체에서 접근 가능하다. 이게 어휘적 유효범위의 특징이다.
반면에 let을 사용하면 for 루프 안에서 선언한 item과 i는 for 블록 내에서만 존재하고, 블록 밖에서는 접근할 수 없다. 이건 블록 유효범위의 특징이다.
클로저 문제와 블록 유효범위
블록 유효범위의 장점은 클로저(closure)와 함께 사용할 때 더 명확하게 드러난다:
// var를 사용한 경우 - 문제 발생
function createButtons() {
var buttons = [];
for (var i = 0; i < 5; i++) {
buttons.push(function() {
console.log("Button " + i + " 클릭됨");
});
}
return buttons;
}
var btns = createButtons();
btns[0](); // "Button 5 클릭됨" (예상과 다름!)
btns[1](); // "Button 5 클릭됨" (예상과 다름!)
// let을 사용한 경우 - 정상 작동
function createButtons() {
let buttons = [];
for (let i = 0; i < 5; i++) {
buttons.push(function() {
console.log("Button " + i + " 클릭됨");
});
}
return buttons;
}
let btns = createButtons();
btns[0](); // "Button 0 클릭됨"
btns[1](); // "Button 1 클릭됨"
var를 사용하면 모든 버튼 함수가 동일한 i 변수를 참조하게 되고, 루프가 끝난 후 i는 5가 되므로 모든 버튼에서 "Button 5 클릭됨"이 출력된다.
하지만 let을 사용하면 각 반복마다 새로운 i 변수가 생성되고, 각 버튼 함수는 자신의 반복에서 생성된 i 값을 기억하게 된다. 그래서 각 버튼마다 다른 번호가 출력된다.
정보 격리의 장점
블록 유효범위 변수를 사용하면 정보를 효과적으로 격리할 수 있다:
- 코드 구조 개선: 변수를 실제로 필요한 곳에만 선언하여 코드 구조를 개선할 수 있다.
- 변수 재사용 방지: 같은 이름의 변수를 다른 블록에서 실수로 재사용하는 것을 방지할 수 있다.
- 메모리 효율성: 블록이 종료되면 변수가 메모리에서 해제될 수 있어 메모리 관리에 도움이 된다.
- 클로저 관련 버그 방지: 위에서 본 것처럼 클로저 사용 시 발생할 수 있는 일반적인 버그를 방지할 수 있다.
블록 유효범위 변수(let, const)를 사용하면 코드의 의도를 더 명확하게 표현하고, 버그를 줄이며, 유지보수성을 향상시킬 수 있다. 특히 반복문이나 조건문같은 블록에서 변수를 선언할 때는 var 대신 let이나 const를 사용하는 것이 훨씬 안전하다.
'개발독서' 카테고리의 다른 글
조건문을 깔끔하게 (0) | 2025.04.27 |
---|---|
특수한 컬렉션을 이용해 코드 명료화을 극대화해라. (0) | 2025.04.06 |
배열로 데이터 컬렉션을 관리하라 (0) | 2025.04.06 |