8편. 반복문 이해하기: for, while, forEach, Iterable
📚 목차
1. 반복문(Loop)의 기본 이해 및 흐름 제어
2. 핵심 반복문 3종 비교 (for / for...in / for...of)
3. 순회(Iteration)의 원리: Iterable과 Iterator 프로토콜
4. 다양한 객체의 forEach 사용법
5. 고급 순회와 지연 평가: 제너레이터(Generator)
✔ 마무리

📂 [GitHub 실습 코드 보러가기] (https://github.com/cericube/nodejs-tutorials) /JavaScript
1. 반복문(Loop)의 기본 이해 및 흐름 제어
🔷 기본적인 반복문: while과 do...while의 문법 및 차이점
▸ while 문 (조건 먼저 검사): 조건이 참(True)인 동안 코드 블록을 계속 반복합니다. 가장 기본적인 형태입니다.
▸ 만약 처음부터 조건이 거짓이면, 코드는 단 한 번도 실행되지 않습니다.
// 실습 코드: while 문
let count = 0;
while (count < 3) { // 조건: count가 3보다 작은 동안
console.log(`while 반복 ${count}번`);
count++; // 반드시 count를 증가시켜 무한 루프를 방지해야 합니다.
}
// 출력: while 반복 0번, while 반복 1번, while 반복 2번
▸ do...while 문 (코드 먼저 실행): 코드를 최소 한 번 실행한 후, 조건을 검사하여 반복 여부를 결정합니다.
▸ 조건이 거짓이더라도 최소 한 번은 실행이 보장됩니다.
// 실습 코드: do...while 문
let num = 5;
do {
console.log(`do...while은 최소 한 번 실행됩니다. (현재 num: ${num})`);
num++;
} while (num < 5); // 조건이 거짓이지만 이미 한 번 실행됨
// 출력: do...while은 최소 한 번 실행됩니다. (현재 num: 5)
🔷 for 반복문: for 문을 사용한 횟수 기반 순회
for 문은 반복 횟수가 정해져 있을 때 가장 깔끔하고 구조적으로 반복 작업을 처리할 수 있게 해 줍니다.
세 부분(초기화; 조건; 증감)을 한 줄에 명시합니다.
▸ 초기화 (Initialization): 루프가 시작될 때 단 한 번 실행됩니다. (보통 카운터 변수 선언)
▸ 조건 (Condition): 매 반복 전에 검사합니다. 참이면 반복, 거짓이면 루프 종료.
▸ 증감 (Increment/Decrement): 매 반복이 끝날 때마다 실행됩니다. (카운터 변수 변경)
// 실습 코드: for 문
const items = ['Pen', 'Pencil', 'Eraser'];
for (let i = 0; i < items.length; i++) { // i를 0부터 items의 길이(3)보다 작을 때까지 1씩 증가
console.log(`[${i}]: ${items[i]}`);
}
// 출력: [0]: Pen, [1]: Pencil, [2]: Eraser
🔷 흐름 제어: break와 continue 키워드의 역할
반복문 내부에서 특별한 상황이 발생했을 때 루프의 흐름을 제어하는 두 가지 키워드입니다.
🔸break : 즉시 루프 종료,반복문 자체를 완전히 빠져나옵니다.
🔸continue : 현재 반복 건너뛰기,"현재 실행 중인 반복만 중단하고, 다음 반복으로 넘어갑니다."
// 실습 코드: break와 continue
for (let i = 1; i <= 5; i++) {
if (i === 3) {
console.log(`숫자 3은 건너뜁니다.`);
continue; // 이 코드가 실행되면 아래 console.log(i)는 실행되지 않고 다음 i=4로 넘어감
}
if (i === 5) {
console.log(`숫자 5에서 반복을 완전히 중단합니다.`);
break; // 반복문 자체가 종료됩니다.
}
console.log(`현재 숫자: ${i}`);
}
// 출력:
// 현재 숫자: 1
// 현재 숫자: 2
// 숫자 3은 건너뜁니다.
// 현재 숫자: 4
// 숫자 5에서 반복을 완전히 중단합니다.
2. 핵심 반복문 3종 비교 (for / for...in / for...of)
JavaScript에서는 for, for...in, for...of가 모두 “반복문”이라는 공통점을 갖고 있지만, 실제로는 순회 대상과 목적이 완전히 다릅니다.
각 문법의 특징을 정확히 이해하면 상황에 맞는 최적의 순회 방식을 선택할 수 있습니다.
🔷 for (인덱스 기반 순회)
▸ 순회 대상: 배열의 인덱스(Index)
▸ 특징: 인덱스를 직접 조작하거나, 순회 횟수를 엄격히 통제해야 할 때 가장 유용합니다.
▸ 사용 예시: 특정 구간만 순회하거나, i를 2씩 증가시키는 등 “반복 구조를 세밀하게 제어”해야 할 때 적합합니다.
// 실습 코드: for (인덱스 순회)
const data = ['A', 'B', 'C'];
for (let i = 0; i < data.length; i++) {
console.log(`data[${i}] = ${data[i]}`);
}
🔷 for...in (속성 키 순회)
▸ 순회 대상: 객체(Object)에 정의된 열거 가능한 속성의 키(Key)
▸ 설명: key는 객체의 속성 이름(문자열)이며, 이를 이용해 값을 조회할 수 있습니다.
💡 주의: 배열 순회에는 사용하지 않는 것을 권장드립니다
배열도 객체의 한 종류이기 때문에 인덱스가 키처럼 보일 수 있으나, 실제로는 다음과 같은 문제가 발생할 수 있습니다.
1. 키 순서가 보장되지 않음 : 배열의 0, 1, 2 순서대로 순회된다는 보장이 없습니다.
2. 예상치 못한 속성이 함께 순회될 수 있음 : 프로토타입 체인에 정의된 속성까지 포함될 가능성이 있습니다.
// 실습 코드: for...in (객체 순회)
const user = { name: 'Kim', age: 30, city: 'Seoul' };
for (const key in user) {
// key는 속성 이름("name", "age", "city")이 됩니다.
console.log(`${key}: ${user[key]}`);
}
// 출력: name: Kim, age: 30, city: Seoul
🔷 for...of (값 기반 순회)
▸ 순회 대상: Iterable 객체 (배열, 문자열, Map, Set 등)
▸ 특징: 순회 과정에서 요소의 “값”을 직접 받을 수 있습니다.
▸ 사용 예시: 배열에서 인덱스가 필요 없고 값만 활용하면 되는 상황에서 가장 깔끔하고 현대적인 방식입니다.
// 실습 코드: for...of (값 순회)
const names = ['철수', '영희', '민수'];
for (const name of names) { // name은 배열의 '값'이 됩니다.
console.log(`이름: ${name}`);
}
// 문자열 순회도 가능
const text = "JS";
for (const char of text) {
console.log(`문자: ${char}`);
}
// 출력: 이름: 철수, 이름: 영희, 이름: 민수
// 출력: 문자: J, 문자: S
🔷 for vs for...in vs for...of 비교표
| 구분 | for | for...in | for...of |
| 순회 대상 | 인덱스(숫자) | 객체의 속성 키(문자열) | 요소의 값(Value) |
| 주요 용도 | 횟수 기반, 인덱스 필요 시 | 객체의 속성 순회 | 배열, Map, Set 등 Iterable 객체 순회 |
| 적합성 | 범용적 | 객체 순회만 | 값 기반 순회에 최적 |
| 성능 (일반적 경향) |
가장 빠름 - 단순 인덱스 접근 중심으로 최적화됨 |
가장 느림 - 키 검색 + 열거 과정이 비효율적 |
중간 - Iterator 프로토콜 호출 비용이 있어 for보다 느림 |
3. 순회(Iteration)의 원리: Iterable과 Iterator 프로토콜
for...of 문이 배열, 문자열, Map, Set 등 다양한 자료구조를 순회할 수 있는 이유는 JavaScript가 제공하는 Iterable / Iterator 프로토콜 덕분입니다.
이 개념을 이해하면 JavaScript에서 “순회가 가능한 객체”가 어떻게 동작하는지 보다 깊이 있게 이해하실 수 있습니다.
| 개념 | 의미 | 조적 | 역할 |
| Iterable | 순회 가능한 객체 | Symbol.iterator 메서드 보유 | Iterator를 생성 |
| Iterator | 순회를 실제 수행하는 객체 | next() 메서드 보유 | 매 단계마다 { value, done } 반환 |
| for...of | 여러 Iterable을 쉽게 순회하는 문법 | Iterable 필요 | Iterator의 동작을 자동으로 처리 |
🔷 Iterable 객체: 순회가 가능한 객체의 조건 - Symbol.iterator
Iterable(이터러블)이란, for...of 같은 반복문에서 사용할 수 있는 “순회 가능한 객체”를 뜻합니다.
✔️ Iterable이 되기 위한 조건
객체가 Iterable이 되기 위한 유일한 조건은 다음과 같습니다.
▸ 객체 내부에 Symbol.iterator 라는 특별한 메서드가 존재해야 합니다.
▸ 이 메서드는 호출되면 Iterator 객체를 반환해야 합니다.
✔️ 대표적인 기본 Iterable
JavaScript는 아래와 같은 대부분의 컬렉션을 이미 Iterable로 만들어 놓았습니다.
▸ Array
▸ String
▸ Map
▸ Set
▸ arguments (함수의 인자 객체)
▸ NodeList (DOM 노드 목록)
즉, 이런 객체들은 별도의 설정 없이 바로 for...of 문으로 순회할 수 있습니다.
🔷 Iterator 객체: 순회를 실제로 수행하는 존재 - next()
Iterator(이터레이터) 는 “순회 과정 자체를 수행하는 객체”입니다.
✔️ Iterator의 조건
Iterator는 반드시 next() 메서드를 갖고 있어야 합니다.
next()를 호출할 때마다 순회가 한 단계씩 진행되고 다음과 같은 형태의 객체가 반환됩니다.
{
value: 현재 값,
done: 순회 종료 여부 (true면 종료)
}
✔️ 예시
const myArray = ['A', 'B'];
const iterator = myArray[Symbol.iterator]();
// 1. 배열의 Symbol.iterator 메서드를 호출해 Iterator를 얻습니다.
console.log(iterator.next()); // 2. next() 호출 시 순회가 한 단계 진행됩니다.
console.log(iterator.next());
console.log(iterator.next()); // 3. 모든 요소를 순회하면 done: true가 됩니다.
🔷 for...of의 내부 작동 방식
for...of 문은 개발자가 직접 Symbol.iterator() 를 호출하거나 next()를 반복 실행할 필요가 없도록 도와주는 일종의 문법적 설탕(Syntactic Sugar) 입니다.
내부에서는 다음과 같은 단계를 거쳐 작동합니다.
1. 순회 시작:
for...of는 대상 객체의 Symbol.iterator() 메서드를 호출해 Iterator 객체를 얻습니다.
2. 반복 처리:
반복이 시작될 때마다 Iterator의 next() 메서드를 호출합니다.\
3. 값 추출:
next()의 반환 값 중 value를 꺼내 반복문 내부에서 사용합니다.
4. 종료 판단:
반환된 값의 done이 true가 되면 반복을 종료합니다.
for (const item of iterable) {
console.log(item);
}
4. 다양한 객체의 forEach 사용법
JavaScript에서는 배열을 포함한 여러 자료구조가 고차 함수(Higher-Order Function)를 이용한 순회를 지원합니다.
고차 함수란 다른 함수를 인자로 받거나, 함수를 반환하는 함수를 의미합니다.
배열에서는 forEach, map, filter, reduce 등이 대표적인 고차 함수이며, 이들은 전통적인 for 문보다 선언적(Declarative)이고 가독성이 높다는 장점이 있습니다.
🔷 Array.prototype.forEach(): 배열의 기본 순회 및 부수 효과 처리
forEach()는 배열의 요소를 하나씩 순회하면서 콜백 함수를 실행하는 가장 기본적인 배열용 고차 함수입니다.
값을 순차적으로 처리하기만 하면 되고, 새로운 배열을 만들 필요가 없는 상황에 적합합니다.
✔️ 특징 요약
▸ 반환값 없음: 새로운 배열을 반환하지 않습니다.
▸ 반복 제어 어려움: break, continue를 사용할 수 없습니다.
▸ 콜백 함수 인자: (요소의 값, 인덱스, 배열 자체)
▸ 주 용도: 콘솔 출력, 외부 변수 업데이트 등 부수 효과(Side Effect) 발생 작업
// 실습 코드: Array.forEach()
const scores = [85, 92, 78];
let total = 0;
scores.forEach((score, index) => {
console.log(`${index + 1}번째 점수: ${score}점`);
total += score; // 외부 변수에 값을 누적하는 부수 효과
});
console.log(`총점: ${total}`);
// 출력: 총점: 255
🔷 Map과 Set의 forEach: 객체 구조별 콜백 인자 차이
배열뿐 아니라 Map과 Set도 고유한 forEach() 메서드를 가지고 있지만, 각 자료구조의 특성에 따라 콜백 함수의 인자 구조가 서로 다르다는 점을 반드시 이해해야 합니다.
✔️ Map 객체 순회
▸ Map은 키–값(Key–Value) 쌍을 저장하는 자료구조입니다.
▸ 콜백 인자 순서: (value, key, map 객체)
▸ 배열과 달리 값이 먼저, 키가 뒤에 옵니다.
// 실습 코드: Map.forEach()
const personMap = new Map([
['id', 101],
['role', 'Admin']
]);
personMap.forEach((value, key) => {
console.log(`[${key}]: ${value}`);
});
// 출력: [id]: 101, [role]: Admin
✔️ Set 객체 순회
▸ Set은 중복 없는 값(Value)만 저장하는 자료구조입니다.
▸ 콜백 인자 순서: (value, value, set 객체)
▸ Set에는 키(Key) 개념이 없기 때문에 첫 번째와 두 번째 인자가 모두 동일한 값(Value)입니다.
// 실습 코드: Set.forEach()
const uniqueItems = new Set(['Mouse', 'Keyboard', 'Monitor']);
uniqueItems.forEach((item1, item2) => {
console.log(`항목: ${item1} (item1 === item2: ${item1 === item2})`);
});
// 출력 예: 항목: Mouse (item1 === item2: true)
※ "왜 두 개의 값이 똑같이 들어오지?"
이는 Set이 내부적으로 Map과 비슷한 구조를 유지하지만 실제로는 키가 없기 때문에 나타나는 결과라고 이해하면 됩니다.
🔷 유사 배열 객체 순회: Array.from() 활용하기
arguments, NodeList(querySelectorAll() 반환값) 등은 겉보기에는 배열처럼 보이지만 실제 배열이 아니기 때문에 forEach, map 등을 직접 사용할 수 없습니다.
이러한 객체들은 length는 가지고 있지만 배열 메서드는 없는 "유사 배열 객체(Array-like Object)"입니다.
✔️ 해결 방법: Array.from()으로 실제 배열로 변환하여 사용
// 실습 코드: Array.from()을 이용한 유사 배열 순회 (예: HTML 요소)
const nodeListExample = document.querySelectorAll('button'); // NodeList (유사 배열)
// 1. 실제 배열로 변환
const buttonArray = Array.from(nodeListExample);
// 2. 배열 메서드 사용 가능
buttonArray.forEach(button => {
button.classList.add('btn-primary');
console.log(`${button.textContent}에 클래스 추가`);
});
// 또는 Array.from() 두 번째 인자에 콜백 제공 가능
Array.from(nodeListExample, (btn) => {
// 변환하면서 동시에 작업 수행
});
🔷 기타 유용한 고차 함수: map, filter, reduce 간단 개요
| 함수 | 목적 | 반환 값 | 특징 |
| map() | 배열 요소 변환 | 새로운 배열 | 원본 배열을 수정하지 않고 1:1 변환 |
| filter() | 조건에 맞는 요소만 추출 | 새로운 배열 | 조건을 만족하는 요소만 남김 |
| reduce() | 배열 전체 집계 | 단일 값 | 합계, 평균 등 누적 연산에 활용 |
const nums = [1, 2, 3, 4, 5];
// map: 각 요소에 2를 곱해 새로운 배열 생성
const doubled = nums.map(n => n * 2); // [2, 4, 6, 8, 10]
// filter: 짝수만 걸러 새로운 배열 생성
const evens = nums.filter(n => n % 2 === 0); // [2, 4]
console.log(`원본: ${nums}`);
console.log(`map 결과: ${doubled}`);
console.log(`filter 결과: ${evens}`);
고차 함수 참고: 3편. 함수 다루기: 함수 선언, this, 화살표 함수, 클로저(Closure), 콜백(Callback)
5. 고급 순회와 지연 평가: 제너레이터(Generator)
제너레이터는 JavaScript에서 반복자(Iterator)를 손쉽게 만들 수 있는 특별한 함수입니다.
일반 함수와 달리 “한 번에 끝까지 실행하지 않고, 필요할 때마다 조금씩 실행을 이어가는 방식”을 제공합니다.
이러한 특징 덕분에 지연 평가(Lazy Evaluation)와 비동기 처리 패턴에서 매우 유용하게 활용됩니다.
🔷 제너레이터 함수 정의: function* 문법과 yield 키워드
🔸제너레이터 함수: function*
▸ 제너레이터 함수는 function 키워드 뒤에 *(asterisk)를 붙여 정의합니다.
▸ 일반 함수와 달리 호출 즉시 실행되지 않습니다.
▸ 대신 “중단 및 재개”가 가능한 제너레이터 객체를 반환합니다.
🔸yield: 값 생산 + 실행 일시 중지
▸ 일반 함수의 return은 값을 반환하면서 함수를 완전히 종료합니다.
▸ 반면, 제너레이터의 yield는 값을 “산출(Produce)”하고
▸ 그 지점에서 실행을 잠시 멈춥니다(Pause).
▸ 이후 next()가 호출되면 “멈춘 지점부터” 다시 실행을 이어갑니다.
// 실습 코드: 간단한 제너레이터 함수
function* countGenerator() {
yield 1; // 1. 첫 번째 값 산출 후 실행 일시 중지
yield 2; // 2. next() 호출 시 두 번째 yield까지 실행
yield 3; // 3. 마지막 값 산출
}
🔷 제너레이터의 역할: Iterator이자 Iterable
제너레이터 함수를 호출하면 즉시 코드가 실행되지 않고, 대신 “반복 가능한(iterable) 객체이자, next() 메서드를 가진 iterator 객체”가 반환됩니다.
즉, 제너레이터는 다음 두 가지 성격을 동시에 지닙니다.
▸ Iterator: next() 호출 시 { value, done } 형태로 다음 값을 돌려줌
▸ Iterable: for...of 같은 순회문에서 직접 사용할 수 있음
// 실습 코드 (이어서): 제너레이터 객체 사용
const counter = countGenerator(); // 함수를 호출해도 바로 실행되지 않고 Iterator 반환
console.log(counter.next()); // { value: 1, done: false } (첫 번째 yield까지 실행)
console.log(counter.next()); // { value: 2, done: false } (두 번째 yield까지 실행)
console.log(counter.next()); // { value: 3, done: false }
console.log(counter.next()); // { value: undefined, done: true } (함수 끝, 종료)
🔷 제너레이터(Generator) 실무 활용 예시
JavaScript의 제너레이터 함수는 단순한 반복문을 넘어, 실행 흐름을 제어하거나 메모리를 효율적으로 관리하는 고급 패턴에서 실무적으로 매우 유용하게 사용됩니다.
주요 실무 활용 분야는 지연 평가(Lazy Evaluation)와 비동기 처리입니다.
✔️ 예시: 무한 ID 생성기
데이터베이스의 레코드 ID나 API 요청에 사용할 고유한 번호를 무한정 생성해야 할 때, 제너레이터를 사용하면 메모리에 수천 개의 ID를 미리 저장할 필요 없이 필요할 때마다 하나씩 생성할 수 있습니다.
/**
* 무한 증가하는 ID를 생성하는 제너레이터
* - 호출될 때(next())만 다음 값을 계산합니다.
*/
function* idGenerator() {
let id = 1;
while (true) {
yield id++;
}
}
const userIds = idGenerator(); // 제너레이터 객체 생성
console.log(userIds.next().value); // 1. 첫 번째 next() 호출 시 1 생성
console.log(userIds.next().value); // 2. 두 번째 next() 호출 시 2 생성
// 필요하다면 나중에 다시 호출하여 계속 사용
console.log(`다음 ID: ${userIds.next().value}`); // 3. 다음 ID
✔️ 예시: 페이징(Pagination) 데이터 지연 로딩
대량 데이터를 한 번에 메모리에 올리는 대신 “필요한 페이지 단위로 데이터 요청”만 하는 패턴입니다.
▸ fetchPages(pageCount) 제너레이터는 page = 1부터 pageCount까지 각 페이지 데이터를 하나씩 생성하며,
▸ for...of가 내부적으로 next()를 반복 호출하면서 yield 지점까지 실행 → 데이터 받기 → 다시 이어서 실행
을 반복하는 구조입니다.
// 예시 2: 페이지 단위로 API 데이터를 가져오는 Lazy Generator
function* fetchPages(pageCount) {
let page = 1;
while (page <= pageCount) {
//실무 예시
//yield fetch(`/api?page=${page}`);
// 실제 API라면 fetch() 호출이 들어갈 부분
const data = { page, items: [`item-${page}-1`, `item-${page}-2`] };
yield data; // 페이지 데이터 반환
page++;
}
}
for (const pageData of fetchPages(3)) {
console.log("페이지 데이터:", pageData);
}
✔️ 예시: 무한 스크롤(Infinite Scroll)에서 Lazy 데이터 제공
웹 프론트엔드에서 무한 스크롤 구현 시 아래처럼 제너레이터로 “필요할 때만 데이터 생산”이 가능합니다.
// 예시 3: 무한 스크롤용 Lazy Generator
function* infiniteItems() {
let id = 1;
while (true) {
yield { id, name: `item-${id}` };
id++;
}
}
const items = infiniteItems();
// 실제로는 스크롤 이벤트에서 next() 호출
console.log(items.next().value);
console.log(items.next().value);
console.log(items.next().value);
✔️ 예시: DB Cursor 기반 Lazy Fetch
데이터베이스 Cursor를 제너레이터로 감싸면 메모리 부담 없이 대량 데이터를 순회할 수 있습니다.
// 예시 9: DB Cursor를 제너레이터로 감싸기 (개념 예시)
async function* readUsers(cursor) {
while (await cursor.hasNext()) {
yield await cursor.next();
}
}
// 사용 예시
(async () => {
const cursor = db.users.find(); // MongoDB 등
for await (const user of readUsers(cursor)) {
console.log(user);
}
})();
✔️ 예시: 대규모 파일 읽기를 Chunk 단위로 처리
백엔드(Node.js)에서는 큰 파일을 읽을 때 메모리 절약을 위해 소량씩(chunk) 나누어 처리하는 패턴을 자주 사용합니다.
아래처럼 Generator를 이용하면 chunk 단위 반복을 깔끔하게 처리할 수 있습니다.
// 예시 4: Node.js 파일을 Chunk 단위로 읽기 (개념 예시)
import fs from "fs";
function* readFileChunks(filePath, chunkSize = 64 * 1024) {
const fd = fs.openSync(filePath, "r");
const buffer = Buffer.alloc(chunkSize);
let bytesRead;
while ((bytesRead = fs.readSync(fd, buffer, 0, chunkSize, null)) > 0) {
yield buffer.slice(0, bytesRead); // 읽은 만큼만 반환
}
fs.closeSync(fd);
}
// 사용 예시
for (const chunk of readFileChunks("./bigfile.txt")) {
console.log("읽은 Chunk 크기:", chunk.length);
}
✔ 마무리
JavaScript의 다양한 반복문과 순회 방식, 그리고 제너레이터를 활용한 고급 패턴까지 폭넓게 살펴보았습니다.
단순히 for 문이나 while 문을 사용하는 수준을 넘어, 어떤 데이터 구조를 어떤 방식으로 순회해야 가장 안전하고 효율적인지, 그리고 이터러블(Iterable)과 제너레이터(Generator)의 개념이 왜 현대 JavaScript에서 중요한지 이해하는 것이 매우 중요합니다.
특히 제너레이터는 “필요할 때 값을 하나씩 생성하며 중단과 재개가 가능한 함수”라는 점에서 기존 반복문과 완전히 다른 차원의 유연성을 제공합니다.
이 덕분에 지연 평가(Lazy Evaluation), 무한 데이터 처리, 비동기 스트리밍, 페이징 로딩 등 다양한 실무 상황에서 강력한 도구가 될 수 있습니다.
※ 게시된 글 및 이미지 중 일부는 AI 도구의 도움을 받아 생성되거나 다듬어졌습니다.
'4.Node.js > JavaScript&TypeScript' 카테고리의 다른 글
| [JavaScript] 10편. 퍼포먼스 & 메모리 최적화 이해하기 (0) | 2025.12.09 |
|---|---|
| [JavaScript] 9편. 에러 처리 기법 이해하기 (0) | 2025.12.09 |
| [JavaScript] 7편. 컬렉션 이해하기: 배열,Map,Set,groupBy,WeakMap (0) | 2025.12.07 |
| [JavaScript] 6편. 모듈 시스템 이해하기: ESM, import/export (0) | 2025.12.07 |
| [JavaScript] 5편. 비동기 처리와 이벤트 루프 이해하기 : Promise, async/await, Event Loop (0) | 2025.12.06 |