Python 면접 질문
Python 인터뷰는 핵심 언어 기능, 데이터 구조, 알고리즘, 객체 지향 프로그래밍에 대한 이해도를 테스트합니다. 개념적인 질문으로 깊이를 평가하고, 실전 코딩 문제로 실용적인 능력을 측정합니다. 주니어든 시니어든 이 주제를 마스터하는 것이 성공의 열쇠입니다.
Python 면접에서 다루는 내용
핵심 문법 및 데이터 구조
리스트, 딕셔너리, 세트, 튜플 및 문자열 조작과 같은 Python 내장 타입에 대한 질문과 시간 복잡도를 다룹니다.
객체 지향 프로그래밍 (OOP)
클래스, 상속, 다형성, __init__, __str__, 프로퍼티 데코레이터와 같은 특수 메서드를 다룹니다.
함수형 프로그래밍 및 컴프리헨션
람다, map, filter, reduce, 리스트/딕셔너리 컴프리헨션, 제너레이터 표현식을 포함합니다.
동시성 및 성능
GIL, 스레딩 대 멀티프로세싱, async/await, 프로파일링 등의 주제.
샘플 Python 면접 질문
- Python의 주요 특징은 무엇인가요?좋은 답변이 다루는 것
- 인터프리터 언어
- 동적 타이핑
- 객체 지향 및 함수형 지원
- 풍부한 표준 라이브러리
- 플랫폼 독립적
샘플 답변 보기
Python은 인터프리터 언어로, 컴파일 없이 바로 실행할 수 있어 개발 속도가 빠릅니다. 동적 타이핑을 지원하므로 변수 선언 시 타입을 명시하지 않아도 되며, 런타임에 타입이 결정됩니다. 객체 지향 프로그래밍을 완전히 지원하며, 함수형 프로그래밍 요소도 포함하고 있습니다. 또한 '배터리 포함' 철학에 따라 방대한 표준 라이브러리를 제공하여 다양한 작업을 쉽게 처리할 수 있습니다. 플랫폼 독립적이어서 한 번 작성한 코드가 여러 운영체제에서 실행될 수 있습니다. 다만 속도가 상대적으로 느리다는 단점이 있으며, GIL로 인한 멀티스레딩 제약이 있습니다.
- 리스트와 튜플의 차이점을 설명하세요. 각각 언제 사용하나요?좋은 답변이 다루는 것
- 가변성
- 메모리 사용
- 속도
- 사용 목적
샘플 답변 보기
리스트는 가변(mutable) 객체로, 생성 후에도 요소를 추가, 삭제, 변경할 수 있습니다. 반면 튜플은 불변(immutable) 객체로, 한 번 생성되면 내용을 바꿀 수 없습니다. 이로 인해 튜플은 리스트보다 메모리를 적게 사용하고, 해시 가능하므로 딕셔너리의 키로 사용할 수 있습니다. 또한 튜플은 리스트보다 약간 더 빠른 접근 속도를 제공합니다. 리스트는 데이터의 크기가 변하거나 자주 수정이 필요한 경우에 사용하고, 튜플은 변경되지 않는 데이터(예: 좌표, 상수)나 딕셔너리의 키로 사용할 때 적합합니다. 주의할 점은 튜플 내에 가변 객체가 포함될 경우 해당 객체의 내용은 변경될 수 있다는 것입니다.
- Python은 메모리를 어떻게 관리하나요? 가비지 컬렉션과 참조 카운팅에 대해 설명하세요.좋은 답변이 다루는 것
- 참조 카운팅
- 가비지 컬렉션
- 순환 참조 처리
- 메모리 효율성
샘플 답변 보기
Python은 메모리 관리를 위해 주로 참조 카운팅(reference counting)과 가비지 컬렉션(garbage collection)을 사용합니다. 참조 카운팅은 각 객체마다 참조 횟수를 추적하여, 참조 횟수가 0이 되면 즉시 메모리를 해제합니다. 이는 빠르고 예측 가능하지만, 순환 참조가 발생하면 참조 횟수가 0이 되지 않아 메모리 누수가 생길 수 있습니다. 이를 해결하기 위해 Python은 별도의 가비지 컬렉터(gc 모듈)를 두어 주기적으로 실행되며, 순환 참조를 탐지하고 해제합니다. 가비지 컬렉션은 generational approach를 사용하여 객체의 생존 기간에 따라 세대를 나누고, 오래된 세대는 덜 자주 검사합니다. 개발자는 gc 모듈을 통해 가비지 컬렉션을 수동으로 제어할 수도 있습니다. 주의할 점은 참조 카운팅과 가비지 컬렉션이 동시에 작동하며, 가비지 컬렉션 중에는 애플리케이션이 일시 중단될 수 있다는 것입니다.
- 정렬을 사용하지 않고 리스트에서 두 번째로 큰 숫자를 찾는 함수를 작성하세요.좋은 답변이 다루는 것
- 두 변수로 최댓값과 두 번째로 큰 값 추적
- O(n) 시간 복잡도
- 중복 값 처리
- 경계 조건
샘플 답변 보기
정렬을 사용하지 않고 리스트에서 두 번째로 큰 숫자를 찾으려면, 리스트를 한 번 순회하면서 첫 번째로 큰 값과 두 번째로 큰 값을 추적합니다. 초기화 시에는 매우 작은 값(예: 음의 무한대) 또는 None을 사용할 수 있으나, 실제 구현에서는 리스트의 첫 번째 요소로 초기화하는 것이 일반적입니다. 중복 값이 있을 경우 두 번째로 큰 값은 첫 번째와 다른 값이어야 하므로 조건문에서 이를 처리해야 합니다. 시간 복잡도는 O(n)이며 공간 복잡도는 O(1)입니다. 주의할 점은 리스트의 길이가 2보다 작으면 적절한 예외 처리가 필요하다는 것입니다. 아래 코드는 이러한 접근 방식을 구현한 예제입니다.
참고 코드python def second_largest(nums): if len(nums) < 2: raise ValueError("리스트는 최소 2개의 요소가 필요합니다") # 첫 번째와 두 번째로 큰 값을 초기화 first = second = float('-inf') for num in nums: if num > first: second = first first = num elif num > second and num != first: second = num if second == float('-inf'): raise ValueError("두 번째로 큰 값이 존재하지 않습니다 (모든 요소가 동일한 경우)") return second # 시간 복잡도: O(n), 공간 복잡도: O(1) - 함수의 실행 시간을 측정하는 데코레이터를 구현하세요.좋은 답변이 다루는 것
- 데코레이터 개념
- functools.wraps 사용
- 실행 시간 측정
- 예외 처리
샘플 답변 보기
함수의 실행 시간을 측정하는 데코레이터는 함수를 감싸서 시작 시간과 종료 시간을 기록하고, 그 차이를 출력하거나 반환합니다. 데코레이터는 일급 객체인 함수를 인자로 받아 새로운 함수를 반환합니다. functools.wraps를 사용하면 데코레이터가 원본 함수의 메타데이터(이름, 독스트링 등)를 유지할 수 있습니다. 또한 예외가 발생하더라도 시간 측정이 정상적으로 이루어질 수 있도록 try-finally 블록을 사용하는 것이 좋습니다. 이 데코레이터는 디버깅이나 성능 분석에 유용하지만, 프로덕션 환경에서는 오버헤드가 발생할 수 있으므로 주의해야 합니다.
참고 코드python import time from functools import wraps def timer(func): @wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() try: return func(*args, **kwargs) finally: end = time.perf_counter() print(f"{func.__name__} 실행 시간: {end - start:.6f}초") return wrapper # 사용 예시 @timer def example_function(): sum(range(1000000)) example_function() # 출력: example_function 실행 시간: 0.023456초 - GIL이란 무엇인가요? 멀티스레딩에 어떤 영향을 미치나요?좋은 답변이 다루는 것
- Global Interpreter Lock
- CPython의 구현
- 멀티스레딩 성능 제약
- I/O 바운드 vs CPU 바운드
샘플 답변 보기
GIL(Global Interpreter Lock)은 CPython 인터프리터에서 한 번에 하나의 스레드만 Python 바이트코드를 실행하도록 하는 뮤텍스입니다. 이는 메모리 관리의 단순성과 스레드 안전성을 제공하지만, 멀티코어 시스템에서 CPU 바운드 작업의 병렬 실행을 방해합니다. 즉, 여러 스레드를 사용하더라도 실제로는 한 번에 하나의 스레드만 실행되므로 CPU 집약적인 작업에서는 성능 향상이 거의 없습니다. 반면 I/O 바운드 작업(파일 읽기/쓰기, 네트워크 요청)에서는 GIL이 해제되는 동안 다른 스레드가 실행될 수 있어 효과적입니다. GIL 문제를 해결하기 위해 멀티프로세싱(multiprocessing) 모듈을 사용하거나, C 확장에서 GIL을 해제하는 방식이 있습니다. Python 3.2 이후 GIL의 세분화가 개선되었으나 근본적인 문제는 남아 있습니다.
- n까지의 피보나치 수를 생성하는 제너레이터를 작성하세요.좋은 답변이 다루는 것
- 제너레이터 개념
- yield 키워드
- 메모리 효율성
- 무한 시퀀스 처리
샘플 답변 보기
피보나치 수를 생성하는 제너레이터는 yield를 사용하여 각 항목을 하나씩 반환하며, 호출될 때마다 다음 값을 계산합니다. 이는 전체 수열을 메모리에 저장하지 않고 필요할 때마다 생성하므로, 특히 큰 n에 대해 메모리 효율적입니다. 제너레이터는 for 루프나 next() 함수로 소비할 수 있습니다. 아래 코드는 upto 매개변수를 받아 n까지의 피보나치 수를 생성합니다. 주의할 점은 제너레이터가 무한히 값을 생성할 수 있으므로, 적절한 종료 조건이 필요하다는 것입니다.
참고 코드python def fibonacci(upto): a, b = 0, 1 while a <= upto: yield a a, b = b, a + b # 사용 예시: 100까지의 피보나치 수 출력 for num in fibonacci(100): print(num, end=' ') # 출력: 0 1 1 2 3 5 8 13 21 34 55 89 # 시간 복잡도: O(n), 공간 복잡도: O(1) - Python의 MRO(메서드 해석 순서)와 super()의 작동 방식을 설명하세요.좋은 답변이 다루는 것
- C3 선형화
- 다이아몬드 상속
- super()의 협력적 메서드 호출
- mro() 메서드
샘플 답변 보기
MRO(Method Resolution Order)는 다중 상속 시 메서드를 탐색하는 순서로, Python은 C3 선형화 알고리즘을 사용합니다. 이는 모든 부모 클래스의 순서를 유지하면서 모순 없이 단일 체인을 만듭니다. super()는 MRO를 기반으로 다음 클래스의 메서드를 호출하는 데 사용되며, 단순히 부모 클래스의 메서드를 호출하는 것이 아니라 협력적 다중 상속을 가능하게 합니다. super()를 올바르게 사용하려면 모든 클래스가 super()를 통해 다음 메서드를 호출하도록 설계되어야 합니다. MRO는 클래스의 __mro__ 속성이나 mro() 메서드로 확인할 수 있습니다. 주의할 점은 super()가 항상 '부모'를 가리키는 것이 아니라 MRO의 다음 클래스를 가리킨다는 점이며, 다이아몬드 상속에서도 중복 호출을 방지합니다.
준비 방법
- 내장 함수와 표준 라이브러리(예: itertools, collections)를 마스터하세요.
- LeetCode나 HackerRank와 같은 플랫폼에서 Python에 특화된 해결책에 초점을 맞춰 코딩 문제를 연습하세요.
- Python의 메모리 모델과 객체 전달 방식(참조 대 값)을 이해하세요.
- 디자인 패턴과 파이썬다운 관용구(예: 컨텍스트 매니저, 데코레이터)를 설명할 수 있어야 합니다.
- 중요한 데이터 구조: 딕셔너리, 세트 및 그 시간 복잡도를 복습하세요.
자주 묻는 질문
`==`와 `is`의 차이점은 무엇인가요?
`==`는 값의 동등성을 확인하고, `is`는 동일성(같은 객체)을 확인합니다. None과 같은 싱글톤에는 `is`를 사용하세요.
Python에서 예외를 어떻게 처리하나요?
try/except 블록을 사용하고, 선택적으로 else와 finally로 정리합니다. 베어 except는 피하세요.
Python의 네임스페이스와 스코프 규칙은 무엇인가요?
LEGB 규칙: 지역(Local), 둘러싼(Enclosing), 전역(Global), 내장(Built-in) 순서로 변수를 찾습니다.
제너레이터란 무엇이며 리스트와 어떻게 다른가요?
제너레이터는 yield를 사용하여 지연(lazily) 항목을 생성하며, 모든 값을 메모리에 저장하지 않아 대용량 데이터에 적합합니다.
Python 코드의 성능을 어떻게 최적화하나요?
내장 함수(예: map, filter), 리스트 컴프리헨션을 사용하고, 전역 조회를 피하며, 프로파일링 도구를 사용하고, C 확장을 고려하세요.
즉각적인 AI 피드백으로 Python 질문 연습하기
이력서를 업로드하고 맞춤형 모의 면접을 받아 무엇을 개선해야 할지 정확히 확인하세요 — 무료로 시작하세요.