[말랑 퀴즈] 26/09/09 해답

게시:     수정

카테고리:

태그:

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

말랑말랑 퀴즈 — 해답지 ✅

날짜: 2026-09-09 문제 수: 5문제 총점: 38.5/50 (77점) ✅ 잘했어요

📊 채점 결과

문항 유형 난이도 결과 점수
Q1 빈칸 🟢 쉬움 🔺 부분 정답 7.2 / 10
Q2 서술형 🔴 어려움 🔺 부분 정답 7.0 / 10
Q3 객관식 🔴 어려움 ⭕ 정답 10 / 10
Q4 서술형 🟡 보통 🔺 부분 정답 4.8 / 10
Q5 OX 🟡 보통 🔺 부분 정답 9.5 / 10
합계       38.5 / 50

총평

77점, 지금까지 중 가장 높은 점수입니다. 그리고 오른 지점이 정확히 지난 회차에서 지적했던 곳들이라 더 의미가 있습니다.

Q5에서 근거를 쓰셨습니다. 어제 “OX는 답을 쓰고 반드시 한 줄을 덧붙이라”고 했는데 바로 적용하셨고, 게다가 그 한 줄이 정확했습니다 — “32비트/128비트는 MAC이 아니라 IP 주소 이야기”라는 게 이 함정의 급소였습니다. 어제 0점이던 근거 항목에서 3점 만점에 2.5점을 받았습니다.

Q4(1)도 그저께 피드백의 직접적인 결과입니다. 데드락과 경쟁 조건을 혼동하셨을 때 구분을 정리해 드렸는데, 이번엔 1-1, 1-2, 2-1, 2-2, 2-3, 1-3으로 실행 순서를 한 치도 틀리지 않게 짚으셨고 이름도 정확히 “레이스 컨디션”이라 쓰셨습니다. 표기는 간결한데 내용은 정답 그대로입니다.

Q3은 만점인 데다 A를 “RTT/2”로 반박한 게 정확합니다. 어려움 난이도 객관식 두 회차 연속 정답입니다.

낮은 곳은 Q4(4.8점) 인데, (1)에서 만점 가까이 받고 (2)(3)에서 무너진 형태입니다. 특히 (2)의 두 번째 문제는 “공간이 부족해지면”이라는 힌트까지 드렸는데 놓치셨습니다 — 답은 primes재할당되면서 배열 포인터가 바뀌는 것입니다. 그리고 (3)의 두 번째 성질은 “순서 보장”이 아니라 일관성입니다. 두 답이 사실 한 이야기라, 아래 피드백에서 묶어 정리했습니다.

Q2는 (2)가 거의 만점인데 (1)에 (4)의 답인 매핑 DB를 가져다 쓰신 것이 아쉽습니다. 순서를 헷갈리신 것 같습니다.


Q1. 🟢 쉬움 — 🔺 7.2/10

문제: 빈칸을 채우시오.

패키지 게임에 게임 서버가 들어오기까지는 네 단계를 거쳤다.

1. 단독 플레이      네트워크 없이 로컬에서만 플레이
        ↓
2. ① ___ 플레이     두 플레이어 간 직접 연결
        ↓
3. ② ___ 방식       플레이어 세 명 이상이 인터넷으로 함께 플레이하되,
                    그중 한 명이 ③ ___ 역할을 겸해 게임 상태를 관리하고 동기화한다
        ↓
4. ④ ___ 서버       렌더링과 사용자 입력 처리를 하지 않고,
                    순전히 클라이언트의 연결만 처리하는 전용 프로그램

3번 방식은 서버 역할을 맡은 플레이어도 게임에 참여하므로 ⑤ ___ 문제가 생기고, 그 플레이어가 나가면 게임 전체가 흔들린다.

📝 내 답: P2P, ?, 서버, 데디케이티드, 형평성

정답:

① 1:1 ② 세션 ③ 호스트 (또는 서버) ④ 데디케이티드 (Dedicated) ⑤ 공정성

해설:

과거의 패키지 게임은 대부분 컴퓨터 네트워크를 쓰지 않았고, 쓰더라도 1:1 플레이만 지원했다.

세션 방식은 플레이어 세 명 이상이 인터넷을 통해 함께 플레이하는 형태다. 별도의 서버가 없으므로 플레이어 중 한 명이 호스트(서버) 역할을 맡아 게임 상태를 관리하고 나머지와 동기화한다.

데디케이티드 서버렌더링과 사용자 입력 처리를 하지 않고, 순전히 클라이언트의 연결을 처리하는 프로그램이다. 게임 플레이에 참여하지 않고 오직 서버 기능만 수행한다.

구분 초기 패키지 게임 세션 방식 데디케이티드 서버
네트워크 사용 없음 또는 1:1만 있음 (3명 이상) 있음 (다수 플레이어)
서버 역할 없음 플레이어 중 한 명 전용 프로그램
렌더링 각자 호스트도 렌더링 렌더링 없음
공정성 - 호스트 유리 가능 공정함
안정성 - 호스트 이탈 시 문제 안정적

세션 방식의 두 약점이 표의 아래 두 줄이다. 호스트도 플레이어이므로 자기 화면에서는 지연이 없어 공정성 문제가 생기고, 그 사람이 나가면 게임을 유지할 주체가 사라진다.

데디케이티드 서버는 이 둘을 함께 해결한다.

  • 호스트 플레이어의 네트워크·성능에 영향받지 않음
  • 게임 진행의 일관성과 공정성 보장
  • 서버 전용 최적화 가능
  • 24시간 안정적인 서비스 제공 가능

🔍 피드백: ③④⑤를 정답 처리하고 ①에 부분 점수를 주어 7.2점입니다.

③ “서버”는 정답입니다. 원문이 “세 명 중 한 명이 서버 역할을 하고”와 “플레이어 중 한 명이 호스트 역할“을 나란히 쓰고 있어 둘 다 맞습니다. ⑤ “형평성”도 정답으로 봤습니다 — 원문의 “공정성”과 사실상 같은 말이고, 호스트가 유리해지는 상황을 정확히 가리킵니다. ④ “데디케이티드” 도 정확합니다.

① “P2P”에는 부분 점수를 드렸습니다. “두 플레이어 간 직접 연결”을 P2P라 부르는 건 기술적으로 틀리지 않습니다. 다만 이 빈칸이 묻는 건 발전 단계의 이름이고, 원문의 표현은 “1:1 플레이” 입니다. 차이가 미묘하지만 중요합니다 — P2P는 “누구를 거치지 않고 직접 연결하느냐” 를 말하는 반면, “1:1”은 “몇 명이 참여하느냐” 를 말합니다. 실제로 바로 다음 단계인 세션 방식도 P2P적 성격을 갖지만 참여 인원은 3명 이상이죠. 이 단계 구분의 축은 인원 수입니다 — 1명 → 2명 → 3명 이상(호스트 겸업) → 3명 이상(전용 서버).

② 는 비워 두셨는데 정답은 “세션”입니다. 3번 단계 전체의 이름이 세션 방식입니다. 세 명 이상이 모여 한 판(세션)을 이루고, 그 세션을 플레이어 중 한 명이 유지해 주는 구조라 이렇게 부릅니다. ③을 맞히셨으니 그 위 칸이 그 방식의 이름이라는 것만 연결하시면 됩니다.

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


Q2. 🔴 어려움 — 🔺 7.0/10

문제: 유저 DB 한 대가 과부하다. 인증 서버는 이미 여러 대지만 DB는 한 대다.

(1) 수평 확장 시 질의가 어느 DB로 가는지 ①→②→③ 순서로, 그리고 인덱스를 얻는 데 쓴 키의 이름은? (2) 샤드 10개 → 11개로 늘리면 무슨 일이 벌어지며 왜 문제인가? (3) 일관된 해시 알고리즘 — ㉠ 일반 해시 테이블과의 차이 ㉡ 재배치 범위 ㉢ 남은 한계 (4) 매핑 DB — ㉠ 샤드 추가가 쉬운 이유 ㉡ 새로 떠안는 위험과 대응

📝 내 풀이:

(1) 인증 서버 → 매핑 DB → 유저 DB, 샤드 키

(2) 11개로 늘어난 샤드를 반영하려면, 해시를 재설정해주어야 한다. 문제는 서버가 오랜 시간 정지된다.

(3) ㄱ: 일반적인 해시 테이블은 항목 전체와 해시 값이 1:1 대응이다. 일관된 해시 테이블은 항목과 해시 값이 n:1 대응이다. ㄴ: 본인이 속한 샤드만 재배치하면 된다. ㄷ: 한계 이상의 데이터가 들어오면 결국 모두 재배치해야한다.

(4) ㄱ: 샤드를 늘릴려면 매핑 DB만 업데이트해주면 되기 때문 ㄴ: 매핑 DB 서버 정지. 이런 상황을 대비해 예비 서버를 둔다.

정답:

(1) 수평 확장 절차와 샤드 키

플레이어 정보를 여러 샤드에 나누어 저장한다.

  1. 클라이언트가 인증 서버에 접속해 ID/PW를 전송한다.
  2. 인증 서버가 ID → 해시 함수 를 통해 DB 샤드 인덱스를 얻는다.
  3. 해당 샤드에 질의를 전송한다.

이때 샤드 인덱스를 얻는 데 쓰인 키(여기서는 ID)를 샤드 키(파티션 키) 라고 한다.

더 많은 처리량이 필요하면 인증 서버와 데이터베이스 샤드를 증설하면 된다. 다만 데이터베이스 샤드를 늘리는 일은 단순하지 않다.

(2) 샤드 10개 → 11개: 리해시가 발생한다

해시로 샤드를 정하는 방식은 보통 “해시 값 % 샤드 개수”에 의존하므로, 항목 개수(샤드 수)가 달라지면 대응 관계가 통째로 바뀐다. 그래서 데이터 항목 재배치가 필요해지고, 기존 레코드도 전부 리해시해 주어야 한다.

문제는 규모다. 리해시해야 하는 레코드가 많으면 게임 서버를 장시간 점검해야 한다. 서버를 늘리려다 서비스를 멈추게 되는 셈이다.

해결 방향은 세 가지다.

  1. 레코드 이동 개수를 최소화 → 일관된 해시 알고리즘
  2. 이동할 일이 없게 만듦 → 매핑 DB
  3. 레코드 이동 크기를 최소화

(3) 일관된 해시 알고리즘

㉠ 일반 해시 테이블과의 차이 — 대응 관계가 일대일에서 일대다로 바뀐다

일반적인 해시 테이블은 항목이 해시 함수 값에 일대일 대응된다. 그래서 항목 개수가 바뀌면 전부 흔들린다.

일관된 해시는 항목 개수를 크게 잡아 고정해 둔다(예: 0~999). 그러면 샤드 하나가 해시 값 다수에 대응된다 — 즉 샤드는 “해시 값들의 집합”을 맡는다.

해시 항목 샤드
hash(“A”) 17 1
hash(“B”) 23 1
hash(“C”) 745 2

㉡ 재배치 범위 — 샤드 개수 변동 1개당 샤드 1개분만

[ 샤드 2개 ]                        [ 샤드 3개 ]

샤드 1: 0 ... 499                   샤드 1: 0 ... 499      ← 그대로
샤드 2: 500 ... 999                 샤드 2: 500 ... 749    ┐ 원래 샤드 2가 맡던
                                    샤드 3: 750 ... 999    ┘ 집합을 둘이 나눠 가진다
  • 샤드 추가: 기존 샤드가 맡던 해시 집합을 두 샤드가 나누어 가진다.
  • 샤드 삭제: 기존 샤드가 맡던 해시 집합을 인접 샤드에 나누어 준다.

해시 테이블은 링형으로 보아야 한다(샤드 3과 샤드 1이 인접). 그래서 일부 레코드에만 리해시하면 되고, 위 그림에서 샤드 1은 아예 건드리지 않는다.

㉢ 남은 한계

샤드가 크게 늘어나거나 줄어들 때는 결국 많은 양을 리해시해야 한다. “변동 1개당 1개분”이므로 변동이 크면 비용도 그만큼 커진다. 즉 이 방식은 문제를 없앤 게 아니라 점진적 증설에 한해 완화한 것이다.

(4) 매핑 DB

입력(키) → 샤드 인덱스를 담은 DB를 따로 둔다. 접속 절차는 이렇게 바뀐다.

  1. 클라이언트가 인증 서버 중 하나에 접속
  2. 인증 서버가 매핑 DB에 질의해 DB 인덱스(샤드 넘버)를 얻음
  3. 인증 서버가 해당 DB에 플레이어 관련 CRUD 질의 수행

㉠ 샤드 추가가 쉬운 이유 — 위치를 계산하지 않고 “적어 두기” 때문이다

해시 방식은 위치가 계산 결과로 정해지므로 샤드 수가 바뀌면 계산 결과가 통째로 바뀐다. 매핑 DB는 위치를 표에 기록해 두므로 샤드 수와 무관하다. 그래서 샤드를 추가할 때 레코드 이동 없이 새 샤드를 채우기만 하면 된다.

(단 샤드 제거는 여전히 일이 있다. 매핑 DB에서 레코드를 옮기고, 유저 DB에서도 바뀐 위치를 반영해야 한다.)

㉡ 새로 떠안는 위험 — 단일 실패 지점(SPOF)

모든 접속이 매핑 DB를 거치므로, 매핑 DB에 과부하가 걸리거나 죽으면 전체가 의미를 잃는다. 병목을 없애려고 만든 구조가 새 병목을 만든 셈이다. 이것이 단일 실패 지점(SPOF, Single Point Of Failure) 이다.

대응은 매핑 DB에도 확장성을 부여하는 것이다 — 매핑 DB의 레코드도 여러 샤드에 나누어 여러 대로 운영한다.

덧붙임 — 인증 정보(Credential): 한 서버에서 인증하고 다른 서버에서 또 인증을 거치는 것은 비효율적이다. 그래서 인증 서버가 비밀 징표(Credential) 를 발급하고, 클라이언트는 그것으로 다른 서버에 로그인한다. 그 서버는 이미 인증 서버로부터 징표와 유저 ID를 전달받아 두었으므로 재인증이 필요 없다.

🔍 피드백: 논점별로 (1) 1.3 / (2) 2.3 / (3) 1.7 / (4) 1.7을 받아 7.0점입니다.

(2)가 거의 만점입니다. “해시를 재설정해주어야 한다”가 곧 리해시이고, “서버가 오랜 시간 정지된다”가 곧 장시간 점검입니다. 두 핵심을 다 짚으셨습니다. 용어만 리해시로 붙여 두시면 완결됩니다.

(1)에서 순서를 하나 앞당겨 쓰셨습니다. “인증 서버 → 매핑 DB → 유저 DB”는 (4)의 매핑 DB 방식입니다. (1)이 묻는 건 그 이전의 기본 수평 확장이고, 거기엔 매핑 DB가 없습니다.

① 클라이언트 → 인증 서버        (ID/PW 전송)
② 인증 서버   → ID를 해시 함수에 넣어 샤드 인덱스 획득    ← 여기가 핵심
③ 인증 서버   → 해당 샤드에 질의

이 차이가 중요한 이유는, ②를 “계산”으로 하느냐 “조회”로 하느냐가 이 문제 전체의 축이기 때문입니다. 계산으로 하면 (2)의 리해시 문제가 생기고, 그래서 (4)에서 조회(매핑 DB)로 바꾸는 흐름이거든요. 샤드 키는 정확히 맞히셨습니다.

(3)㉠은 방향만 뒤집으면 됩니다. “1:1 → n:1”이라 쓰셨는데, 정확히는 샤드 하나가 해시 값 여러 개를 맡는 1:다 관계입니다(샤드 1개 : 해시 값 500개). 그리고 그게 가능한 전제가 빠졌습니다 — 해시 항목 개수를 크게 잡아 고정해 두기 때문입니다. 항목이 0~999로 고정돼 있으니 샤드가 2개든 3개든 그 1000칸을 나눠 맡기만 하면 되는 거죠.

㉡ “본인이 속한 샤드만 재배치” 는 취지가 맞습니다. 조금 더 정확히는 샤드 개수 변동 1개당 샤드 1개분입니다 — 샤드를 하나 추가하면 기존 샤드 하나가 맡던 집합을 둘이 나눠 가지고, 나머지 샤드는 전혀 건드리지 않습니다. 위 그림에서 샤드 1이 그대로인 게 그 뜻입니다.

㉢의 조건이 어긋났습니다. 한계가 드러나는 건 데이터가 많이 들어올 때가 아니라 샤드 수가 크게 변할 때입니다. “변동 1개당 1개분”이니 한 번에 10개를 늘리면 10개분을 리해시해야 하죠. 즉 이 알고리즘은 점진적 증설에서만 이득이고, 대규모 변경은 여전히 비쌉니다.

(4)㉠은 핵심을 맞히셨습니다. 한 걸음만 더 들어가면 이유가 선명해집니다 — 해시 방식은 위치가 계산 결과라 샤드 수가 바뀌면 계산이 통째로 달라지지만, 매핑 DB는 위치를 표에 적어 둔 것이라 샤드 수와 무관합니다. “계산에서 조회로 바꿨다” 가 이 방식의 전부입니다.

㉡은 위험 인식이 정확한데 두 가지가 빠졌습니다. 첫째, 문제가 “약어로도 답하시오” 라고 했는데 그 답이 SPOF(Single Point Of Failure, 단일 실패 지점) 입니다. 둘째, 대응책이 다릅니다. “예비 서버(이중화)”는 장애 대비로는 맞지만, 이 항목이 지적하는 건 과부하이고 그 해법은 매핑 DB에도 확장성을 주는 것 — 즉 매핑 DB의 레코드도 여러 샤드에 나눠 여러 대로 운영하는 것입니다. 유저 DB를 나눈 것과 똑같은 처방을 매핑 DB에 다시 적용하는 셈이죠.

출처: server/game_server/9/2026-03-26-game_server_10_2.md


Q3. 🔴 어려움 — ⭕ 10/10

문제: 추측 항법과 레이턴시 측정에 대한 설명으로 가장 올바른 것은?

t=0 시점 : P(t=0+a) = P0(t=0) + a * V0(t=0)
t=1 시점 : P(t=1+a) = P0(t=1) + a * V0(t=1)
① 기기 A가 기기 B에 패킷을 보낸다
② 기기 B는 받자마자 기기 A에게 패킷을 되돌려 보낸다
③ 기기 A는 (현재 시간 − 보낸 시간)을 잰다
  • A. ③에서 잰 값이 곧 레이턴시 a이므로 그대로 예측식에 넣으면 된다. 이 왕복 측정값을 RTT라 부르며, 편도 시간을 따로 구할 필요는 없다.
  • B. t=0에서 하던 예측과 t=1에서 새로 시작한 예측은 어차피 예측이므로 값이 일치할 수 없다. 그래서 실제로 렌더링하는 위치 P_follow를 새 목표 P_target으로 순간 이동시키지 않고 선형 보간하며 따라가게 만든다. 이렇게 레이턴시가 만드는 문제를 감추는 기법들을 통틀어 레이턴시 마스킹이라 한다.
  • C. 추측 항법을 도입하면 위치가 정확히 예측되므로, 전송 텀이 길어서 생기는 끊김을 메우는 상태 값 보정(선형 보간·스플라인)은 더 이상 필요 없다. 둘은 같은 문제를 푸는 방법이라 하나만 쓰면 된다.
  • D. 서버가 게임 로직·렌더링·화면 송출을 모두 맡고 클라이언트는 입력과 화면 출력만 하는 방식이 있다. 클라이언트가 그래픽 리소스를 갖지 않아 보안이 완벽하고, 클라이언트가 할 일이 적어 레이턴시도 가장 낮다. 그래서 현대 온라인 게임은 이 방식으로 돌아가는 추세다.

📝 내 선택: B — A: ③에서 잰 값은 RTT이며, a는 RTT/2로 구해야 한다. / C: 위치가 정확히 예측되지 않아서 쓰는 것이 레이턴시 마스킹이다. / D: 마지막 문단이 틀렸다. 현대 온라인 게임은 서버 부하가 커지기에, 클라/서버가 나눠 처리한다.

정답: B

해설:

추측 항법은 새 원본이 도착할 때마다 예측을 다시 시작한다. 그런데 t=0에서 예측해 둔 위치 P(t=0+a+?)와, t=1의 원본을 기준으로 새로 예측한 P(t=1+a)둘 다 예측값이므로 일치할 수가 없다. 그대로 그리면 캐릭터가 매 갱신마다 순간 이동하듯 튄다.

그래서 위치를 둘로 나눈다.

  • P_target — 예측된 목표 위치
  • P_follow — 실제로 렌더링하는 위치

P_followP_target을 향해 선형 보간하며 따라가게 하면 튀는 대신 부드럽게 수렴한다. 이렇게 레이턴시로 발생하는 문제를 감추는 방법을 통틀어 레이턴시 마스킹이라 부른다.

  • A — 절반만 맞다. ①~③은 RTT(라운드 트립 레이턴시) 측정이 맞지만, 그 값은 왕복 시간이다. 편도 레이턴시를 얻으려면 2로 나눠야 한다.

    a = (현재 시간 − A가 보낸 시간) / 2
    

    나누지 않고 그대로 쓰면 실제의 두 배만큼 앞질러 예측하게 되어 캐릭터가 계속 앞서 나간다.

  • C — 둘은 다른 문제를 푸는 다른 기법이다.
    • 상태 값 보정(선형 보간·스플라인) — 전송 텀을 길게 잡아 생기는 끊김을 메운다. (문제점 1의 해결)
    • 추측 항법 — 레이턴시 때문에 한 템포 늦어 보이는 것을 메운다. (문제점 2의 해결)

    게다가 추측 항법 자체가 위 해설처럼 보간을 다시 필요로 한다(P_followP_target). 둘은 대체 관계가 아니라 함께 쓰는 관계다.

  • D — “모든 역할을 서버에서 하기”는 가장 오래된 방식으로, MUD 게임에서나 썼고 현대 게임에서는 어림도 없다. 서버가 렌더링해서 비디오를 스트리밍해야 하므로 엄청난 레이턴시가 발생한다. 보안이 좋다는 점만 맞고, “레이턴시가 가장 낮다”와 “현대 게임이 회귀하고 있다”는 정반대다.
방식 장점 단점 사용 예시
서버 전담 보안 완벽 엄청난 레이턴시 MUD, 텍스트 게임
클라 렌더링 레이턴시 감소, 보안 유지 동기화 복잡 현대 온라인 게임
추측항법 부드러운 움직임 예측 오차 FPS, MMORPG

🔍 피드백: 만점입니다. 어려움 난이도 객관식 두 회차 연속 정답입니다.

A를 쳐낸 근거가 가장 정확합니다. “③에서 잰 값은 RTT이며, a는 RTT/2”— 이 문항에서 A가 함정인 지점을 정확히 짚으셨습니다. 측정 절차를 그대로 읽으면 A → B → A 왕복이니 편도를 얻으려면 반으로 나눠야 하죠. 나누지 않으면 실제의 두 배만큼 앞질러 예측하게 되어 캐릭터가 계속 앞서 나가는 증상이 나옵니다.

C와 D의 근거는 조금 다듬으면 좋겠습니다. 점수엔 영향이 없지만 개념이 살짝 어긋나 있습니다.

C — “위치가 정확히 예측되지 않아서 쓰는 것이 레이턴시 마스킹”이라 쓰셨는데, 레이턴시 마스킹은 특정 기법의 이름이 아니라 “레이턴시로 생기는 문제를 감추는 방법들”을 통틀어 부르는 상위 개념입니다. C가 틀린 진짜 이유는 두 기법이 서로 다른 문제를 푼다는 데 있습니다.

기법 무슨 문제를 푸는가
상태 값 보정(선형 보간·스플라인) 전송 텀이 길어서 생기는 끊김
추측 항법 레이턴시 때문에 한 템포 늦어 보이는 것

그리고 결정적으로, 추측 항법 자체가 보간을 다시 필요로 합니다(P_followP_target을 따라가는 그 보간이 바로 선형 보간이죠). 대체 관계가 아니라 포개어 쓰는 관계입니다.

D — “서버 부하가 커지기에”라고 하셨는데, 원문이 드는 이유는 부하가 아니라 레이턴시입니다. 서버가 렌더링해서 비디오를 스트리밍해야 하니 화면 한 장이 오기까지의 지연이 어마어마해집니다. 그래서 MUD 같은 텍스트 게임에서나 썼고 “현대 게임에서는 어림도 없다”고 적혀 있습니다. 서버 부하도 물론 크지만, 이 방식을 못 쓰게 만드는 결정적 이유는 레이턴시입니다.

출처: server/game_server/5/2026-02-13-game_server_5_2.md


Q4. 🟡 보통 — 🔺 4.8/10

문제: x += y는 기계어 수준에서 t = x / t = t + y / x = t 세 연산으로 쪼개진다.

(1) ㉠ x = 2에서 스레드 1이 +3, 스레드 2가 +4를 할 때 x = 5가 되는 실행 순서 ㉡ 이 현상의 이름 (2) 소수 구하기 코드에 숨은 두 가지 문제 (3) 보장해야 할 두 성질과 그것을 가능하게 하는 기법 세 가지

📝 내 풀이:

(1) ㄱ: 스레드/줄 번호라고 쳤을때. 1-1, 1-2, 2-1, 2-2, 2-3, 1-3 ㄴ: 레이스 컨디션

(2) 1. 스레드 간 primes.Add(num)num++ 순서가 보장되어 있지 않다.

  1. 한 스레드당 25만번의 while문을 돌기에 생기는 크기 문제? 잘 모르겠다.

(3) 원자성, 순서 보장 잘 모르겠다.

정답:

(1)㉠ x = 5가 되는 실행 순서

x = 2

# 스레드 1
t1 = x         // t1 = 2
t1 = t1 + 3    // t1 = 5
                         여기서 컨텍스트 스위치 발생! (아직 x 쓰지 않았다)

# 스레드 2
t2 = x         // t2 = 2   ← 스레드 1의 결과를 아직 못 봤으므로 여전히 2
t2 = t2 + 4    // t2 = 6
x = t2         // x = 6

# 다시 스레드 1
x = t1         // x = 5    ← ❗ 스레드 2가 쓴 6을 덮어써 버린다

핵심은 “읽기”와 “쓰기” 사이가 벌어져 있다는 점이다. 스레드 1이 x를 읽은 뒤 다시 쓰기 전까지의 틈에 스레드 2가 통째로 끼어들었고, 그 결과 스레드 2의 작업이 통째로 사라졌다.

참고로 순서대로 잘 돌았다면 이렇게 된다.

x = 2
# 스레드 1 :  t1 = 2 → t1 = 5 → x = 5
# 스레드 2 :  t2 = 5 → t2 = 9 → x = 9      ← 기대했던 결과

(1)㉡ 경쟁 상태(데이터 레이스)

두 스레드가 데이터에 접근해서 그 데이터 상태를 예측할 수 없게 되는 상황

(2) 소수 구하기 코드의 두 가지 문제

문제 1 — 여러 스레드가 num에 동시에 접근

num++ 역시 기계어 수준에서는 세 연산이다.

r1 = num
r1 = r1 + 1
num = r1

그래서 (1)과 똑같은 일이 벌어진다. 결과적으로 같은 값을 여러 번 검사하거나, 어떤 값을 아예 건너뛰는 일이 생긴다. 게다가 while (num <= 1000000) 조건 검사와 증가 사이에도 다른 스레드가 끼어들 수 있다.

문제 2 — 여러 스레드가 primes에 동시에 접근

Array<int>는 내부에 배열을 가리키는 포인터배열의 크기 정보 두 멤버를 갖는다. 원소를 추가하다 공간이 부족해지면 메모리를 재할당하는데, 이때 포인터가 가리키는 위치가 바뀐다.

다른 스레드가 그 사실을 모른 채 예전 포인터로 접근하면 이미 해제된 메모리를 건드리게 되고, 충돌이 발생한다. 포인터와 크기가 서로 어긋난 순간에 끼어드는 것도 같은 문제다.

(3) 보장해야 할 두 성질과 기법

성질 이 코드에서 지켜 주는 것
원자성(Atomicity) 하나의 작업 단위가 절대 쪼개지지 않게 만든다 num++가 세 연산으로 쪼개져 중간에 끼어들지 못하게 한다
일관성(Consistency) 여러 멤버 변수가 항상 서로 어울리는 상태여야 한다 primes배열 포인터와 크기 정보가 어긋난 순간에 다른 스레드가 접근하지 못하게 한다 (재할당 중간 보호)

이를 가능하게 하는 기법이 동기화(Synchronization) 이며, 대표적으로 세 가지가 있다.

  • 임계 영역 (Critical Section)
  • 뮤텍스 (Mutex)
  • 잠금 (Lock)

공유 데이터에 접근하는 순간만큼은 다른 스레드가 접근하지 못하도록 막는 것이 요지다.

🔍 피드백: 논점별로 (1) 3.0 / (2) 1.0 / (3) 0.8을 받아 4.8점입니다.

(1)이 이번 회차에서 가장 좋았습니다. 1-1, 1-2, 2-1, 2-2, 2-3, 1-3 — 표기는 짧은데 정답 순서와 완전히 일치합니다. 스레드 1이 x를 읽고 더한 뒤 아직 쓰지 않은 상태에서 스레드 2가 통째로 끼어들고, 마지막에 스레드 1이 자기 값을 써서 스레드 2의 결과를 덮어쓰는 구조를 정확히 잡으셨습니다. 이름도 레이스 컨디션으로 맞으셨고요. 지난 회차에 데드락과 경쟁 조건을 혼동하셨던 걸 생각하면 확실히 정리가 된 겁니다.

0.3점만 빠진 건 값 추적이 없어서입니다. t1 = 5, t2 = 6, x = 5 처럼 각 단계에서 값이 어떻게 되는지 한 줄씩 붙이면 만점입니다 — 특히 스레드 2가 읽는 시점의 x가 여전히 2라는 것이 이 시나리오의 핵심이라 그 값은 적어 두는 게 좋습니다.

(2)의 첫 번째 문제는 표현이 아쉽습니다.primes.Add(num)num++ 순서가 보장되지 않는다”고 하셨는데, 문제는 두 문장의 순서가 아니라 num++ 한 줄 안에서 벌어집니다. num++도 (1)의 x += y와 똑같이 세 연산으로 쪼개지거든요.

r1 = num
r1 = r1 + 1
num = r1

그래서 (1)에서 직접 추적하신 그 일이 여기서도 그대로 일어납니다 — 같은 값을 여러 스레드가 중복 검사하거나, 어떤 값은 아예 건너뛰게 됩니다. (1)과 (2)-1이 같은 이야기라는 걸 연결하시면 됩니다.

두 번째 문제는 힌트가 가리키던 곳을 놓치셨습니다. “공간이 부족해지면”이라는 힌트는 primes의 메모리 재할당을 가리킨 것이었습니다.

Array<int>는 내부에 ① 배열을 가리키는 포인터② 크기 정보 두 멤버를 갖습니다. 원소를 넣다가 공간이 모자라면 더 큰 메모리를 새로 잡고 포인터가 가리키는 위치를 바꿉니다. 그런데 그 순간 다른 스레드가 예전 포인터로 접근하면 이미 해제된 메모리를 건드리게 되고, 곧바로 충돌입니다.

“한 스레드당 25만 번”이라고 쓰신 부분도 짚고 넘어가면, num을 네 스레드가 공유하므로 균등하게 25만 번씩 나뉘지 않습니다. 각자 num을 읽고 올리기 때문에 몇 번씩 돌지는 실행할 때마다 달라집니다 — 그게 바로 (2)-1의 증상이기도 하죠.

(3) “원자성”은 맞습니다. 두 번째는 “순서 보장”이 아니라 일관성(Consistency) 입니다. 그리고 두 성질이 각각 (2)의 두 문제에 하나씩 대응한다는 점이 이 문항의 설계입니다.

성질 막아 주는 문제
원자성 — 작업 단위가 쪼개지지 않게 (2)-1의 num++ 가 중간에 끊기는 것
일관성 — 여러 멤버가 항상 서로 어울리는 상태 (2)-2의 primes의 포인터와 크기가 어긋난 순간에 끼어드는 것

“순서 보장”과 무엇이 다른지도 짚어 두시면 좋습니다. 동기화가 보장하는 건 “누가 먼저 하느냐”가 아니라 “하는 도중에 끼어들지 못한다” 는 것입니다. 스레드 1이 먼저 갈지 스레드 2가 먼저 갈지는 여전히 알 수 없고, 알 필요도 없습니다.

이를 가능하게 하는 기법 세 가지는 임계 영역(Critical Section) / 뮤텍스(Mutex) / 잠금(Lock) 이고, 이들을 통틀어 동기화(Synchronization) 라 부릅니다.

출처: server/game_server/1/2025-05-30-game_server_1_5.md


Q5. 🟡 보통 — 🔺 9.5/10

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

OSI 2계층인 데이터 링크 계층은 LAN 안에서의 통신을 담당한다. 단말기마다 고유한 MAC 주소가 있고, 데이터는 프레임 단위로 오간다. 프레임은 송신자와 수신자 주소를 담은 헤더와 실제 데이터인 페이로드로 이루어진다.

3계층인 네트워크 계층은 여러 LAN 사이의 경로를 설정하고 데이터를 전달한다. 라우팅·포워딩·세그멘테이션·인터네트워킹이 주요 기능이며, 라우터와 일부 L3 스위치가 이 계층에서 동작한다.

그런데 스위치 하나에 연결할 수 있는 단말기 수에 한계가 있는 것은, 결국 MAC 주소가 32비트뿐이라 주소 공간이 모자라기 때문이다. 그래서 128비트 주소를 쓰는 IPv6로 넘어가면 이 한계가 사라져 LAN 하나에 사실상 무제한으로 단말기를 붙일 수 있게 된다.

📝 내 답: X — 마지막 단락이 틀렸다. 이는 MAC 주소가 아닌 IP 주소에 대한 내용이다.

정답: X

해설:

앞의 두 문단은 전부 참이다.

  • 2계층 = 데이터 링크 계층, LAN 내부 통신 담당, 고유한 MAC 주소, 프레임 단위 전송, 프레임 = 헤더(송·수신자 주소) + 페이로드(실제 데이터)
  • 3계층 = 네트워크 계층, 여러 LAN 간 경로 설정, 라우팅·포워딩·세그멘테이션·인터네트워킹, 라우터와 일부 L3 스위치가 동작 ✅

틀린 곳은 마지막 문단이며, 세 군데가 한꺼번에 어긋나 있다.

① 32비트는 MAC 주소가 아니라 IPv4 주소다.

172.16.254.1처럼 8비트 숫자 4개 = 총 32비트인 것이 IPv4다. 이론상 2³²개까지 배정할 수 있는데 그 한계에 다다라 NAT 같은 기술로 버티고 있다. MAC 주소와는 아무 관계가 없다.

② IPv6는 3계층의 이야기이지 2계층의 한계와 무관하다.

IPv6는 16비트씩 8개 = 총 128비트로, 이론상 2¹²⁸개를 배정할 수 있다. 이것은 IP 주소가 모자라는 문제의 해법이다. 반면 스위치의 한계는 2계층에서 벌어지는 일이므로, 3계층 주소 체계를 바꾼다고 해결될 성질이 아니다.

③ 스위치의 한계에 대한 원인 진단 자체가 틀렸다.

원문이 드는 한계는 두 가지다.

  • 하나의 스위치가 연결할 수 있는 단말기 수에 한계가 있다 — 이건 주소 공간이 아니라 물리적 포트 수와 장비 용량의 문제다.
  • 단말기가 많아지면 고유한 MAC 주소 관리가 어려워진다 — 주소가 모자라서가 아니라 관리가 어려워지는 것이다.

그리고 이 한계를 해결하려고 등장한 것은 IPv6가 아니라 WAN(Wide Area Network) 이며, 그 통신을 담당하는 것이 3계층의 라우터다.

정리 — 두 계층을 섞지 않는 것이 핵심이다.

  2계층 (데이터 링크) 3계층 (네트워크)
범위 LAN 내부 LAN과 LAN 사이 (WAN)
장비 스위치 라우터
주소 MAC 주소 IP 주소 (IPv4 32비트 / IPv6 128비트)
단위 프레임 (헤더 + 페이로드) 패킷

이 명제는 3계층의 사실(32비트/128비트)을 2계층의 문제(스위치 한계)에 갖다 붙여 만든 함정이다. 앞 두 문단이 두 계층을 정확히 설명해 두었기 때문에 오히려 더 그럴듯하게 읽힌다.

🔍 피드백: 판단 7점 만점, 근거 3점 중 2.5점으로 9.5점입니다.

어제 피드백을 바로 반영하셨습니다. 지난 회차 OX에서 근거를 안 써 3점을 통째로 놓치셨는데, 이번엔 한 줄을 덧붙이셨고 그 한 줄이 정확히 급소를 찔렀습니다.

“이는 MAC 주소가 아닌 IP 주소에 대한 내용이다.”

이 문항의 함정이 정확히 그것입니다. 32비트/128비트는 IP 주소(IPv4/IPv6)의 이야기인데, 그걸 MAC 주소에 갖다 붙여 놓은 겁니다. 앞 두 문단이 2계층과 3계층을 워낙 정확하게 설명해 두어서 마지막 문단도 같은 결로 읽히게 만든 문제였는데, 계층을 섞었다는 것을 잡아내셨습니다. 이건 최근 여러 회차에 걸쳐 반복해 온 “2계층 MAC / 3계층 IP” 경계가 자리 잡았다는 뜻입니다.

0.5점이 남은 이유는 원인 진단 부분입니다. 명제는 주소 체계 이야기 말고도 하나를 더 틀렸습니다 — “스위치 한 대에 붙일 수 있는 단말기 수의 한계”가 주소 공간 때문이라는 진단 자체입니다. 실제 이유는 이렇습니다.

  • 스위치가 연결할 수 있는 단말기 수의 한계 → 주소가 모자라서가 아니라 물리적 포트 수와 장비 용량의 문제
  • MAC 주소 관리가 어려워지는 것 → 주소가 부족한 게 아니라 관리가 힘들어지는

그리고 이 한계를 넘으려고 등장한 것은 IPv6가 아니라 WAN이고, 그 통신을 맡는 게 3계층의 라우터입니다. 즉 명제는 문제도 해법도 엉뚱한 계층에서 찾고 있었습니다.

출처: server/game_server/2/2025-06-30-game_server_2_1.md


📌 복습 포인트

  • Q4 데이터 레이스 (이번 회차 최우선)num++도 세 연산으로 쪼개진다는 것, primes재할당 시 포인터가 바뀌어 다른 스레드가 해제된 메모리를 건드린다는 것. 두 성질은 원자성 + 일관성(순서 보장 ✕), 기법은 임계 영역 / 뮤텍스 / 잠금server/game_server/1/2025-05-30-game_server_1_5.md
  • Q2 수평 확장의 두 갈래 — 기본형은 ID → 해시 함수 → 샤드 인덱스(계산), 매핑 DB는 키 → 표 조회(기록). 이 차이가 리해시 문제의 유무를 가른다. 매핑 DB의 위험은 SPOF, 대응은 매핑 DB에도 샤딩server/game_server/9/2026-03-26-game_server_10_2.md
  • Q2 일관된 해시의 한계 조건 — 데이터가 많아질 때가 아니라 샤드 수가 크게 변할 때 비싸진다 → 같은 문서
  • Q1 발전 4단계 — 구분 축은 참여 인원이다. 단독 → 1:1세션(3명 이상, 한 명이 호스트 겸업) → 데디케이티드(전용 서버) → server/game_server/4/2026-02-08-game_server_4_1.md
  • Q5 마무리 한 조각 — 스위치의 한계는 주소 공간이 아니라 포트 수·관리 부담의 문제이고, 그 해법은 IPv6가 아니라 WAN과 라우터server/game_server/2/2025-06-30-game_server_2_1.md

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

댓글남기기