Korean National Assembly Database

열린국회정보 Open API 8종을 결합하여 구축한 대한민국 국회 법안 생애주기 마스터 데이터베이스. 17대부터 22대까지의 발의, 심사, 표결, 공포 전 과정을 추적합니다.

110,778 Total Bills
6 Assemblies (17-22대)
17,638 Laws Enacted
2004-2026 Date Range
DATA ARCHITECTURE

데이터 구조와 수집 파이프라인

8개의 열린국회정보 Open API를 결합하여 법안 단위(bill-level) 마스터 테이블과 회의 단위(meeting-level) 위성 테이블을 구축합니다.

Collection Pipeline
열린국회정보
Open API
open.assembly.go.kr
Phase 1: Batch
의원발의법률안
접수목록 (BILLRCP)
심사정보 (BILLJUDGE)
표결현황
처리의안
~180 requests / 대수
Phase 2: Per-Bill
BILLINFODETAIL
BILLJUDGECONF
BILLLWJUDGECONF
~17,000 x 3 calls / 대수
Phase 3: Integration
BILL_ID JOIN
Derived Variables
.parquet + .sqlite
법안의 여정 (Life of a Bill)
발의
ppsl_dt
17,205
소관위 회부
committee_dt
16,071
소관위 심사
cmt_proc_dt
4,060
법사위
law_proc_dt
459
본회의
rgs_rsln_dt
4,729
공포
prom_dt
1,060
각 단계의 날짜가 개별 변수로 기록됨 · 22대 법안 기준 건수 표시
Master Database Schema
📑
master_bills
법안 단위 마스터 테이블
1 row = 1 bill
ID bill_id, bill_no, age, bill_kind, bill_nm
발의자 ppsr_kind, rst_proposer, rst_mona_cd, publ_mona_cd
타임스탬프 ppsl_dt → committee_dt → cmt_proc_dt → law_proc_dt → rgs_rsln_dt → prom_dt
결과 status, passed, enacted, proc_rslt
표결 vote_yes, vote_no, vote_abstain
파생 days_to_proc, days_to_committee
54 variables · 17,205 rows (22대)
📅
committee_meetings
위원회 회의 기록 (1:N)
1 row = 1 bill-meeting
bill_id (FK), conf_name, conf_dt, conf_result
108,749 rows (22대)
judiciary_meetings
법사위 회의 기록 (1:N)
1 row = 1 bill-meeting
bill_id (FK), conf_name, conf_dt, conf_result
1,082 rows (22대)
SECTION 1

Cross-Assembly Overview

17대 국회(2004)부터 22대(2024-)까지 약 20년간 발의된 법안 현황을 조망합니다. 발의 건수는 꾸준히 증가하는 반면, 가결률은 지속적으로 하락하는 추세를 보입니다.

Key finding: 17대에 8,369건이었던 발의 법안 수가 21대에는 26,711건으로 약 3.2배 증가했습니다. 반면, 광의 가결률(대안반영 포함)은 53.3%에서 35.7%로, 협의 가결률(공포 기준)은 30.4%에서 13.3%로 하락했습니다. '입법 인플레이션'의 전형적 패턴입니다. 22대는 아직 진행 중이므로 최종 수치는 변동될 수 있습니다.
SECTION 2

22대 국회 심층 분석

22대 국회의 17,205건 법안을 위원회별, 처리 상태별, 발의자 유형별로 살펴봅니다. 현재 진행 중인 회기이므로 주기적으로 갱신됩니다.

발의자 유형 비교: 정부제출 법안과 위원장 발의 법안은 의원 발의 법안 대비 현저히 높은 가결률을 보입니다. 위원장 발의 법안은 소관위에서 여야 합의로 마련된 대안(위원회안)이기 때문에 사실상 전수 통과합니다. 의원 발의 법안의 실질 가결률은 3.3%에 불과합니다.
SECTION 3

입법 타임라인

22대 국회 개원(2024.5) 이후 월별 법률안 발의 추이와, 발의자 유형에 따른 처리 소요일 분포를 보여줍니다.

처리 소요일: 정부 제출 법안은 중위 처리기간이 상대적으로 짧으며 분포도 좁은 편입니다. 의원 발의 법안은 편차가 크고, 장기 계류되는 사례가 많아 분포의 꼬리가 깁니다.
SECTION 4

입법 퍼널

법률안이 발의부터 공포까지 각 단계를 얼마나 통과하는지 보여줍니다. 대안반영(위원회 대안에 흡수)된 법안은 별도 경로를 거치므로, 단계별 수치가 단순 감소하지 않을 수 있습니다.

생존율: 22대 법률안 16,907건 중 소관위에 상정된 것은 12,935건(76.5%), 소관위 처리까지 이른 것은 4,060건(24.0%), 최종 공포에 이른 것은 1,060건(6.3%)입니다. 대부분의 법안이 소관위 단계에서 계류 또는 대안반영으로 소멸합니다.
SECTION 5

표결 패턴

본회의 기명 표결이 이루어진 1,236건의 법안에 대한 투표 현황입니다. 찬성률 80% 미만 법안을 '쟁점 법안'으로 표시하여 여야 갈등 법안을 식별합니다.

표결 분포: 대다수 법안은 찬성률 90% 이상으로 가결되며, 이는 본회의 상정 전에 이미 여야 합의가 이루어졌음을 시사합니다. 찬성률이 낮은 쟁점 법안은 소수이지만, 정치적으로 중요한 법안이 포함되어 있습니다.
SECTION 6

의원 발의 순위

22대 국회에서 법률안을 가장 많이 대표발의한 의원 20인입니다. 막대 색상은 해당 의원의 협의 가결률(enacted rate)을 나타냅니다.

SECTION 7

데이터 구축 현황

대수별 마스터 데이터 구축 수준을 정리합니다. 17-22대 모두 열린국회정보 API를 결합한 Full Master이며, 공포 건수·소관위 처리·처리 소요일 등 법안 생애주기 전체를 포함합니다. 표결 데이터(건별 찬반)는 20-22대에서 API로 제공됩니다.

대수총 법안수준표결 데이터표결 건수 소관위 처리공포 건수공동발의자처리 소요일
17대 8,369 Full Master - - O 1,912 O O
18대 14,762 Full Master - - O 2,353 O O
19대 18,735 Full Master - - O 2,793 O O
20대 24,996 Full Master O 3,435 O 3,195 O O
21대 26,711 Full Master O 3,220 O 2,959 O O
22대 17,205 Full Master O 1,236 O 1,060 O O
갱신 안내: 22대 데이터는 현재 진행 중인 회기이므로 주기적으로 갱신됩니다. 16대 이전 데이터는 API 제공 범위 밖이므로 PDF 본회의 회의록에서 별도 추출합니다.
SECTION 8

이 데이터로 답할 수 있는 연구 질문들

아래는 본 데이터베이스를 활용하여 탐구할 수 있는 연구 질문입니다. 각 질문에 필요한 변수, 방법론, 그리고 데이터 가용 수준을 함께 표기합니다.

Descriptive

입법 인플레이션과 중복 발의

법안 발의 건수의 급증은 실질적 의제 다양성 확대인가, 아니면 동일 법률에 대한 중복 발의(credit claiming)의 증가인가?

핵심 변수: bill_nm, ppsl_dt, rst_proposer, committee_nm
방법론: 법안명 텍스트 클러스터링, 대수별 고유 법률명 수 대비 총 발의 건수 추세
데이터: 17-22대 lite master만으로 가능
Quick preview: 22대에서 조세특례제한법 일부개정법률안만 661건이 발의되었습니다. 17,205건 중 고유 법안명은 2,984종뿐입니다.
Causal Inference

여소야대와 입법 효율

Divided government(여소야대)는 법안 통과율과 처리 소요기간에 어떤 영향을 미치는가? 어느 입법 단계에서 그 효과가 가장 두드러지는가?

핵심 변수: passed, enacted, days_to_proc, ppsr_kind + 외부 여소야대 코딩
방법론: DiD (대통령 교체/선거 전후), 단계별 생존분석
데이터: Phase 2 완료 후 17-22대 full master 권장. 20-21대(박근혜 탄핵 전후)가 자연실험 조건.
Quick preview: 통과율이 17대 53.3%에서 21대 35.7%로 꾸준히 하락. 이것이 여소야대의 빈도 증가 때문인지, 발의 건수 증가 때문인지 분리해야 합니다.
Survival Analysis

위원회 병목과 법안의 죽음

법안은 입법 과정의 어느 단계에서 "죽는가"? 위원회별로 병목 패턴이 다른가? 위원회 위원장의 정당이 심사 속도에 영향을 미치는가?

핵심 변수: ppsl_dt ~ prom_dt (전 lifecycle 타임스탬프), committee_nm, status
방법론: Multi-state survival model, Random Survival Forests, Cox proportional hazards
데이터: 22대 full master (lifecycle 날짜 완비). 확장 시 17-22대 전체.
Quick preview: 22대 법률안 16,907건 중 소관위 처리까지 도달한 것은 24.0%. 재정경제기획위원회 가결률 0.5%로 최저, 문화체육관광위원회 6.1%로 최고.
Causal Inference

법사위 Veto Player 가설

법제사법위원회가 야당 법안의 사실상 거부권자(veto player)로 기능하는가? 법사위 체계/자구 심사가 정치적 필터링 기제인가?

핵심 변수: law_submit_dt, law_proc_dt, law_proc_rslt + 발의자 여야 코딩
방법론: 법사위 단계 체류기간의 발의자 정당별 차이, hazard models
데이터: 22대 full master + judiciary_meetings 위성 테이블. Phase 2 완료 후 다세대 비교 가능.
Quick preview: 법사위 회부까지 도달하는 법안은 22대 기준 3.0% (510건)에 불과. 도달한 법안의 가결률은 99.6% (459/461건). 핵심 필터는 법사위 회부 여부 자체.
Machine Learning

법안 통과 예측과 제도적 변수의 중요도

법안 특성(발의 주체, 위원회, 공동발의 규모, 시기 등)으로 통과 여부를 예측할 수 있는가? 어떤 변수가 가장 예측력이 높은가?

핵심 변수: passed/enacted (Y), ppsr_kind, committee_nm, proposer_text(공동발의자 수 파싱), ppsl_dt(시기)
방법론: Gradient Boosting (XGBoost/LightGBM) + SHAP interpretability
데이터: 17-22대 전체. 완료된 국회(17-21대)로 학습, 22대로 검증.
Quick preview: 발의 주체가 가장 강력한 예측 변수일 가능성 높음. 의원 가결률 3.3% vs 정부 62.6% vs 위원장 99.7% - 이 격차가 다른 변수 통제 후에도 유지되는지가 관건.
Network Analysis

공동발의 네트워크와 입법 성과

교차정당 공동발의 관계가 실제 법안 통과율을 높이는가? 네트워크상 중심성이 높은 의원의 법안이 더 성공적인가?

핵심 변수: rst_mona_cd, publ_mona_cd(파싱 → edge list), passed, enacted
방법론: Cosponsorship 네트워크 구축, centrality 측정, GNN (Graph Neural Networks)
데이터: 17-22대 의원발의 법안 (93,288건). na-legislative-events-korea 프로젝트와 직접 연결 가능.
Quick preview: publ_mona_cd 필드를 파싱하면 의원 간 공동발의 edge list를 즉시 생성 가능. 22대 기준 421명의 대표발의자, 13,894개의 고유 공동발의 조합이 존재합니다.
Descriptive / NLP

정책 의제 공간의 구조와 변화

한국 국회의 정책 의제 공간은 어떤 구조이며, 정당 간/대수 간 어떻게 변화하는가? 여야가 다른 주제의 법안을 발의하는가?

핵심 변수: bill_nm (법안명 텍스트), ppsr_kind, rst_mona_cd + 의원 정당 정보
방법론: Korean LLM 임베딩 (KLUE-RoBERTa), UMAP 시각화, Zero-shot CAP 분류
데이터: 17-22대 법안명 (110,778건). 법안 원문 크롤링 시 더 정밀한 분류 가능.
Quick preview: 법안명만으로도 주제 분류 가능. "부동산", "조세", "형법" 등 키워드 기반 초기 분류 후 임베딩으로 세밀한 의제 매핑이 가능합니다.
SECTION 9

Getting Started

아래 코드 예시를 통해 데이터를 로드하고 기본적인 분석을 시작할 수 있습니다. Python + pandas 환경을 전제합니다.

1. 데이터 로드
import pandas as pd

# 22대 Full Master (전 생애주기 타임스탬프 포함)
master = pd.read_parquet("data/processed/master_bills_22.parquet")
print(f"22대: {len(master):,} bills, {len(master.columns)} variables")

# 위원회 회의 기록 (1:N)
meetings = pd.read_parquet("data/processed/committee_meetings_22.parquet")

# 17-21대 Full Master
for age in range(17, 22):
    df = pd.read_parquet(f"data/processed/master_bills_{age}.parquet")
    print(f"{age}대: {len(df):,} bills, {len(df.columns)} variables")
2. 기본 필터링
# 법률안만 필터링
laws = master[master["bill_kind"] == "법률안"]

# 의원 발의만
member_bills = laws[laws["ppsr_kind"] == "의원"]

# 특정 위원회
health = laws[laws["committee_nm"] == "보건복지위원회"]

# 처리 완료된 법안만
processed = laws[laws["status"] != "계류중"]

# 가결된 법안만
enacted = laws[laws["enacted"] == 1]
3. 공동발의자 네트워크 Edge List 생성
# publ_mona_cd를 파싱하여 edge list 생성
edges = []
for _, row in member_bills.iterrows():
    if pd.notna(row["publ_mona_cd"]) and pd.notna(row["rst_mona_cd"]):
        co_sponsors = row["publ_mona_cd"].split(",")
        for cs in co_sponsors:
            edges.append({
                "bill_id": row["bill_id"],
                "from": row["rst_mona_cd"],
                "to": cs.strip(),
                "passed": row["passed"],
            })

edge_df = pd.DataFrame(edges)
print(f"Edges: {len(edge_df):,}")  # 수십만 개의 공동발의 관계
4. 다세대 통합 분석
# 17-22대 통합
frames = []
for age in range(17, 23):
    suffix = "" if age == 22 else "_lite"
    path = f"data/processed/master_bills_{age}{suffix}.parquet"
    df = pd.read_parquet(path)
    frames.append(df)

all_bills = pd.concat(frames, ignore_index=True)
print(f"Total: {len(all_bills):,} bills across {all_bills['age'].nunique()} assemblies")

# 대수별 가결률 추이
trend = all_bills.groupby("age").agg(
    total=("bill_id", "count"),
    enacted=("enacted", "sum"),
).assign(rate=lambda x: x["enacted"] / x["total"] * 100)
print(trend)
5. SQLite로 쿼리하기
import sqlite3

conn = sqlite3.connect("data/processed/master_bills_22.sqlite")

# 위원회별 통과율
query = """
SELECT committee_nm,
       COUNT(*) as total,
       SUM(enacted) as enacted,
       ROUND(SUM(enacted) * 100.0 / COUNT(*), 1) as rate
FROM bills
WHERE bill_kind = '법률안' AND committee_nm IS NOT NULL
GROUP BY committee_nm
HAVING total >= 50
ORDER BY rate DESC
"""
pd.read_sql(query, conn)

R Implementation

R(tidyverse + arrow) 환경에서의 동일한 분석 코드입니다.

1. 데이터 로드 (R)
library(arrow)
library(dplyr)
library(tidyr)
library(ggplot2)

# 22대 Full Master
master <- read_parquet("data/processed/master_bills_22.parquet")
cat(sprintf("22대: %s bills, %d variables\n", format(nrow(master), big.mark=","), ncol(master)))

# 위원회 회의 기록
meetings <- read_parquet("data/processed/committee_meetings_22.parquet")

# 17-22대 통합
all_bills <- bind_rows(
  lapply(17:22, function(age) read_parquet(sprintf("data/processed/master_bills_%d.parquet", age)))
)
cat(sprintf("Total: %s bills\n", format(nrow(all_bills), big.mark=",")))
2. 대수별 가결률 추이 (R + ggplot2)
library(tidyplots)  # 또는 ggplot2

trend <- all_bills %>%
  group_by(age) %>%
  summarise(
    total = n(),
    enacted = sum(enacted),
    passed = sum(passed),
    .groups = "drop"
  ) %>%
  mutate(
    enact_rate = enacted / total * 100,
    pass_rate = passed / total * 100
  )

# tidyplots 방식
trend %>%
  pivot_longer(cols = c(enact_rate, pass_rate),
               names_to = "measure", values_to = "rate") %>%
  tidyplot(x = factor(age), y = rate, color = measure) %>%
  add_data_points(size = 3) %>%
  add_line() %>%
  adjust_colors(c("#D55E00", "#0072B2")) %>%
  adjust_labels(x = "국회 대수", y = "가결률 (%)") %>%
  remove_title() %>%
  adjust_size(width = 150, height = 90) %>%
  save_plot("output/passage_trend.pdf")
3. 위원회별 가결률 비교 (R)
cmt_stats <- master %>%
  filter(bill_kind == "법률안", !is.na(committee_nm)) %>%
  group_by(committee_nm) %>%
  summarise(
    total = n(),
    enacted = sum(enacted),
    passed = sum(passed),
    avg_days = mean(days_to_proc, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  filter(total >= 50) %>%
  mutate(enact_rate = enacted / total * 100) %>%
  arrange(desc(total))

# 가결률 수평 막대
cmt_stats %>%
  tidyplot(x = enact_rate, y = reorder(committee_nm, enact_rate)) %>%
  add_barstack_absolute() %>%
  add_reference_lines(x = median(cmt_stats$enact_rate), linetype = "dashed") %>%
  adjust_colors("#57068C") %>%
  adjust_labels(x = "가결률 (%)", y = "") %>%
  remove_title() %>%
  adjust_size(width = 150, height = 120) %>%
  save_plot("output/committee_rates.pdf")
4. 생존분석 (R + survival)
library(survival)
library(fixest)

# 처리까지의 생존 데이터 구성
surv_data <- master %>%
  filter(bill_kind == "법률안", ppsr_kind %in% c("의원", "정부", "위원장")) %>%
  mutate(
    # 관측 종료: 처리일 또는 현재 날짜
    event = as.integer(!is.na(proc_dt)),
    duration = as.numeric(
      difftime(coalesce(proc_dt, Sys.Date()), ppsl_dt, units = "days")
    )
  ) %>%
  filter(duration >= 0)

# Kaplan-Meier by proposer type
km <- survfit(Surv(duration, event) ~ ppsr_kind, data = surv_data)
plot(km, col = c("#E69F00", "#56B4E9", "#009E73"),
     xlab = "Days", ylab = "Survival probability",
     lwd = 2, mark.time = FALSE)
legend("topright", levels(factor(surv_data$ppsr_kind)),
       col = c("#E69F00", "#56B4E9", "#009E73"), lwd = 2)

# Cox PH model
cox <- coxph(Surv(duration, event) ~ ppsr_kind + committee_nm, data = surv_data)
summary(cox)
5. 회귀분석: 통과 여부 예측 (R + fixest)
library(fixest)

# 공동발의자 수 파싱
reg_data <- master %>%
  filter(bill_kind == "법률안", ppsr_kind == "의원") %>%
  mutate(
    n_cosponsors = stringr::str_extract(proposer_text, "\\d+") %>% as.integer(),
    month = format(ppsl_dt, "%Y-%m")
  ) %>%
  filter(!is.na(n_cosponsors))

# Linear probability model with committee FE
m1 <- feols(enacted ~ n_cosponsors | committee_nm, data = reg_data)
m2 <- feols(passed ~ n_cosponsors | committee_nm, data = reg_data)

etable(m1, m2, se = "hetero",
       headers = c("Enacted", "Passed (broad)"),
       notes = "Committee FE included. Robust SE.")
추가 리소스: CODEBOOK.md에 54개 변수의 상세 설명, DATA_AVAILABILITY.md에 대수별 데이터 가용성 및 제약사항, MASTER_DATA_PLAN.md에 확장 로드맵이 정리되어 있습니다.