02 분석 — 산업 배분, Λ 보정, 산업별 경로, 취업계수¶
부가가치 프리미엄. 산업 $i$의 연도 $t$ AI 부가가치 프리미엄(연 %p)은
$$p_{i,t} = k \cdot a_i \cdot r(t), \qquad a_i = s_i^{2040} - 1,$$
이다. $s_i^{2040}$은 E4-1(성장에 대한 AI 영향의 정도) 2040년 점수, 1은 척도 최저점('매우 낮음'), $r(t)$는 전체 응답 평균 궤적으로 만든 시점 램프(2025=0, 2040=1)이다. 배율 $k$는 2035년 실질부가가치 가중평균 프리미엄이 $\Lambda$(중심 0.5%p)가 되도록 정한다. AI 확산 경로는 기준 성장률에 프리미엄을 더해 누적한다.
$$VA^{AI}_{i,t} = VA^{AI}_{i,t-1} \times \frac{VA^{기준}_{i,t}}{VA^{기준}_{i,t-1}} \times \left(1 + \frac{p_{i,t}}{100}\right)$$
취업계수. AI 확산에 따른 취업계수 연변화는 $(\varepsilon - 1)\,p_{i,t}$이다. 중심은 고용 중립($\varepsilon=0$)으로, AI가 만드는 추가 부가가치가 고용을 늘리지 않는다고 보아 취업계수가 프리미엄만큼 내려간다. E4·E5 기대 증감률로 구한 업종별 탄력성 $\varepsilon_i = \ln(1+\Delta L_i)/\ln(1+\Delta Y_i)$는 대부분 0 이하이므로 고용 중립은 고용 측 상한이다. 다만 이 탄력성에는 고령화·해외 이전 같은 AI 외 요인이 섞여 있으므로, 그대로 적용한 값은 하방 민감도로 둔다.
2026-10 정비판. 보고서1의 기준 시나리오가 정비되었다. BOKDPM 장기 정상상태를 고치고(잠재성장률 1.8%, 물가안정목표 2%, 실질유가 불변),
실질금리를 1차 차분으로 투입하며, 시나리오 외생 경로의 레버를 연결한 뒤 산업 전망과 정합화를 다시 실행한 결과이다.
이 판은 그 기준 시나리오(data/inputs/base_va_62.csv·base_va_69.csv)만 교체하였고, AI 확산 층(산업 배분 A1, Λ 보정, 고용 중립 취업계수)은 이전 판과 같다.
이전 판 기준 시나리오는 data/published_prev/에 두고 정비 전후 비교와 이전 판 재현 점검에만 쓴다.
8절은 같은 AI 확산 층을 이전 판 기준 시나리오에 적용해 정비 전후를 비교한다.
산출물. output/ai_index_62.csv(비공개), lambda_sensitivity.csv, ai_va_62.csv, ai_va_69.csv, ai_premium_labor_62.csv, ai_premium_labor_69.csv, elasticity_62.csv, allocation_variants.csv, compare_prev.csv
import os, hashlib
import numpy as np, pandas as pd
import config as C
import ai_forecast as F
pd.set_option("display.float_format", lambda v: f"{v:,.3f}")
C.setup()
signal = pd.read_csv(os.path.join(C.INTERIM, "survey_signal_21.csv"), index_col=0)
expect = pd.read_csv(os.path.join(C.INTERIM, "change_expect_21.csv"), index_col=0)
cw = pd.read_csv(C.CROSSWALK)
carve = dict(pd.read_csv(C.CARVEOUT)[["69분화산업", "모산업_62번"]].values)
base62, base69 = F.read_base(C.BASE_62), F.read_base(C.BASE_69)
tot_g = signal.loc["전체", [f"AI성장_{t}" for t in F.TIME_POINTS]].tolist()
print("배분 방식:", C.ALLOCATION)
Python 3.12.10 · pandas 2.2.3 · numpy 2.4.6 · openpyxl 3.1.5 · matplotlib 3.11.0 판: 2026-10 정비판 · 배분 A1 · 취업계수 neutral · Λ 중심 0.5 기준 62 있음 data\inputs\base_va_62.csv 기준 69 있음 data\inputs\base_va_69.csv 이전 판 기준 62 있음 data\published_prev\base_va_62_prev.csv 이전 판 기준 69 있음 data\published_prev\base_va_69_prev.csv 크로스워크 있음 data\crosswalk_21_62.csv 분화표 있음 data\carveout_69.csv 설문 통계표(비공개) 있음 data\private\AI수용도조사_통계표_260417.xlsx 배분 방식: A1
1. 21→62 크로스워크 적용¶
설문 21개 업종을 62개 산업에 대응시킨다. 대응 업종이 없는 7개 산업(농업·임업·어업·공공행정은 전체 평균, 목재·펄프종이·인쇄는 제조업 평균)은 상위 평균으로 대체한다.
idx62 = F.apply_crosswalk(signal, cw)
idx62.to_csv(os.path.join(C.OUTPUT, "ai_index_62.csv"), encoding="utf-8-sig")
print(idx62["대응유형"].value_counts().to_string())
idx62[["62산업", "설문업종", "AI성장_2040"]].sort_values("AI성장_2040", ascending=False).head(8)
(비공개 설문 집계를 보여주는 셀이다. 공개 화면에서는 출력을 생략했다. 자료를 가진 경우 직접 실행하면 표시된다.)
2. 시점 램프 r(t)¶
전체 응답 평균 성장 영향(E4-1)의 4시점 값을 연간 선형보간하고 2025년 0, 2040년 1로 정규화한다. 2035년 값이 Λ 보정의 기준 시점이다.
ramp = F.ramp_factory(tot_g)
pd.Series({y: ramp(y) for y in range(C.START, C.END + 1)}, name="r(t)").to_frame().T
| 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | 2032 | 2033 | 2034 | 2035 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| r(t) | 0.000 | 0.108 | 0.215 | 0.323 | 0.431 | 0.495 | 0.559 | 0.624 | 0.688 | 0.752 | 0.793 |
3. Λ 보정과 민감도¶
Λ는 문헌의 AI 생산성 추정 범위(보수적 약 0.1%p/년 ~ 낙관적 약 1.5%p/년)의 중도인 0.5%p를 중심으로 하고 0.3·0.8을 민감도로 둔다. 목표는 2035년 실질부가가치 가중평균 프리미엄이다.
fn = F.central_premium_fn(idx62, tot_g, C.ALLOCATION)
b25, b35 = base62.loc[C.START].sum() / 1e3, base62.loc[C.END].sum() / 1e3
rows, paths, prems = [], {}, {}
for tgt in C.LAMBDA_SENSITIVITY:
ai, prem = F.project_variant(base62, fn, tgt)
paths[tgt], prems[tgt] = ai, prem
a35 = ai.loc[C.END].sum() / 1e3
rows.append({"Λ(%p)": tgt, "2035 AI확산(조원)": a35, "CAGR(%)": F.cagr(b25, a35, 10),
"기준 대비(%p)": F.cagr(b25, a35, 10) - F.cagr(b25, b35, 10), "수준 차이(조원)": a35 - b35})
sens = pd.DataFrame(rows)
sens.to_csv(os.path.join(C.OUTPUT, "lambda_sensitivity.csv"), index=False, encoding="utf-8-sig")
print(f"기준: {b25:,.1f}조 → {b35:,.1f}조, CAGR {F.cagr(b25, b35, 10):.2f}%")
sens
기준: 2,178.5조 → 2,609.0조, CAGR 1.82%
| Λ(%p) | 2035 AI확산(조원) | CAGR(%) | 기준 대비(%p) | 수준 차이(조원) | |
|---|---|---|---|---|---|
| 0 | 0.300 | 2,658.662 | 2.012 | 0.192 | 49.634 |
| 1 | 0.500 | 2,692.217 | 2.140 | 0.320 | 83.189 |
| 2 | 0.800 | 2,743.259 | 2.332 | 0.512 | 134.231 |
4. 고용 탄력성¶
E4·E5 기대 증감률로 업종별 탄력성을 구한다. 기대 매출 증가율이 5% 미만인 업종은 분모가 0에 가까워 비율이 불안정하므로 제조업·비제조업 평균 탄력성으로 대체한다. 69분류의 분화 산업은 모산업의 탄력성을 따른다.
el = F.employment_elasticity(expect)
eps62 = {c: float(el.loc[idx62.loc[int(c.split(".")[0]), "설문업종"], "탄력성_ε"]) for c in base62.columns}
pd.DataFrame({"산업": list(eps62), "고용탄력성_ε": list(eps62.values())}).to_csv(
os.path.join(C.OUTPUT, "elasticity_62.csv"), index=False, encoding="utf-8-sig")
print("대체 업종:", ", ".join(el.index[el["탄력성_출처"] != "업종 값"].drop(["전체", "제조업", "비제조업"], errors="ignore")))
print(f"전체 평균 ε = {el.loc['전체', '탄력성_ε']:.2f} · 제조업 {el.loc['제조업', '탄력성_ε']:.2f} · 비제조업 {el.loc['비제조업', '탄력성_ε']:.2f}")
대체 업종: 12. 운수, 18. 사업지원서비스, 21. 문화/예술 전체 평균 ε = -0.62 · 제조업 -0.47 · 비제조업 -0.87
5. 62분류 산업별 경로(중심 Λ=0.5)와 취업계수¶
def to_long(base, ai, label):
b = base.loc[C.START:C.END].stack().rename("실질VA_십억원").reset_index().assign(시나리오="기준(S1)")
a = ai.stack().rename("실질VA_십억원").reset_index().assign(시나리오=label)
return pd.concat([b, a])[["시나리오", "연도", "산업", "실질VA_십억원"]]
ai62, prem62v = paths[C.LAMBDA_CENTRAL], prems[C.LAMBDA_CENTRAL]
to_long(base62, ai62, "AI확산(Λ=0.5)").to_csv(os.path.join(C.OUTPUT, "ai_va_62.csv"), index=False, encoding="utf-8-sig")
lab62 = F.labor_coef_change(prem62v, eps62, C.EMPLOYMENT)
lab62.to_csv(os.path.join(C.OUTPUT, "ai_premium_labor_62.csv"), encoding="utf-8-sig")
lab62.sort_values("VA프리미엄_2035_%p", ascending=False).head(6)
| VA프리미엄_2035_%p | 고용탄력성_ε(설문) | 취업계수변화_2035_%p | 취업계수변화_고용중립_%p | 취업계수변화_설문탄력성_%p | |
|---|---|---|---|---|---|
| 산업 | |||||
| 44.컴퓨터 프로그래밍ㆍ시스템통합관리업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
| 45.정보서비스업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
| 40.출판업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
| 41.영상ㆍ오디오기록물제작 배급업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
| 42.방송업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
| 43.통신업 | 0.620 | -0.154 | -0.620 | -0.620 | -0.716 |
6. 69분류 — 분화 산업은 모산업의 점수와 탄력성을 이어받는다¶
분화 산업 8개(반도체·이차전지·신재생에너지·조선업·철강·택배·건물건설·토목건설)는 모산업(62분류)의 설문 점수와 탄력성을 그대로 쓴다. 배율은 69분류 가중치로 다시 보정한다.
def proxy62(c):
p = F.parent_of(c, carve)
return [x for x in base62.columns if int(x.split(".")[0]) == p][0]
ai69, prem69v = F.project_variant(base69, lambda c, t: fn(proxy62(c), t), C.LAMBDA_CENTRAL)
to_long(base69, ai69, "AI확산(Λ=0.5)").to_csv(os.path.join(C.OUTPUT, "ai_va_69.csv"), index=False, encoding="utf-8-sig")
lab69 = F.labor_coef_change(prem69v, {c: eps62[proxy62(c)] for c in base69.columns}, C.EMPLOYMENT)
lab69.to_csv(os.path.join(C.OUTPUT, "ai_premium_labor_69.csv"), encoding="utf-8-sig")
print(f"2035 AI확산 전산업: 62분류 {ai62.loc[C.END].sum()/1e3:,.1f}조 · 69분류 {ai69.loc[C.END].sum()/1e3:,.1f}조")
lab69.loc[list(carve)]
2035 AI확산 전산업: 62분류 2,692.2조 · 69분류 2,692.2조
| VA프리미엄_2035_%p | 고용탄력성_ε(설문) | 취업계수변화_2035_%p | 취업계수변화_고용중립_%p | 취업계수변화_설문탄력성_%p | |
|---|---|---|---|---|---|
| 산업 | |||||
| 반도체 | 0.559 | -0.216 | -0.559 | -0.559 | -0.681 |
| 이차전지 | 0.559 | -0.216 | -0.559 | -0.559 | -0.681 |
| 신재생에너지 | 0.440 | -0.056 | -0.440 | -0.440 | -0.465 |
| 조선업 | 0.503 | -1.144 | -0.503 | -0.503 | -1.077 |
| 철강 | 0.479 | -0.646 | -0.479 | -0.479 | -0.788 |
| 택배 | 0.458 | -0.874 | -0.458 | -0.458 | -0.858 |
| 건물건설건축보수 | 0.425 | -1.275 | -0.425 | -0.425 | -0.966 |
| 토목건설 | 0.425 | -1.275 | -0.425 | -0.425 | -0.966 |
7. 배분 방식 민감도 — 기준점 선택¶
네 방식 모두 2035년 VA 가중평균 프리미엄을 0.5%p로 보정하므로 전산업 총량은 거의 같다. 산업 간 배분만 달라진다.
| 방식 | 산식(보정 전) | 해석 |
|---|---|---|
| A1 중심 | $(s_i^{2040}-1)\,r(t)$ | 척도 최저점 '매우 낮음'을 영향 최소로 둔다 |
| A 이전 | $(s_i^{2040}-5)\,r(t)$ | 중간값 '보통'을 0으로 둔다. 정도 척도를 방향 척도로 읽은 방식이다 |
| B 증가분 | $s_i(t)-s_i(2025)$ | 2025년 영향은 기준선에 반영되었다고 보고 이후 증가분만 쓴다 |
| C 상대강도 | $s_i^{2040}/\bar s^{2040}\,r(t)$ | 전체 평균 대비 비율 |
variants = F.allocation_variants(idx62, tot_g)
rows = {}
for name, vfn in variants.items():
ai_v, prem_v = F.project_variant(base62, vfn, C.LAMBDA_CENTRAL)
rows[name] = prem_v
a35 = ai_v.loc[C.END].sum() / 1e3
print(f"{name:<14} 2035 {a35:,.1f}조 · 기준 대비 {F.cagr(b25, a35, 10) - F.cagr(b25, b35, 10):+.3f}%p · 최대/최소 {prem_v.max() / prem_v.min():5.1f}배")
var = pd.DataFrame(rows)
var.to_csv(os.path.join(C.OUTPUT, "allocation_variants.csv"), encoding="utf-8-sig")
pick = [c for c in var.index if c.split(".")[0] in ("44", "56", "23", "22", "6", "46", "33", "39", "59")]
var.loc[pick]
A 현행(s−5) 2035 2,692.5조 · 기준 대비 +0.321%p · 최대/최소 36.4배 A1 앵커1(s−1) 2035 2,692.2조 · 기준 대비 +0.320%p · 최대/최소 1.6배 B 증가분 2035 2,691.5조 · 기준 대비 +0.318%p · 최대/최소 1.8배 C 상대강도 2035 2,692.2조 · 기준 대비 +0.320%p · 최대/최소 1.4배
| A 현행(s−5) | A1 앵커1(s−1) | B 증가분 | C 상대강도 | |
|---|---|---|---|---|
| 22.전자부품ㆍ컴퓨터ㆍ영상ㆍ음향ㆍ통신장비 | 0.780 | 0.559 | 0.591 | 0.550 |
| 23.의료ㆍ정밀ㆍ광학기기ㆍ시계 | 0.800 | 0.564 | 0.649 | 0.553 |
| 33.건설업 | 0.146 | 0.425 | 0.385 | 0.437 |
| 39.음식점ㆍ숙박업 | 0.180 | 0.432 | 0.434 | 0.443 |
| 44.컴퓨터 프로그래밍ㆍ시스템통합관리업 | 1.067 | 0.620 | 0.534 | 0.600 |
| 46.금융업 | 0.334 | 0.465 | 0.403 | 0.471 |
| 56.교육서비스업 | 0.897 | 0.584 | 0.471 | 0.570 |
| 59.문화서비스업 | 0.029 | 0.400 | 0.536 | 0.417 |
| 6.식료품 | 0.639 | 0.530 | 0.595 | 0.525 |
8. 정비 전후 비교 — 같은 AI 확산 층을 이전 판 기준 시나리오에 적용¶
설문 점수·크로스워크·시점 램프·배분 방식(A1)·Λ·탄력성은 그대로 두고 기준 시나리오만 이전 판(data/published_prev/)으로 바꾸어 같은 계산을 한다.
이전 판 열은 이전 판 공표 수치를 재현해야 하며, 03의 검증 셀이 이를 확인한다(이전 판 재현 점검).
Λ 보정은 2035년 기준 시나리오의 산업 구성을 가중치로 쓰므로, 기준 시나리오가 바뀌면 배율 $k$가 다시 정해진다. $p_{i,t}=k\,a_i\,r(t)$에서 $a_i$와 $r(t)$는 설문에서 오므로 그대로이고, 산업별 프리미엄은 모든 산업에서 같은 비율 $k^{정비}/k^{이전}$만큼 바뀐다.
prev62, prev69 = F.read_base(C.BASE_62_PREV), F.read_base(C.BASE_69_PREV)
fn69 = lambda c, t: fn(proxy62(c), t)
eps69 = {c: eps62[proxy62(c)] for c in base69.columns}
args = (fn, fn69, eps62, eps69, list(carve), C.LAMBDA_SENSITIVITY, C.LAMBDA_CENTRAL, C.EMPLOYMENT)
new = F.scenario_summary(base62, base69, *args)
old = F.scenario_summary(prev62, prev69, *args)
cmp = new.rename(columns={"값": "정비판"}).merge(old.rename(columns={"값": "이전 판"}), on=["구분", "항목"], validate="one_to_one")
cmp["차이"] = cmp["정비판"] - cmp["이전 판"]
cmp.to_csv(os.path.join(C.OUTPUT, "compare_prev.csv"), index=False, encoding="utf-8-sig")
# 정비판 열은 1–6절의 결과와 같아야 한다(같은 함수·같은 입력)
assert abs(F.lookup(cmp, "정비판", "총량", "AI_2035_조") - ai62.loc[C.END].sum() / 1e3) < 1e-9
assert abs(F.lookup(cmp, "정비판", "62 프리미엄(%p)", 44) - lab62.loc[[c for c in lab62.index if c.startswith("44.")][0], "VA프리미엄_2035_%p"]) < 1e-12
assert abs(F.lookup(cmp, "정비판", "69 분화 AI 2035(조원)", "반도체") - ai69.loc[C.END, "반도체"] / 1e3) < 1e-9
sub = cmp[cmp["구분"] == "62 프리미엄(%p)"]
ratio = sub["정비판"] / sub["이전 판"]
print(f"62분류 산업별 프리미엄 비율(정비판/이전 판): 최소 {ratio.min():.6f} · 최대 {ratio.max():.6f}")
cmp[cmp["구분"] == "총량"].set_index("항목")[["이전 판", "정비판", "차이"]]
62분류 산업별 프리미엄 비율(정비판/이전 판): 최소 1.002474 · 최대 1.002474
| 이전 판 | 정비판 | 차이 | |
|---|---|---|---|
| 항목 | |||
| 기준_2025_조 | 2,178.489 | 2,178.489 | 0.000 |
| 기준_2035_조 | 2,688.518 | 2,609.028 | -79.490 |
| 기준_CAGR | 2.126 | 1.820 | -0.306 |
| L03_2035_조 | 2,739.664 | 2,658.662 | -81.002 |
| L03_CAGR | 2.319 | 2.012 | -0.307 |
| L03_차이_%p | 0.193 | 0.192 | -0.001 |
| L03_수준차이_조 | 51.146 | 49.634 | -1.512 |
| L03_수준차이_% | 1.902 | 1.902 | 0.000 |
| AI_2035_조 | 2,774.242 | 2,692.217 | -82.024 |
| AI_CAGR | 2.447 | 2.140 | -0.307 |
| AI_차이_%p | 0.321 | 0.320 | -0.001 |
| AI_수준차이_조 | 85.724 | 83.189 | -2.534 |
| AI_수준차이_% | 3.189 | 3.189 | 0.000 |
| L08_2035_조 | 2,826.838 | 2,743.259 | -83.579 |
| L08_CAGR | 2.640 | 2.332 | -0.308 |
| L08_차이_%p | 0.514 | 0.512 | -0.002 |
| L08_수준차이_조 | 138.320 | 134.231 | -4.089 |
| L08_수준차이_% | 5.145 | 5.145 | 0.000 |