패스잇

백엔드 개발

Python 면접 질문

GIL, 데코레이터, 제너레이터, 가비지 컬렉션, 동등성과 식별성 — Python 면접은 언어의 내부 동작을 얼마나 정확히 아는지를 봅니다. 자주 나오는 질문을 모범답안과 함께 단계별로 준비하세요.

총 21문제 · 기초 7 · 중급 7 · 심화 7 · 모범답안 포함

Python 면접 질문 — 기초

Q1 기초

Python의 리스트 컴프리헨션과 제너레이터 표현식의 차이점은?

힌트 · 메모리 사용량과 지연 평가(lazy evaluation)를 비교해보세요.

리스트 컴프리헨션과 제너레이터 표현식은 둘 다 반복 가능한 객체를 만드는 간결한 방법이지만, 중요한 차이점이 있습니다.

전체 모범답안 펼치기

리스트 컴프리헨션과 제너레이터 표현식은 둘 다 반복 가능한 객체를 만드는 간결한 방법이지만, 중요한 차이점이 있습니다.

리스트 컴프리헨션은 대괄호 []를 사용하며, 생성 즉시 모든 요소를 메모리에 저장합니다. 따라서 큰 데이터를 처리할 때는 메모리 사용량이 많아질 수 있습니다.

반면, 제너레이터 표현식은 괄호 ()를 사용하고, 필요할 때마다 요소를 생성하는 지연 평가(lazy evaluation) 방식을 사용합니다. 즉, 모든 요소를 미리 메모리에 저장하지 않고, next() 함수를 통해 요청될 때만 값을 생성하여 반환합니다. 따라서 메모리 효율성이 훨씬 좋습니다.

결론적으로, 작은 데이터셋에는 리스트 컴프리헨션이 빠를 수 있지만, 큰 데이터셋에는 제너레이터 표현식이 메모리 측면에서 더 효율적입니다. 제너레이터는 이터레이터를 반환한다는 점도 기억해야 합니다.

#메모리#생성 시점#이터레이터#lazy evaluation#대괄호 vs 괄호

이 질문 단독 페이지 →

Q2 기초

Python의 *args와 **kwargs의 차이점과 사용법을 설명해주세요.

힌트 · 가변 위치 인자와 가변 키워드 인자의 패킹/언패킹을 설명해보세요.

args와 kwargs는 Python에서 가변 인자를 처리하는 데 사용됩니다.

전체 모범답안 펼치기

*args**kwargs는 Python에서 가변 인자를 처리하는 데 사용됩니다.

*args는 임의의 개수의 위치 인자를 함수에 전달할 때 사용합니다. 함수 내에서 args는 튜플로 묶여 처리됩니다. 예를 들어, def my_func(*args): 와 같이 정의하면, my_func(1, 2, 3)을 호출했을 때 args(1, 2, 3)이 됩니다.

**kwargs는 임의의 개수의 키워드 인자를 함수에 전달할 때 사용합니다. 함수 내에서 kwargs는 딕셔너리로 묶여 처리됩니다. 예를 들어, def my_func(**kwargs): 와 같이 정의하면, my_func(a=1, b=2)를 호출했을 때 kwargs{'a': 1, 'b': 2}가 됩니다.

이 두 가지를 사용하면 함수의 인자 개수에 제한 없이 유연하게 함수를 정의할 수 있습니다.

#가변인자#*args#**kwargs#튜플#딕셔너리

이 질문 단독 페이지 →

Q3 기초

Python의 가상 환경이 필요한 이유와 사용법을 설명해주세요.

힌트 · 프로젝트별 의존성 격리와 버전 관리를 생각해보세요.

Python 가상 환경은 프로젝트별로 필요한 패키지들을 격리하여 관리하기 위해 필요합니다.

전체 모범답안 펼치기

Python 가상 환경은 프로젝트별로 필요한 패키지들을 격리하여 관리하기 위해 필요합니다.

만약 여러 프로젝트를 진행하는데, 각 프로젝트가 서로 다른 버전의 동일한 패키지를 필요로 한다면 충돌이 발생할 수 있습니다. 가상 환경을 사용하면 각 프로젝트는 독립적인 환경을 가지므로 이러한 충돌을 방지할 수 있습니다.

가상 환경을 만드는 방법은 venv 모듈을 사용하는 것이 일반적입니다. 예를 들어, python -m venv myenv 명령어를 통해 myenv라는 이름의 가상 환경을 생성할 수 있습니다. 이후 source myenv/bin/activate (Linux/macOS) 또는 myenv\Scripts\activate (Windows) 명령어를 사용하여 가상 환경을 활성화하면, 해당 환경에 필요한 패키지들을 pip install 명령어로 설치하여 프로젝트를 진행할 수 있습니다. 이렇게 하면 프로젝트별로 의존성을 깔끔하게 관리하고, 다른 환경에서도 동일한 환경을 재현하는 데 용이합니다.

#의존성 관리#격리#재현성#패키지 충돌#venv

이 질문 단독 페이지 →

Q4 기초

Python의 Type Hints의 장점과 사용법에 대해 설명해주세요.

힌트 · 정적 분석, IDE 지원, 가독성 향상을 생각해보세요.

Python Type Hints는 Python 3.5부터 도입된 기능으로, 변수, 함수 매개변수, 반환 값에 예상되는 타입을 명시적으로 지정할 수 있게 해줍니다.

전체 모범답안 펼치기

Python Type Hints는 Python 3.5부터 도입된 기능으로, 변수, 함수 매개변수, 반환 값에 예상되는 타입을 명시적으로 지정할 수 있게 해줍니다.

Type Hints의 가장 큰 장점은 코드의 가독성을 높여준다는 것입니다. 함수나 변수의 역할을 더 명확하게 이해할 수 있게 되죠. 또한, mypy와 같은 정적 분석 도구를 사용하여 런타임 전에 타입 에러를 미리 발견할 수 있어 디버깅 시간을 줄여줍니다. IDE에서도 Type Hints를 활용하여 자동 완성, 오류 검사 등의 기능을 제공하여 개발 생산성을 향상시킵니다. 결과적으로 코드 유지보수성도 높아지죠.

사용법은 간단합니다. 예를 들어, def greet(name: str) -> str: 와 같이 함수 정의 시 매개변수와 반환 값에 타입을 명시하면 됩니다.

#정적 타입#코드 가독성#디버깅#mypy#유지보수

이 질문 단독 페이지 →

Q5 기초

Python의 mutable과 immutable 객체의 차이점을 설명해주세요.

힌트 · 리스트 vs 튜플, 딕셔너리 vs frozenset을 비교해보세요.

Python에서 mutable 객체와 immutable 객체의 가장 큰 차이점은 객체가 생성된 후 값을 변경할 수 있는지 여부입니다.

전체 모범답안 펼치기

Python에서 mutable 객체와 immutable 객체의 가장 큰 차이점은 객체가 생성된 후 값을 변경할 수 있는지 여부입니다.

Mutable 객체는 값을 변경할 수 있습니다. 예를 들어 리스트(list)나 딕셔너리(dictionary)가 있습니다. 리스트에 요소를 추가하거나 딕셔너리의 값을 변경해도 객체의 메모리 주소는 바뀌지 않습니다.

반면, immutable 객체는 값을 변경할 수 없습니다. 튜플(tuple), 문자열(string), 숫자(int, float) 등이 있습니다. immutable 객체의 값을 변경하려고 하면, 기존 객체를 수정하는 것이 아니라 새로운 객체를 생성합니다. 따라서 메모리 주소가 변경됩니다.

이러한 차이점은 함수 인자로 객체를 전달할 때 중요한 영향을 미칩니다. mutable 객체를 함수 내에서 변경하면 원본 객체도 변경되지만, immutable 객체는 함수 내에서 변경해도 원본 객체는 변하지 않습니다.

#가변#불변#메모리 주소#객체#수정

이 질문 단독 페이지 →

Q6 기초

Python의 lambda 함수와 일반 함수의 차이점은 무엇인가요?

힌트 · 익명 함수, 단일 표현식, 사용 사례를 생각해보세요.

lambda 함수와 일반 함수(def로 정의된 함수)의 주요 차이점은 크게 세 가지 정도로 볼 수 있습니다.

전체 모범답안 펼치기

lambda 함수와 일반 함수(def로 정의된 함수)의 주요 차이점은 크게 세 가지 정도로 볼 수 있습니다.

첫째, lambda 함수는 익명 함수라는 점입니다. 즉, 이름이 따로 없고, 주로 함수가 필요한 곳에 간단하게 정의해서 바로 사용합니다. 반면, 일반 함수는 def 키워드를 사용하여 이름을 명시적으로 지정합니다.

둘째, lambda 함수는 단일 표현식으로만 구성될 수 있습니다. 따라서 복잡한 로직이나 여러 줄의 코드를 포함할 수 없습니다. 일반 함수는 여러 문장과 복잡한 로직을 포함할 수 있습니다.

셋째, 사용 목적이 다릅니다. lambda 함수는 주로 간단한 연산이나 함수를 인자로 전달할 때 유용합니다. 예를 들어, map이나 filter 함수와 함께 사용되는 경우가 많습니다. 일반 함수는 더 복잡하고 재사용 가능한 코드를 작성할 때 사용됩니다.

결론적으로, lambda 함수는 간단하고 일회성으로 사용되는 반면, 일반 함수는 더 복잡하고 재사용 가능한 로직을 구현하는 데 적합합니다.

#익명 함수#표현식#단일 표현식#함수 객체#def

이 질문 단독 페이지 →

Q7 기초

Python의 dataclass의 특징과 사용법에 대해 설명해주세요.

힌트 · 보일러플레이트 코드 감소와 자동 생성 메서드를 생각해보세요.

네, Python의 dataclass에 대해 설명드리겠습니다.

전체 모범답안 펼치기

네, Python의 dataclass에 대해 설명드리겠습니다.

dataclass는 Python 3.7부터 도입된 데코레이터입니다. 클래스를 만들 때 반복적으로 작성해야 하는 __init__, __repr__, __eq__ 같은 메서드들을 자동으로 생성해줘서 코드 양을 줄여줍니다.

사용법은 간단합니다. 클래스 선언 위에 @dataclass 데코레이터를 붙이고, 클래스 내부에 필드들을 정의하면 됩니다. 예를 들어, Point 클래스를 만들 때 xy 좌표를 필드로 정의하면, dataclass가 자동으로 __init__ 메서드를 만들어줘서 Point(x=1, y=2)처럼 객체를 생성할 수 있습니다.

dataclass는 기본적으로 mutable 객체를 생성하지만, frozen=True 옵션을 사용하면 immutable 객체를 만들 수도 있습니다. 또한, 비교 연산도 자동으로 지원해서 객체 간의 동등성을 쉽게 비교할 수 있습니다.

#데코레이터#자동 생성#불변 객체#비교 연산#__init__

이 질문 단독 페이지 →

읽기만으론 부족합니다 — 직접 말해보세요

패스잇 앱에서 Python 질문에 직접 답하면 AI가 1:1로 답변을 코칭합니다.

Python 면접 질문 — 중급

Q8 중급

Python의 GIL(Global Interpreter Lock)이란 무엇이며, 멀티스레딩에 어떤 영향을 주나요?

힌트 · CPU 바운드 vs I/O 바운드 작업에서의 차이를 생각해보세요.

Python의 GIL(Global Interpreter Lock)은 CPython 인터프리터에서 단일 Python 바이트코드 실행 스레드만 실행되도록 하는 메커니즘입니다. 즉, 여러 스레드가 동시에 Python 코드…

전체 모범답안 펼치기

Python의 GIL(Global Interpreter Lock)은 CPython 인터프리터에서 단일 Python 바이트코드 실행 스레드만 실행되도록 하는 메커니즘입니다. 즉, 여러 스레드가 동시에 Python 코드를 실행하는 것을 막습니다.

멀티스레딩 환경에서 GIL은 CPU 바운드 작업의 병렬성을 제한합니다. 여러 스레드를 사용하더라도 실제로 동시에 코어가 활용되지 않기 때문에, 싱글 스레드보다 오히려 성능이 떨어질 수도 있습니다. 컨텍스트 스위칭 오버헤드가 발생하기 때문입니다.

하지만 I/O 바운드 작업에서는 GIL의 영향이 적습니다. 스레드가 I/O 작업을 기다리는 동안 GIL이 해제되어 다른 스레드가 실행될 수 있기 때문입니다. 따라서 I/O 바운드 작업에서는 멀티스레딩이 유용할 수 있습니다.

GIL을 우회하기 위해 멀티프로세싱을 사용하거나, GIL이 없는 다른 Python 인터프리터(예: Jython, IronPython)를 사용하는 방법도 있습니다.

#GIL#CPython#멀티스레딩#병렬성#컨텍스트 스위칭

이 질문 단독 페이지 →

Q9 중급

Python의 데코레이터(Decorator)란 무엇이며, 사용 예시를 들어주세요.

힌트 · 함수를 감싸는 함수와 @wrapper 문법을 설명해보세요.

데코레이터는 파이썬에서 함수를 감싸서 기능을 추가하거나 변경할 때 사용하는 기능입니다. 일종의 함수 래핑(Wrapping)이라고 생각하시면 됩니다. @ 기호를 사용하여 함수 위에 데코레이터를 붙이는 방식으로 사용하며…

전체 모범답안 펼치기

데코레이터는 파이썬에서 함수를 감싸서 기능을 추가하거나 변경할 때 사용하는 기능입니다. 일종의 함수 래핑(Wrapping)이라고 생각하시면 됩니다. @ 기호를 사용하여 함수 위에 데코레이터를 붙이는 방식으로 사용하며, 이를 통해 코드의 재사용성을 높일 수 있습니다.

예를 들어, 함수의 실행 시간을 측정하는 데코레이터를 만들 수 있습니다.

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 실행 시간: {end_time - start_time:.4f}초")
        return result
    return wrapper

@timer
def my_function():
    time.sleep(1)

my_function()

@timer 데코레이터를 my_function 위에 붙임으로써, my_function의 실행 시간을 자동으로 측정하고 출력할 수 있습니다. 데코레이터를 사용하면 여러 함수에 동일한 기능을 쉽게 추가할 수 있어 코드 중복을 줄이고 유지보수를 용이하게 할 수 있습니다.

#함수#래핑(Wrapping)#합성(Composition)#@(at symbol)#재사용성

이 질문 단독 페이지 →

Q10 중급

Python의 @classmethod와 @staticmethod의 차이점은?

힌트 · cls 파라미터 유무와 상속 관계에서의 동작을 비교해보세요.

@classmethod와 @staticmethod는 클래스 내에서 정의되는 메서드인데, 호출 방식과 역할에 차이가 있습니다.

전체 모범답안 펼치기

@classmethod와 @staticmethod는 클래스 내에서 정의되는 메서드인데, 호출 방식과 역할에 차이가 있습니다.

@classmethod는 클래스 객체를 첫 번째 인자로 받는 메서드입니다. 관례적으로 cls라는 이름으로 받죠. 이를 통해 클래스 속성에 접근하거나, 팩토리 메서드처럼 클래스의 새로운 인스턴스를 생성하는 데 활용될 수 있습니다. 상속 관계에서 특히 유용하게 사용되는데, 자식 클래스에서 호출하면 자식 클래스 객체를 cls로 받기 때문에, 부모 클래스의 코드를 수정하지 않고도 자식 클래스에 맞게 동작을 변경할 수 있습니다.

반면 @staticmethod는 클래스 객체나 인스턴스 객체를 암묵적으로 전달받지 않는 메서드입니다. 일반 함수와 거의 동일하게 동작하며, 클래스 내에 포함되어 있다는 점만 다릅니다. 클래스와 관련된 유틸리티 함수를 정의하거나, 클래스의 상태를 변경하지 않고 특정 작업을 수행하는 데 적합합니다. 클래스 이름으로 직접 호출하거나 인스턴스를 통해 호출할 수 있지만, 클래스나 인스턴스의 상태에는 영향을 주지 않습니다.

#클래스 객체#인스턴스 객체#self#cls#상태 변경

이 질문 단독 페이지 →

Q11 중급

Python의 __init__과 __new__의 차이점은 무엇인가요?

힌트 · 인스턴스 생성 단계와 초기화 단계를 구분해보세요.

new와 init은 Python에서 객체 생성과 초기화에 관련된 특별한 메서드입니다.

전체 모범답안 펼치기

__new____init__은 Python에서 객체 생성과 초기화에 관련된 특별한 메서드입니다.

__new__는 클래스 메서드이고, 객체의 인스턴스를 실제로 생성하는 역할을 합니다. 즉, 메모리 공간을 할당하고 객체를 만드는 것이죠. __new__는 클래스를 인자로 받아 해당 클래스의 새로운 인스턴스를 반환해야 합니다. 만약 __new__None을 반환하면 __init__은 호출되지 않습니다.

반면 __init__은 인스턴스 메서드이고, 객체가 생성된 후에 그 객체를 초기화하는 역할을 합니다. 즉, 객체의 속성을 설정하는 등의 작업을 수행합니다. __init__은 생성된 인스턴스를 첫 번째 인자(self)로 받습니다.

따라서 __new__는 객체 생성의 '전' 단계, __init__은 객체 생성의 '후' 단계라고 생각하면 이해하기 쉽습니다. __new__를 오버라이딩하는 경우는 흔하지 않지만, 불변 객체를 만들거나 객체 생성 과정을 특별하게 제어해야 할 때 사용될 수 있습니다.

#객체 생성#인스턴스 초기화#__new__ 클래스 메서드#__init__ 인스턴스 메서드#반환 값

이 질문 단독 페이지 →

Q12 중급

Python의 컨텍스트 매니저와 with문의 동작 원리를 설명해주세요.

힌트 · __enter__와 __exit__ 메서드의 역할을 설명해보세요.

Python의 컨텍스트 매니저는 with 문과 함께 사용되어 특정 코드 블록의 실행 전후에 필요한 작업을 자동으로 처리해주는 역할을 합니다. 예를 들어 파일 열기/닫기, 네트워크 연결 설정/해제 같은 리소스 관리에…

전체 모범답안 펼치기

Python의 컨텍스트 매니저는 with 문과 함께 사용되어 특정 코드 블록의 실행 전후에 필요한 작업을 자동으로 처리해주는 역할을 합니다. 예를 들어 파일 열기/닫기, 네트워크 연결 설정/해제 같은 리소스 관리에 유용하죠.

with 문이 실행되면 컨텍스트 매니저 객체의 __enter__ 메서드가 호출됩니다. 이 메서드는 필요한 설정을 수행하고, with 문에 as 키워드가 있다면 값을 반환하여 변수에 할당합니다.

with 블록의 실행이 끝나면 (정상 종료든 예외 발생이든) 컨텍스트 매니저 객체의 __exit__ 메서드가 호출됩니다. __exit__ 메서드는 리소스를 정리하고, 예외가 발생했을 경우 이를 처리할 수 있습니다. __exit__ 메서드의 반환값에 따라 예외를 무시하거나 다시 발생시킬 수도 있습니다.

이러한 메커니즘을 통해 컨텍스트 매니저는 코드의 가독성을 높이고, 리소스 누수를 방지하며, 예외 처리 로직을 간결하게 만들어줍니다.

#__enter__#__exit__#리소스 관리#예외 처리#컨텍스트

이 질문 단독 페이지 →

Q13 중급

Python의 asyncio와 비동기 프로그래밍에 대해 설명해주세요.

힌트 · 코루틴, event loop, await 키워드를 설명해보세요.

asyncio는 Python에서 비동기 프로그래밍을 쉽게 구현할 수 있도록 도와주는 라이브러리입니다. 특히 I/O 바운드 작업(네트워크 요청, 파일 읽기/쓰기 등)을 효율적으로 처리하는 데 유용합니다.

전체 모범답안 펼치기

asyncio는 Python에서 비동기 프로그래밍을 쉽게 구현할 수 있도록 도와주는 라이브러리입니다. 특히 I/O 바운드 작업(네트워크 요청, 파일 읽기/쓰기 등)을 효율적으로 처리하는 데 유용합니다.

asyncio의 핵심은 이벤트 루프, 코루틴, 그리고 async/await 키워드입니다. 코루틴은 실행을 일시 중단하고 재개할 수 있는 함수로, async def로 정의됩니다. await 키워드는 코루틴 내에서 다른 코루틴의 완료를 기다리는 동안 실행을 일시 중단하는 데 사용됩니다.

이벤트 루프는 코루틴의 실행을 관리하고, I/O 작업이 완료되면 해당 코루틴을 다시 실행합니다. 이를 통해 여러 작업을 동시에 처리하면서도 단일 스레드에서 실행되므로, 멀티 스레딩의 복잡성을 피할 수 있습니다.

예를 들어, 여러 웹 페이지를 동시에 다운로드하는 경우, 각 다운로드를 코루틴으로 만들고 await를 사용하여 각 요청의 완료를 기다리면, 전체 다운로드 시간을 크게 줄일 수 있습니다.

#async/await#이벤트 루프#코루틴#I/O 바운드#동시성

이 질문 단독 페이지 →

Q14 중급

Python의 메모리 관리와 가비지 컬렉션 동작 방식에 대해 설명해주세요.

힌트 · 레퍼런스 카운팅과 순환 참조 해결을 생각해보세요.

Python은 자동 메모리 관리를 제공하며, 크게 두 가지 메커니즘을 통해 이루어집니다.

전체 모범답안 펼치기

Python은 자동 메모리 관리를 제공하며, 크게 두 가지 메커니즘을 통해 이루어집니다.

첫째는 참조 카운팅입니다. 모든 객체는 참조 횟수를 가지고 있으며, 이 횟수가 0이 되면 즉시 메모리에서 해제됩니다. 이는 간단하고 효율적이지만, 순환 참조 문제를 해결하지 못합니다.

둘째는 세대별 가비지 컬렉션입니다. 이는 순환 참조를 탐지하고 해결하기 위해 주기적으로 실행됩니다. 객체를 세대별로 분류하여, 오래된 객체일수록 덜 자주 검사합니다. gc 모듈을 통해 가비지 컬렉션 동작을 제어할 수 있습니다. 예를 들어, gc.collect()를 호출하여 명시적으로 가비지 컬렉션을 수행할 수 있습니다.

Python은 또한 작은 객체들을 효율적으로 관리하기 위해 메모리 풀을 사용합니다. 이를 통해 메모리 할당 및 해제의 오버헤드를 줄입니다.

#참조 카운팅#세대별 가비지 컬렉션#순환 참조#gc 모듈#메모리 풀

이 질문 단독 페이지 →

Python 면접 질문 — 심화

Q15 심화

Python의 딕셔너리 내부 구현과 해시 충돌 처리 방식을 설명해주세요.

힌트 · 해시 테이블과 오픈 어드레싱 방식을 생각해보세요.

Python 딕셔너리는 해시 테이블을 기반으로 구현되어 있습니다. 해시 테이블은 키를 해시 함수를 통해 특정 인덱스로 변환하여 값을 저장하는 자료구조입니다.

전체 모범답안 펼치기

Python 딕셔너리는 해시 테이블을 기반으로 구현되어 있습니다. 해시 테이블은 키를 해시 함수를 통해 특정 인덱스로 변환하여 값을 저장하는 자료구조입니다.

딕셔너리에 키-값 쌍을 저장할 때, 먼저 키의 해시값을 계산합니다. 이 해시값을 인덱스로 사용하여 해당 위치에 값을 저장합니다.

문제는 서로 다른 키가 동일한 해시값을 가질 수 있다는 점입니다. 이를 해시 충돌이라고 합니다. Python은 충돌 해결을 위해 개방 주소법(Open Addressing) 중 하나인 탐사(Probing) 방식을 사용합니다. 충돌이 발생하면, 미리 정의된 규칙에 따라 다음 빈 슬롯을 찾아 값을 저장합니다. 일반적인 탐사 방식으로는 선형 탐사, 이차 탐사 등이 있습니다.

Python 딕셔너리는 성능을 위해 테이블의 크기를 동적으로 조절하며, 키의 개수가 일정 비율 이상으로 증가하면 테이블 크기를 확장하여 탐색 효율을 유지합니다.

#해시 테이블#해시 함수#충돌 해결#개방 주소법#체이닝

이 질문 단독 페이지 →

Q16 심화

Python의 metaclass란 무엇이며, 어떤 상황에서 사용하나요?

힌트 · 클래스를 생성하는 클래스와 Django ORM의 예시를 생각해보세요.

면접관님, Python의 metaclass는 "클래스를 만드는 클래스"라고 생각하시면 됩니다. 일반적인 클래스가 객체를 생성하는 것처럼, metaclass는 클래스 자체를 생성하는 역할을 합니다.

전체 모범답안 펼치기

면접관님, Python의 metaclass는 "클래스를 만드는 클래스"라고 생각하시면 됩니다. 일반적인 클래스가 객체를 생성하는 것처럼, metaclass는 클래스 자체를 생성하는 역할을 합니다.

클래스가 정의될 때, Python은 metaclass를 사용하여 해당 클래스를 생성합니다. 기본적으로 type이라는 metaclass가 사용되죠. metaclass를 사용하면 클래스가 생성되는 과정을 가로채서 클래스의 속성이나 메서드를 동적으로 변경하거나, 클래스 생성 로직 자체를 커스터마이징할 수 있습니다.

주로 클래스 정의를 제어하거나, 특정 패턴을 강제해야 할 때 사용합니다. 예를 들어, Django ORM에서 모델 클래스를 정의할 때, metaclass를 사용하여 데이터베이스 필드를 자동으로 매핑하거나, 싱글톤 패턴을 구현할 때 활용할 수 있습니다.

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class MyClass(metaclass=Singleton):
    pass

위 예시는 싱글톤 패턴을 metaclass로 구현한 간단한 예시입니다.

#클래스 생성#클래스의 클래스#클래스 커스터마이징#ORM#싱글톤

이 질문 단독 페이지 →

Q17 심화

Python의 __slots__의 용도와 사용 시 이점은 무엇인가요?

힌트 · __dict__ 생략으로 인한 메모리 절약을 생각해보세요.

slots는 Python 클래스에서 인스턴스 변수를 저장하는 방식을 최적화하는 데 사용됩니다. 기본적으로 Python은 각 인스턴스의 속성을 dict라는 딕셔너리에 저장합니다. 하지만 slots를 사용하면, 딕셔너리…

전체 모범답안 펼치기

__slots__는 Python 클래스에서 인스턴스 변수를 저장하는 방식을 최적화하는 데 사용됩니다. 기본적으로 Python은 각 인스턴스의 속성을 __dict__라는 딕셔너리에 저장합니다. 하지만 __slots__를 사용하면, 딕셔너리 대신 고정된 크기의 배열을 사용하여 속성을 저장합니다.

이렇게 하면 다음과 같은 이점이 있습니다.

  • 메모리 사용량 감소: 특히 많은 수의 인스턴스를 생성할 때, 딕셔너리를 사용하는 것보다 메모리 효율성이 훨씬 높아집니다.
  • 속도 향상: 속성에 접근하는 속도가 약간 빨라질 수 있습니다.

다만, __slots__를 사용하면 몇 가지 제약 사항이 있습니다.

  • 새로운 속성을 동적으로 추가할 수 없습니다.
  • __weakref__를 사용할 수 없습니다.

따라서, 메모리 사용량이 중요한 상황이고, 클래스의 속성이 미리 정의되어 변경될 필요가 없을 때 __slots__를 사용하는 것이 좋습니다.

#메모리#어트리뷰트#딕셔너리#성능#클래스

이 질문 단독 페이지 →

Q18 심화

Python의 descriptor란 무엇이며, 어떻게 동작하나요?

힌트 · __get__, __set__, __delete__ 메서드를 설명해보세요.

Python의 descriptor는 객체 속성(attribute) 접근 방식을 제어하는 메커니즘입니다. 간단히 말해, 속성에 접근할 때 특별한 동작을 수행하도록 해주는 것이죠.

전체 모범답안 펼치기

Python의 descriptor는 객체 속성(attribute) 접근 방식을 제어하는 메커니즘입니다. 간단히 말해, 속성에 접근할 때 특별한 동작을 수행하도록 해주는 것이죠.

descriptor를 구현하려면 클래스에 __get__, __set__, __delete__ 중 하나 이상의 메서드를 정의해야 합니다.

  • __get__(self, instance, owner): 속성 값을 가져올 때 호출됩니다.
  • __set__(self, instance, value): 속성 값을 설정할 때 호출됩니다.
  • __delete__(self, instance): 속성을 삭제할 때 호출됩니다.

이 메서드들을 통해 속성 접근, 설정, 삭제 시점을 가로채서 원하는 로직을 실행할 수 있습니다. 예를 들어, 데이터 유효성 검사나 읽기 전용 속성 구현 등에 활용할 수 있습니다. descriptor를 사용하면 속성 접근을 캡슐화하고 더 유연하고 제어 가능한 코드를 작성할 수 있습니다.

#attribute 접근#get#set#delete#데이터 캡슐화

이 질문 단독 페이지 →

Q19 심화

Python의 GIL(Global Interpreter Lock)이 멀티스레딩 기반 동시성 프로그래밍에 미치는 영향과 이를 극복하기 위한 대표적인 전략들을 설명하고, 각 전략의 장단점을 비교하여 설명해주세요.

힌트 · GIL의 역할, CPU 바운드 vs I/O 바운드 작업, `multiprocessing` 모듈, 비동기 I/O (`asyncio`)의 적용 시나리오와 한계를 고려하여 설명하세요.

Python의 GIL은 한 번에 하나의 스레드만 파이썬 바이트코드를 실행하도록 제한하여, CPU 바운드 작업에서 멀티스레딩의 병렬성을 저해하는 주요 원인입니다. 컨텍스트 스위칭 오버헤드만 증가시켜 오히려 성능 저하를…

전체 모범답안 펼치기

Python의 GIL은 한 번에 하나의 스레드만 파이썬 바이트코드를 실행하도록 제한하여, CPU 바운드 작업에서 멀티스레딩의 병렬성을 저해하는 주요 원인입니다. 컨텍스트 스위칭 오버헤드만 증가시켜 오히려 성능 저하를 야기할 수 있죠.

이러한 GIL의 영향을 극복하기 위한 대표적인 전략으로는 multiprocessing 모듈을 사용하는 멀티프로세싱과 비동기 프로그래밍 (asyncio)이 있습니다.

multiprocessing은 각 프로세스가 독립적인 파이썬 인터프리터를 가지므로 GIL의 제약을 받지 않아 CPU 바운드 작업에 효과적입니다. 하지만 프로세스 간 통신 오버헤드가 크고 메모리 사용량이 많다는 단점이 있습니다.

반면 asyncio는 단일 스레드 내에서 이벤트 루프를 통해 비동기적으로 I/O 작업을 처리합니다. I/O 바운드 작업에서는 스레드 전환 없이 효율적으로 여러 작업을 처리할 수 있지만, CPU 바운드 작업에는 GIL의 영향을 그대로 받습니다.

따라서 작업의 특성에 따라 적절한 전략을 선택하는 것이 중요합니다.

#GIL#컨텍스트 스위칭#병목 현상#멀티프로세싱#비동기 프로그래밍

이 질문 단독 페이지 →

Q20 심화

Python에서 메타클래스(Metaclass)는 언제, 어떤 목적으로 사용되며, 이를 활용한 실제 설계 패턴의 예시를 들어 설명해주세요. `type()` 함수와의 관계도 함께 설명해주세요.

힌트 · 클래스의 클래스로서 런타임에 클래스 생성/수정, ORM 매핑, 플러그인 시스템 등 특정 규칙을 강제하는 용도로 활용될 수 있습니다.

메타클래스는 "클래스의 클래스"라고 생각하시면 됩니다. 즉, 클래스를 만드는 역할을 하는 클래스죠. 파이썬에서 클래스는 type()이라는 메타클래스의 인스턴스입니다.

전체 모범답안 펼치기

메타클래스는 "클래스의 클래스"라고 생각하시면 됩니다. 즉, 클래스를 만드는 역할을 하는 클래스죠. 파이썬에서 클래스는 type()이라는 메타클래스의 인스턴스입니다.

메타클래스는 클래스가 생성될 때 그 생성 과정을 제어하거나, 클래스의 속성을 동적으로 변경하고 싶을 때 사용합니다. 예를 들어, 모든 클래스가 특정 속성을 반드시 가지도록 강제하거나, 싱글톤 패턴을 구현하거나, ORM에서 데이터베이스 테이블과 클래스를 매핑하는 등의 작업을 할 수 있습니다.

싱글톤 패턴을 예로 들면, 메타클래스를 사용하여 클래스의 인스턴스가 단 하나만 생성되도록 제어할 수 있습니다. type() 함수는 클래스의 타입을 반환하는 동시에, 동적으로 클래스를 생성하는 데에도 사용될 수 있습니다. 메타클래스를 사용하면 클래스 생성 시점에 원하는 로직을 추가하여 클래스를 더욱 유연하고 강력하게 만들 수 있습니다.

#클래스 생성 제어#클래스 커스터마이징#type#싱글톤 패턴#ORM

이 질문 단독 페이지 →

Q21 심화

Python의 디스크립터(Descriptor) 프로토콜은 무엇이며, `__get__`, `__set__`, `__delete__` 메서드가 어떻게 동작하는지 설명해주세요. 또한, 실제 코드에서 디스크립터를 활용하여 속성 접근을 제어하는 실용적인 예시를 제시해주세요.

힌트 · `property`의 내부 구현 원리와 관련지어 설명하고, 속성 유효성 검사, 캐싱, 지연 로딩 등 특정 로직을 속성 접근에 연결하는 방법을 예시로 드세요.

디스크립터 프로토콜은 객체의 속성 접근(get, set, delete) 동작을 제어하는 메커니즘입니다. get, set, delete 메서드를 가진 클래스를 디스크립터라고 부르며, 이 메서드들을 통해 속성 접근 시…

전체 모범답안 펼치기

디스크립터 프로토콜은 객체의 속성 접근(get, set, delete) 동작을 제어하는 메커니즘입니다. __get__, __set__, __delete__ 메서드를 가진 클래스를 디스크립터라고 부르며, 이 메서드들을 통해 속성 접근 시 특별한 로직을 수행할 수 있습니다.

__get__은 속성 값을 가져올 때 호출됩니다. __set__은 속성 값을 설정할 때, __delete__는 속성을 삭제할 때 호출됩니다.

예를 들어, 속성 값의 유효성을 검사하는 디스크립터를 만들 수 있습니다.

class ValidatedNumber:
    def __set_name__(self, owner, name):
        self.private_name = '_' + name

    def __set__(self, instance, value):
        if not isinstance(value, (int, float)):
            raise ValueError("숫자만 할당 가능합니다.")
        instance.__dict__[self.private_name] = value

    def __get__(self, instance, owner):
        return instance.__dict__.get(self.private_name)

class MyClass:
    number = ValidatedNumber()

이 예시에서 number 속성에 숫자가 아닌 값을 할당하려고 하면 ValueError가 발생합니다. property도 내부적으로 디스크립터 프로토콜을 사용하여 구현됩니다. 디스크립터를 활용하면 속성 접근에 대한 세밀한 제어가 가능해져 유효성 검사, 캐싱, 지연 로딩 등 다양한 기능을 구현할 수 있습니다.

#디스크립터 프로토콜#__get__#__set__#__delete__#속성 접근 제어

이 질문 단독 페이지 →

함께 보면 좋은 백엔드 개발 면접 질문

← 전체 면접 질문 카테고리 보기

보유한 Python 질문은 이게 전부가 아닙니다

패스잇 앱에는 직무별 면접 질문 수천 개와 모범답안이 담겨 있습니다. AI 모의면접으로 직접 답하고, 약점을 분석받아 보세요.