한국정보기술진흥원
한국정보기술신문
thumbnail

정보기술 ·

파이썬 프로그래머가 알아야 할 성능 수치 공개...메모리 최적화부터 웹 프레임워크 속도까지

발행일
읽는 시간3분 43초

마이클 케네디, 파이썬 성능 벤치마크 종합 가이드 발표. 개발자 최적화 의사결정 도움 목표.

[한국정보기술신문] 파이썬 전문 강사이자 Talk Python 팟캐스트 진행자인 마이클 케네디가 파이썬 개발자를 위한 종합 성능 벤치마크 가이드를 발표했다. 이번 벤치마크는 2025년 12월 31일 공개됐으며, 메모리 사용량부터 웹 프레임워크 속도까지 파이썬 프로그래밍의 핵심 성능 지표를 담고 있다.

케네디는 자신의 블로그를 통해 파이썬 개발자라면 반드시 알아야 할 성능 수치들을 체계적으로 정리했다. 리스트에 항목을 추가하는 데 얼마나 걸리는지, 파일을 여는 데 1밀리초 미만이 소요되는지, 성능에 민감한 알고리즘에는 어떤 자료구조를 사용해야 하는지 등의 질문에 구체적인 답을 제시한다.

테스트 환경과 방법론

이번 벤치마크는 Mac Mini M4 Pro 환경에서 CPython 3.14.2 버전으로 진행됐다. 14개의 물리 코어와 24GB 램을 갖춘 시스템에서 측정된 결과다. 케네디는 절대적인 속도보다 상대적인 비교가 중요하다고 강조하며, 모든 벤치마크 코드를 깃허브에 공개해 투명성을 확보했다.

측정 항목은 메모리 사용량, 기본 연산, 컬렉션, JSON 직렬화, 웹 프레임워크, 파일 입출력, 데이터베이스, 함수 호출, 비동기 오버헤드 등 9개 범주로 나뉜다. 각 범주별로 실제 개발에서 자주 사용되는 연산들의 성능을 나노초 단위까지 측정했다.

메모리 사용량의 놀라운 진실

벤치마크 결과 파이썬 객체의 메모리 오버헤드가 예상보다 크다는 사실이 드러났다. 빈 파이썬 프로세스만으로도 15.73MB를 사용하며, 빈 문자열조차 41바이트를 차지한다. 100자 문자열은 141바이트로, 문자당 1바이트씩 증가하는 규칙을 보인다.

정수와 부동소수점 수의 메모리 사용량도 주목할 만하다. 0부터 256까지의 작은 정수는 28바이트, 일반 정수도 28바이트를 사용한다. 부동소수점은 24바이트다. 이는 C나 C++에서 일반적으로 생각하는 2바이트 또는 4바이트보다 훨씬 크다. CPython의 PyObject 구조체와 참조 카운팅 방식의 가비지 컬렉션 때문이다.

컬렉션의 경우 빈 리스트가 56바이트, 빈 딕셔너리가 64바이트, 빈 집합은 216바이트를 차지한다. 1000개의 정수를 담은 리스트는 7.87KB, 같은 크기의 딕셔너리는 36.1KB를 사용한다.

slots 클래스로 메모리 절반 절약

클래스 인스턴스의 메모리 사용에서 흥미로운 결과가 나왔다. 일반 클래스 인스턴스는 48바이트지만, slots를 사용한 클래스는 72바이트로 오히려 크다. 하지만 1000개의 인스턴스를 리스트에 담으면 상황이 역전된다. 일반 클래스는 165.2KB를 사용하지만, slots 클래스는 79.1KB로 절반 수준이다.

케네디는 대량의 객체를 메모리에 보관하는 경우 slots를 사용하면 최소한의 노력으로 극적인 메모리 절감 효과를 얻을 수 있다고 설명했다. slots는 인스턴스의 딕셔너리 개념을 제거해 필드 추적 오버헤드를 없앤다.

자료구조 선택이 성능을 좌우한다

자료구조 선택의 중요성도 명확히 드러났다. 딕셔너리 키 검색은 21.9나노초, 집합의 멤버십 확인은 19.0나노초가 걸린다. 반면 1000개 항목을 가진 리스트에서 멤버십 확인은 3.85마이크로초로 200배나 느리다.

리스트 컴프리헨션은 동등한 for 루프보다 20퍼센트 빠른 것으로 측정됐다. 1000개 항목 생성 시 리스트 컴프리헨션은 9.45마이크로초, for 루프는 11.9마이크로초가 소요됐다. len 함수는 18.8나노초로 매우 빠르게 작동해 루프 조건문에서 최적화를 고민할 필요가 없다는 결론을 내렸다.

JSON 라이브러리 성능 격차 11배

JSON 직렬화 성능에서 라이브러리 간 격차가 크게 나타났다. 표준 라이브러리의 json 모듈은 복잡한 객체 직렬화에 2.65마이크로초가 걸리지만, orjson은 310나노초로 11배 빠르다. 역직렬화에서도 json은 2.22마이크로초, orjson은 839나노초로 큰 차이를 보인다.

msgspec도 445나노초로 표준 라이브러리보다 6배 빠른 성능을 보였다. ujson은 1.64마이크로초로 중간 수준이다. 케네디는 orjson이 더 많은 데이터 타입을 지원하면서도 압도적인 속도를 자랑한다고 평가했다.

Pydantic의 model_dump_json은 1.54마이크로초, model_validate_json은 2.99마이크로초가 소요됐다. 타입 검증과 데이터 변환 기능을 고려하면 합리적인 성능이다.

웹 프레임워크 속도 비교

웹 프레임워크 벤치마크에서는 FastAPI가 8.63마이크로초로 초당 115900건의 요청을 처리해 가장 빠른 성능을 보였다. Starlette는 8.01마이크로초로 124800건, Litestar는 8.19마이크로초로 122100건을 처리했다.

전통적인 프레임워크인 Flask는 16.5마이크로초로 60700건, Django는 18.1마이크로초로 55400건을 처리했다. FastAPI가 Flask보다 약 2배, Django보다 2배 이상 빠른 셈이다. 이 테스트는 Granian에서 4개 워커로 실행된 로컬호스트 환경에서 진행됐으며, 데이터베이스 접근 없이 순수한 프레임워크 오버헤드만을 측정했다.

파일 입출력과 데이터베이스

파일 입출력에서 1KB 파일 읽기는 10.0마이크로초, 쓰기는 35.1마이크로초가 걸렸다. 1MB 파일 쓰기는 207마이크로초였다. pickle 직렬화는 1.30마이크로초, 역직렬화는 1.44마이크로초로 JSON보다 빠른 것으로 나타났다.

데이터베이스 비교에서는 SQLite가 복잡한 객체 삽입에 192마이크로초, 기본 키로 조회에 3.57마이크로초가 소요됐다. diskcache는 설정에 23.9마이크로초, 조회에 4.25마이크로초를 기록했다. MongoDB는 삽입에 119마이크로초, 조회에 121마이크로초가 걸렸다. 케네디는 MongoDB가 네트워크 접근 방식이라 인프로세스 방식인 SQLite나 diskcache보다 불리하다고 설명했다.

비동기 프로그래밍의 오버헤드

비동기 프로그래밍의 비용도 측정됐다. 코루틴 객체 생성은 47.0나노초로 빠르지만, run_until_complete로 실행하면 27.6마이크로초가 걸린다. 일반 함수 호출이 20.3나노초인 것과 비교하면 1000배 이상 느리다.

asyncio.sleep(0)은 39.4마이크로초, 10개 코루틴을 gather하는 데 55.0마이크로초가 소요됐다. 케네디는 코루틴 생성과 대기에 측정 가능한 오버헤드가 있으므로, 실제로 동시성이 필요할 때만 비동기를 사용해야 한다고 조언했다.

예외 처리도 성능에 영향을 미친다. try-except 블록이 예외를 발생시키지 않으면 21.5나노초지만, 예외가 발생하면 139나노초로 6배 이상 느려진다. isinstance 타입 체크는 18.3나노초로 빠른 편이다.

개발자 커뮤니티 반응

이번 벤치마크는 파이썬 커뮤니티에서 큰 관심을 받고 있다. 개발자들은 구체적인 수치를 바탕으로 성능 최적화 의사결정을 내릴 수 있게 됐다고 평가한다. 특히 orjson 같은 대체 라이브러리의 성능 우위가 명확히 입증돼 실무 적용이 늘어날 것으로 전망된다.

케네디는 이번 벤치마크가 2003년 제프 딘과 피터 노르비그가 발표한 지연시간 수치 가이드에서 영감을 받았다고 밝혔다. 모든 벤치마크 코드는 깃허브에서 확인할 수 있으며, 개발자들이 직접 환경에서 재현하고 검증할 수 있다.

그는 파이썬의 절대적인 속도보다 상대적인 비교가 중요하다고 강조하며, 적절한 자료구조와 라이브러리 선택이 성능에 큰 영향을 미친다고 덧붙였다. 향후 파이썬 버전 업데이트에 따라 벤치마크도 지속적으로 갱신할 계획이라고 전했다.

한국정보기술신문 정보기술분과 김지원 기자 news@kitpa.org