
반복문은 지정한 조건에 의해 조건을 만족시킬 때 까지 반복해서
입력한 코드를 실행시키는 동작을 한다.
조건문이 여러 조건들 중 특정한 조건을 찾아 일치하는 조건이 있는 경우와
없는 경우를 나누어 조건에 따른 코드를 반환하고 동작을 멈추는 것과는 다르다.
반복문은 필요한 만큼 반복해서 데이터를 처리해야 할 때 필요하다.
따라서 주로 코드의 실행 횟수를 제어하는 기능이 필요한 경우
매우 유용하게 사용된다.
수억개의 데이터들을 가져와서 그 데이터들 하나하나에
함수나 조건문 등을 통한 가공 및 분류를 해야할 때
조건문의 간단한 식과 사용 방법만 알고있다면
수억번의 작업을 모두 하나의 코드로 자동화 처리할 수 있다.
뭔가 2차 산업혁명의 컨베이어 벨트 냄새가 난다.

반복문에 나름의 비유와 추상화를 적용하면 다음과 같다.
배열은 데이터가 한줄로 나열되어있는 형태로
각각의 elements는 나열된 순서대로 index를 가지고 있고
이 특성 때문에 반복문과의 조합이 자주 사용된다.
// index는 element의 정보(구분)이자 배열의 정보(갯수)다.
let 과일가게 = ["사과", "낑깡", "자두", "포도", "수박"];
// element가 10억개라도 이 코드 하나면 끝!!
for (let i = 0; i < 과일가게.length; i++) {
console.log(`${과일가게[i]}의 index는 ${i}입니다.`);
}
// 만약 1만개의 정보를 출력해야했다면..아니 1천개라도 아마 다른 삶의 의미를 찾게될것이다.
console.log(`${과일가게[0]}의 index는 ${과일가게.length-5}입니다.`);
console.log(`${과일가게[1]}의 index는 ${과일가게.length-4}입니다.`);
console.log(`${과일가게[2]}의 index는 ${과일가게.length-3}입니다.`);
console.log(`${과일가게[3]}의 index는 ${과일가게.length-2}입니다.`);
console.log(`${과일가게[4]}의 index는 ${과일가게.length-1}입니다.`);
// 위 둘의 결과는 같다.
/* 사과의 index는 0입니다.
낑깡의 index는 1입니다.
자두의 index는 2입니다.
포도의 index는 3입니다.
수박의 index는 4입니다. */
반면 또다른 데이터의 묶음인 객체의 property에는 순서가 없다.
또한 가지각색의 key들은 반복문으로 통제하기에 무리가 있다.
개성있는 key로 식별하는 객체는 규칙 없이 쌓여있고
내용물의 이름이 써 있는 상자같아서 사람이 찾고 쓰기 좋아보인다.
앞서 말했듯 반복문은 횟수가 중심인 도구다.
배열이 가진 index는 반복문의 횟수를 제어하기에 더 할 나위 없는
기준이 되어주며 단순히 반복문의 시작과 종료를 알려주는 용도 뿐만이 아닌
그 횟수 자체가 기준이 되어 작업의 전환을 도울 수도 있다.
배열 안에 배열과 같은 다차원 배열(multi dimensional array)에
접근하여 더 복잡한 형태의 데이터를 다룰 수도 있다.
이렇게 데이터의 식별이 숫자와 순서인 배열은 마치 컨베이어 벨트에
순서대로 들어오는 과일들과 같아서 컴퓨터가 분류하기에 딱인 것 같다.
그러니 이제부터 배열의 짝꿍 반복문에 대해 알아보겠다.
반복문의 형태는 다양하다.
그리고 각자의 목적은 같지만 동작이 조금씩은 다르다.
개념이 같고 문법도 유사하기 때문에 가장 많이 쓰이는 for문을 확실히 이해하면 다른 반복문은 어렵지 않게 사용할 수 있다.
반대로 for문의 동작이 잘 이해되지 않는다면 다른 반복문의 구조를 탐구해보자.
✔️ 반복문의 뼈대는 for (반복환경) {...code}의 구조다.
for (let i = 0; i < 3; i++) {
console.log(i) // 0 1 2
}
✔️ ()에 들어가는 3가지 구성요소는 각자의 역할을 하면서 동시에 서로 영향을 주고, 이에 따라 코드의 반복 횟수와 데이터 변화가 조작된다.
let i = 0;반복문이 처음 시작될 때는 초기상태의 값이 실행할 코드에 전달되며 이후 반복될 때마다 step(증감)을 거쳐 count되듯 값이 변화된다.(🤗 변화되는 값을 얻기 위해 변수에 값을 할당하는 것.)
변화된 값은 condition(조건)에서 참고하여 반복횟수를 결정짓는다.
또한 실행할 코드에서 배열 element의 index 역할 등의 지표가 되어준다.
각각의 요소 사이에는 구분자;를 넣어줘야 한다.
i < 5;피연산자(연산이 될 대상) 중
i는 begin에서 지정한 변수명과 일치시켜야 하고 그에 따라 step에 의해 증감되는let i의 값과 같은 값이 된다.
비교연산자를 사용하여 증감된 begin과 내가 지정한 횟수를 비교하고 조건이 만족되면 false가 되면서 반복문을 종료시키는 역할을 한다.
(🤗{}에 본문코드는 이 condition이 달성될때까지 반복해서 연산된다.)
i++최초 코드실행을 제외하고 반복문이 본문 코드를 한바퀴 돌고 끝날 때마다 begin의 변수인
i의 값을 증가 또는 감소시키는 역할을 한다.
i++는i변수를 1만큼 증가시킨다는 의미이며i+1,i+=1과 같은 형태로도 표시할 수 있으며 반드시 연산자가+나 피연산값이 1이여야 하는 것은 아니다.(감소:i--,i-1,i-=1)
✔️ 반복문의 코드가 한줄인 경우 {}는 생략해도 된다.
for (let i = 0; i < 3; i++) console.log(i); // 0 1 2
✔️ while 조건문은 condition만을 반복환경으로 갖고있기 때문에 for문과 같은 조건을 만들기 위해서는 begin과 step을 따로 적용해줘야 한다.
// step
let i = 0;
// condition
while (i < 3) {
console.log(i); // 0 1 2
// step
i++;
}
✔️ step i++를 쓰지 않으면(조건을 만족시키지 않으면) 무한히 반복 할 수도 있다.
let i = 0;
while (i < 5) {
console.log(i);
} // 0이 무한대로 출력된다. ctr + z로 빠져나오자.
for문의 while문으로의 변신
for문은 구성요소를 생략할 수 있으며;는 남겨둬야한다.let i = 0; for (; i < 3;) { console.log(i); // 0 1 2 i++ }
✔️ 본문코드를 한번 실행한 후 반복문을 실행하고 싶을 때 사용한다.
✔️ while문과 마찬가지로 step이 없으면 무한반복이 된다.
// begin
let i = 0;
do {
console.log(i);
// step
i++;
// condition
} while (i < 3); // 0 1 2
❗️ while문과 do...while문은 step의 위치에 따라 결과가 달라질 수 있다.
step이 begin을 쓰는 코드 위에 있다면 증감된 begin이, 반대의 경우 증감 전 begin이 코드에 적용된다.
for문 역시 본문코드에서 begin을 조작하는 경우 결과가 달라질 수 있다.for (let i = 0; i < 105; i++) { i = i + 100; console.log(i); // 100 201 }for (let i = 0; i < 105; i++) { console.log(i); // 0 101 i = i + 100; }
이 항목은 객체에 쓰이는 반복문도 있다는 것과
배열 + 반복문의 원리와 일부 공통점이 있어서 이해에 도움이 될까 해서 넣었다.
그러니 객체에 대한 지식이 아직 없으시거나
배열에 대한 반복문에 집중하고 싶으신 경우 건너뛰어도 괜찮다.
객체편에서 똑같이 다시 나올 것이다.
✔️ for...in문은 객체를 대상으로 하는 반복문이다.
✔️ 객체의 key를 순회할 수 있으며 모든 property를 다룰 수 있다.
✔️ 기본 형태는 for (let key in object) {...}로 ()는 각각
let key는 property들의 key를 나타내는 변수로 변수명은 아무렇게나 지어도 상관 없으며 이것을 통해서 property를 불러올 수 있다.in은 for과 마찬가지로 for..in문을 구성하는 기본 뼈대로 그대로 작성한다.object에는 가져올 객체를 담고있는 변수명을 넣고 key를 가리키는 변수명과 함께 object[key]의 형태로 property의 value를 불러올 수 있다.let 게임평가 = {
서머너즈워: "즐거웠다",
라그나로크: "음머~~",
리니지: "nc주식을 샀어야해"
}
for (let 너의정보는 in 게임평가) {
console.log(`게임 ${너의정보는}는 내 기억에 ${게임평가[너의정보는]}이다.`);
}
/* 게임 서머너즈워는 한마디로 "즐거웠다"다.
게임 라그나로크는 한마디로 "음머~~"다.
게임 리니지는 한마디로 "nc주식을 샀어야해"다.*/
❗️객체는 배열처럼 index로 정렬되지 않고 객체만의 방식으로 정렬된다.
정수 프로퍼티(integer property)는 key가 "1"과 가까운 부터 순서대로 정렬되고 나머지는 객체에 추가한 순서대로 출력된다.
데이터의 순서가 주된 특징인 배열은 반복문을 통해 다루기 좋은 대상이다.
element에 자동으로 주어지는 index를 통해 배열의 길이를 그때그때 일일이
세지 않고도 간단하게 배열의 모든 element를 순회할 수 있는
유연성있는 코드를 만들 수 있다.(arr.length)
index는 곧 그 element이기 때문에 index를 지칭하는것 만으로
element를 조작하기도 쉽다.(if (arr[i] == String) {...})
그리고 다양한 배열 method들을 조합하여 사용할 수도 있어서
여러가지 세분화된 형태로의 조작 또한 가능하다.
순서대로 예시를 보면서 차근히 build-up 해보자.
✔️ 배열의 길이를 알려주는 배열.length로 배열 길이만큼만 반복문을 실행시킬 수 있다.
✔️ 또한 element들의 index도 구할 수 있다.
let 여친가방 = ["썬크림", "거울", "지갑", "화장품", "과자"];
for (let i = 0; i < 여친가방.length; i++) {
console.log(i); // 0 1 2 3 4
}
✔️ 반복문에서 index를 통해 배열의 element를 가져올 수 있다.
let 여친가방 = ["썬크림", "거울", "지갑", "화장품", "과자"];
// condition에 배열.length를 넣어 알아서 배열의 길이만큼 본문코드를 반복한다.
for (let i = 0; i < 여친가방.length; i++) {
console.log(`${여친가방[i]}의 index는 ${i}입니다.`);
}
/* 썬크림의 index는 0입니다.
거울의 index는 1입니다.
지갑의 index는 2입니다.
화장품의 index는 3입니다.
과자의 index는 4입니다. */
- 배열에서 데이터를 가져올 때는
배열[index]를 사용한다.- begin의 초기값을 0으로 지정하고 변수명을 index자리에 넣으면 한 번 순회할 때마다 step에 의해 1씩 증가하면서 element를 하나씩 가져올 수 있게 된다.(배열[0] → 배열[1] → 배열[2]...)
✔️ element를 가져올 수 있으니 여자친구의 과자도 가져와보자.
✔️ 반복문을 통해 element를 새롭게 가공할 수도 있다.
let 여친가방 = ["썬크림", "거울", "지갑", "화장품", "과자"];
let 내주머니 = [];
for (let i = 0; i < 여친가방.length; i++) {
if (여친가방[i] === "과자") {
let 꼭갚을게 = 여친가방.splice(i, i);
내주머니.push(꼭갚을게);
} else {
// element를 가공할 수 있다.
여친가방[i] += "(내 지문)";
}
}
console.log("내주머니:", 내주머니); // 내주머니: ['과자']
console.log("여친가방:", 여친가방);
// 여친가방: ['썬크림(내 지문)', '거울(내 지문)', '지갑(내 지문)', '화장품(내 지문)']
🤗 배열의 length와 index 단 두가지만으로 반복문은 배열속의 element들을
너무나 쉽게 찾고 가져오고 보내고 재가공하는 등 모든 종류의 수단을
사용할 수 있으니 반드시 기본기를 탄탄하게 닦아 널리 이롭게 쓰자.
반복문은 기본적으로 지정한 condition에 의해 끝이 정해져있다.
그러나 지시자 break와 continue를 반복문과 조합하면
지정한 추가조건이나 예외상황을 만날 때 반복문을 빠져나오거나
다음 반복으로 넘어갈 수 있다.
✔️ 지시자break는 반복문 안에서 지정한 조건을 만나면 반복문을 종료시킨다.
🤗 여자친구는 지난번에 과자를 잃고 가방에 덫을 놓았다.
let 여친가방 = ["썬크림", "거울", "지갑", "덫", "과자"];
let 내주머니 = [];
for (let i = 0; i < 여친가방.length; i++) {
if (여친가방[i] === "과자") {
let 한방에갚을게 = 여친가방.splice(i, i);
내주머니.push(한방에갚을게);
// 여친가방[3]이 덫이기 때문에 if문에 걸려 break가 발동됐다.
} else if (여친가방[i] === "덫") {
break;
} else {
여친가방[i] += "(내 지문)";
}
}
console.log(내주머니): // []
// 지문만 남기고 잡혀갔다.
console.log(여친가방);
// ['썬크림(내 지문)', '거울(내 지문)', '지갑(내 지문)', '덫']
- 지시자
break에 걸린 시점부터 element에 (내 지문)이 찍히지 않은 것으로 보아break조건이 만족하는 순간부터 그 다음 코드가 연산되지 않고 반복문이 종료됐다는 것을 알 수 있다.- 배열 전체에 대해 순회해야 하는 경우가 아니라 특정 조건을 만나면 반복문을
종료시키는 것이 효율적이거나 종료시켜야만 할 경우, 무한반복문과 같은 곳에 유용해보인다.
✔️ 지시자 continue는 반복문을 종료시키는 것이 아니라 현재의 순환만 종료시킨 후 (condition이 true라면)다음 순환을 시작한다.
🤗 여자친구의 덫에 걸렸던 도둑남자친구는 덫을 피하는 연습을 하고 돌아왔다.
let 여친가방 = ["썬크림", "거울", "지갑", "덫", "과자"];
let 내주머니 = [];
for (let i = 0; i < 여친가방.length; i++) {
if (여친가방[i] === "과자") {
let 한방에갚을게 = 여친가방.splice(i, i);
내주머니.push(한방에갚을게);
// 여친가방[3]이 덫이기 때문에 if문에 걸려 continue가 발동됐다.
} else if (여친가방[i] === "덫") {
continue;
} else {
여친가방[i] += "(내 지문)";
}
}
// splice() method는 element를 배열로 가져오기 때문에 [[]]의 형태가 된것.
console.log(내주머니): // [['과자']]
// 과자만 쏙 빼갔다.
console.log(여친가방);
// ['썬크림(내 지문)', '거울(내 지문)', '지갑(내 지문)', '덫']
- 지시자
break와 마찬가지로continue도 실행되면 그 아래 코드는 무시되기 때문에 '덫'에는 그 아래 코드인 (내지문)이 적용되지 않았다.- 하지만
break와 달리 반복문을 종료시키지 않고 다음 순환이 실행되면서 '덫' 뒤에 있는 element를 조작할 수 있었다.continue는 특정 element에 대해서 연산 건너 뛰기, 어떤 element에 대해서는 본문코드의 일부 작업만 하고 끝내야 할 때와 같은 작업에 유용할 것 같다.

반복문 안에는 또다른 반복문을 쓸 수 있다.
구구단 예제를 통해 두개의 반복문이 겹쳐있을 때의 동작을 탐구하며
반복문에 대한 이해도를 높여보자!!
(걸그룹 구구단님들을 보면서 눈보신도 하자.)
✔️ 반복문에 대해 어느정도 이해했다면 한개의 반복문으로 단계별 구구단을 따로따로 만드는 것은 어렵지 않을 것이다.
for (let i = 1; i <= 9; i++) {
console.log(`2 x ${i} = ${2 * i}`)
}
/* 2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18 */
✔️ 이제 다른 단계의 구구단을 만들려면 반복문을 또 만들어야 하는 상황이다.
✔️ 하지만 중첩 반복문을 쓰면 한번에 2단에서 9단 까지 구구단을 찍어낼 수 있다!
// 이것만 알면 우리는 이제 2단부터 1만단까지 1초컷이다.(macbook-pro m1 16g 기준)
for (let i = 2; i <= 9; i++) {
for (let j = 1; j <= 9; j++) {
console.log(`${i} x ${j} = ${i * j}`)
}
}
/* 2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
.
.
.
9 x 8 = 72
9 x 9 = 81 */
begin인 2가 하위 반복문으로 전달된다.(하위 반복문이 상위 반복문의 본문코드이기 때문)2를 받아 구구단의 앞자리로 사용하고 자신의 조건환경에 따라 1에서 9까지 순환하며 console.log()를 찍은 후 죽는다.step에 의해 begin이 3으로 증가된 후 condition이 true임을 확인하고 3을 다시 하위 반복문으로 보낸다.3을 받은 하위 반복문은 부활하며 초기화되고 다시 1부터 열심히 증가하며 연산을 시작한다...9를 받고 연산을 끝낸 시점에서 상위 반복문은 다시 step이 begin의 9를 10으로 증가시키고 condition을 확인한 후 9보다 커진 상위 반복문을 감당하지 못하고 fale가 되면서 반복문을 최종 종료시킨다. 💡 중첩반복문 구구단으로 나는 무엇을 얻었나.
상호 연관성이 있는 두번의 연산이 가능했다.
예를 들면 상위 반복문에서 구구단 2단을 지정했기에 하위 반복문은 이어서 2단에 대한 상세 반복작업을 수행했다.
element에 대해 순차적이고 반복이 요구되는 작업이 필요한 경우 유용해보인다.
뭔가 집요하게 각개격파하고 싶을 때 쓰면 좋지 않을까..?
또한 하위반복문의 연산이 끝나면 처음 세팅으로 초기화되는 생명주기를 응용했다는 점이 흥미로웠고 한편으로는 너무 당연한 것을 고민해서 이해한 내 자신이 조금 슬펐다..🥲
알긴 하겠는데 와닿지 않는 상태의 지식들이 쌓이거나
심지어 알고나면 너무 당연한 부분이라 딱히 설명도 없을 때도 있다.
이런 것들 때문에 나는 분명 반복문을 배웠는데 혼자 코드를 때려보면
요상하게 동작하거나 그냥 동작하지 않을 때가 종종 있다.
별거 아니지만 정확히 정리하고 시원하게 반복문을 사용해보자.
✔️ 첫 반복문 실행시 begin은 condition에서 조건만 확인한 후 초기상태 변수의 값 그대로 본문코드에 전달된다.
✔️ step은 첫번째 본문코드가 끝난 이후부터 매번 본문코드가 끝나는 시점에 begin을 증감시킨다.
for (let i = 0; i < 2; i++) {
console.log("첫번째 log는 증감이 적용되지 않은 \"초기값 0\"일 것이다.🤗", `${i + 1}번째 log:`, i)
}
/* 첫번째 log는 증감이 적용되지 않은 "초기값 0"일 것이다.🤗 1번째 log: 0
첫번째 log는 증감이 적용되지 않은 "초기값 0"일 것이다.🤗 2번째 log: 1 */
🤗 빙글빙글 돌아가는
짱구반복문의 하루~
begin → condition(true) → {...} → step(set begin) → condition(true) → {...} → step(set begin)→ condition(false) → iterate end.
❗️ 마지막까지 step이 begin을 증감시고 condition을 확인한 다는 것 까지 기억.
✔️ for문의 ()안에 선언한 변수(인라인 변수)는 반복문 안에서만 접근할 수 있다.
for (let i = 0; i < 3; i++) {
// ...code
}
// 외부에서 i를 읽을 수 없어서 에러가 난다.
console.log(i) // ReferenceError: i is not defined
✔️ 따라서 for문 본문코드에서는 인라인변수 조작이 되므로 알고 사용하자.
// 본문코드에서 인라인 변수를 조작하여 무한반복문을 만들 수도 있다.
for (let i = 0; i < 3; i++) {
if (i === 2) {
i = 0
} else {
// 0 1 이후 무한히 1만 찍힌다. ctr + z로 빠져나오자.
// 첫 begin 이후에는 step을 거치기 때문에 0은 한번만 뜬 것이다.
console.log(i) // 0 1 1 1 1 1 1 1 1 1 1...
}
}
✔️ 만약 경우에 따라 for의 변수를 조작고 싶으면 외부변수를 선언해 가져오자.
// 외부변수 선언
let i = 0
// begin에서 변수를 선언하지 않고 외부변수를 가져온다.
for (i = 0; i < 3; i++) {
console.log(i) // 0, 1, 2
}
console.log(i) // 3
✔️ 반복문은 조건을 만족하면 false가 되어 종료된다는 것을 배운다.
✔️ 반복문은 재사용될 경우 처음 설정된 세팅으로 돌아가고 begin또한 그렇다.
✔️ 이것이 반복문의 생명주기이며 반복문 예제에 무수히 나오는 별찍기, 구구단에서 꼭 알아야할 기본개념이다.
let 드래곤볼 = '';
for (let i = 0; i <= 6; i++) {
// 별을 찍으면 초기화되고 전보다 1이 증가된 i를 받는다.
for (let j = 0; j < i; j++) {
드래곤볼 += '*';
}
드래곤볼 += '\n';
}
console.log(드래곤볼);
/*
*
**
***
****
*****
******
*/
✔️ 첫번째 for문에 속한 두번째 for문은 i < j의 조건을 만족하면 별을 남기며 죽고 초기화되어 다시 첫번째 세팅인 let j = 0으로 돌아가게 되기 때문에 i++를 거친 다음 턴이 돌아오는 경우 전보다 더 많은 별을 찍을 수 있게 되는 것이다.
뭔가 일이 많은 일주일이라 글을 쓰다가 끊기는 일이 잦았다.
어제는 발표준비를 하다가 욕심이 생겨서 아이디어도 나름 짜보고
맥북에 적응도 하고싶어서 처음 써보는 key-note라는 어플을
파워포인트 대신 사용하며 기능을 익히면서 자료를 만들어갔다.

한장짜리 분량을 25장 넘게 늘리며 결국 7시간 넘게 준비했고 3시간 자고
일어나서 부랴부랴 회의시간에 맞춰 입장해 발표를 끝냈다.
그리고 마침내 이어서 글을 쓰려는데 여자친구님이 이전 게시물에
오타가 있다고 하여 고치고 예시코드가 안된대서 다시 확인하고 고치고..
지난주도 글을 끊어쓰게 되는 일이 많아서 그랬는지 오타 천국이...
글을 짧게 끊어서 써야하나 싶은데 그러고싶지는 않공..
아무튼 어쨌든간 이번에도 왠만큼 쓰고싶은 내용들은 다 쓴 것 같아 행복하다.🕺

내 작은 지식과 미약한 이해력으로 써나가는 글들에 기술블로그라는
정체성을 담아야 한다는 것이 항상 부담스럽긴 하다.
그렇기에 혹시나 나를 믿고 읽으실 누군가를 위해
늘 더 정확한 내용을 담으려 노력하게 된다.
더 많은 자료들을 보며 이미 작성한 내용을 다시 검토하고
재정리하고 나름 그 핵심만 담은 코드를 만들어보고
어떻게 해야 간결하면서 전달력 있는 문장을 쓸까 썼다지웠다의 연속이다.
덕분에 내 글은 속도를 포기하고 말았다.
그리고 나도 노트북을 덮고 나가고 싶어진다.
하지만 고맙게도 매번 미숙한 내 글을 봐주며
덕분에 좀 더 이해됐다고 말해주고 오타까지 찾아주는 여자친구가
글쓰다 지쳐 멍때릴때마다 떠올라서 힘이 났다..
그래서 이번 글은 내 복덩이 껌딱지님에게 바치며 턴을 마치겠다.
곧 맛있는것도 사다 바치겠다.
아, 하나 확실한건 이런 과정이 정말 많은 도움이 되는걸 느낀다.
배운 것들이 내것이 되어있는 상황들이 빈번해지는 경험을 한다.
괜히 기술블로그를 쓰라는게 아닌 것을 매우 체감하고 있는 중.🙂