[말랑 퀴즈] 26/08/31 문제

게시:     수정

카테고리:

태그:

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

말랑말랑 퀴즈 📝

날짜: 2026-08-31 문제 수: 5문제


Q1. 🟢 쉬움

빈칸을 채우시오.

1인용 게임은 아래 세 단계가 계속 반복되는 게임 루프로 돌아간다.

┌─────────────────────────────────────────────┐
│  ① ___  : 입력 장치를 통해 정보를 획득한다      │
│      ↓                                       │
│  ② ___  : 세션의 상태를 변화시킨다             │
│           (보통 1초에 ③ ___ 번)              │
│      ↓                                       │
│  ④ ___  : 변화된 상태를 화면에 표현한다        │
└──────────────────┘ ← 다시 위로 반복

그런데 온라인 게임은 한 명이 아니라 여러 명이 동시에 행동한다. 그래서 서로 간의 상호작용을 중재해서 ⑤ ___ 시켜 주어야 하고, 바로 여기서 서버와 클라이언트가 등장한다.

대부분의 게임 서버는 클라이언트가 하던 ⑥ ___ 처리를 일부 떼어내 서버로 옮긴 뒤 데이터를 주고받는다. 성능상의 이유만은 아니다 — 클라이언트가 허튼 수를 부리지 못하게 막으려는 목적도 있다.

출처: server/game_server/4/2026-02-08-game_server_4_3.md

📝 내 답: (빈칸 수에 맞게 작성하세요)


Q2. 🟡 보통

아래 코드를 보자.

std::string* stringArray = new std::string[100];
...
delete stringArray;        // ← []를 빠뜨렸다

이 코드에 대한 설명으로 가장 올바른 것은?

  • A. new std::string[100]이 잡은 것은 결국 연속된 메모리 한 덩어리이므로, delete를 쓰든 delete[]를 쓰든 그 블록 전체가 운영체제에 반환된다. delete[]는 관례상 읽기 좋으라고 쓰는 표기일 뿐이다.
  • B. 배열을 할당하면 원소들과 함께 배열의 크기 정보도 저장되고, delete[]는 그 값을 읽어 각 원소의 소멸자를 정확한 횟수만큼 호출한다. delete를 쓰면 그 구조를 모르는 채 단일 객체로 취급하므로 첫 번째 객체만 소멸되고 나머지 소멸자는 호출되지 않는 정의되지 않은 동작이 된다.
  • C. 문제가 되는 것은 std::string처럼 소멸자가 있는 타입일 때뿐이다. new int[100]처럼 소멸자가 없는 타입이라면 해제할 소멸자가 애초에 없으므로 delete로 지워도 표준상 안전하다.
  • D. typedef std::string AddressLines[4]; 처럼 배열을 typedef로 감싸 두면 컴파일러가 그 이름이 배열임을 기억한다. 따라서 new AddressLines로 만든 것은 delete로 지워도 되며, 오히려 이런 실수를 막으려면 배열 타입을 typedef로 감싸 두는 편이 안전하다.

출처: game_dev/cpp/chapter3/2025-06-12-cpp_3_16.md

📝 내 선택: ( )


Q3. 🔴 어려움

게임 서버가 데이터베이스를 다루는 방식에 대한 문제다.

(1) 게임 서버가 필요할 때마다 아래처럼 질의 구문을 DB로 던지는 방식은 비효율적이다. 그 이유를 세 가지 쓰시오. 그리고 이를 줄이기 위해 쓰는 기법의 이름과, 그 기법이 어떻게 문제를 완화하는지 설명하시오.

select * from Character where CharacterID='Little Elf'
select * from Item      where OwnerCharacterID='Little Elf'

(2) 아래는 강부자가 홍길동에게 100원을 보내는 코드다.

begin transaction
update UserAccount set Money=Money+100 where ID='Kang Bu Ja'
update UserAccount set Money=Money-100 where ID='Hong Gil Dong'
-- commit 또는 rollback transaction
  • ㉠ 여기서 트랜잭션이 필요한 이유는 무엇인가?
  • ㉡ 그런데 트랜잭션은 공짜가 아니다. 아래 상황에서 무슨 일이 벌어지는지 쓰고, 이것이 멀티스레딩의 무엇과 닮았는지 답하시오.
쿼리 프로세스 1              쿼리 프로세스 2
BEGIN TRANS                 BEGIN TRANS
A = A + 10
                            B = B + 10
B = B - 10   ⚠️
                            A = A - 10   ⚠️
  • ㉢ ㉡을 예방하는 방법을 두 가지 이상 쓰시오.

(3) 아래는 두 플레이어가 아이템을 교환하는 게임 서버 코드다. 트랜잭션을 쓰지 않고 있다.

void RequestExchangeItems(player1, player2, item1, item2) {
    // 사전 검증
    if (!player1.hasItem(item1)) { ResponseExchangeItemsFail(...); return; }
    if (!player2.hasItem(item2)) { ResponseExchangeItemsFail(...); return; }
    ...

    player1.removeItem(item1);   // 메모리상에서 먼저 처리
    player2.removeItem(item2);
    player1.addItem(item2);
    player2.addItem(item1);

    db.execute("update Item set owner={player2} where itemID={item1}");
    db.execute("update Item set owner={player1} where itemID={item2}");
}
  • ㉠ 이 코드가 트랜잭션 없이도 비교적 안전한 이유는 무엇인가? (코드에서 근거를 짚으시오.)
  • ㉡ 그럼에도 두 db.execute 사이에서 게임 서버가 크래시하면 데이터가 어긋난다. 이 경우를 어떻게 대비하는가?

출처: server/game_server/7/2026-03-05-game_server_7_9.md

📝 내 풀이:

<풀이를 여기에="" 작성하세요=""> --- ## Q4. 🟡 보통 다음 명제가 참(O)인지 거짓(X)인지 판단하라. > 분산 처리는 **확장성**뿐 아니라 **안정성**에도 효과를 준다. 서버가 한 대뿐이라면 그 한 대가 멈추는 순간 서비스 전체가 멈추기 때문이다. > > **수평 분산**의 경우, 서버 한 대가 중지되어도 **그 서버에 있던 플레이어들만** 접속이 끊어진다. 그들은 다른 서버에 접속하면 되므로 나머지 플레이어에게는 영향이 없다. > > **수직 분산** 역시 마찬가지다. 기능별로 서버를 나눠 두었으므로 한 대가 멈추면 **그 서버가 담당하던 기능을 남은 서버들이 나눠 맡게 되어**, 서비스 전체가 아무런 영향 없이 그대로 계속된다. > **출처:** `server/game_server/9/2026-03-22-game_server_9_11.md` **📝 내 답:** O / X --- ## Q5. 🔴 어려움 C++ 템플릿에서 `typename` 키워드에 대한 문제다. (1) 아래 두 선언의 차이는 무엇인가? ```cpp template class Widget; template class Widget; ``` (2) 아래 함수는 컨테이너의 두 번째 원소를 출력하려는 코드인데, **컴파일되지 않는다.** ```cpp template void print2nd(const C& container) { if (container.size() >= 2) { C::const_iterator iter(container.begin()); // ← 여기가 문제 ++iter; int value = *iter; std::cout << value; } } ``` - ㉠ `C::const_iterator`처럼 **템플릿 매개변수에 종속된 이름**과, `int`처럼 **종속되지 않은 이름**을 각각 무엇이라 부르는가? - ㉡ 아래와 같은 클래스가 세상에 존재할 수 있다는 점을 근거로, 컴파일러가 `C::const_iterator`를 두고 **무엇과 무엇 사이에서 헷갈리는지** 구체적으로 설명하시오. (힌트: `C::const_iterator* x;` 라는 한 줄이 두 가지로 읽힐 수 있다.) ```cpp struct Foo { static int const_iterator; // 타입이 아니라 변수다! }; ``` (3) 위 코드를 고치시오. 그리고 그로부터 끌어낼 수 있는 **일반 규칙**을 한 문장으로 쓰시오. (4) 그런데 중첩 의존 타입 이름인데도 `typename`을 **붙이면 안 되는** 자리가 두 군데 있다. 아래 코드에서 ⓐ~ⓒ 중 `typename`이 필요한 곳과 필요 없는 곳을 각각 고르고, 그 두 예외가 무엇인지 쓰시오. ```cpp template class Derived: public Base::Nested { // ⓐ public: explicit Derived(int x) : Base::Nested(x) { // ⓑ Base::Nested temp; // ⓒ ... } }; ``` > **출처:** `game_dev/cpp/chapter7/2025-10-29-cpp_7_42.md` **📝 내 풀이:** <풀이를 여기에="" 작성하세요=""> ---

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

댓글남기기