본문 바로가기
TYLER SONGBlog
블로그 목록
LLM Research

반복문·range·list: 리스트를 순회하며 가공하는 법

for와 while로 반복 작업을 처리하고, range로 숫자 구간을 만들고, list를 인덱싱·슬라이싱·컴프리헨션으로 다루는 법을 배운다. 내장함수 없이 최댓값·평균을 직접 구현하면서 반복문이 실제로 데이터를 어떻게 훑고 계산하는지 손으로 익힌다. 오늘 배운 패턴은 이후 데이터셋을 배치로 나누고 순회하는 코드의 뼈대가 된다.

송민성5분 읽기

오늘의 목표

숫자나 값이 여러 개 들어있는 리스트를 하나씩 훑으면서(순회) 원하는 대로 골라내거나, 더하거나, 바꾸는 코드를 짤 수 있게 되는 게 오늘 목표다. "반복해서 뭔가를 한다"는 것만 할 줄 알면 나중에 수백만 개 데이터를 처리하는 코드도 결국 같은 패턴이다.

개념과 직관

for문과 range

반복문(loop)은 "같은 작업을 여러 번 반복해서 실행하라"는 명령이다. 사람이 손으로 1부터 10까지 하나씩 더하면 지치지만, 컴퓨터는 반복문으로 순식간에 해낸다.

range(n)은 0부터 n-1까지의 숫자를 순서대로 만들어주는 발생기다. 리스트처럼 보이지만 실제로 숫자를 미리 다 만들어두지 않고 필요할 때마다 하나씩 내놓는다(메모리 절약).

python
for i in range(5): print(i) # 0 1 2 3 4 출력

비유하자면 range(5)는 "0번째부터 4번째까지 5장의 번호표를 순서대로 뽑아주는 기계"다. for문은 그 번호표를 하나씩 받아서 i라는 이름표에 붙이고, 몸통 코드를 실행한다.

while문

while문은 "조건이 참인 동안 계속 반복"이다. 반복 횟수를 미리 모를 때 쓴다.

python
n = 5 total = 0 i = 1 while i <= n: total += i i += 1 print(total) # 15

주의할 점: i += 1을 빼먹으면 조건이 영원히 참이 되어 무한루프(infinite loop, 멈추지 않는 반복)에 빠진다. for문은 range가 알아서 끝나지만 while문은 직접 종료 조건을 관리해야 한다.

break와 continue

  • break: 반복문을 즉시 탈출한다. "그만 찾아, 나가"
  • continue: 이번 반복만 건너뛰고 다음 반복으로 간다. "이건 패스, 다음 거"
python
for i in range(10): if i == 5: break # 5에서 완전히 멈춤 if i % 2 == 0: continue # 짝수는 건너뛰고 다음으로 print(i) # 1, 3 출력

list: 생성·인덱싱·슬라이싱·append·pop

list(리스트)는 여러 값을 순서대로 담는 상자 줄이다. 상자마다 번호(인덱스, index)가 매겨져 있고 0번부터 시작한다.

python
nums = [10, 20, 30, 40, 50] print(nums[0]) # 10 (첫 번째) print(nums[-1]) # 50 (맨 마지막, 음수 인덱스는 뒤에서부터) print(nums[1:3]) # [20, 30] 슬라이싱: 1번부터 3번 전까지 nums.append(60) # 맨 뒤에 추가 -> [10,20,30,40,50,60] last = nums.pop() # 맨 뒤 하나 꺼내서 제거 -> last=60

슬라이싱 nums[start:end]는 "start번 상자부터 end번 상자 직전까지"를 잘라낸다는 규칙만 외우면 헷갈리지 않는다. end는 포함되지 않는다.

리스트 컴프리헨션

리스트를 만드는 for문을 한 줄로 축약한 문법이다.

python
squares = [x**2 for x in range(5)] # 위는 아래와 완전히 같은 결과 squares = [] for x in range(5): squares.append(x**2)

조건을 붙이면 필터링도 가능하다: [x for x in nums if x % 2 == 0]은 "nums를 순회하면서 짝수인 것만 골라 새 리스트를 만들어라"는 뜻이다.

코드로 직접 해보기

1) 1~N 합

python
def sum_to_n(n): total = 0 for i in range(1, n + 1): # 1부터 n까지 total += i return total print(sum_to_n(10)) # 55

2) 구구단

python
for dan in range(2, 10): # 2단부터 9단까지 for i in range(1, 10): # 1부터 9까지 print(f"{dan} x {i} = {dan * i}") print() # 단마다 줄바꿈

for문 안에 for문을 넣는 걸 중첩 반복문(nested loop)이라 부른다. 바깥 for가 한 번 돌 때마다 안쪽 for가 처음부터 끝까지 통째로 돈다.

3) 리스트에서 짝수만 뽑기

python
nums = [3, 8, 15, 22, 7, 10] # 방식 1: 일반 for문 evens = [] for n in nums: if n % 2 == 0: evens.append(n) # 방식 2: 컴프리헨션 (같은 결과) evens2 = [n for n in nums if n % 2 == 0] print(evens, evens2) # [8, 22, 10] [8, 22, 10]

4) 최댓값을 내장함수(max) 없이 구하기

python
def my_max(nums): biggest = nums[0] # 일단 첫 번째 값을 최댓값 후보로 for n in nums[1:]: # 두 번째 값부터 끝까지 비교 if n > biggest: biggest = n return biggest print(my_max([3, 8, 15, 22, 7, 10])) # 22

직관: 지금까지 본 것 중 가장 큰 값을 손에 쥐고 다니다가, 더 큰 걸 만나면 손을 바꿔 쥐는 과정이다.

5) 평균을 내장함수(sum, len) 없이 구하기

python
def my_average(nums): total = 0 count = 0 for n in nums: total += n count += 1 return total / count print(my_average([3, 8, 15, 22, 7, 10])) # 10.833333333333334

오늘의 실험

없음 (오늘은 코드 구현과 알고리즘 문제 풀이에 집중하는 날).

왜 이걸 배우나 (LLM / Post-training 연결)

지금은 숫자 리스트를 다루지만, 나중에 딥러닝을 배우면 "데이터셋에서 배치(batch, 한 번에 처리할 묶음)를 하나씩 꺼내서 학습에 넣는" 과정이 결국 오늘 짠 for문과 똑같은 패턴이다. 예를 들어 학습 데이터 10만 개를 100개씩 묶어 반복적으로 모델에 넣고 손실(loss)을 계산하는 학습 루프(training loop)는 for문 + 인덱싱/슬라이싱의 확장판일 뿐이다. Post-training에서 데이터를 필터링하거나(예: 품질 낮은 샘플 제거) 특정 조건의 샘플만 골라내는 전처리 코드도 오늘 배운 리스트 컴프리헨션과 조건문 조합 그대로 쓰인다.

초보자가 막히는 지점

  • 인덱스 범위 초과(IndexError): nums[len(nums)]처럼 마지막 인덱스보다 하나 큰 값을 참조하면 에러가 난다. 리스트 길이가 5면 유효한 인덱스는 0~4까지다.
  • while문 무한루프: 조건을 갱신하는 코드(i += 1 등)를 반복문 안에 넣는 걸 잊으면 프로그램이 멈추지 않는다. 실행 중 멈추지 않으면 Ctrl+C로 강제 종료하고 코드를 다시 확인한다.
  • 슬라이싱 end 인덱스 착각: nums[1:3]이 3번째 원소까지 포함한다고 착각하기 쉽다. 실제로는 3번 인덱스 "직전"까지만, 즉 1번과 2번만 포함된다.
  • append와 리스트 자체를 혼동: nums.append(x)는 반환값이 없다(None). nums = nums.append(x)처럼 쓰면 nums가 None이 되어버리는 흔한 실수다.
  • 컴프리헨션을 너무 일찍 남발: 조건이 복잡해지면 오히려 일반 for문이 읽기 쉽다. 처음엔 for문으로 짜보고 익숙해지면 한 줄로 줄이는 순서를 권장한다.

알고리즘 (병행 1시간)

LeetCode Easy 중 반복문으로 풀 수 있는 문제 2개를 고른다. 예를 들어 "배열 원소 합/최댓값 찾기" 유형이나 "특정 조건 만족하는 원소 세기" 유형처럼 오늘 배운 개념(for, 리스트 순회, append)만으로 풀리는 문제를 선택하면 된다.

풀 때 아래 세 가지를 반드시 기록해라:

  • 접근: 문제를 어떤 반복 방식으로 풀었는지 (for/while, 한 번 순회인지 두 번 순회인지)
  • 시간복잡도: 리스트를 몇 번 훑었는지 눈대중으로 세어보기 (한 번이면 대략 "선형", 이중 for문이면 "리스트 길이의 제곱" 수준이라고 직관적으로 적어도 충분하다. 정확한 표기법은 이후 알고리즘 Day에서 다룬다)
  • 틀린 이유: 처음에 틀렸다면 인덱스 범위 문제였는지, 조건문 부등호를 잘못 썼는지, 빈 리스트 같은 예외 상황을 놓쳤는지 구체적으로 남긴다
© 2026 Tyler Song