[말랑 퀴즈] 26/10/18 해답

게시:     수정

카테고리:

태그:

제 말랑말랑 퀴즈 생성기는 이곳에서 확인하실 수 있습니다.

말랑말랑 퀴즈 — 해답지 ✅

날짜: 2026-10-18 문제 수: 6문제 총점: 46.2/60 (77점) ✅ 잘했어요

📊 채점 결과

문항 유형 난이도 결과 점수
Q1 OX 🟢 쉬움 🔺 부분 정답 9 / 10
Q2 객관식 🟡 보통 ⭕ 정답 10 / 10
Q3 빈칸 채우기 🟡 보통 🔺 부분 정답 2.5 / 10
Q4 OX 🟢 쉬움 🔺 부분 정답 7 / 10
Q5 객관식 🟡 보통 ⭕ 정답 10 / 10
Q6 📌 서술형 🔴 어려움 🔺 부분 정답 7.7 / 10
합계       46.2 / 60

총평

객관식 두 문제(Q2, Q5)는 오답 보기 근거까지 정확하게 푸셨고, OX 두 문제도 판단은 모두 맞혔습니다. 반면 Q3(람다 이동 캡처)은 “초기화 캡처”만 맞고 나머지(자료 멤버, bind, mutable)를 놓쳤습니다. Q4는 판단(X)은 맞았지만 틀린 위치를 잘못 짚었고, Q6(private 상속)은 (3)이 만점이었지만 EBO 적용 조건(단일 상속)과 private 상속을 써야 하는 세 번째 경우(protected 멤버 접근)가 빠졌습니다.


Q1. 🟢 쉬움 — 🔺 9/10

문제: 다음 명제가 참(O)인지 거짓(X)인지 판단하라.

4코어 CPU에서 싱글스레드로 소수를 구하면 CPU 사용량은 전체의 25%(1코어만 사용)에 그치므로, 모든 코어를 활용하려는 것이 멀티스레딩이 필요한 이유 중 하나다. 또 디스크에서 플레이어 정보를 읽는 동안 CPU가 놀아서 프로그램이 정지한 것처럼 느려지는 문제는, 멀티스레딩으로는 해결할 수 없고 비동기 프로그래밍으로만 해결할 수 있다.

📝 내 답: X. 멀티스레딩을 사용해 비동기 프로그래밍을 하는 것으로 알고 있다.

정답: X

해설:

앞 문장은 맞다. 싱글스레드로 소수를 구하면 4코어 CPU에서 1코어(25%)만 사용하며, 모든 CPU 코어를 최대한 활용하려는 것이 멀티스레딩이 필요한 상황 중 하나다. 그러나 디스크 I/O 대기 중 CPU가 노는 문제는 멀티스레딩으로 디스크 작업과 나머지 처리를 병렬로 수행하거나, 또는 비동기 프로그래밍을 활용해 해결할 수 있다. 비동기 프로그래밍만이 유일한 방법은 아니다.

🔍 피드백: 판단(X)이 맞아 7점입니다. 근거는 “멀티스레딩으로도 해결할 수 있다”는 방향이 맞지만, 틀린 부분이 “비동기 프로그래밍으로만 해결할 수 있다”는 단정(둘째 문장)이라는 점을 명시하지 않았고 멀티스레딩과 비동기를 한 덩어리로 말씀하셔서 2점만 드렸습니다. 멀티스레딩(디스크 작업과 나머지 처리를 병렬 수행)과 비동기 프로그래밍은 각각 독립적인 해결책입니다.

출처: server/game_server/1/2025-05-28-game_server_1_3.md


Q2. 🟡 보통 — ⭕ 10/10

문제: 물리적 서버(온프레미스)와 클라우드 서버를 비교한 설명으로 가장 올바른 것은?

  • A. 클라우드 서버는 서버 증설과 철거가 빠르고 자동 스케일 아웃이 가능하지만, 가상 머신을 사용하므로 처리 속도 균일성은 물리적 서버보다 낮다.
  • B. 물리적 서버는 서버 한 대당 유지 비용이 높고, 서버 증설 속도가 클라우드 서버보다 빠르다.
  • C. 클라우드 서버는 처리 속도 균일성이 물리적 서버보다 높고, 장애 처리 속도는 느리다.
  • D. IaaS는 운영체제와 프레임워크 소프트웨어가 이미 돌아가고 있어서 사용자가 건드릴 수 없는 서비스 계층이다.

📝 내 선택: A

정답: A

해설:

비교표에서 클라우드 서버는 서버 증설·철거 속도가 빠르고 자동 스케일 아웃이 가능하며 장애 처리도 빠르지만, 처리 속도 균일성은 낮고(가상 머신은 리얼 머신보다 느림) 서버 한 대당 유지 비용은 높다.

  • B: 물리적 서버는 한 대당 유지 비용이 낮고, 증설 속도는 느리다.
  • C: 클라우드 서버의 처리 속도 균일성은 낮고, 장애 처리는 빠르다.
  • D: 운영체제·프레임워크가 이미 돌아가고 건드릴 수 없는 것은 PaaS다. IaaS는 가상 머신 자체를 제공하며 운영체제부터 직접 관리한다.

🔍 피드백: A를 정확히 골랐고, C(처리 속도 균일성은 낮고 장애 처리는 빠름), D(IaaS는 사용자가 건드릴 수 있음) 근거가 맞습니다. B에서는 “물리적 서버가 한 대당 유지 비용이 높다”고 쓰셨는데, 정확히는 물리적 서버가 한 대당 유지 비용이 낮고, 클라우드 서버가 높습니다. 증설 속도가 느리다는 부분은 맞습니다.

출처: server/game_server/4/2026-02-11-game_server_4_8.md


Q3. 🟡 보통 — 🔺 2.5/10

문제: 빈칸을 채우시오.

C++에서 객체를 람다의 클로저 안으로 이동하는 방법에 대한 설명이다.

  • std::unique_ptr처럼 이동 전용인 객체를 클로저 안으로 이동하려면 C++14에서 도입된 ① ___를 사용한다. (한글 용어 두 단어, ‘일반화된 람다 캡처’라고도 한다)
  • [pw = std::move(pw)]에서 =의 좌변은 람다로부터 생성되는 클로저 클래스에 속한 ② ___의 이름이고, 우변은 그것을 초기화하는 표현식이다. (두 단어)
  • C++11에서는 이동 캡처를 직접 지원하지 않으므로, 객체를 ③ ___가 생성하는 함수 객체(바인드 객체) 안으로 이동 생성한 뒤 그 객체에 대한 참조를 람다에 넘겨주는 방식으로 흉내 낸다. (함수 이름, std:: 제외)
  • 위 방식에서 람다 안에서 이동된 객체를 수정하려면, 람다를 ④ ___(으)로 선언하고 매개변수 선언에서 const를 제거해야 한다. (C++ 키워드)

📝 내 답: 일반화 캡처, 지역 변수, function, const

정답:

① 초기화 캡처 (init capture) ② 자료 멤버 ③ bind (std::bind) ④ mutable

해설:

C++14의 초기화 캡처(일반화된 람다 캡처)는 클로저 클래스의 자료 멤버 이름과 그것을 초기화하는 표현식을 지정한다. C++11에서는 std::bind가 만드는 바인드 객체 안으로 객체를 이동 생성하고 람다에 참조로 넘겨 이동 캡처를 흉내 낸다. 람다의 operator()는 기본적으로 const이므로 수정이 필요하면 mutable로 선언해야 한다.

🔍 피드백: 빈칸당 2.5점입니다. ①은 “일반화 캡처”로 쓰셨고 문제의 별칭(“일반화된 람다 캡처”)과 같은 개념이라 인정했습니다(정식 용어는 초기화 캡처). ②는 “지역 변수”가 아니라 자료 멤버입니다. =의 좌변은 클로저 클래스 안에 새로 생기는 멤버 이름이고, 우변이 그것을 초기화하는 표현식입니다. ③은 function이 아니라 바인드 객체를 만드는 std::bind입니다. ④는 const가 아니라 mutable입니다. 람다의 operator()는 기본이 const라서, 수정하려면 mutable로 선언해야 합니다.

출처: game_dev/moderncpp/6/2026-10-01-moderncpp_6_32.md


Q4. 🟢 쉬움 — 🔺 7/10

문제: 다음 명제가 참(O)인지 거짓(X)인지 판단하라.

소켓은 각각 송신 버퍼와 수신 버퍼를 가지며, 송신 버퍼는 FIFO 방식으로 사용자가 push()하고 운영체제가 pop()한다. 송신 버퍼가 가득 차면 send() 함수는 보내지 못한 데이터를 버리고 즉시 리턴한다.

📝 내 답: X. 운영체제가 push하고, 송신 버퍼가 pop한다는 점만 틀렸다.

정답: X

해설:

앞 문장(소켓별 송신·수신 버퍼, FIFO, 사용자 push / 운영체제 pop)은 맞다. 그러나 송신 버퍼가 가득 차면 send()는 데이터를 버리고 리턴하는 것이 아니라, 빈 공간이 생길 때까지 블로킹된다. 일반적으로는 송신 버퍼가 수천 바이트를 담을 수 있어서 send()가 즉시 리턴된다.

🔍 피드백: 판단(X)이 맞아 7점입니다. 그러나 근거가 틀렸습니다. “사용자가 push()하고 운영체제가 pop()한다”는 문장은 맞는 설명입니다(송신 버퍼에 사용자가 넣고, 운영체제가 꺼내서 네트워크로 내보냄). 이 명제가 틀린 곳은 둘째 문장으로, 송신 버퍼가 가득 차면 send()는 데이터를 버리고 리턴하지 않고 빈 공간이 생길 때까지 블로킹됩니다. 근거 3점은 드리지 못했습니다.

출처: server/game_server/3/2026-02-03-game_server_3_3.md


Q5. 🟡 보통 — ⭕ 10/10

문제: 데이터베이스의 ACID 속성을 설명한 것이다.

  • 원자성: 데이터 2개 이상을 전부 변경하고자 할 때 전부 혹은 전무(全無) 처리가 되게 한다.
  • 일관성: 잘못된 상태의 데이터를 원천 봉쇄한다.
  • 고립성: 경쟁 상태로부터 자유롭게 해 준다.
  • 지속성: 장애 직전의 상태로 복구 가능한지에 관한 것이다.

ACID 속성과 그것을 지원하는 데이터베이스 기능의 짝으로 올바른 것은?

  • A. 원자성 ― 락 기능
  • B. 일관성 ― 제약(constraints) 기능
  • C. 고립성 ― 로그 버퍼 기능
  • D. 지속성 ― 트랜잭션 기능

📝 내 선택: B

정답: B

해설:

올바른 짝은 원자성 ― 트랜잭션, 일관성 ― 제약(constraints), 고립성 ― 락, 지속성 ― 로그 버퍼다.

  • A: 원자성은 락이 아니라 트랜잭션 기능이다.
  • C: 고립성은 로그 버퍼가 아니라 락 기능이다.
  • D: 지속성은 트랜잭션이 아니라 로그 버퍼 기능이다.

🔍 피드백: B를 정확히 골랐고, A(원자성 ― 트랜잭션), C(고립성 ― 락), D(지속성 ― 로그 버퍼)로 각 보기를 올바른 짝으로 바로잡은 근거가 모두 맞습니다.

출처: server/game_server/7/2026-03-02-game_server_7_1.md


Q6. 🔴 어려움 · 📌 오답노트 — 🔺 7.7/10

문제: C++ private 상속과 공백 클래스에 대해 답하시오.

class Empty {};

class HoldsAnInt {
private:
	int x;
	Empty e;
};

(1) 위 코드에서 sizeof(HoldsAnInt)가 sizeof(int)보다 커지는 이유를 쓰시오.

(2) HoldsAnInt가 Empty를 private으로 상속하도록 바꾸면 sizeof(HoldsAnInt)가 어떻게 되는가? 이 최적화의 이름과, 이 최적화가 적용되는 조건(상속의 형태)을 쓰시오.

(3) class Student : private Person { ... };일 때, void eat(const Person& p);에 Student 객체를 넘기면 컴파일되지 않는다. 그 이유와, private 상속이 의미하는 관계를 쓰시오. 기본 클래스에서 물려받은 멤버는 파생 클래스에서 어떤 접근 수준이 되는가?

(4) 객체 합성을 쓸 수 있다면 합성을 쓰는 것이 원칙이다. 그럼에도 private 상속을 써야 하는 경우 세 가지를 쓰시오.

📝 내 풀이:

(1) 공백 클래스를 멤버로 가지려면 1바이트라도 채워야하기 때문이다. 그렇기에 커진다.

(2) 공백 클래스가 크기를 가지지 않는다. EBO이며, private여야 하고 멤버로 가지면 안되며, 공백 클래스이어야한다.

(3) private 상속을 하게 되면, 암시적 변환을 허용하지 않는다. private 상속은 is-implemented-means-of이다. 물려받은 멤버는 파생 클래스에서 private 접근 수준이 된다.

(4) 함수 중 일부만 재정의하여야 하는 경우, EBO를 사용해야하는 경우, 나머지 하나는 모르겠다.

정답:

(1) C++의 규칙상 독립 구조의 객체는 크기가 반드시 0보다 커야 하므로, 공백 클래스 Empty의 멤버 e에도 char 한 개가 들어간다. 바이트 정렬이 필요하다고 판단되면 패딩까지 추가되어 sizeof(HoldsAnInt) > sizeof(int)가 된다.

(2) sizeof(HoldsAnInt) == sizeof(int)가 된다. 이 최적화는 공백 기본 클래스 최적화(EBO)이며, 단일 상속에만 적용된다(기본 클래스를 두 개 이상 상속하는 경우는 적용되지 않는다).

(3) private 상속이면 컴파일러는 일반적으로 파생 클래스 객체(Student)를 기본 클래스 객체(Person)로 변환하지 않으므로, Student는 Person의 일종(is-a)이 아니라서 eat(s)가 컴파일되지 않는다. private 상속의 의미는 is-implemented-in-terms-of(…는 …를 써서 구현된다)로, 구현만 물려받고 인터페이스는 물려받지 않는다. 물려받은 멤버는 파생 클래스에서 모두 private 멤버가 된다.

(4) ① 기본 클래스의 protected 멤버에 접근해야 할 때, ② 가상 함수를 재정의해야 할 때(객체 합성으로는 복잡해지는 경우), ③ 공백 기본 클래스 최적화(EBO)를 활성화해야 할 때.

🔍 피드백:

  • (1) 2/2.5 — 공백 클래스 멤버도 1바이트를 차지한다는 핵심이 맞습니다. 다만 그 이유(C++ 규칙상 독립 객체의 크기는 0보다 커야 한다)와, 바이트 정렬 때문에 패딩까지 붙을 수 있다는 점이 빠졌습니다.
  • (2) 1.5/2.5 — 크기가 0이 되어 sizeof(int)와 같아진다는 점과 EBO라는 이름은 맞습니다. 그러나 적용 조건은 “private이어야 하고…”가 아니라 단일 상속에만 적용된다는 것입니다(기본 클래스를 둘 이상 상속하면 적용되지 않음). “공백 클래스여야 한다”는 EBO 이름에서 이미 드러나는 전제입니다.
  • (3) 2.5/2.5 — 암시적 변환 불가, is-implemented-in-terms-of, 물려받은 멤버가 private이 된다는 점 모두 정확합니다.
  • (4) 1.7/2.5 — “일부 가상 함수를 재정의해야 하는 경우”와 “EBO를 활성화해야 하는 경우” 두 가지는 맞습니다. 빠진 세 번째는 기본 클래스의 protected 멤버에 접근해야 하는 경우입니다.

출처: game_dev/cpp/chapter6/2025-10-26-cpp_6_39.md 오답노트: wn-61908b44 · 2026-09-16 최초 오답 · 이번이 2번째 복습


📌 복습 포인트

  • Q1 멀티스레딩과 비동기 프로그래밍 — 디스크 I/O 대기 문제는 멀티스레딩 병렬 처리 또는 비동기 프로그래밍으로 해결 가능(비동기만이 유일하지 않음) → server/game_server/1/2025-05-28-game_server_1_3.md
  • Q3 람다 이동 캡처 — 초기화 캡처의 좌변은 클로저의 자료 멤버, C++11 흉내는 std::bind, 수정하려면 mutable → game_dev/moderncpp/6/2026-10-01-moderncpp_6_32.md
  • Q4 소켓 송신 버퍼 — 사용자 push / 운영체제 pop은 맞는 설명이며, 버퍼가 가득 차면 send()는 버리지 않고 블로킹됨 → server/game_server/3/2026-02-03-game_server_3_3.md
  • Q6 private 상속과 EBO — EBO는 단일 상속에만 적용, private 상속을 써야 하는 세 경우(protected 멤버 접근, 가상 함수 재정의, EBO) → game_dev/cpp/chapter6/2025-10-26-cpp_6_39.md

MallangQuiz 카테고리 내 다른 글 보러가기

댓글남기기