[도구/환경#6] 파이썬 성능 최적화 (속도 개선 팁)

한줄 요약:
“파이썬은 느리다?” 🤔
👉 알고리즘, 데이터 구조, 내장 함수, 멀티프로세싱으로 10배 빠른 코드 만들기!


목표

  • 파이썬 코드 속도를 느리게 만드는 원인을 이해
  • 빠른 코드를 작성하기 위한 실전 최적화 전략 5가지 익히기
  • 프로파일링, 멀티프로세싱, Numpy 활용으로 성능 극대화

1. 알고리즘과 데이터 구조 먼저 점검하라

파이썬이 느린 이유 대부분은 알고리즘자료구조 선택이 비효율적이기 때문이에요.

✅ 예시: 리스트 탐색 vs 딕셔너리 탐색

# 리스트 탐색
nums = list(range(1000000))
print(999999 in nums)  # 느림 😩

# 딕셔너리 탐색
nums_dict = {x: True for x in range(1000000)}
print(999999 in nums_dict)  # 훨씬 빠름 😎

💡 리스트 탐색은 O(n), 딕셔너리 탐색은 O(1)!
→ “검색”이나 “존재 여부 확인”에는 항상 dict / set을 고려하자.


2. 내장 함수와 컴프리헨션 적극 활용

파이썬의 내장 함수들은 C로 구현되어 있어서 매우 빠릅니다.

✅ 느린 예시

result = []
for i in range(1000000):
    result.append(i * 2)

⚡ 빠른 예시

result = [i * 2 for i in range(1000000)]  # 리스트 컴프리헨션

✅ 더 빠르게: map + lambda

result = list(map(lambda x: x * 2, range(1000000)))

💡 반복문 대신 컴프리헨션map/filter/sum/max/min 같은 내장 함수를 쓰면 속도가 2~5배까지 향상됩니다.


3. 불필요한 연산과 복사 줄이기

❌ 느린 코드

data = [x for x in range(1000000)]
filtered = []
for d in data:
    filtered.append(d * 2)

✅ 빠른 코드

filtered = (x * 2 for x in range(1000000))  # 제너레이터

**제너레이터(generator)**는 값을 “필요할 때만” 만들어서 메모리 사용을 줄입니다.
→ 대용량 데이터 처리 시 메모리 절약 + 속도 향상.


4. Numpy로 수치 계산 가속

❌ 순수 파이썬

data = [i for i in range(1000000)]
result = [x * 2 for x in data]

⚡ Numpy 사용

import numpy as np
data = np.arange(1000000)
result = data * 2

💡 Numpy는 C 기반 배열 연산이기 때문에 순수 파이썬보다 최대 100배 이상 빠름.
→ 루프 연산 대신 Numpy로 벡터화(vectorization)하라!


5. 멀티프로세싱으로 CPU 100% 활용

파이썬은 GIL(Global Interpreter Lock) 때문에 한 번에 하나의 스레드만 실행되지만,
**멀티프로세싱(multiprocessing)**을 이용하면 CPU 코어를 전부 사용할 수 있습니다.

✅ 예시: 병렬 실행

from multiprocessing import Pool

def square(n):
    return n * n

if __name__ == "__main__":
    nums = [x for x in range(10_000_000)]
    with Pool() as p:
        results = p.map(square, nums)

Pool()을 사용하면 CPU 코어 개수만큼 프로세스가 자동으로 병렬로 실행됩니다.


6. 프로파일링으로 병목 구간 찾기

“어디가 느린지” 모르고 최적화하면 헛수고!
프로파일링으로 먼저 확인해보세요 👇

import cProfile
import pstats

def heavy_task():
    for i in range(1000000):
        _ = i ** 2

cProfile.run('heavy_task()', 'result.stats')

p = pstats.Stats('result.stats')
p.sort_stats('cumtime').print_stats(5)

출력 예시:

1000000 function calls in 0.421 seconds
Ordered by: cumulative time

🔍 cumtime이 높은 함수가 병목 구간입니다.
→ 그 부분만 집중적으로 최적화!


7. 캐싱으로 중복 계산 제거 (functools.lru_cache)

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

print(fib(35))

중복 계산을 자동으로 캐시
→ 속도 100배 향상 (메모이제이션 기법)


8. I/O(입출력) 최적화

입출력은 파이썬의 가장 큰 병목 중 하나입니다.
가능한 한 “묶어서 처리”해야 합니다.

# ❌ 비효율적
for line in open("data.txt"):
    process(line)

# ✅ 효율적
with open("data.txt") as f:
    lines = f.readlines()
for line in lines:
    process(line)

또는 큰 파일일 경우 버퍼링 I/O:

with open("data.txt", buffering=1024*1024) as f:
    for line in f:
        process(line)

9. Cython, Numba로 코드 가속

✅ Numba 예시

from numba import njit

@njit
def fast_square(n):
    result = 0
    for i in range(n):
        result += i * i
    return result

print(fast_square(10_000_000))

💡 Numba는 파이썬 코드를 JIT(Just-In-Time) 컴파일해 C 수준 속도로 가속합니다.
→ 반복 연산이나 과학 계산에 효과적!


10. 메모리 사용량 줄이기

  • 리스트보다 제너레이터 사용
  • 필요 없는 객체 삭제 (del obj)
  • gc.collect()로 가비지 컬렉션 명시 호출
  • 데이터프레임은 pandas 대신 polars로 시도 pip install polars

11. 자주 묻는 질문(FAQ)

Q. 파이썬을 컴파일 언어처럼 빠르게 만들 수 있나요?
A. 완전히는 어렵지만, Numba나 Cython을 사용하면 10~100배 속도 향상이 가능합니다.

Q. 데이터가 너무 커서 메모리 부족이 나요.
A. 데이터를 제너레이터로 처리하거나, chunk 단위로 나누어 읽기를 사용하세요.
예:

pd.read_csv("data.csv", chunksize=100000)

Q. 반복문 속도가 느릴 때는?
A. for문 대신 map, sum, any, all, max, min내장 함수로 대체하세요.


12. 최종 점검 체크리스트

  • 자료구조를 효율적으로 사용했다 (list → dict/set).
  • 반복문 대신 컴프리헨션/내장 함수 사용.
  • Numpy 또는 Numba로 수치 연산 가속.
  • 멀티프로세싱으로 CPU 코어 활용.
  • 프로파일링으로 병목 구간 식별.
  • I/O 최적화 및 캐싱 적용.

13. 요약 한 줄

“파이썬은 느리다”가 아니라, “잘못 쓴 파이썬은 느리다.
구조, 알고리즘, 캐싱, 병렬화로 속도를 10배 올릴 수 있다 ⚡


이전 강좌 👈 [도구/환경#5] 테스트 자동화 (unittest, pytest)
다음 강좌 👉 [응용#1] 웹 크롤러 만들기 (BeautifulSoup + requests 실전 예제)

댓글 남기기

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.