[말랑 퀴즈] 26/08/26 문제
카테고리: MallangQuiz
태그: Quiz
제 말랑말랑 퀴즈 생성기는 이곳에서 확인하실 수 있습니다.
말랑말랑 퀴즈 📝
날짜: 2026-08-26 문제 수: 5문제
Q1. 🟡 보통
컴퓨터 네트워크는 통신의 주체인 단말기와, 단말기 간의 연결을 담당하는 네트워크 기기로 구성된다. 아래는 단말기를 잇는 두 가지 위상(topology)이다.
[ 링 위상 ] [ 별 위상 ]
[💻 A] - [💻 B] [💻 A] [💻 B]
| | \ /
[💻 D] - [💻 C] [📁 ? ]
/ \
[💻 C] [💻 D]
이 두 구조와, 그 위에서 이루어지는 통신에 대한 설명으로 가장 올바른 것은?
- A. 링 위상에서 A가 C에게 데이터를 보내면 중앙 기기가 목적지를 판별해 곧바로 C에게 전달하므로, 경유하는 단말기 없이 한 번에 도착한다.
- B. 요즘 네트워크는 대부분 링 위상으로 구성된다. 단말기 하나가 고장 나도 반대 방향으로 우회할 수 있어, 중앙 기기 한 대에 의존하는 별 위상보다 안정적이기 때문이다.
- C. 별 위상에서
?자리에 오는 기기는 네트워크 스위치이며, 이렇게 구성된 근거리 네트워크를 LAN이라 부른다. 같은 LAN 안의 단말기끼리는 스위치만으로 통신이 되지만, 스위치 한 대가 연결할 수 있는 단말기 수에는 한계가 있어 LAN을 넘어서는 통신에는 별도의 기기가 필요하다. - D. 별 위상에서
?자리에 오는 기기는 라우터다. 같은 LAN 안이든 밖이든 모든 통신은 IP 주소를 보고 경로를 정해야 하므로, LAN 내부 통신에도 라우터가 반드시 있어야 한다.
출처:
server/game_server/2/2025-06-30-game_server_2_1.md
📝 내 선택: C
Q2. 🔴 어려움
C++에서 객체를 복사하는 함수는 복사 생성자와 복사 대입 연산자 두 가지이며, 둘을 묶어 객체 복사 함수라 부른다. 아래 코드를 보자.
void logCall(const std::string& funcName); // 로그 기록용
class Customer {
public:
Customer(); // 기본 생성자
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
private:
std::string name;
Date lastTransaction;
};
class PriorityCustomer : public Customer { // public 상속
public:
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
private:
int priority;
};
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
: priority(rhs.priority)
{
logCall("PriorityCustomer 복사 생성자");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer 복사 대입 연산자");
priority = rhs.priority;
return *this;
}
PriorityCustomer 쪽 두 함수는 컴파일러 경고 하나 없이 통과한다. 그런데 priority는 잘 복사되는 반면, Customer로부터 물려받은 부분(name, lastTransaction)은 복사되지 않는다.
(1) 아래 코드를 실행했을 때, b가 물려받은 Customer 부분은 어떤 값을 갖게 되는가? 그렇게 되는 이유도 함께 쓰시오.
PriorityCustomer a = /* name="John", lastTransaction=2026-08-25 인 객체 */;
PriorityCustomer b(a); // 복사 생성자
(2) 이번에는 아래처럼 이미 만들어져 있던 c에 대입한다. 이 경우 c가 물려받은 Customer 부분은 어떤 값을 갖게 되는가? (1)과 결과가 어떻게 다른지 대비해서 설명하시오.
PriorityCustomer c; // name="Alice" 등으로 이미 채워져 있음
c = a; // 복사 대입 연산자
(3) 위 두 함수를 올바르게 고치시오.
(4) 어떤 개발자가 두 복사 함수의 중복을 없애려고, 복사 생성자를 아래처럼 한 줄로 구현했다. 왜 이렇게 하면 안 되는가? 그리고 중복을 없애는 올바른 방법은 무엇인가?
Customer::Customer(const Customer& rhs)
{
*this = rhs; // 복사 생성자 안에서 복사 대입 연산자 호출
}
출처:
game_dev/cpp/chapter2/2025-06-08-cpp_2_12.md
📝 내 풀이:
(1) name은 Alice, lastTransaction은 기본 생성자로 인한 값을 가진다.
priority는 PriorityCustomer의 값을 가진다.
(2) name, lastTransaction은 기본 생성자로 인한 값을 가진다.
priority는 PriorityCustomer의 값을 가진다.
(3)
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
: super(rhs), priority(rhs.priority)
{
logCall("PriorityCustomer 복사 생성자");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer 복사 대입 연산자");
*this = super::operator=(rhs);
priority = rhs.priority;
return *this;
}
(4) 복사 대입 생성자가 먼저 컴파일되지 않을수 있기 때문이었던 것 같다. 초기화 리스트를 통해 부모의 생성자를 호출한다.
Q3. 🟢 쉬움
빈칸을 채우시오.
게임 서버에서 MongoDB 명령을 실행하는 전형적인 순서다. (의사코드)
// 1단계: 연결 객체 생성 — 매개변수로 ① ___ 를 넘긴다
client = new client("mongodb://localhost:27017");
// 2단계: ② ___ 이름을 넘겨 액세스 획득
db = client["mydb"];
// 3단계: ③ ___ 이름을 넘겨 액세스 객체 획득
coll = db["mycollection"];
// 4단계: 도큐먼트를 만들어 넣는다
doc = new ④ ___ Document
{
{ "name", "John" },
{ "address", new ④ ___ Document
{
{ "City", "Seoul" },
{ "Street", "Nambu-street" }
}
}
};
coll.⑤ ___ (doc);
- ④는 MongoDB API가 도큐먼트에 액세스할 때 사용하는 객체 형식으로, Binary JSON의 약자다. JSON과 같은 역할이지만 트리 구조를 사용한다.
- ⑤는 만들어 둔 도큐먼트를 컬렉션에 넣는 함수다.
출처:
server/game_server/8/2026-03-14-game_server_8_9.md
📝 내 답: 끝점 주소, 데이터베이스, 콜렉션, ?, addDocument
Q4. 🔴 어려움
다음 명제가 참(O)인지 거짓(X)인지 판단하라.
C++에는 “독립 구조의 객체는 반드시 크기가 0이 넘어야 한다” 는 규칙이 있다. 그래서 비정적 데이터 멤버가 하나도 없는 공백 클래스라 하더라도, 다른 클래스의 멤버 변수로 품으면 크기를 차지한다.
class Empty {}; // 공백 클래스. 메모리를 쓰지 말아야 한다 class HoldsAnInt { private: int x; Empty e; // 객체 합성 }; // → sizeof(HoldsAnInt) > sizeof(int)
Empty자리에 char 한 개가 들어가고, 바이트 정렬이 필요하다고 판단되면 패딩까지 붙기 때문이다.이때 객체 합성 대신 private 상속으로 바꾸면 이 낭비가 사라진다.
class HoldsAnInt : private Empty { private: int x; }; // → sizeof(HoldsAnInt) == sizeof(int)이것을 공백 기본 클래스 최적화(EBO) 라고 한다. 그리고 이 최적화는 기본 클래스를 여러 개 상속해도 똑같이 적용되므로, 품어야 할 공백 클래스가 여러 개일 때 특히 이득이 크다.
출처:
game_dev/cpp/chapter6/2025-10-26-cpp_6_39.md
📝 내 답: O. 잘 모르겠다.
Q5. 🟡 보통
UML은 프로그램의 구조 명세를 표현하는 표기법이며, 여러 종류의 다이어그램이 있다. 아래는 채팅 기능을 두 가지 다이어그램으로 표현한 것이다.
(가)
클라이언트1 서버 클라이언트2 클라이언트3
│ │ │ │
│──Chat()─────▶│ │ │
│ │──ShowChat()──▶│ │
│ │──ShowChat()─────────────────▶│
(나)
[클라이언트] [서버] [클라이언트]
사용자 입력 텍스트 RMI Chat 호출 RMI ShowChat 호출
│ │ │
▼ ▼ ▼
RMI Chat ──────▶ 유효성 검사 채팅 텍스트 출력
╱ ╲
(해커) (실제 사용자)
▼ ▼
로그 경고 다른 클라이언트 목록 얻기
│
▼
RMI ShowChat ────────▶
(1) (가)와 (나)는 각각 어떤 다이어그램인가? 그리고 각 다이어그램의 구성 요소(무엇을 무엇으로 그리는지)를 쓰시오.
(2) (가)만 보고서는 알 수 없지만 (나)를 보면 알 수 있는 정보가 무엇인지, 위 그림에서 구체적인 예를 하나 짚어 설명하시오.
(3) 팀에서 아래 두 작업을 나눠 맡았다. 각각 어느 다이어그램이 더 적합한지 고르고, 그 이유를 쓰시오.
- 작업 A: 클라이언트와 서버가 주고받을 통신 프로토콜(패킷 순서) 설계
- 작업 B: 아이템 획득 시 서버가 거치는 게임 로직 흐름(조건 분기 포함) 설계
출처:
server/game_server/5/2026-02-12-game_server_5_1.md
📝 내 풀이:
(1) 시퀀스 다이어그램, 상태 다이어그램. 각 구성 요소를 뭐라 하는지 잊어버렸다.
(2) 다양한 분기에서의 흐름
(3) 시퀀스, 상태 다이어그램
댓글남기기