---
title: 합성패널은 어떻게 만들어지는가
date: 2026-08-19
category: 방법론
tags: 합성패널, 패널설계, 반응함수
summary: 가상 시민 한 명의 22칸 기록을 펼치고, 4,433명이 어떤 유형으로 나뉘며, 네 개의 질문에 각자 어떻게 답하는지를 실제 산출값으로 따라간다.
---

Reble.ai는 현실 세계를 반영하는 동적 사회 시뮬레이션 엔진이다. 그 엔진의 부품 중 가장 자주 오해받는 것이 **합성패널**이다. "가상의 사람을 만들어 여론을 예측한다"는 설명은 맞지만, 그 한 문장만으로는 무엇이 관측이고 무엇이 가정인지 알 수 없다.

[지난 글](/blog/posts/dp-synthetic-panel-4433/)이 시스템 전체를 위에서 내려다봤다면, 이 글은 **한 명에서 출발해 위로 올라간다.** 합성패널 한 명을 펼쳐 22칸을 전부 보이고, 그 한 명이 질문에 어떻게 답하는지를 실제 파라미터로 계산해 보인 다음, 4,433명이 어떻게 하나의 결과가 되는지까지 따라간다.

이 글이 답하는 질문은 하나다. **합성패널 한 명은 무엇으로 이루어져 있고, 무엇을 묻으면 어떻게 답하는가.**

## 1. 합성패널 한 명은 22개의 칸이다  {#s1}

추상적인 설명 대신 실제 기록 한 장을 그대로 펼친다.

<figure class="reble-figure wide"><style>.reble-figure{margin:2.2rem 0}.reble-figure svg{width:100%;height:auto;display:block}.reble-figure figcaption{margin:.7rem 0 0;font-size:.86em;opacity:.72;line-height:1.7}/* 가로로 정보가 많은 도표는 본문 폭(41rem)을 넘어 좌우로 벌린다.    figcaption 은 본문 폭에 맞춰 되돌려야 읽기 리듬이 깨지지 않는다. */.reble-figure.wide{width:min(56rem,calc(100vw - 2.5rem));max-width:none;margin-left:50%;transform:translateX(-50%)}.reble-figure.wide figcaption{max-width:41rem;margin-left:auto;margin-right:auto}@media(max-width:640px){.reble-figure{overflow-x:auto}.reble-figure svg{width:660px}.reble-figure.wide{width:100%;margin-left:0;transform:none}}</style>
<!--figure: panel-card.svg-->
<figcaption><b>도표 1.</b> 합성패널 <code>KR-V2-281687</code>의 전체 기록. 실존 인물이 아니며, 인구분포를 보존하도록 생성된 가상 시민이다. 칸 밝기는 정보의 출처 등급을 뜻한다.</figcaption></figure>

이 사람은 **대전 동구에 사는 64세 여성**이다. 고졸, 서비스직, 소득 1분위, 기혼, 전남 출신. 이념은 진보, 지지정당은 더불어민주당, 정치관심도는 낮음, 투표의향은 있음.

중요한 것은 22칸이 **같은 자격을 갖지 않는다**는 점이다.

| 등급 | 칸 수 | 내용 | 성격 |
|---|---|---|---|
| **A** | 10 | 거주지·시군구·성별·연령·학력·직업·소득·혼인·출신지역 | 통계청 인구총조사에서 직접 관측 |
| **B** | 4 | 이념·지지정당·정치관심도·투표의향 | 조사 데이터를 학습한 모델이 예측 |
| **C** | 8 | panel_id·확률값 3개·권역·이념3·셀비중·가중치 | 파이프라인이 계산 |

B등급 옆에는 반드시 확률이 따라붙는다. 이 사람의 `_지지정당_proba`는 **0.565**다. "민주당 지지자"라고 단정한 것이 아니라 **56.5%의 확신으로 그렇게 분류했다**는 뜻이고, 시스템은 이 불확실성을 끝까지 들고 간다.

## 2. 4,433명은 어디서 왔고, 몇 종류인가  {#s2}

<figure class="reble-figure wide">
<!--figure: panel-pipeline.svg-->
<figcaption><b>도표 2.</b> 통계청 인구구조에서 출발해 민주당 지지층 4,433명에 도달하기까지의 6단계. 막대 높이는 인원(4제곱근 축).</figcaption></figure>

79만 4,000명의 합성인구를 만들고, 정치 성향을 예측해 붙이고, 최신 여론조사에 맞춰 재보정한 뒤, 지역·성별·연령을 대표하는 **1만 249명**을 뽑는다. 그중 지지정당이 더불어민주당인 사람이 **정확히 4,433명**이다.

그러면 이 4,433명은 몇 종류의 사람인가.

<figure class="reble-figure wide">
<!--figure: panel-types.svg-->
<figcaption><b>도표 3.</b> 권역 8 × 연령대 7 × 성별 2 × 이념 3 = 이론상 336가지 조합 중 실제로 존재하는 유형은 202개다. 가로축은 유형의 크기, 세로축은 그 크기의 유형이 몇 개인지.</figcaption></figure>

가장 큰 유형은 「인천·경기 · 40대 · 여성 · 진보」로 **145명**이고, **혼자뿐인 유형이 27개** 있다. 여기에 학력·직업·소득·혼인까지 넣으면 유형은 **3,249개**가 되고 한 유형당 평균 1.36명이 된다. 즉 **거칠게 보면 202종이고, 세밀하게 보면 사실상 전원이 다른 사람**이다.

속성별로 값이 몇 가지인지도 그대로 세어진다 — 권역 8, 연령대 7, 성별 2, 이념 5단계(진보·중도진보·중도·중도보수·보수), 학력 10, 직업 7, 소득 5분위, 혼인 4, 출신지역 17.

## 3. 표본을 실제 선거인단으로 되돌린다  {#s3}

여기까지는 "민주당 지지층"의 표본이지 "권리당원"이 아니다. 둘의 구조는 반대 방향으로 어긋나 있다.

<figure class="reble-figure wide">
<!--figure: panel-reweight.svg-->
<figcaption><b>도표 4.</b> 원래 표본 비중(위 막대)과 맞춰야 할 실제 권리당원 구조(아래 막대). 수도권은 줄이고 호남은 키운다.</figcaption></figure>

표본에서 서울·인천·경기는 **52.4%**인데 실제 권리당원 구조에서는 42.1%다. 반대로 광주·전라는 표본 **17.0%**인데 실제로는 **33.0%**다. 그래서 호남 합성패널 한 명의 무게를 평균 **1.94배**로 올리고 수도권은 낮춘다.

이 조정 뒤에는 합성패널 한 명이 더 이상 한 명이 아니다. 어떤 사람은 수백 명을 대표하고 어떤 사람은 그보다 적게 대표한다. 도표 1의 `weight` 칸(1.033)이 그 값이다.

## 4. 무엇을 묻고, 어떻게 답하는가  {#s4}

합성패널은 만들어 놓고 끝나는 명단이 아니다. **질문을 받고 답하는 응답자**다. 현재 이 패널이 답하는 질문은 네 개다.

<figure class="reble-figure wide">
<!--figure: panel-questions.svg-->
<figcaption><b>도표 5.</b> 합성패널이 답하는 네 개의 질문과 선택지. 답은 하나를 고르는 방식이 아니라 선택지마다 확률을 매기는 방식이다.</figcaption></figure>

여기가 사람과 다른 지점이다. 실제 응답자는 "김민석"이라고 하나를 고르지만, 합성패널은 **「김민석 30.3% · 정청래 27.6% · 송영길 13.0% · 유보 29.1%」처럼 확률벡터로 답한다.** 한 명 안에 여러 가능성이 동시에 들어 있고, 시뮬레이션이 한 번 돌 때마다 그 확률에 따라 한 장을 뽑는다.

그리고 유형이 다르면 같은 질문에 답이 확연히 달라진다.

<figure class="reble-figure wide">
<!--figure: panel-answers.svg-->
<figcaption><b>도표 6.</b> 세 유형이 네 질문에 답한 실제 산출값(%). 강조된 첫 막대는 각 유형의 최다 선택지다. 3% 미만이거나 상위 5개 밖 선택지는 생략했다.</figcaption></figure>

읽는 법은 이렇다.

- **광주·전라 × 진보** (793명) — 국정 평가는 **80% 긍정**, 정당 지지는 민주 70%, 차기 대선주자도 김민석 27%, 당대표도 김민석 30%. 네 질문이 한 방향으로 정렬돼 있다.
- **대구·경북 × 보수** (667명) — 국정 평가 **68% 부정**, 국민의힘 63%. 그런데 당대표 질문에서는 **유보가 47%**다. 민주당 경선에 관심이 없다는 사실이 "무응답"이 아니라 **유보 확률 47%**라는 숫자로 표현된다.
- **인천·경기 × 중도** (1,662명) — 국정 평가가 49% 대 45%로 팽팽하고, 차기 대선주자에서 **유보가 22%로 1위**다. 마음을 정하지 않은 상태 자체가 하나의 응답으로 기록된다.

당대표 시뮬레이션이 쓰는 것은 **q004** 하나다. 다만 그대로 쓰지 않는다. 실제 투표지에는 "유보" 칸이 없으므로, 유보 확률을 제거하고 나머지 후보에게 비례 배분해 투표지 위의 확률로 바꾼다. 이것이 지난 글에서 말한 **후보 선택확률 b**다.

## 5. "투표하러 나올 것인가"는 확률로 답한다  {#s5}

두 번째 핵심 질문은 선택이 아니라 **참여**다. 이 답은 공식 하나로 계산된다.

```
τ = 1 / (1 + e^−(α_권역 + γ · z_연령))          γ = 1.0
z_연령 = 18-29 −1.532 · 30대 −0.675 · 40대 +0.118
         50대 +0.680 · 60대 +1.634 · 70+ −0.225
α_권역 = 충청 −0.6455 · 부울경 +0.1443 · 제주 −0.9156
         인천 −0.0055 · 강원·대구·경북 +0.0328
```

`z_연령`은 연령대별 투표 의향의 상대 순서만 담는다. 60대가 가장 높고 18~29세가 가장 낮으며, **70세 이상은 오히려 −0.225로 내려간다** — 거동 문제로 실제 참여가 떨어지는 현상이 그대로 들어 있다. `α_권역`은 이미 개표가 끝난 다섯 권역의 실측 투표율에 정확히 맞도록 역산한 값이다(재현 오차 0.0000%p).

앞서 펼친 그 사람에게 이 공식을 적용하면 이렇게 된다.

<figure class="reble-figure wide">
<!--figure: panel-turnout.svg-->
<figcaption><b>도표 7.</b> 참여함수 곡선 위에 실제 합성패널 세 명을 올린 것. 권역이 곡선 위에서 좌우 위치를 정하고, 연령이 그 위치를 밀어 올리거나 내린다.</figcaption></figure>

| 합성패널 | α (권역) | z (연령) | 참여확률 τ |
|---|---|---|---|
| 대전 동구 · 여성 64세 | −0.6455 | +1.634 | **72.9%** |
| 인천 · 남성 55세 | −0.0055 | +0.680 | **66.3%** |
| 부산 서구 · 여성 29세 | +0.1443 | −1.532 | **20.0%** |

부산의 29세는 권역 자체는 참여율이 높은 곳(α가 양수)인데도 연령이 크게 끌어내려 20%에 그친다. 반대로 대전의 64세는 권역이 불리한데도 연령이 밀어 올려 72.9%가 된다. **같은 나이라도 사는 곳이 다르면, 같은 곳이라도 나이가 다르면 답이 달라진다** — 그것이 이 곡선 하나에 담겨 있다.

아직 개표되지 않은 권역에는 α가 없다. 그런 곳은 값을 하나로 정하지 않고 **투표율 자체를 매번 추첨**한다.

## 6. 한 명의 확률이 결과가 되기까지  {#s6}

이제 재료가 모두 모였다. 합성패널 한 명이 가진 것은 세 가지다 — **참여확률 τ**, **후보 선택확률 b**, **대표 인원 w**.

<figure class="reble-figure wide">
<!--figure: panel-journey.svg-->
<figcaption><b>도표 8.</b> 개인의 확률이 최종 득표율이 되는 경로. 어느 단계에서도 "이 사람은 누구를 찍는다"고 단정하지 않는다.</figcaption></figure>

권역별 예측 구성은 이렇게 계산된다.

```
ŝ = Σ (w · τ · b) / Σ (w · τ)
     └ 많이 대표하고, 투표하러 나올 사람의 선택이 더 크게 반영된다
```

여기서 끝이 아니다. 인구 구성만으로 설명되지 않는 지역 차이(δ)를 실측에서 뽑아 더하고, 당원 70%와 국민여론조사 30%를 합치고, 과반 미달이면 3위 표 이양을 적용한다. 그리고 이 전체를 **1만 5,000번 반복**한다. 매번 투표율·지역 격차·이양률·연령 시나리오를 새로 추첨하기 때문에 결과는 하나의 숫자가 아니라 분포로 나온다.

[지난 채점 글](/blog/posts/dp-leader-scorecard/)에서 이 파이프라인이 실제 개표와 얼마나 맞았는지 기록했다 — 최종 득표율은 1.2%p 차이로 맞혔고, 호남 격차에서는 12.8%p 편차가 났다.

## 결론  {#conclusion}

합성패널의 정체는 세 문장으로 줄일 수 있다.

**첫째, 한 명은 22칸짜리 기록이다.** 그중 10칸은 통계청에서 관측한 사실이고, 4칸은 조사를 학습한 모델의 예측이며, 8칸은 계산값이다. 어느 칸이 어느 등급인지가 파일에 남아 있다.

**둘째, 한 명은 확률로 답한다.** "김민석을 찍는다"가 아니라 "김민석 30.3%, 정청래 27.6%, 유보 29.1%"로 답하고, 참여 여부도 72.9%처럼 확률이다. 단정하지 않는 것이 이 설계의 핵심이다.

**셋째, 4,433명은 202개 유형으로 갈리고 세밀하게는 3,249개로 갈린다.** 유형마다 네 질문에 다르게 답하고, 그 차이가 가중치를 타고 최종 결과의 차이를 만든다.

그리고 반드시 덧붙여야 할 한계가 있다. **합성패널은 실존 인물이 아니다.** 개인정보를 모아 만든 명단이 아니라 분포를 보존하도록 생성된 통계적 시민이며, `panel_id`는 합성 식별자다. 또한 이 패널에는 "실제 권리당원인가"를 나타내는 칸이 없어 "민주당 지지층의 특성이 권리당원과 비슷하다"는 가정이 들어간다. 지난 채점에서 호남 편차가 크게 난 지점도 바로 여기와 맞닿아 있다.

패널이 실제로 어떻게 움직이는지는 [민주당 당대표 시뮬레이션](/dp-leader/)에서 직접 조작해 볼 수 있다. 조건을 바꾸면 이 글에서 본 확률들이 어떻게 재계산되는지 화면에서 보인다.

## 🧑 독자 질문 — 합성패널 한 명은 몇 명인가  {#qa}

이 블로그와 합성패널 시뮬레이션을 해보고 가장 많이 나오는 질문 하나를 그대로 옮긴다.

> **합성패널 한 명은 실제 사람 한 명인가, 아니면 여러 명을 대표하는가? 그러면 합성패널 20명은 실제 사람 20명에 해당하는가?**

짧게 답하면 **아니다.** 셋으로 나눠서 설명한다.

**첫째, 한 명은 한 명이 아니다.** 4,433명의 합성패널이 152만 7,261명의 권리당원을 대표하므로, 산술적으로 한 명이 평균 **344.5명**을 대표한다. 도표 1에서 본 `weight` 칸이 바로 그 몫을 정하는 값이다.

**둘째, 그 몫이 사람마다 다르다.** 3장에서 표본과 실제 구조를 맞추는 재가중을 했기 때문에, 어디에 사는 합성패널이냐에 따라 짊어지는 인원이 달라진다.

| 권역 | 합성패널 | 1명이 대표하는 실제 인원 | 평균 대비 |
|---|---|---|---|
| 광주·전라 | 752명 | **약 670명** | 1.95배 |
| 대전·세종·충청 | 520명 | 약 314명 | 0.91배 |
| 제주 | 146명 | 약 303명 | 0.88배 |
| 서울·인천·경기 | 2,322명 | 약 277명 | 0.80배 |
| 부산·울산·경남 | 379명 | 약 262명 | 0.76배 |
| 강원·대구·경북 | 314명 | 약 229명 | 0.66배 |

그래서 질문하신 "20명"의 답은 **어디의 20명이냐에 달려 있다.** 호남 합성패널 20명은 실제 권리당원 약 **1만 3,404명**분이고, 수도권 합성패널 20명은 약 **5,538명**분이다. 같은 20명인데 **2.42배** 차이가 난다. 표본에는 수도권이 훨씬 많이 뽑혔지만 실제 권리당원은 호남에 더 많이 몰려 있기 때문이다.

**셋째, 그리고 애초에 1:1로 대응하는 실제 사람이 없다.** 도표 1의 `KR-V2-281687`에 해당하는 실존 인물은 존재하지 않는다. 이 사람은 "대전 동구의 64세 여성 아무개"를 복제한 것이 아니라, **"대전 동구에 사는 64세·고졸·서비스직·1분위·기혼 여성이라는 조건의 사람들이 인구 안에 이만큼 있다"**는 사실을 한 줄로 대표하는 통계 단위다. 대응 관계는 개인 대 개인이 아니라 **분포 대 분포**다.

여기에 한 가지가 더 붙는다. **합성패널 한 명은 한 표도 아니다.** 4장에서 봤듯 이 사람은 "김민석 30.3% · 정청래 27.6% · 유보 29.1%"처럼 확률로 답하므로, 1만 5,000번의 시뮬레이션에서 어떤 회차에는 김민석을, 어떤 회차에는 정청래를 선택한다. 참여 여부조차 72.9% 확률이라 안 나오는 회차도 있다. **한 명이 대표하는 것은 사람 수만이 아니라 그 사람들이 가진 가능성의 폭이기도 하다.**

정리하면 이렇다. 합성패널 한 명은 평균 344명분의 무게를 지고, 그 무게는 지역에 따라 229명에서 670명까지 달라지며, 특정 실존 인물과는 대응하지 않고, 매 시뮬레이션마다 다르게 답할 수 있는 확률 묶음이다.

---

**자료 출처** — 패널 원본 `panel10k.csv`(1만 249명 22속성), 질문별 산출 `panel_q001~q004.json`(각 전국 topline·권역×이념 24세그먼트), 참여함수 파라미터 `turnout_calib.json`(γ·z_연령·α_권역), 재가중 로직 `member_panel.py`, 선택·집계 로직 `dp_choice.py`. 유형 수·속성 가짓수·권역 비중은 `panel10k.csv`를 직접 집계한 값이고, 참여확률 표는 위 공식에 실제 파라미터를 넣어 계산한 값이다. 권리당원 목표 구조는 [지난 글](/blog/posts/dp-synthetic-panel-4433/)과 동일한 당 공표 자료 기준.
