[말랑 퀴즈] 26/08/22 문제
카테고리: MallangQuiz
태그: Quiz
제 말랑말랑 퀴즈 생성기는 이곳에서 확인하실 수 있습니다.
말랑말랑 퀴즈 📝
날짜: 2026-08-23 문제 수: 5문제
Q1. 🔴 어려움
UE5에서 바닥에 떨어진 아이템을 나타내는 AEPPickup 액터를 만들었다. 서버가 아이템을 스폰하면서 InitPickup()으로 ItemId를 채우고, 그 ItemId에 맞는 메시를 화면에 적용해야 한다.
class AEPPickup : public AActor
{
UPROPERTY(ReplicatedUsing = OnRep_ItemId)
FName ItemId;
void InitPickup(FName InItemId); // 서버가 스폰 직후 호출
void OnRep_ItemId();
void ApplyVisual(); // ItemId에 맞는 메시를 적용
};
테스트는 PIE Play As Listen Server(서버 창 1개 + 클라이언트 창 1개)로 한다.
(1) 위처럼 UPROPERTY(ReplicatedUsing = OnRep_ItemId)를 붙이기만 하면 ItemId가 복제되는가? 안 된다면 무엇이 더 필요하며, ReplicatedUsing 지정자는 정확히 무슨 역할을 하는가?
(2) 메시 적용을 아래처럼 OnRep_ItemId() 안에서만 하면 문제가 생긴다. 무슨 문제이며 왜 그런지, 그리고 어느 창에서 증상이 보이는지 설명하시오.
void AEPPickup::InitPickup(FName InItemId)
{
ItemId = InItemId;
}
void AEPPickup::OnRep_ItemId()
{
ApplyVisual();
}
서버 화면에서는 DeveloperSettings에 넣어둔 기본 메시로 보인다.
해당 콜백은 클라이언트에서 실행되기 때문이다.
(3) (1)을 빠뜨렸을 때와 (2)의 상황은 증상이 정반대라 원인을 헷갈리기 쉽다. 둘을 가르려면 어떤 질문 하나를 던지면 되는가?
출처:
game_dev/devlog/2026-08-02-EP_Loot-2.md
📝 내 풀이:
(1) 안된다. GetLifetimeReplicated 함수에서 DOREPLIFETIME을 사용해주어야 한다.
클라이언트에서 실행될 콜백 함수를 지정해주는 역할이다.
(2) 서버 화면에서는 DeveloperSettings에 넣어둔 기본 메시로 보인다.
해당 콜백은 클라이언트에서 실행되기 때문이다.
(3) 서버에서 실행되는가? 정확히는 모르겠다.
Q2. 🟡 보통
다음 C++ 코드를 보자.
class Transaction {
public:
Transaction() {
init(); // 비가상 함수 호출
}
virtual void logTransaction() const = 0;
private:
void init() {
logTransaction(); // 여기서 가상 함수 호출
}
};
class BuyTransaction : public Transaction {
public:
virtual void logTransaction() const override {
// 거래 로깅 구현
}
};
BuyTransaction b;
이 코드에 대한 설명으로 가장 올바른 것은?
- A.
init()이 비가상 함수이므로 가상 함수 호출 문제를 우회할 수 있고,BuyTransaction::logTransaction이 정상적으로 호출된다. - B. 기본 클래스 생성자가 먼저 실행되는 시점에는 파생 클래스 부분이 아직 초기화되지 않았으므로 가상 함수가 파생 클래스 버전으로 동작하지 않는다.
init()을 거친 간접 호출이라 눈에 잘 띄지 않을 뿐, 위험은 직접 호출과 동일하다. - C. 소멸자에서는 파생 클래스 → 기본 클래스 순서로 소멸되므로, 소멸자 안에서 가상 함수를 호출하면 파생 클래스 버전이 안전하게 호출된다.
- D.
logTransaction을 순수 가상 함수 대신 기본 구현이 있는 단순 가상 함수로 바꾸면, 생성자에서도 파생 클래스 버전이 호출되므로 문제가 해결된다.
출처:
game_dev/cpp/chapter2/2025-05-29-cpp_2_9.md
📝 내 선택: B
Q3. 🟢 쉬움
빈칸을 채우시오.
데이터베이스의 기본 작업 네 가지(Create / Read / Update / Delete)를 SQL로 표현하면 다음과 같다.
-- table1에 a=1, b=2, c=3인 레코드를 삽입
① ___ table1 (a,b,c) values (1,2,3)
-- table1의 레코드 중 a가 1인 것의 필드 a,b,c 얻기
select a,b,c from table1 ② ___ a=1
-- table1의 레코드 중 a가 1인 것의 필드 b를 2로 변경
update table1 ③ ___ b=2 where a=1
-- table1의 레코드 중 a가 1인 것을 모두 삭제
delete from table1 where a=1
출처:
server/game_server/7/2026-03-03-game_server_7_5.md
📝 내 답: insert, where, set
Q4. 🔴 어려움
다음 명제가 참(O)인지 거짓(X)인지 판단하라.
인라인 함수는 컴파일 타임에 호출 지점으로 본문이 삽입되어야 하므로, 대체로 헤더 파일에 들어가 있어야 한다.
함수 템플릿 역시 대개 헤더 파일에 들어간다. 따라서 함수 템플릿을 작성할 때는 아래처럼
inline으로 선언하는 것이 맞다.template <typename T> inline const T& max(const T& a, const T& b) { return a < b ? b : a; }
출처:
game_dev/cpp/chapter5/2025-09-22-cpp_5_30.md
📝 내 답: X. 컴파일 시점에 함수가 호출될 부분을 실제 코드로 치환하는 것이기에 템플릿 타입 추론이 안되므로, 함수 템플릿을 사용하면 안된다
Q5. 🟡 보통
MongoDB를 수평 확장(샤딩)하면 서버가 세 종류로 나뉜다.
애플리케이션 서버
│
mongos ← 명령을 받아 적절한 샤드로 송수신
│
├── mongod (ConfigDB) ← 샤드 목록, 샤딩 키 정보, 청크 분포 등을 저장
│
├── mongod (Shard#1) ← 샤드 키로 구분된 도큐먼트를 나눠 보관
├── mongod (Shard#2)
└── mongod (Shard#3)
이 구조에 대한 설명으로 가장 올바른 것은?
- A. ConfigDB도 결국 같은 mongod이므로, 샤드 정보를 바꿀 때는
db.config.update(...)같은 일반 질의 구문으로 수정하는 것이 권장된다. - B. ConfigDB가 죽으면 모든 샤드를 쓸 수 없게 되므로 별도 서버 기기에 두고 이중화(replica set)를 구성한다. 반면 개별 샤드 하나가 죽더라도 나머지 샤드는 계속 사용할 수 있다.
- C. 샤드 키가 포함되지 않은 질의 명령을 받으면 mongos는 어느 샤드로 보낼지 알 수 없으므로 그 요청을 거부한다.
- D. mongos가 샤드 클러스터의 메타데이터를 직접 들고 있으므로, ConfigDB 없이도 클러스터는 정상 동작한다.
출처:
server/game_server/8/2026-03-13-game_server_8_8.md
📝 내 선택: B
댓글남기기