본문으로 건너뛰기
Previous
Next
C++ 개발자 기술 면접 | 자주 나오는 질문과 답변 스크립트(30초·90초)·꼬리 질문 대비

C++ 개발자 기술 면접 | 자주 나오는 질문과 답변 스크립트(30초·90초)·꼬리 질문 대비

C++ 개발자 기술 면접 | 자주 나오는 질문과 답변 스크립트(30초·90초)·꼬리 질문 대비

이 글의 핵심

면접은 “아는 것”보다 “구조화해서 말하는 것”이 중요합니다. 이 글은 C++ 기술 면접에서 자주 나오는 주제별로 30초 요약·90초 확장 스크립트와 꼬리 질문 대비를 묶었고, 질문 목록만 길게 나열한 기존 글과 겹치지 않게 답변 흐름에 초점을 둡니다.

들어가며: 같은 답변도 “순서”가 다르면 점수가 갈린다

C++ 기술 면접에서 자주 지는 패턴은 지식 부족이 아니라 말하는 순서입니다. 정의를 길게 늘어놓다 시간이 지나면, 면접관은 “이 사람이 핵심을 짚는 사람인가?”를 확인하지 못한 채 끝나 버립니다.

이 글은 기술 면접 질문 30선·자주 틀리는 질문 50선처럼 목차형 정리는 다른 글에 맡기고, 여기서는 답변 골격말로 바로 쓸 수 있는 스크립트를 드립니다. 면접 전에 소리 내어 읽어 보고, 본인 경험 한 문장만 끼워 넣으면 그대로 현장에서 쓸 수 있습니다.

이 글에서 다루는 것:

  • 답변 프레임: 결론 → 메커니즘 → 실무 선택 → 한계/트레이드오프
  • 고빈도 주제 12개: 각각 30초 스크립트90초 스크립트, 꼬리 질문 한 줄
  • 코드 리뷰형 질문에 쓰는 체크리스트 한 블록

아래 예제는 복사해 로컬에서 돌려 보며 “무엇을 설명할지”만 맞춰 두면, 면접에서 의사 코드로도 이어 말하기 쉽습니다.

// g++ -std=c++17 -Wall -Wextra -pedantic -O2 demo.cpp && ./demo
#include <iostream>
#include <memory>
#include <vector>

int main() {
    auto p = std::make_unique<int>(42);
    std::vector<int> v = {1, 2, 3};
    v.shrink_to_fit();  // 용량만 줄이는 힌트 — 면접에서 "보장?" 꼬리 질문 나오기 좋음
    std::cout << *p << ' ' << v.size() << '\n';
    return 0;
}

1. 답변 프레임: 네 블록만 기억하면 된다

면접관이 듣고 싶은 정보는 대부분 아래 네 덩어리 안에 있습니다.

  1. 결론(10초): “한 문장으로 무엇인가 / 언제 쓰는가”
  2. 메커니즘(30초): 컴파일러·런타임·메모리 모델 중 관련된 층만
  3. 실무(20초): 팀 코드에서의 선택 기준, 본인이 겪은 증상
  4. 한계(10초): 비용, UB, ABI, 예외 상황 중 하나만 짚고 마무리

모르는 질문이면 1번을 “확실히 아는 범위에서만” 짧게 말하고, 2번을 추측 대신 확인 방법(cppreference, 컴파일러 경고, Sanitizer, 최소 재현)으로 바꿉니다.


2. 주제별 스크립트

각 항목은 30초는 거의 그대로 외워도 되고, 90초는 숫자·경험만 바꿔 넣으면 됩니다. 꼬리는 면접관이 이어서 묻기 좋은 방향입니다.

2.1 RAII와 스마트 포인터(소유권)

30초: “RAII는 생성자에서 자원을 잡고 소멸자에서 푸는 패턴이라서, 스코프를 벗어나면 해제 시점이 보장됩니다. C++에서는 기본이 unique_ptr로 단일 소유를 표현하고, 정말로 공유가 필요할 때만 shared_ptr을 씁니다.”

90초: “수동 new/delete는 예외 경로에서 누락되기 쉬워서 RAII로 감쌉니다. unique_ptr은 복사 없이 이동만 되니 소유권이 명확하고, shared_ptr은 참조 카운트 비용과 순환 참조 이슈가 있어서 기본값으로 두지 않습니다. weak_ptr은 캐시나 옵저버처럼 소유하지 않고 관찰만 할 때 씁니다.”

꼬리: “make_shared가 왜 shared_ptr 생성에 유리한가요?” → “제어 블록과 객체를 한 번에 할당해 할당 횟수와 캐시 친화를 노린다” 정도면 충분합니다.


2.2 이동 의미론·복사·RVO

30초: “이동은 ‘깊은 복사’ 대신 내부 버퍼 포인터 같은 자원 핸들만 넘겨서 O(1)에 가깝게 옮기는 것입니다. 복사 생성자가 무거운 타입에서 특히 중요합니다.”

90초: “rvalue는 보통 임시값이고, 이동 생성자·이동 대입이 있으면 그 임시의 자원을 빼앗아 옵니다. 반환값 최적화(RVO)가 되는 형태에서는 returnstd::move를 붙이면 오히려 NRVO를 막을 수 있어서 조심합니다. std::move는 캐스트에 가깝고, 실제 이동은 이동 연산이 있을 때만 일어난다고 말합니다.”

꼬리: “다섯 특수 멤버에서 Rule of 0/3/5는?” → “직접 자원을 잡으면 규칙을 맞추고, 스마트 포인터로 위임하면 0으로 둔다” 수준.


2.3 가상 함수·vtable·디스패치 비용

30초: “가상 함수는 동적 디스패치입니다. 객체에 vptr이 있고 vtable을 통해 실제 구현을 찾습니다. 정적 디스패치보다 간접 호출 비용이 있지만, 인터페이스 치환과 확장에 씁니다.”

90초: “컴파일 타임에 타입이 고정되면 인라인·디버추얼라이제이션(devirtualization)이 가능하지만, 인터페이스 뒤에 구현이 바뀌면 런타임에 함수 포인터 테이블을 탑니다. 그래서 핫 루프 안에서 가상 호출을 남발하면 캐시 미스와 분기 예측 실패가 아프다는 식으로 트레이드오프를 말합니다.”

꼬리: “소멸자는 왜 virtual이어야 하나요?” → “기본 클래스 포인터로 파생 객체를 지울 때 파생 소멸자까지 타려면 필요하다”.


2.4 const correctness

30초: “const는 컴파일 타임 계약입니다. 인자를 const T&로 받으면 호출 측에 수정 안 한다는 신호를 주고, 멤버 함수에 const를 붙이면 그 객체 상태를 바꾸지 않겠다는 약속입니다.”

90초: “mutable은 논리적 const와 물리적 const가 갈릴 때 쓰고, const_cast는 상수성 제거라 UB 위험이 있어서 면접에서는 ‘정말 필요한가’를 같이 말합니다.”

꼬리: “const 반복자와 반복자 차이?” → “가리키는 요소를 바꿀 수 있느냐”로 한 줄.


2.5 Data race·mutex·atomic

30초: “Data race는 둘 이상의 스레드가 동기화 없이 같은 메모리에 쓰기·읽기를 겹치는 것이고, C++에서는 정의되지 않은 동작이 될 수 있습니다. 공유 상태는 mutex로 임계 구역을 보호하거나, 단순 카운터처럼 조건이 맞으면 atomic을 씁니다.”

90초: “mutex는 여러 필드를 한 번에 일관되게 바꿀 때 유리하고, atomic은 단일 변수·단순 연산에 맞을 때 고릅니다. false sharing, memory order는 포지션에 따라 깊이를 조절하면 됩니다.”

꼬리: “lock_guard vs unique_lock?” → “재진입·조건변수·try_lock이 필요하면 unique_lock”.


2.6 예외 안전성(기본기)

30초: “예외가 나도 리소스가 새지 않고 불변식이 깨지지 않아야 합니다. RAII가 기본 도구고, 강한 보장까지 못 가더라도 기본 보장은 지키려고 설계합니다.”

90초: “복사 대입에서 자기 대입·부분 실패 시 상태를 말할 수 있으면 좋습니다. 실무에서는 noexcept가 이동 컨테이너 최적화에 영향을 준다는 정도까지 연결하면 플러스입니다.”

꼬리: “소멸자에서 예외?” → “일반적으로 삼키지 말고, noexcept 경로를 설계한다”.


2.7 깊은 복사 vs 얕은 복사

30초: “얕은 복사는 포인터 값만 복사해서 같은 힙을 가리키고, 깊은 복사는 새 메모리를 잡아 독립된 내용을 만듭니다. 기본 복사가 위험한 이유를 예로 들 수 있어야 합니다.”

90초: “Rule of Three/Five 시절에는 직접 자원을 잡으면 복사·이동·소멸을 같이 설계했고, 지금은 스마트 포인터와 컨테이너로 위임하는 쪽이 흔합니다.”

꼬리: “복사 대입 연산자에서 자기 대입?” → “먼저 검사하거나 copy-and-swap”.


2.8 std::vector와 반복자 무효화

30초: “vector에 삽입·재할당이 생기면 capacity를 넘을 때 storage가 옮겨져서 기존 반복자·참조가 무효화될 수 있습니다. erase는 반환 반복자로 이어 받아야 합니다.”

90초: “범위 for 안에서 erase하면 UB로 이어지기 쉬워서, 클래식 for 루프나 remove-erase 관용구를 말합니다.”

꼬리: “reserve 후 push_back?” → “재할당을 줄이는 힌트지만 예외 안전 이야기까지 갈 수 있음”.


2.9 템플릿 인스턴스화·컴파일 시간

30초: “템플릿은 사용되는 타입마다 코드가 생성됩니다. 그래서 헤더에 정의가 있고, 인스턴스가 많으면 바이너리와 빌드 시간이 늘 수 있습니다.”

90초: “명시적 인스턴스화나 모듈(C++20)로 완화할 수 있다는 정도까지 말하면 충분합니다.”

꼬리: “typename이 필요한 이유?” → “의존 이름 해석” 한 줄.


2.10 PIMPL

30초: “구현 세부를 포인터 뒤로 숨겨 헤더 의존을 줄이는 관용구입니다. 바이너리 호환과 컴파일 시간에 도움이 됩니다.”

90초: “헤더에는 전방 선언만 두고, 실제 멤버는 cpp의 impl 클래스에 둡니다. unique_ptr 특수성 때문에 소멸자를 cpp에 두는 패턴도 같이 말하면 좋습니다.”

꼬리: “비용은?” → “간접 접근 한 번, 힙 할당”.


2.11 undefined behavior 대표 사례

30초: “C++에서 UB는 최적화 여지가 커서, 컴파일러가 상상하기 어려운 기계어를 만들 수 있습니다. 대표적으로 null 역참조, 배열 벗어남, 미초기화 읽기, data race가 있습니다.”

90초: “UB를 줄이려면 경계 검사·Sanitizer·정적 분석·코드 리뷰를 조합한다고 말합니다.”

꼬리: “implementation-defined vs UB?” → “구현이 문서로 정하는 것 vs 아예 나쁜 상태”.


2.12 링크 단계·ODR·inline

30초: “ODR은 하나의 정의 규칙입니다. 같은 함수가 여러 번 정의되면 링크 에러나 UB가 될 수 있어서, 헤더에는 inline 함수나 템플릿을 두는 식으로 관리합니다.”

90초: “inline은 ‘인라인 확장’보다 ODR 예외에 가깝다는 면접용 한 마디가 있으면 좋습니다.”

꼬리: “static vs anonymous namespace?” → “내부 링크·번역 단위 한정” 수준.


3. “이 코드 문제점은?” 스타일 답변 체크리스트

코드를 주고 토론하는 라운드에서는 아래 순서로 훑으면 빈칸이 줄어듭니다.

순서볼 것
1수명: 댕글링 참조, 반환 지역 변수 주소, 캡처된 포인터
2소유권: 누가 delete하는지, 이중 해제, 스마트 포인터 혼용
3예외 경로: 중간 return에서 누수 없는지
4동시성: 읽기/쓰기 겹침, 락 순서(데드락)
5성능: 불필요한 복사, O(n²) 삽입, 시스템 콜 반복
6API 계약: nullptr, 빈 컨테이너, 오버플로

한 가지를 짚을 때는 “증상 → 원인 → 수정 → 검증 방법” 순으로 말하면 신뢰가 쌓입니다.


4. 같이 보면 좋은 글

질문 목록을 더 촘촘히 보강하려면 아래를 이어 붙이면 됩니다.


이 글에서 다루는 키워드

C++, 기술면접, 면접준비, 답변스크립트, RAII, 이동의미론, 가상함수, 동시성, 예외안전성, PIMPL 등으로 검색하시면 이 글이 도움이 됩니다.