[파이썬 100강] 12강. 리스트 컴프리헨션으로 코드 짧고 빠르게 쓰기

[파이썬 100강] 12강. 리스트 컴프리헨션으로 코드 짧고 빠르게 쓰기

리스트 컴프리헨션를 "실수 없이" 다루는 감각을 만드는 것이 이번 강의의 목표입니다. 문법 자체는 금방 외울 수 있지만, 실제 코드에서는 입력 데이터가 항상 깨끗하지 않고 운영 환경도 일정하지 않습니다. 그래서 오늘은 단순한 문법 소개를 넘어서 왜 이 기능이 필요한지, 어떤 실수를 반복하는지, 실무에서는 어떤 규칙으로 안전하게 쓰는지까지 함께 정리하겠습니다.


핵심 개념

  • 리스트 컴프리헨션는 "기능"이 아니라 안정성을 위한 기본 장치입니다.
  • 초보 단계에서 중요한 것은 "동작했다"가 아니라 "다시 실행해도 같은 결과가 나온다"는 재현성입니다.
  • 작은 예제를 여러 번 실행하며 입력/출력/오류를 함께 관찰하는 습관이 실력을 가장 빠르게 끌어올립니다.

많은 분이 파이썬을 배울 때 함수 이름이나 옵션을 먼저 외웁니다. 물론 필요하지만, 실무에서는 "왜 이런 API가 이렇게 생겼는지"를 이해해야 코드가 단단해집니다. 예를 들어 파일을 읽거나 문자열을 다루거나 클래스를 설계할 때, 대부분의 버그는 문법 오류가 아니라 가정이 틀린 상태에서 코드를 짠 것에서 시작됩니다. 그래서 이번 강의는 기능을 하나씩 나열하기보다, 초보가 놓치기 쉬운 전제를 먼저 짚습니다. 그리고 REPL 예제로 작은 성공을 반복해서 만들고, 바로 이어서 실패 케이스를 보여드리겠습니다. 실패를 먼저 배워 두면 실제 프로젝트에서 디버깅 시간이 크게 줄어듭니다. 이 관점이 바로 100강 전체를 관통하는 학습 방식입니다.

왜 중요한가

  • 운영 환경에서는 입력 데이터가 매번 동일하지 않습니다.
  • "한 번 실행 성공"보다 "100번 실행해도 동일한 결과"가 더 중요합니다.
  • 팀 협업에서는 읽기 쉬운 구조와 예외 처리 규칙이 생산성을 결정합니다.

처음에는 "지금 돌아가면 됐지"라고 생각하기 쉽습니다. 하지만 자동화 스크립트, 배치 작업, API 연동처럼 실제로 돈과 시간이 걸린 작업에서는 작은 예외 하나가 전체 파이프라인을 멈출 수 있습니다. 리스트 컴프리헨션를 정확히 익히면 장애를 완전히 없앨 수는 없어도, 장애가 발생했을 때 영향을 좁히고 복구를 빠르게 만들 수 있습니다. 또 협업 관점에서도 중요합니다. 내가 작성한 코드가 다음 달의 나, 혹은 동료에게 읽히고 수정되어야 하기 때문입니다. 설명 가능한 코드, 예측 가능한 동작, 명확한 오류 메시지. 이 세 가지가 실무에서 "잘 만든 코드"의 기준입니다.

기본 사용

예제 1) 가장 기본 패턴

>>> values = [1, 2, 3, 4]
>>> total = sum(values)
>>> total
10

해설:

  • 단순한 계산도 중간 값을 변수로 분리하면 디버깅이 쉬워집니다.
  • REPL에서는 한 줄씩 실행하며 상태를 확인하는 습관이 중요합니다.

예제 2) 조건/반복/조합 확장

>>> data = [3, 7, 10, 11]
>>> even = []
>>> for x in data:
...     if x % 2 == 0:
...         even.append(x)
>>> even
[10]

해설:

  • 반복문과 조건문 조합은 대부분의 데이터 처리 코드의 기본입니다.
  • 결과 리스트를 먼저 선언하고 누적하면 흐름이 눈에 잘 들어옵니다.

예제 3) 실전형 미니 케이스

>>> raw = "  Python,100,Course  "
>>> parts = [p.strip().lower() for p in raw.split(',')]
>>> parts
['python', '100', 'course']

해설:

  • 공백 제거(strip), 분리(split), 정규화(lower)를 한 번에 처리했습니다.
  • 실제 로그/CSV/API 응답 전처리에서 매우 자주 쓰는 패턴입니다.

예제 4) 검증 포함 처리

>>> text = "42"
>>> if text.isdigit():
...     number = int(text)
... else:
...     number = None
>>> number
42

해설:

  • 변환 전 검증은 예외를 줄이는 가장 간단한 방법입니다.
  • None 같은 명시적 실패 값을 정하면 후속 로직이 명확해집니다.

자주 하는 실수

실수 1) "입력은 항상 정상"이라고 가정하기

>>> int("3.14")
Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 10: '3.14'

원인:

  • 숫자처럼 보이는 문자열이 모두 정수로 변환 가능하다고 오해합니다.

해결:

>>> value = "3.14"
>>> number = float(value)
>>> number
3.14

실수 2) 예외를 무시하고 넘어가기

  • 증상: 오류가 사라진 것처럼 보이지만 결과 데이터가 비어 있거나 누락됩니다.
  • 원인: except: pass처럼 원인 기록 없이 예외를 삼켜 버립니다.
  • 해결: 최소한 오류 타입과 입력 값을 함께 로깅하고, 필요하면 재발생(raise)시킵니다.

실수 3) 변수 이름을 모호하게 짓기

  • 증상: 한 달 뒤 코드를 봤을 때 의도를 기억하지 못합니다.
  • 원인: a, tmp, x1 같은 임시 이름을 그대로 둡니다.
  • 해결: user_count, failed_rows, output_path처럼 역할이 드러나는 이름을 사용합니다.

실무 패턴

  • 입력 검증 규칙: 변환 전에 형식 점검(길이, 타입, 허용 값)부터 수행합니다.
  • 로그/예외 처리 규칙: 실패를 숨기지 말고 "어디서/무엇이/왜"를 남깁니다.
  • 재사용 함수/구조화 팁: 20줄 이상 반복되는 로직은 함수로 추출합니다.
  • 성능/메모리 체크 포인트: 작은 데이터는 단순성, 큰 데이터는 스트리밍/분할 처리 우선입니다.

여기서 핵심은 "완벽한 코드"가 아니라 "운영 가능한 코드"입니다. 운영 가능한 코드는 장애를 0으로 만드는 코드가 아니라, 장애가 발생했을 때 원인을 빠르게 찾고 복구할 수 있는 코드입니다. 그래서 데이터 처리 전 검증, 단계별 로그, 함수 분리, 테스트 가능한 단위 설계를 함께 가져가야 합니다. 특히 초보 단계에서는 화려한 기법보다 명확한 흐름이 훨씬 큰 가치를 만듭니다.

심화 이해 메모

초보에서 중급으로 넘어가는 구간에서는 "코드를 더 짧게"보다 "코드를 더 신뢰 가능하게" 만드는 훈련이 중요합니다. 같은 결과를 만드는 코드라도, 입력이 조금만 달라졌을 때 안정적으로 동작하는 쪽이 실무에서는 훨씬 높은 점수를 받습니다. 그래서 작업을 시작하기 전에 입력 스키마를 간단히 문서화하고, 실패 시 동작(재시도/중단/건너뛰기)을 미리 정해 두는 습관이 필요합니다. 또한 동작이 맞는지 확인할 때는 정상 케이스 1개만 보지 말고, 경계값(빈 값, 매우 큰 값, 형식 오류)을 함께 테스트해야 합니다. 이 과정을 반복하면 디버깅 시간이 눈에 띄게 줄고, 유지보수 시 변경 영향도 예측하기 쉬워집니다. 결국 좋은 코드는 "처음부터 완벽"해서가 아니라, 실패를 가정하고 설계했기 때문에 오래 버팁니다.

추가 체크리스트: 기능 구현 후에는 샘플 입력 3종(정상/경계/오류)을 반드시 남겨 두고, 다음 수정 시 회귀 테스트로 재사용하세요.

오늘의 결론

한 줄 요약: 리스트 컴프리헨션의 본질은 문법이 아니라 "예측 가능한 동작"을 만드는 것입니다.

기억할 것:

  • 먼저 검증하고, 그다음 변환하세요.
  • 예외를 숨기지 말고 기록하세요.
  • 읽기 쉬운 구조가 디버깅 시간을 줄입니다.

연습문제

  1. 문자열 리스트 ['10', '20', 'oops', '30']를 순회하며 숫자만 합산하는 코드를 작성하세요.
  2. 입력 값이 비어 있을 때 기본값을 넣어 처리하는 함수를 작성하세요.
  3. 처리 성공/실패 건수를 함께 반환하는 미니 집계 함수를 만들어 보세요.

이전 강의 정답 (11강)

  1. 입력 정규화 후 처리
>>> raw = "  Alice  "
>>> name = raw.strip().title()
>>> name
'Alice'
  1. 조건 분기 기본
>>> score = 82
>>> grade = 'A' if score >= 80 else 'B'
>>> grade
'A'
  1. 반복 누적 패턴
>>> nums = [1, 2, 3, 4]
>>> acc = 0
>>> for n in nums:
...     acc += n
>>> acc
10

실습 환경/재현 정보

  • 실행 환경: conda env python100 (Python 3.11.14)
  • 가정한 OS: macOS/Linux 공통
  • 인코딩: UTF-8
  • 실행 방식: REPL(python) 또는 .py 파일 실행
  • 재현 체크: 동일 입력에서 동일 출력이 나오는지 2회 이상 확인