반응형

python 8

제너레이터 vs 이터레이터 - Python yield는 언제 쓰나

몇 년 전에 로그 파일 하나가 20GB짜리인데 이걸 통째로 readlines()로 읽어서 처리하는 코드를 짠 적이 있어요. 로컬에서 500MB 짜리로 테스트할 때는 잘 돌더니 운영에서 메모리 부족으로 프로세스가 죽었죠. 원인은 20GB를 리스트로 다 올린 것. 그때 yield로 한 줄씩 뽑아주는 형태로 바꿨더니 메모리 20MB로도 잘 돌아갔습니다. 오늘은 이터레이터·제너레이터가 뭐고, 언제 yield를 써야 하는지 정리해볼게요.개념 / 원리먼저 용어부터 갈라봅시다.이터러블(Iterable): for로 순회할 수 있는 모든 것. __iter__ 메서드가 있다. 예: list, dict, 문자열, 파일 객체.이터레이터(Iterator): next()가 호출될 때마다 다음 값을 하나씩 뱉는 것. __iter_..

HMAC의 정체 - sha256(secret + msg)가 안 되는 이유

예전에 결제 콜백을 받아 처리하는 서버 코드를 열어봤다가 서명 검증이 hashlib.sha256((secret + payload).encode()).hexdigest()로 짜여 있는 걸 발견한 적이 있어요. 저도 처음엔 "어? 원래 이렇게 하는 거 아닌가?" 싶었는데, 파보니 이 방식은 Length Extension Attack이라는 오래된 공격에 뚫립니다. 그래서 실무의 웹훅(Stripe, GitHub, Slack)은 하나같이 HMAC이라는 별도 구조를 써요. 오늘은 왜 순진한 sha256(secret + msg)가 안 되는지, HMAC이 그걸 어떻게 해결하는지 한 번 파헤쳐볼게요.개념 / 원리문제부터 봅시다. 서명 = SHA-256(secret + message)로 만들면 뭐가 나쁠까요?SHA-256..

보안 2026.07.03

패스워드 해싱 - bcrypt와 argon2, 뭘 선택해야 할까

신입 때 처음 짠 회원가입 코드를 떠올리면 지금도 식은땀이 납니다. 패스워드를 그냥 hashlib.sha256(password) 한 줄로 해시해서 DB에 박아 넣었거든요. 당시엔 "암호화했으니 안전하지 않나?"라고 생각했는데, 사실 SHA-256만 쓰는 건 그냥 빠른 해시일 뿐 패스워드 보호 용도로는 매우 위험합니다. 오늘은 왜 일반 해시가 안 되는지, 그리고 bcrypt와 argon2 중에 뭘 골라야 할지 정리해 보겠습니다.개념 / 원리SHA-256은 빠릅니다. 빠른 게 평소엔 장점이지만 패스워드 해싱에선 단점입니다. 공격자가 레인보우 테이블이나 GPU 가지고 초당 수십억 번씩 시도할 수 있거든요. 8자리 패스워드는 GPU 한 대로 몇 시간 안에 다 깨집니다.그래서 패스워드 해싱 전용 알고리즘이 따로 ..

보안 2026.06.24

dataclass vs Pydantic - 언제 뭘 써야 할까

Python으로 API 응답 모델을 만들 때 저도 처음엔 @dataclass로 시작했습니다. 깔끔하고 표준 라이브러리라 의존성도 없어서 좋았는데요, 그런데 외부에서 들어오는 JSON을 받기 시작하니까 문제가 생겼습니다. age 필드에 "twenty" 같은 문자열이 들어와도 dataclass는 그냥 받아주거든요. 결국 일일이 if not isinstance(...) 검증을 붙이다가 "이럴 거면 Pydantic 쓰자"로 갈아탔던 기억이 있습니다. 오늘은 이 두 가지를 언제 뭘 쓸지, 차이가 정확히 뭔지 정리해 보겠습니다.개념 / 원리dataclass는 Python 3.7부터 표준 라이브러리로 들어온 기능입니다. 클래스에 __init__, __repr__, __eq__ 같은 보일러플레이트 코드를 자동으로 만들..

multiprocessing vs threading - GIL 때문에 헷갈리는 두 모듈 정리

파이썬으로 처음 병렬 처리를 시도했을 때 저는 별생각 없이 threading을 썼다가, 속도가 한 톨도 안 빨라져서 한참 헤맸습니다. 이게 다 GIL 때문이라는 걸 알게 되고, 그래서 multiprocessing이 따로 있다는 것까지 깨닫는 데 일주일이 걸렸어요. 지금은 두 모듈을 상황별로 골라 쓰는데, 오늘은 그 기준을 정리해 보겠습니다.개념 / 원리두 모듈의 차이는 결국 GIL(Global Interpreter Lock) 한 가지에서 출발합니다.threading: 하나의 프로세스 안에서 여러 스레드를 만듭니다. 모든 스레드가 같은 GIL을 공유해서 동시에 파이썬 바이트코드를 실행하는 건 한 번에 하나뿐입니다.multiprocessing: 별도의 프로세스를 띄웁니다. 각 프로세스는 자기만의 파이썬 인터..

데코레이터 만들기와 활용 - @ 한 줄 뒤에 숨은 클로저

파이썬 코드를 보다 보면 @something 한 줄이 함수 위에 떡 붙어 있는 걸 자주 봅니다. @app.route("/users"), @functools.lru_cache, @pytest.fixture 같은 것들요. 처음엔 "이게 뭔가 마법 같은 어노테이션인가" 싶지만, 까보면 그냥 함수를 인자로 받아 함수를 반환하는 함수일 뿐입니다. 원리만 잡으면 직접 만드는 것도 어렵지 않아요. 오늘은 데코레이터의 정체부터 시작해서, 인자를 받는 데코레이터, 그리고 functools.wraps를 왜 꼭 써야 하는지까지 정리해 볼게요.개념 / 원리데코레이터를 한 줄로 정의하면 "함수를 감싸서 동작을 추가하는 고차 함수"입니다. 비유하자면 선물 포장 같은 거예요. 안에 든 선물(원래 함수)은 그대로 있는데, 겉포장(데..

asyncio - 코루틴은 GIL을 어떻게 피해 다니는가

지난 글에서 GIL을 다루고 나니, 자연스럽게 따라오는 의문이 하나 있습니다. "그럼 asyncio는 GIL 안에서 어떻게 그렇게 빠른 건가요?" 솔직히 저도 파이썬 처음 입문해서 asyncio를 봤을 때 한참 헷갈렸어요. 단일 스레드라며? 그런데 HTTP 요청 1만 개를 1초 안에 끝낸다고? 알고 보니 asyncio는 GIL을 우회하는 게 아니라, 애초에 GIL과 싸울 일이 없게 설계된 동시성 모델입니다. 오늘은 이벤트 루프가 어떻게 돌아가는지, async/await 한 줄에 무슨 일이 벌어지는지, 그리고 실무에서 자주 터지는 함정까지 정리해 볼게요.개념 / 원리먼저 threading과 asyncio의 본질적인 차이부터 짚어야 합니다. 스레드는 선점형(preemptive) 동시성이에요. OS가 마음대로..

GIL의 정체 - 왜 멀티스레드가 안 빠를까

파이썬으로 데이터 처리 스크립트 짜다가 "그래, 이건 멀티스레드로 돌리면 빠르겠지" 싶어서 threading.Thread를 4개 띄워본 적, 한 번씩은 있으실 거예요. 그런데 막상 돌려보면 어이없는 결과가 나옵니다. CPU 사용률이 한 코어만 100%를 찍고 나머지는 멀쩡한데, 전체 실행 시간은 싱글 스레드보다 오히려 느려지는 경우도 있죠. 처음 이걸 봤을 때 저도 "내 코드가 잘못됐나" 한참 디버깅했습니다. 범인은 코드가 아니라 GIL(Global Interpreter Lock)이었어요. 오늘은 이 GIL이라는 녀석이 왜 존재하고, 어떤 상황에서 발목을 잡는지, 그리고 우회하는 방법까지 정리해 볼게요.개념 / 원리GIL을 한 줄로 설명하자면 "CPython 인터프리터가 한 번에 하나의 스레드만 파이썬 ..