[#5] 중첩(이중, 삼중) 반복문과 별 쌓기

이번에는 이중, 삼중 반복문인 중첩 반복문을 배우고 이전에 배운 지식들과 중첩 반복문을 활용해 별 쌓기를 해보겠습니다.

 


 

이중 반복문

 

이중 반복문 반복문인 for문을 두 번 겹치는 것을 말합니다.

말로는 이해가 잘 되지 않는 파트인만큼, 바로 실습으로 들어가며 이해해 보겠습니다.

for (int i = 1; i<=4; i++)
{
	printf("여기가 첫 번째 : %d\n", i)
}

먼저 이렇게 코드를 입력해 봅시다.

그럼 반복문인 for로 인해서 1인 변수 i 는 4가 될때까지 총 4번을 반복하게 될 겁니다.

그럼 이 반복문 안에다가 반복문을 한 번 더 넣어서 이중 반복문을 만들어 볼까요?

방법은 간단합니다. 그냥 저 for문 {} 안쪽에 원하는 for문을 아무거나 하나 더 넣으면 끝입니다.

    for (int i = 1; i <= 4; i++)
    {
        printf("여기가 첫 번째 : %d\n", i);

        for (int j = 1; j <= 3; j++)
            printf("    여기가 두 번째 : %d\n", j);
    }

전 j라는 변수에 1이란 값을 주고 j <= 3으로 j가 1에서 3일 될 때 까지 총 세번을 반복하게 설정했고,

출력문은 "    여기가 두 번 째 : "로 설정했습니다. 앞에 띄어쓰기를 좀 한 이유는 첫번째와 두번째를 칸으로 구분하기 위함입니다.

이렇게 해보고 한 번 실행을 해볼까요??

그럼 위의 이미지처럼 변수 i가 총 4번 반복되고, 변수 i가 한번 반복될 때 마다 i 안에 들어가 있는 이중 반복문인 j가 조건을 달성할 때 까지 총 세 번을 반복하는 것을 알 수 있습니다.

 

이렇게 봐도 사실 처음엔 이해가 잘 가지 않으실 겁니다.

중첩 반복문은 매우 중요한 파트기에, 어떻게든 이해를 하고 넘어갈 수 있게 더 쉽게 풀이해 보겠습니다.

 

중첩 반복문을 이해하는 가장 좋은 방법은 상황을 눈앞에 그려보는 것입니다.
이해하기 쉬운 비유를 하나 들어볼게요.



🍽️ 비유: i는 ‘손님’, j는 ‘손님이 먹은 음식’


여러분이 식당을 운영하는 사장님인데, 오늘은 뭔가 이상한 날입니다.

왜냐면 들어오는 손님마다 꼭 메뉴를 세개씩 시켜 먹었거든요.

 

오늘은 총 4명의 손님(i)이 들어왔고, 각 손님은 3개의 메뉴(j)를 차례대로 시켜서 먹었습니다.
이 상황을 반복문으로 표현하면 이런 겁니다.

    for (손님 i = 1; i <= 4; i++) {
        printf("손님 %d 등장!\n", i);

        for (메뉴 j = 1; j <= 3; j++) {
            printf("    메뉴 %d 먹는 중!\n", j);
        }
    }

저걸 그대로 복사해서 붙여넣으면 당연히 오류가 날테니, 입력할때 '손님'과 '메뉴'는 int로 바꿔줍시다. 그리고 실행시키면??

이렇게 출력이 될 겁니다.

즉, 각 손님이 들어올 때마다, 그 손님은 세 가지 메뉴를 차례차례 먹고 나갑니다.
이게 바로 중첩 반복문입니다.

 

계속 추가 실습을 하면서 더 확실히 이해해 보겠습니다.

 


 

구구단 만들기

 

위에 배운 이중 반복문을 응용해서 2부터 9까지의 구구단을 한 번 만들어 보겠습니다.

 

먼저 컴퓨터에게 구구단을 시키려면 어떻게 해야할까요?

“2단부터 9단까지, 각 단에서 1부터 9까지 곱해서 출력해줘!”라고 알려줘야겠죠.

그리고 이 명령은 위의 이중 반복문을 조금만 응용하면 어렵지 않게 만들 수 있습니다.

 

먼저 구구단을 하려면 2부터 9의 숫자가 가장 먼저 필요하겠죠?

그럼 반복문의 for문은 가장 먼저 2부터 9의 숫자를 만들어줘야 할 겁니다.

for (int i = 2; i <= 9; i++)
{
	printf("%d\n", i);
}

일단 변수값을 2부터 시작해서 9까지 출력하게 위처럼 작성합시다.

결과물은 나와야되니 급한대로 printf로 값만 출력하게 입력해 줬습니다.

 

이제 여기에 살을 붙여볼 차례입니다.

일단 2~9까진 출력하게 했으니, 여기에다가 각 숫자마다 1부터 9를 곱해줘야겠죠?

그럴려면 곱하기를 만들기 전에 먼저 2~9의 숫자 하나당 1~9가 한번씩은 출력되도록 해줘야 합니다.

 

이는 위에서 배운 이중 반복문의 수치만 바꾸면 쉽게 해결되죠.

for (int i = 2; i <= 9; i++)
{
	printf("%d\n", i);
    
    for (int j = 1; j <=9; j++)
    printf("   %d\n", j);
}

 

자, 위의 2~9위 아래의 1~9를 구분하기 위해 아래 printf는 아까처럼 공백을 좀 줬습니다.

이제 실행해보면

이렇게 반복이 되겠죠??

 

이제 여기에다가 글씨로 살만 좀 붙여주고, i와 j를 곱하기만 시켜버리면 구구단은 끝입니다.

먼저 첫번째 for문의 printf의 "%d\n"쪽을 채워줘야 되겠죠?

구구단이니까 저는 "=== 구구단을 외우자. %d단. =="을 넣어 보겠습니다.

for (int i = 2; i <= 9; i++)
{
	printf("=== 구구단을 외우자. %d단 ===\n", i);
    
    for (int j = 1; j <=9; j++)
    printf("   %d\n", j);
}

자 이렇게 넣고 다시 실행을 해보면, 저 문구가 출력되면서, '%d단'에 변하는 변수 i의 값이 계속 들어가겠죠?

이렇게요.

 

이제 아래에 실제로 저 i와 j를 곱하는 식만 넣어주면 되겠군요. 일단 "i x j ="이라는 걸 넣어서 구구단을 표시를 해주고,

뒤에서 실제로 그 둘을 곱해주는 사칙연산을 넣어주면 되겠습니다.

 

그럼 아래와 같은 코드가 완성될 겁니다.

for (int i = 2; i <= 9; i++)
{
	printf("=== 구구단을 외우자. %d단 ===\n", i);
    
    for (int j = 1; j <=9; j++)
    printf("%d x %d = %d\n", i, j, i*j);
}

printf에 총 세개의 정수를 출력하도록 해줬고, 그 정수값에 각각 변수인 i, j, i*j를 넣어줬습니다.

이러면 이제 정상적으로 구구단 내용이 출력되겠죠??

 

만약 지금 저 printf에 적은 내용이 이해가 안된다면, 이전 강의들을 제대로 이해하지 못하고 넘어왔을 가능성이 큽니다.

이해가 안됐는데 무작정 진행하기보단 다시 한 번 되돌아가서 복습하고 오는것이 더 많은 도움이 됩니다!

 

아무튼 저 결과는

최종적으로 이렇게 나오게 될 겁니다.

 


 

별 쌓기

많은 초보 프로그래머를 좌절시켰던 전설의 게임, 별 쌓기입니다.

이게 이중 반복문의 원리를 잘 이용하고, 또 \n이 작동하는 원리, 그리고 수학적 원리를 잘 알면 별로 어렵지 않은데

이런것들이 트레이닝 되지 않은 문과감성 프로그래머들한텐 정말 커다란 장벽으로 느껴집니다. 저도 그랬고요.

 

일단 우리는

*

**

***

****

이런식으로 매번 반복될때마다 별이 하나씩 더 쌓이는 구조를 만들어볼 겁니다.

총 7개의 층을 쌓아볼건데, 그럼 가장먼저 우리에게 익숙한 것부터 만들어 봅시다.

printf("별쌓기 Start!\n");
for (int i = 0; i < 7; i++)
{
	printf("%d\n", i);
}

가장 위에 "별쌓기 Start!"라고 타이틀을 먼저 만들어 줬습니다.

그 아래 for문도 익숙할 겁니다. 변수 i는 0이고 i < 7이니까 0, 1, 2, 3, 4, 5, 6 이렇게 총 일곱 번 반복되겠군요.

 

이제 이 숫자들을 별로 바꾸고, 또 한칸씩 올라갈때마다 실제 저 숫자에 맞는 별 개수를 출력해줘야 하는데, 어떻게 해야할까요?

당연히 이중 반복문이 등장해야겠죠. 그럼 for문 안에 for문을 하나 더 넣어 봅시다. 출력을 위해 넣었던 printf("%d\n");은 지웁시다.

printf("별쌓기 Start!\n");
for (int i = 0; i < 7; i++)
{
	for (int j = ???)
}

자, 이중 반복문으로 for int i 안에 for int j는 만들었습니다. 근데 대체 뒤에 뭘 적어야 저걸 쌓을 수 있을까요??

 

정답은

for (int j = 0; j <= i; j++)
printf("*");

입니다. 자 그럼 왜 이게 정답이 되는지 하나씩 뜯어봅시다.

 

먼저 이 반복문을 실행하면 i는 0부터 시작할겁니다. 0인 i는 7보다 작으니 for문은 다시 반복되게 될 겁니다.

다만, 반복되기 전에 먼저 이중 반복문인 j로 넘어가게 될 겁니다.

 

j 역시 0이고, 조건은 j <= i입니다.
이 조건은 j가 i보다 작거나 같을 동안 계속 반복하라는 뜻이죠.

이제 구체적으로 들여다봅시다.


📌 i = 0일 때

· 바깥쪽 for (int i = 0; i < 7; i++)에서 i는 0입니다. 0은 7보다 작으니 다음 반복문인 j로 넘어가게 됩니다.
· 안쪽 for (int j = 0; j <= i; j++)에서도 j = 0, 조건도 j(0) <= i(0) 이기에 참이므로 통과하게 됩니다.
·  j가 조건을 충족해 통과했으니 이젠 마지막인 printf("*");를 수행하게 될 겁니다. 그럼 별 하나가 출력되겠죠.
·  그 후 j++로 인해 j는 1이 됩니다. 다시 j가 반복문을 수행하려 했더니 이제는 j(1) <= i(0)은 거짓이 됐습니다. 고로 반복을 종료하고 빠져나오게 됩니다.

📌 i = 1일 때

· 바깥쪽 for (int i = 0; i < 7; i++)에서 i는 1입니다. 1도 여전히 7보단 작으니 다음 반복문인 j로 넘어가게 됩니다.

· 여기서 한가지 주의할 점, 가장 바깥쪽의 i가 1이 됐다고해서 안에 있는 j도 1부터 시작하는건 아닙니다. i안에 j가 있고, j는 이미 거짓으로 반복문을 빠져나왔으니, j=0이기에 다시 0부터 시작해야 하는 것이죠.

· 그럼 계속 가보겠습니다. 안쪽 for (int j = 0; j <= i; j++)에서 j = 0이지만, i는 현재 1인 상태죠. 조건도 j(0) <= i(1) 이기에 참이므로 통과하게 됩니다.
·  j가 조건을 충족해 통과했으니 이젠 마지막인 printf("*");를 수행하게 될 겁니다. 그럼 별 하나가 출력되겠죠.
·  그 후 j++로 인해 j는 1이 됩니다. 다시 j가 반복문을 수행하려 가보니 여전히 j(1) <= i(1)이기에 참인 상태입니다. 고로 또 한번 별(*)을 출력하게 됩니다. 이 줄에는 이제 총 두개의 별이 출력되겠군요.

·  그 후 j++로 인해 j는 이제 2가 됐습니다. 다시 j가 반복문을 수행하러 가보니 이번엔 j(2) <= i(1)로 j가 i보다 커지면서 거짓이 됐습니다.  고로 반복을 종료하고 빠져나오게 됩니다.

 

이런식으로 0~7까지 반복을 계속 하다보면, 결국 별은 총 7층까지 쌓이게 됩니다.

코드로 보면 아래와 같습니다.

    printf("별쌓기 Start!\n");
    for (int i = 0; i < 7; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            printf("*");
        }
    }

 

근데 아마 이걸 실행하면 결과가 뭔가 이상하게 나올 겁니다.

이런식으로 별이 쌓이는 형태가 아니라 한줄에 쭉 이어져 나오는 일이 발생하는거죠.

이걸 방지하기 위해선 가장 바깥에 있는 반복문인 i가 i++을 하며 반복문을 탈출할 때, 줄바꿈을 해줘야 합니다.

 

즉, printf("\n");을 가장 마지막에 넣어줘야 한단 소리죠.

    printf("별쌓기 Start!\n");
    for (int i = 0; i < 7; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            printf("*");
        }
        printf("\n");
    }

이렇게요.

그럼 결과가 이렇게 잘 나올 겁니다.

 

사실 이번 강의에서 역으로 별쌓기랑 피라미드 쌓기까지 만들 생각이었는데, 정작 만들고 나니 이 내용 자체도 꽤 난이도가 있는 내용이라 다음 강의로 넘기기로 결정했습니다.

 


 

AI피드백

 

Q. 오늘은 반복문에서도 중첩(이중, 삼중) 반복문에 대해 배웠어. 그리고 그걸 응용해서 별쌓기까지 해봤지. 이 별쌓기가 프로그래밍 입문 시 첫번째로 마주하는 통곡의 벽 같은 거라던데, 왜 그렇게 불리는거고 또 이걸 배워야 하는 이유가 뭘까?

 

A. 오늘 너는 단순히 “별을 잘 찍었다”에서 끝나지 않고, "왜 이런 걸 배우는지, 그 의미는 뭔지"를 궁금해하고 있어. 이런 정신이 바로 진짜 프로그래머가 되는 길이야.

 




🧱 왜 별쌓기가 "통곡의 벽"이라고 불릴까?


1. 눈에 보이는 것과 코드가 직관적으로 연결되지 않기 때문
·  화면에는 *가 1개 → 2개 → 3개 늘어나는데,
·  코드는 for문이 2개나 중첩되고,
·  그 안에 공백 조건, 줄바꿈 등 “머릿속으로 그림을 그려야” 이해할 수 있어.
→ 즉, 출력 결과가 단순해 보여도, 머릿속 처리 구조는 굉장히 복잡해.

2. 중첩 반복문에 대한 논리적 사고가 요구됨
·  바깥 루프 → 줄 수
·  안쪽 루프 → 줄마다 출력되는 내용
→ 이 관계를 이해하고, 흐름을 시뮬레이션할 수 있어야 패턴을 만들 수 있어.
(처음엔 "왜 j가 i까지 반복되는 거지?", "공백은 왜 저렇게 계산해야 하지?" 같은 혼란이 생김)

3. 응용력이 요구됨
·  피라미드 → 다이아몬드 → 숫자삼각형 → 문자 계단 등으로
→ 문제는 금방 복잡해지고 패턴도 다양해져
→ 단순한 반복문이 아니라 창의력과 수학적 규칙성 파악 능력까지 테스트되는 문제가 돼

 

💡 그래서 왜 이걸 배우는 걸까?


✅ 1. 반복문의 동작 흐름을 몸으로 체득할 수 있음
·  단순한 숫자만 다루는 for (i = 0; i < 5; i++)보다

· 눈으로 결과가 보이고,
·  반복이 시각화되니까 “왜 이게 반복인가”를 직관적으로 이해하게 돼.

✅ 2. 제어 흐름 능력의 첫 번째 시험대
·  중첩 반복문은 프로그래밍 구조에서 가장 많이 쓰이는 기법이야.
     ·  예: 2D 게임 맵 처리
     ·  예: 행렬 계산
     ·  예: 웹 테이블 그리기
·  그래서 이걸 이해하지 못하면 그 이상을 만들 수 없어

✅ 3. 패턴 인식 + 설계 능력 향상의 지름길
·  별쌓기는 단순히 별을 찍는 게 아니라,
→ “데이터와 공간의 패턴”을 코드로 표현하는 연습이야

·  예: 공백을 앞에 찍는 건 정렬,
   별을 반대로 찍으면 대칭,
   줄 수로 조건을 걸면 피라미드 → 다이아몬드
→ 즉, 단순한 것처럼 보여도 프로그래밍 사고력을 훈련시키는 최고의 문제


🎯 결론 요약

왜 통곡의 벽인가? 왜 배워야 하는가?
결과는 단순하지만 내부 흐름이 복잡 중첩 반복문 구조를 직관적으로 체득
머릿속 시뮬레이션이 어려움 패턴 처리 능력을 기르기 위한 첫 훈련
공백/정렬/대칭 등 다양한 조건이 섞임 실전에서 쓰이는 2차원 반복처리의 기본기
구조는 쉽지만 정답은 무한히 다양 창의적 설계 능력 키우는 기반 문제