💻 프로그래밍

Python

Python Language

가독성 좋은 범용 프로그래밍 언어. 데이터 과학, AI, 웹 개발에 널리 사용. 동적 타이핑.

📖 상세 설명

Python은 1991년 네덜란드 프로그래머 Guido van Rossum이 개발한 고수준 범용 프로그래밍 언어입니다. 이름은 영국 코미디 그룹 'Monty Python'에서 따왔습니다. 인터프리터 언어로 동적 타이핑을 지원하며, 1994년 Python 1.0, 2000년 Python 2.0, 2008년 Python 3.0이 출시되었습니다. 2020년 Python 2가 공식 종료되면서 현재는 Python 3.x가 표준입니다.

Python의 설계 철학은 "The Zen of Python"(PEP 20)에 담겨 있습니다. 핵심 원칙은 "읽기 쉬운 코드가 아름답다(Beautiful is better than ugly)", "명시적이 암시적보다 낫다(Explicit is better than implicit)", "단순함이 복잡함보다 낫다(Simple is better than complex)"입니다. 들여쓰기로 코드 블록을 구분하는 문법 덕분에 가독성이 높고, 배우기 쉬워 프로그래밍 입문 언어로 많이 사용됩니다.

활용 분야가 매우 넓습니다. AI/ML 분야에서는 TensorFlow, PyTorch, scikit-learn 등 주요 라이브러리가 Python을 지원해 사실상 표준 언어입니다. 웹 개발에는 Django, Flask, FastAPI 같은 프레임워크가 있고, 데이터 분석에는 Pandas, NumPy, Matplotlib가 있습니다. 자동화, 스크립팅, DevOps, 과학 연구 등에서도 핵심적으로 활용됩니다.

Python 생태계의 핵심은 pip(패키지 관리자)와 PyPI(Python Package Index)입니다. 2025년 기준 PyPI에 50만 개 이상의 패키지가 등록되어 있습니다. 가상 환경(venv, conda)으로 프로젝트별 의존성을 관리하고, Poetry, PDM 같은 현대적 도구도 많이 사용됩니다. 3.10부터 도입된 패턴 매칭(match-case), 3.12의 성능 개선 등 계속 발전 중입니다.

💻 코드 예제

# Python 기본 문법 예제

# 1. 변수와 데이터 타입
name = "Python"           # 문자열
version = 3.12            # 실수
is_awesome = True         # 불리언
features = ["simple", "readable", "powerful"]  # 리스트

# 2. 조건문
if version >= 3.10:
    print("패턴 매칭 사용 가능!")
elif version >= 3.0:
    print("Python 3 기능 사용 가능")
else:
    print("업그레이드가 필요합니다")

# 3. 반복문
for feature in features:
    print(f"Python is {feature}")

# 4. 함수 정의 (타입 힌팅 포함)
def greet(name: str, times: int = 1) -> str:
    """인사말을 반환하는 함수"""
    return f"Hello, {name}! " * times

# 5. 클래스 정의
class Developer:
    def __init__(self, name: str, language: str = "Python"):
        self.name = name
        self.language = language

    def introduce(self) -> str:
        return f"저는 {self.name}이고, {self.language}를 사용합니다."

# 6. 예외 처리
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"오류 발생: {e}")
finally:
    print("정리 작업 완료")
# 리스트 컴프리헨션 - Python의 핵심 문법

# 1. 기본 리스트 컴프리헨션
squares = [x**2 for x in range(10)]
# 결과: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 2. 조건부 필터링
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# 결과: [0, 4, 16, 36, 64]

# 3. 중첩 리스트 컴프리헨션
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
# 결과: [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 4. 딕셔너리 컴프리헨션
word = "python"
char_index = {char: idx for idx, char in enumerate(word)}
# 결과: {'p': 0, 'y': 1, 't': 2, 'h': 3, 'o': 4, 'n': 5}

# 5. 셋 컴프리헨션
unique_lengths = {len(word) for word in ["apple", "banana", "cherry", "date"]}
# 결과: {4, 5, 6}

# 6. 제너레이터 표현식 (메모리 효율적)
sum_of_squares = sum(x**2 for x in range(1000000))
# 리스트를 생성하지 않고 한 번에 하나씩 처리

# 7. 실전 예제: 파일에서 특정 라인 필터링
# config_lines = [line.strip() for line in open('config.txt')
#                 if line.strip() and not line.startswith('#')]

# 8. 조건부 값 변환
numbers = [1, -2, 3, -4, 5]
absolute = [x if x > 0 else -x for x in numbers]
# 결과: [1, 2, 3, 4, 5]
# 데코레이터 - Python의 강력한 메타프로그래밍 기능
import functools
import time
from typing import Callable, Any

# 1. 기본 데코레이터 - 실행 시간 측정
def timer(func: Callable) -> Callable:
    """함수 실행 시간을 측정하는 데코레이터"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs) -> Any:
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__} 실행 시간: {end - start:.4f}초")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    return "완료"

# 2. 인자를 받는 데코레이터
def retry(max_attempts: int = 3, delay: float = 1.0):
    """재시도 데코레이터"""
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    print(f"시도 {attempt + 1} 실패, {delay}초 후 재시도...")
                    time.sleep(delay)
        return wrapper
    return decorator

@retry(max_attempts=3, delay=0.5)
def unstable_api_call():
    import random
    if random.random() < 0.7:
        raise ConnectionError("API 연결 실패")
    return "성공!"

# 3. 클래스 기반 데코레이터
class Cache:
    """결과를 캐싱하는 데코레이터"""
    def __init__(self, func: Callable):
        self.func = func
        self.cache = {}
        functools.update_wrapper(self, func)

    def __call__(self, *args) -> Any:
        if args not in self.cache:
            self.cache[args] = self.func(*args)
        return self.cache[args]

@Cache
def fibonacci(n: int) -> int:
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

# 4. 내장 데코레이터 활용
class MyClass:
    _instance = None

    @staticmethod
    def utility_function():
        """인스턴스 없이 호출 가능"""
        return "유틸리티 결과"

    @classmethod
    def get_instance(cls):
        """싱글톤 패턴 구현"""
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    @property
    def computed_value(self):
        """속성처럼 접근 가능한 메서드"""
        return self._value * 2

🗣️ 실무 대화 예시

💬 회의에서: 언어 선택 논의

"이번 AI 서비스 백엔드는 Python으로 가겠습니다. ML 파이프라인이 PyTorch 기반이고, FastAPI로 API 서버를 빠르게 구축할 수 있어요. 자바의 성능이 필요한 부분은 마이크로서비스로 분리하면 됩니다. 데이터 사이언스 팀과 협업할 때도 Python이 공통 언어라 커뮤니케이션 비용이 줄어듭니다."

💬 면접에서: GIL 질문

"GIL은 Global Interpreter Lock의 약자로, CPython에서 한 번에 하나의 스레드만 Python 바이트코드를 실행할 수 있게 하는 뮤텍스입니다. CPU-bound 작업에서 멀티스레딩의 이점을 얻기 어렵습니다. 대안으로 multiprocessing 모듈로 프로세스를 분리하거나, I/O-bound 작업에는 asyncio를 사용합니다. 최근에는 PEP 703 free-threaded Python이 3.13에서 실험적으로 도입되어 GIL 제거가 진행 중입니다."

💬 코드 리뷰에서

"이 함수에 타입 힌팅 추가해주세요. def process_data(data: list[dict[str, Any]]) -> pd.DataFrame 형태로요. mypy로 정적 분석할 때 버그를 미리 잡을 수 있고, IDE 자동완성도 잘 동작합니다. 3.10부터는 list[dict]처럼 빌트인 타입 직접 사용 가능해서 typing 모듈 import도 줄일 수 있어요."

⚠️ 주의사항

🔒
GIL(Global Interpreter Lock) 한계

CPU-bound 멀티스레딩에서 성능 이점이 없습니다. 병렬 처리가 필요하면 multiprocessing, concurrent.futures, 또는 Cython/Numba 같은 도구를 사용하세요. I/O-bound 작업에는 asyncio나 threading이 효과적입니다.

Python 2 vs 3 호환성

Python 2는 2020년 1월 지원 종료되었습니다. 레거시 코드 마이그레이션 시 print 함수, 정수 나눗셈(//, /), 문자열 인코딩(unicode default), 라이브러리 변경(ConfigParser 등)에 주의하세요. 2to3 도구나 python-future 라이브러리가 마이그레이션에 도움됩니다.

📝
타입 힌팅 활용

동적 타이핑은 편리하지만 대규모 프로젝트에서 버그 원인이 됩니다. 타입 힌팅(PEP 484)과 mypy, Pyright 같은 정적 분석 도구를 사용하세요. Pydantic, attrs 같은 라이브러리로 런타임 타입 검증도 추가하면 더욱 안전합니다.

📦
의존성 관리

프로젝트마다 반드시 가상 환경을 사용하세요(venv, conda, poetry). requirements.txt에 버전을 고정(==)하고, pip-tools나 Poetry로 의존성 잠금(lock) 파일을 관리하세요. 글로벌 설치는 버전 충돌의 원인이 됩니다.

🔗 관련 용어

📚 더 배우기