Python#
다양한 특징을 가진 강력하고 유연한 프로그래밍 언어.
인터프리터 언어#
파이썬은 인터프리터 언어.
이는 코드가 한 줄씩 실행되며, 컴파일 과정 없이 바로 실행할 수 있다는 의미.
장점:
- 마치 대화를 하듯이 즉각적인 결과를 볼 수 있어서, 특히 학습과 디버깅에 매우 유용.
- 플랫폼 독립적으로 실행 가능
- REPL(대화형 셸)을 통한 빠른 테스트와 학습
단점:
- 컴파일 언어에 비해 실행 속도가 상대적으로 느림
- 런타임 에러가 실행 시점에서만 발견됨
예를 들어, 다음과 같은 코드를 바로 실행하고 결과를 확인할 수 있다:
1
2
3
4
| >>> x = 5
>>> y = 3
>>> print(x + y)
8
|
동적 타이핑#
파이썬은 변수의 타입을 미리 선언할 필요가 없다.
변수는 할당되는 값에 따라 자동으로 타입이 결정된다:
장점:
- 코드 작성이 빠르고 간편
- 유연한 프로그래밍 가능
- 프로토타이핑에 적합
단점:
- 타입 관련 오류가 런타임에 발생할 수 있음
- 대규모 프로젝트에서 유지보수가 어려울 수 있음
1
2
3
4
| # 같은 변수에 다른 타입의 값을 자유롭게 할당할 수 있습니다
x = 42 # 정수
x = "Hello" # 문자열
x = [1, 2, 3] # 리스트
|
객체 지향 프로그래밍 지원#
파이썬은 클래스와 객체를 사용한 객체 지향 프로그래밍을 완벽하게 지원한다:
장점:
- 클래스, 상속, 다형성 등 OOP 개념 완벽 지원
- 코드 재사용성과 유지보수성 향상
단점:
- 간단한 스크립트에 OOP를 과도하게 적용할 경우 복잡성 증가
1
2
3
4
5
6
7
8
9
10
| class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
|
풍부한 표준 라이브러리와 생태계#
장점:
- 다양한 기능을 즉시 사용 가능
- 외부 라이브러리가 풍부
- 활발한 커뮤니티 지원
단점:
- 라이브러리 의존성 관리가 복잡할 수 있음
- 버전 호환성 문제 발생 가능
1
2
3
4
5
6
7
8
9
| # 데이터 분석
import pandas as pd
import numpy as np
# 웹 개발
from flask import Flask
# 머신러닝
from sklearn import linear_model
|
1
2
3
4
5
6
7
8
9
10
11
| # 가상 환경과 의존성 관리 도구 사용
"""
# requirements.txt 생성
pip freeze > requirements.txt
# 가상 환경 생성
python -m venv myenv
# 의존성 설치
pip install -r requirements.txt
"""
|
크로스 플랫폼 지원#
장점:
- 다양한 운영 체제에서 동일하게 실행 가능
- 코드의 이식성이 높음
단점:
문법적 특징#
들여쓰기를 통한 코드 블록 구분#
장점:
- 코드의 가독성이 높음
- 일관된 코드 스타일 강제
- 깔끔한 코드 구조
단점:
- 들여쓰기 오류로 인한 문법 에러 발생 가능
- 복사-붙여넣기 시 들여쓰기 깨질 수 있음
1
2
3
4
5
6
7
8
9
| def calculate_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
else:
return 'F'
|
리스트 컴프리헨션과 제너레이터 표현식#
장점:
- 간결하고 표현력 있는 코드 작성 가능
- 메모리 효율적인 처리 가능
- 함수형 프로그래밍 스타일 지원
단점:
- 과도한 사용 시 가독성 저하
- 복잡한 로직에서는 디버깅이 어려울 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 적절한 주석과 분리로 가독성 향상
# 복잡한 컴프리헨션은 일반 반복문으로 분리
numbers = [1, 2, 3, 4, 5]
# 간단한 경우 리스트 컴프리헨션 사용
squares = [x**2 for x in numbers]
# 복잡한 경우 일반 반복문 사용
filtered_squares = []
for x in numbers:
if x % 2 == 0:
if x**2 > 10:
filtered_squares.append(x**2)
|
다중 상속과 믹스인#
장점:
- 코드 재사용성 향상
- 유연한 클래스 설계 가능
- 기능의 조합이 용이
단점:
- 다이아몬드 문제 발생 가능
- 복잡한 상속 관계로 인한 유지보수 어려움
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 믹스인 패턴과 명시적 메서드 해결 순서 사용
class LoggerMixin:
def log(self, message):
print(f"[LOG] {message}")
class ServiceMixin:
def service_method(self):
self.log("Service method called")
class MyService(ServiceMixin, LoggerMixin):
pass
# MRO(Method Resolution Order) 확인
print(MyService.__mro__)
|
덕 타이핑#
장점:
- 유연한 인터페이스 구현
- 코드 재사용성 향상
- 테스트가 용이
단점:
- 타입 안정성이 낮을 수 있음
- 런타임 에러 발생 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 프로토콜과 추상 기본 클래스 사용
from typing import Protocol
from abc import ABC, abstractmethod
class Drawable(Protocol):
def draw(self) -> None: …
class Shape(ABC):
@abstractmethod
def draw(self) -> None:
pass
class Circle(Shape):
def draw(self) -> None:
print("Drawing circle")
|
파이썬의 단점과 해결 방안#
실행 속도#
인터프리터 언어의 특성상 컴파일 언어에 비해 실행 속도가 느리다.
해결 방안#
- Cython 사용: 파이썬 코드를 C로 변환하여 성능 향상
1
2
3
4
5
| # Cython 예시
%%cython
def fast_calculation(int x, int y):
cdef int result = x * y
return result
|
- NumPy 활용: 수치 계산을 최적화된 배열 연산으로 처리
1
2
3
4
5
| import numpy as np
# 일반 파이썬 리스트 대신 NumPy 배열 사용
array = np.array([1, 2, 3, 4, 5])
result = array * 2 # 빠른 벡터화 연산
|
GIL(Global Interpreter Lock)로 인한 멀티스레딩 제한#
GIL로 인해 멀티코어 CPU를 완전히 활용하기 어렵다.
해결 방안#
1
2
3
4
5
6
7
8
| from multiprocessing import Pool
def heavy_computation(x):
return x * x
if __name__ == '__main__':
with Pool(4) as p: # 4개의 프로세스 생성
result = p.map(heavy_computation, range(1000))
|
1
2
3
4
5
6
7
8
9
10
| import asyncio
async def async_task(name):
print(f'Task {name} starting')
await asyncio.sleep(1)
print(f'Task {name} completed')
async def main():
tasks = [async_task(f'Task_{i}') for i in range(3)]
await asyncio.gather(*tasks)
|
메모리 사용량#
동적 타이핑으로 인해 메모리 사용량이 많을 수 있다.
해결 방안#
1
2
3
4
5
6
7
8
| # 리스트 대신 제네레이터 사용
def number_generator(n):
for i in range(n):
yield i ** 2
# 메모리 효율적인 처리
for num in number_generator(1000000):
process(num)
|
1
2
3
4
5
6
| class MemoryEfficientClass:
__slots__ = ['name', 'age'] # 인스턴스 속성 제한
def __init__(self, name, age):
self.name = name
self.age = age
|
타입 안정성#
동적 타이핑으로 인해 런타임 에러가 발생할 수 있다.
해결 방안#
1
2
3
4
5
6
7
8
9
| from typing import List, Dict
def calculate_average(numbers: List[float]) -> float:
return sum(numbers) / len(numbers)
def process_user_data(data: Dict[str, str]) -> None:
name = data['name']
email = data['email']
print(f"Processing user {name} with email {email}")
|
1
2
| # 터미널에서 실행
mypy your_script.py
|
참고 및 출처#
Roadmap#
Data Types Python은 동적 타입 언어로, 변수를 선언할 때 명시적으로 타입을 지정할 필요가 없다.
하지만 각 데이터 타입을 이해하는 것은 효율적인 코딩과 디버깅에 필수적이다.
숫자형 (Numeric) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 정수형 (Integer): 양의 정수, 음의 정수, 0을 포함하는 숫자형 age = 25 population = 1000000000000 # Python3는 정수 크기 제한이 없습니다 print(type(age)) # <class 'int'> print(type(population)) # <class 'int'> # 부동소수점 (Float): 소수점을 포함하는 숫자형 height = 175.5 pi = 3.14159 print(type(height)) # <class 'float'> print(type(pi)) # <class 'float'> # 복소수 (Complex): 실수부와 허수부로 구성된 숫자형 complex_number = 3 + 4j print(complex_number.real) # 실수부: 3.0 print(complex_number.imag) # 허수부: 4.0 print(type(complex_number)) # <class 'complex'> 문자열 (str) 문자들의 집합으로, 작은따옴표(’’)나 큰따옴표("")로 감싸서 표현한다.
...
Python Testing 특성 pytest unittest nose2 doctest behave hypothesis 유형 일반 테스트 프레임워크 표준 라이브러리 테스트 확장 프레임워크 문서 기반 테스트 행동 주도 개발(BDD) 속성 기반 테스트 주요 특징 - 간단한 문법
- 풍부한 플러그인
- 자동 테스트 발견
- 상세한 오류 리포트 - Python 기본 제공
- 클래스 기반 테스트
- 자체 검증 방법
- 테스트 격리 - unittest 호환
- 플러그인 구조
- 테스트 레이어
- 유연한 테스트 발견 - 문서에서 테스트
- 간단한 예제 테스트
- 문서화와 테스트 통합
- 대화형 세션 스타일 - 자연어 명세
- 시나리오 기반
- 비개발자 이해 용이
- 단계별 테스트 - 자동 테스트 케이스
- 엣지 케이스 발견
- 속성 기반 검증
- 무작위 테스트 문법 복잡도 낮음 중간 중간 매우 낮음 중간 높음 학습 곡선 완만함 중간 완만함 매우 낮음 중간 가파름 확장성 매우 높음 중간 높음 낮음 중간 높음 실행 속도 빠름 중간 빠름 매우 빠름 중간 느림 사용 사례 - 일반적인 단위 테스트
- 통합 테스트
- 기능 테스트
API 테스트 - 기본적인 단위 테스트
OOP 테스트
- 레거시 코드 테스트 - 대규모 테스트 스위트
unittest 마이그레이션
- 플러그인 기반 테스트 - API 문서 검증
- 간단한 함수 테스트
- 튜토리얼 예제 - 사용자 스토리 테스트
- 인수 테스트
- 시나리오 기반 테스트 - 복잡한 입력 테스트
- 데이터 변환 테스트
- 엣지 케이스 발견 도구 통합 매우 높음 기본 높음 기본 중간 높음 보고서 기능 상세함 기본적 상세함 기본적 상세함 매우 상세함 병렬 실행 지원 제한적 지원 미지원 지원 지원 커버리지 분석 통합 지원 별도 도구 필요 통합 지원 제한적 별도 도구 필요 통합 지원 주요 장점 - 직관적인 API
- 풍부한 생태계
- 높은 유연성
- 뛰어난 디버깅 - 표준 라이브러리
- 안정성
- 기본 기능 충실
- 별도 설치 불필요 - 호환성
- 플러그인 확장
- 유연한 설정
unittest 친화적 - 문서화 통합
- 간단한 사용법
- 빠른 실행
- 예제 중심 - 비즈니스 친화적
- 명확한 명세
- 협업 용이
- 시나리오 중심 - 자동화된 테스트
- 버그 발견 효과적
- 철저한 테스트
- 엣지 케이스 발견 주요 단점 - 설정 복잡도
- 높은 자유도
- 일관성 유지 필요 - 장황한 문법
- 제한된 기능
- 유연성 부족 - 개발 속도 느림
- 문서화 부족
- 복잡한 설정 - 제한된 기능
- 복잡한 케이스 어려움
- 유지보수 어려움 - 설정 시간 필요
- 유지보수 부담
- 성능 오버헤드 - 복잡한 설정
- 긴 실행 시간
- 높은 학습 곡선 각 테스팅 도구는 서로 다른 상황에서 최적의 선택이 될 수 있다:
...
Python Linter와 Formatter Linter와 Formatter는 코드의 품질과 일관성을 유지하는 데 필수적인 도구.
Linter는 코드의 잠재적인 에러, 버그, 스타일 문제, 그리고 의심스러운 구조들을 찾아내는 도구.
마치 교정 편집자가 글의 문법과 표현을 검토하는 것처럼, Linter는 코드의 품질을 검사한다.
주요 기능:
구문 오류 감지 코딩 스타일 검사 잠재적 버그 발견 코드 복잡도 분석 베스트 프랙티스 제안 보안 취약점 식별 성능 문제 파악 장점:
코드 품질 향상 일관된 코딩 스타일 유지 버그 조기 발견 단점:
...
ASGI CGI WSGI 비교 분석 이 기술들은 웹 서버와 애플리케이션 간의 통신 방식을 정의하는 인터페이스 규격.
시대 순으로 발전 과정을 이해하면 좋을 것 같다.
ASGI CGI WSGI 비교 특징 CGI WSGI ASGI 등장 시기 1990년대 초반 2003년 (PEP 333) 2016년 처리 방식 프로세스 기반 동기식 비동기식 성능 매 요청마다 새 프로세스 생성 (낮음) 프로세스 재사용 (중간) 비동기 처리로 높은 성능 프로토콜 지원 HTTP/1.0 HTTP/1.1 HTTP/1.1, HTTP/2, WebSocket 구현 복잡도 단순함 중간 상대적으로 복잡함 메모리 사용 높음 (프로세스당) 중간 효율적 동시성 처리 프로세스 기반 스레드/프로세스 기반 이벤트 루프 기반 주요 사용 사례 레거시 시스템 전통적인 웹 애플리케이션 현대적 웹 애플리케이션 환경 변수 처리 시스템 환경 변수 environ 딕셔너리 scope 딕셔너리 스트리밍 지원 제한적 이터레이터 기반 네이티브 지원 프레임워크 예시 직접 구현 Django, Flask FastAPI, Starlette 서버 예시 Apache gunicorn, uWSGI uvicorn, daphne 오류 처리 제한적 표준화된 방식 포괄적 지원 설정 복잡도 간단 중간 상대적으로 복잡 확장성 제한적 중간 높음 각 기술의 기본적인 구현 예제 CGI (Common Gateway Interface):
...
Poetry Python 프로젝트의 의존성 관리와 패키징을 위한 도구. 특징 의존성 관리: pyproject.toml 파일을 사용하여 프로젝트의 의존성을 선언적으로 관리. 의존성 해결 및 버전 충돌 방지를 자동으로 처리. poetry.lock 파일을 통해 정확한 패키지 버전을 고정하여 일관된 환경을 보장. 가상 환경 관리: 프로젝트별로 독립된 가상 환경을 자동으로 생성하고 관리. 패키지 관리: 패키지 추가, 제거, 업데이트를 간단한 명령어로 수행 가능. 프로젝트 빌드 및 배포: 프로젝트 빌드와 PyPI 배포를 쉽게 할 수 있는 기능 제공. 사용 편의성: pip, virtualenv, setuptools 등 여러 도구의 통합 지원. 호환성: PEP 517 및 PEP 518 표준을 준수 PEP 517
...
Rye Rye는 파이썬 프로젝트와 패키지 관리를 위한 통합 솔루션으로, 2022년 11월에 Pynecone이라는 이름으로 처음 공개되었으나, 2023년 6월에 Rye로 이름이 변경되었다.
Rye는 파이썬 개발자들이 겪는 다양한 환경 설정 및 관리 문제를 해결하기 위해 설계되었다.
주요 특징 통합 환경 관리: Rye는 파이썬 설치, 프로젝트 초기화, 의존성 관리, 가상 환경 설정 등을 단일 도구로 통합한다. pyproject.toml 기반: 프로젝트 구성을 위해 현대적인 pyproject.toml 파일을 사용한다. 빠른 성능: Rust로 작성되어 기존 도구들보다 훨씬 빠른 성능을 제공한다. 다목적성: 복잡한 프로젝트, 모노레포, 글로벌 도구 설치 등 다양한 시나리오를 지원한다. 자동화된 가상 환경: 프로젝트별로 독립적인 가상 환경을 자동으로 생성하고 관리한다. 설치 및 사용 Rye는 다양한 운영 체제에서 쉽게 설치할 수 있다:
...