5장 수출 성장 분해하기#
출처: UNCTAD (2012), A Practical Guide to Trade Policy Analysis, Chapter 1.
1. 개요#
무역 패턴은 고정된 것이 아니라 끊임없이 변화한다. 수출 확대는 제품 또는 목적지 측면에서 내연적 증가(intensive margin), 외연적 증가(extensive margin), 그리고 지속가능성 증가(sustainability margin)로 구분될 수 있다. 내연적 증가는 기존 수출품의 동일 목적지로의 수출 증가를 의미하고, 외연적 증가는 신규 수출품 또는 신규 목적지 개척을 의미하며, 지속가능성 증가는 수출 지속 기간의 증가를 의미한다.
이를 유용하게 분해하는 방식은 다음과 같다. 기준 연도의 자국 수출품 집합을 \(K_0\), 비교 연도의 수출품 집합을 \(K_1\)으로 정의하자. 기준 연도의 수출 총액은 다음과 같다.
그리고 비교 연도의 수출 총액은 다음과 같다.
두 연도 사이 총수출의 가치 변화는 다음과 같이 분해할 수 있다.
여기서 첫 번째 항은 내연적 증가(기존 수출품의 가치 변화), 두 번째 항은 외연적 증가(새롭게 수출된 제품의 가치), 세 번째 항은 제품소멸 변화(중단된 수출품의 가치)다. 즉, 수출 성장은 기존 제품의 수출량 증가, 신규 제품의 수출 증가, 그리고 기존 제품의 수출 중단에 따른 수출 감소를 통해 이루어진다. 이와 같은 분해 방식은 제품과 목적지를 조합하여 보다 복잡한 형태로 확대시킬 수도 있다.
일반적으로 수출 성장에서 외연적 증가가 기여하는 비중이 크지 않다. 그 이유는 두 가지로 나뉜다. 첫 번째는 기술적 이유로, 특정 제품이 외연적 증가에 속하는 것은 처음 수출된 연도에 한정되며, 이후에는 내연적 증가에 포함되기 때문이다. 따라서, 기업이 첫해부터 대규모 수출을 개시하지 않는 한, 외연적 증가가 전체 수출 성장에 미치는 기여도는 작을 수밖에 없다.
두 번째는 본질적 이유로, 대부분의 신규 수출품은 도입된 후 얼마 지나지 않아 실패한다는 점이다. 개발도상국의 수출 지속 기간 중위값은 약 2년에 불과하다. 즉, 많은 기업이 수출을 시도하지만 상당수가 곧 시장에서 퇴출된다. 이는 무역 지원 정책에서 수출의 지속가능성을 높이는 것(즉, 수출 실패율이 높은 이유를 파악하는 것)이 중요한 과제라는 것을 의미한다.
2. 데이터#
OECD 6개국 사례 분석#
1995년과 2004년의 UN Comtrade 데이터를 활용한다.
여기에는 전체 수출국의 (모든 목적지에 대한) 제품별 총수출 데이터가 담겨있다.
이 데이터세트를 활용해 OECD 6개국(미국, 일본, 독일, 프랑스, 영국, 이탈리아)의 총수출 가치 변화를 위 식 1의 방식으로 분해한다.
아래 결과를 보면, OECD 국가의 경우에도 수출 변동의 거의 대부분은 기존 수출 관계의 확대에 의해 설명된다.
import numpy as np
import pandas as pd
# comtrade_exports.dta 파일 읽기 (Comtrade 데이터)
df = pd.read_stata("../Data/comtrade_exports.dta")
df
| reporter | reportername | partner | partnername | year | productname | flowname | product | tradevalue000 | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | AIA | Anguila | WLD | World | 2004 | Frozen boneless bovine meat | Gross Exp. | 020230 | 1.657 |
| 1 | AIA | Anguila | WLD | World | 2004 | Animal products, nes; dead animals | Gross Exp. | 051199 | 2.593 |
| 2 | AIA | Anguila | WLD | World | 2004 | Potatoes, frozen | Gross Exp. | 071010 | 2.543 |
| 3 | AIA | Anguila | WLD | World | 2004 | Mixtures of vegetables, frozen | Gross Exp. | 071090 | 1.042 |
| 4 | AIA | Anguila | WLD | World | 2004 | Curry | Gross Exp. | 091050 | 0.384 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 641035 | ZWE | Zimbabwe | WLD | World | 2004 | Tailors' dummies/lay figures; autom | Gross Exp. | 961800 | 0.265 |
| 641036 | ZWE | Zimbabwe | WLD | World | 2004 | Paintings,drawings and pastels exec | Gross Exp. | 970110 | 27.663 |
| 641037 | ZWE | Zimbabwe | WLD | World | 2004 | Collages and similar decorative pla | Gross Exp. | 970190 | 26.088 |
| 641038 | ZWE | Zimbabwe | WLD | World | 2004 | Original sculptures and statuary, i | Gross Exp. | 970300 | 2458.594 |
| 641039 | ZWE | Zimbabwe | WLD | World | 2004 | Coll & coll pce of zoo,bot,mineral, | Gross Exp. | 970500 | 6874.195 |
641040 rows × 9 columns
변수 설명
reporter: 보고국 코드reportername: 보고국 이름partner: 상대국 코드partnername: 상대국 이름year: 연도productname: 제품 이름flowname: 무역 흐름의 종류(예: 총수출)product: 제품 코드tradevalue000: 거래 금액(천 달러)
reporter와 product별로, year를 열로 하여 세계 총수출액(tradevalue000)을 피벗
df_wide = df.pivot(index=["reporter", "product"], columns="year", values="tradevalue000").reset_index()
df_wide
| year | reporter | product | 1995 | 2004 |
|---|---|---|---|---|
| 0 | AIA | 020230 | NaN | 1.657 |
| 1 | AIA | 051199 | NaN | 2.593 |
| 2 | AIA | 071010 | NaN | 2.543 |
| 3 | AIA | 071090 | NaN | 1.042 |
| 4 | AIA | 091050 | NaN | 0.384 |
| ... | ... | ... | ... | ... |
| 421790 | ZWE | 970190 | 34.583 | 26.088 |
| 421791 | ZWE | 970200 | 13.899 | NaN |
| 421792 | ZWE | 970300 | 7139.766 | 2458.594 |
| 421793 | ZWE | 970500 | 7341.143 | 6874.195 |
| 421794 | ZWE | 970600 | 20.841 | NaN |
421795 rows × 4 columns
열 이름 1995, 2004를 “tradevalue0001995”, “tradevalue0002004”로 변경
df_wide = df_wide.rename(columns={1995: "tradevalue0001995",
2004: "tradevalue0002004"})
# 데이터 확인
df_wide.tail()
| year | reporter | product | tradevalue0001995 | tradevalue0002004 |
|---|---|---|---|---|
| 421790 | ZWE | 970190 | 34.583 | 26.088 |
| 421791 | ZWE | 970200 | 13.899 | NaN |
| 421792 | ZWE | 970300 | 7139.766 | 2458.594 |
| 421793 | ZWE | 970500 | 7341.143 | 6874.195 |
| 421794 | ZWE | 970600 | 20.841 | NaN |
3. 수출 성장 분해#
각 나라별로 각 연도의 총수출액 및 변화를 계산
# reporter별로 각 연도의 총합을 계산
totals = df_wide.groupby("reporter").agg(
tot_trade_all_6_dgt_1995 = ("tradevalue0001995", "sum"),
tot_trade_all_6_dgt_2004 = ("tradevalue0002004", "sum")
).reset_index()
totals["change_tot_trade_all_6_dgt"] = totals["tot_trade_all_6_dgt_2004"] - totals["tot_trade_all_6_dgt_1995"]
# totals를 원본 데이터에 병합
df_wide = df_wide.merge(totals[["reporter", "change_tot_trade_all_6_dgt"]], on="reporter", how="left")
# 데이터 확인
df_wide.tail()
| reporter | product | tradevalue0001995 | tradevalue0002004 | change_tot_trade_all_6_dgt | |
|---|---|---|---|---|---|
| 421790 | ZWE | 970190 | 34.583 | 26.088 | 87318.318 |
| 421791 | ZWE | 970200 | 13.899 | NaN | 87318.318 |
| 421792 | ZWE | 970300 | 7139.766 | 2458.594 | 87318.318 |
| 421793 | ZWE | 970500 | 7341.143 | 6874.195 | 87318.318 |
| 421794 | ZWE | 970600 | 20.841 | NaN | 87318.318 |
내연적 증가(x1) 계산
# 각 행별 계산: 기존 거래 관계의 무역량 증가(두 연도 모두 값이 존재하는 경우)
df_wide["temp1"] = np.where(
df_wide["tradevalue0002004"].notna() & df_wide["tradevalue0001995"].notna(),
df_wide["tradevalue0002004"] - df_wide["tradevalue0001995"],
np.nan
)
# 나라별 t1: 기존 거래에서의 변화량 총합 (delta의 합계)
df_wide["x1"] = df_wide.groupby("reporter")["temp1"].transform("sum")
외연적 증가(x2) 계산
# tradevalue0002004가 존재하고 tradevalue0001995는 결측인 경우
df_wide["temp2"] = np.where(
df_wide["tradevalue0002004"].notna() & df_wide["tradevalue0001995"].isna(),
df_wide["tradevalue0002004"],
np.nan
)
df_wide["x2"] = df_wide.groupby("reporter")["temp2"].transform("sum")
제품소멸 변화(x3) 계산
# tradevalue0002004가 결측이고 tradevalue0001995는 존재하는 경우
df_wide["temp3"] = np.where(
df_wide["tradevalue0002004"].isna() & df_wide["tradevalue0001995"].notna(),
df_wide["tradevalue0001995"],
np.nan
)
df_wide["x3"] = df_wide.groupby("reporter")["temp3"].transform("sum")
항목별 기여도
# dx = x1 + x2 - x3
df_wide["dx"] = df_wide["x1"] + df_wide["x2"] - df_wide["x3"]
# 각 마진별 기여도 계산
df_wide["c1"] = df_wide["x1"] / df_wide["dx"] # 내연적(기존 거래) 증가 기여도
df_wide["c2"] = df_wide["x2"] / df_wide["dx"] # 외연적 증가 기여도
df_wide["c3"] = df_wide["x3"] / df_wide["dx"] # 제품소멸 변화
df_wide["c"] = df_wide["c1"] + df_wide["c2"] - df_wide["c3"]
# 필요한 변수만 유지 (중복 제거)
df_result = df_wide[["reporter", "change_tot_trade_all_6_dgt", "dx", "x1", "x2", "x3", "c1", "c2", "c3", "c"]].drop_duplicates()
df_result = df_result.rename(columns={"change_tot_trade_all_6_dgt": "change"})
1995–2004년 수출 성장 분해, OECD 상위 6개국
# GDP 데이터와 병합
gdp = pd.read_stata("../Data/gdp_data.dta")
# reporter를 기준으로 merge
df_merged = pd.merge(df_result, gdp, on="reporter", how="left")
df_merged = df_merged.drop_duplicates()
# avg_gdp_95_04 기준 내림차순 정렬 후, 상위 6개 행 출력
df_merged = df_merged.sort_values(by="avg_gdp_95_04", ascending=False)
print("1995–2004년 수출 성장 분해, OECD 상위 6개국")
df_merged[["reporter", "c1", "c2", "c3"]].head(6)
1995–2004년 수출 성장 분해, OECD 상위 6개국
| reporter | c1 | c2 | c3 | |
|---|---|---|---|---|
| 259 | USA | 0.978453 | 0.043298 | 0.021751 |
| 133 | JPN | 1.011665 | 0.013764 | 0.025429 |
| 61 | DEU | 1.002045 | 0.007966 | 0.010011 |
| 83 | FRA | 0.966314 | 0.048183 | 0.014498 |
| 88 | GBR | 0.977226 | 0.117817 | 0.095043 |
| 128 | ITA | 0.953962 | 0.063254 | 0.017216 |