開発mdx-playground

Economistの韓国DRAMチャートを再現しようとした話

The Economist の Graphic detail(May 15th 2025)に「Korean DRAM prices hit another record high」というチャートがあった。Surging demand for AI memory drives 18% jump in just ten days というサブタイトルで、韓国の DRAM 輸出単価( per kg, 月次)が 2020-05〜2025-05 でほぼ水平に推移していたものが、2025年に入って急騰し、2025年5月に **64,000/kg** に達したという内容。出所は Korea Customs Service と書いてあった。

このチャートを Vue ページとして自分のサイトに作りたい。元データを取りに行ってみたら、想定の3倍くらい紆余曲折があった上に、最後まで Economist の数字とは完全一致できなかった。その経緯をそのまま残しておく。

完成したチャートはこちら → /blog/korea-dram-export-prices

出発点:UN Comtrade Public API

最初は UN Comtrade の Public API を試した。理由は3つ:

  • API キー無しで叩ける
  • HS コード単位(6桁)で月次データが世界中の国について取れる
  • 韓国の reporterCode = 410、DRAM の HS6桁 = 854232 で一発
curl "https://comtradeapi.un.org/public/v1/preview/C/M/HS?reporterCode=410&period=202405&cmdCode=854232&flowCode=X&partnerCode=0&maxRecords=10"

これで月次の primaryValue(FOB値、USD)と netWgt(kg)が返ってくる。unitPriceUsdPerKg = primaryValue / netWgt で単価計算。2020-01〜2024-12 の60ヶ月をまとめて取れた。

ところが、計算結果を見て手が止まった。

UN Comtrade 単価Economist グラフ
2020-05$22,964/kgだいたい $10,000
2024-05$22,109/kgだいたい $20,000

2024-05 はだいたい合うが、2020-05 で 5,000〜10,000 ベースラインがズレる。HS 6桁(854232 = memory IC)には DRAM 以外(SRAM、フラッシュ、ロジック付き memory 等)が混入しているせいだと判明。Economist は Korea Customs Service の HS10桁 で「DRAM だけ」を抜いている。

そして決定的な問題:UN Comtrade は 2025年のデータがまだ未収載(2026-05時点でも)。Economist の記事の主役である 2025年1〜5月の急騰区間が空白。つまり最重要な数字が取れない。

UN Comtrade ルートはここで打ち切り。

KITA k-stat への移行

韓国側の公式ソースに行くしかない。候補:

  • 韓国関税庁 unipass(公式)
  • KOSIS(韓国統計庁)
  • KITA k-stat(韓国貿易協会、無料アクセス可)

WebFetch で unipass と KOSIS は接続失敗(タイムアウト)。SSL証明書周りか相手側のbot対策と思われる。残った k-stat も WebFetch では仕様取得まで。フォームを自動操作してデータを引き出す必要がある

ここで agent-browser スキル(CLAUDE.mdに書いてある WebFetch の正規フォールバック)を起動した。

agent-browser + Chrome DevTools MCP

戦術はこう決めた:

  1. ユーザーのChromeを --remote-debugging-port=9223 で起動済みにする
  2. agent-browser を --cdp 9223 で繋ぐ(これでログイン状態を流用)
  3. ページ操作とデータ抽出は Chrome DevTools MCPevaluate_script 経由で JavaScript を直接走らせる

agent-browser は CDP接続にトラブルがあった(auto-connectが効かないなど)が、Chrome DevTools MCP の方は port 9223 経由で安定して動いた。結局 agent-browser は接続トリガーとして使い、データ抽出は Chrome DevTools MCP に集約する形に落ち着いた。

k-stat の構造を読み解く

k-stat の品목수출입ページ(/stat/kts/pum/ItemImpExpList.screen)に到達。HS単位を「10단위(10桁)」、시작코드を 854232 で絞ると、HS10桁の細分が見えた:

HSコード品목명(韓)意味
8542321010디램DRAM 単体(chip)
8542321020에스램SRAM
8542321030플래시 메모리フラッシュメモリ
8542321090기타その他(HBM 単体含む可能性)
8542322000하이브리드 집적회로Hybrid IC
8542323000복합구조집 집적회로Multi-structure IC
8542324000복합부품 집적회로(MCOs)Multi-Component IC(HBM 等のメモリモジュール)

「DRAM」と一口に言っても10桁レベルでは 85423210108542324000(MCOs = HBM のような複合パッケージ)に分かれている。Economist の "Korean DRAM (including modules)" の "modules" が何を指すかが、ここで疑問になる。

ItemImpExpList.screen の制約

このページで月次時系列を取りたかったが、UI 上は 「特定月 vs 前年同月」 の比較しか出ない。s_year=2025, s_month=05 で「2024-05 と 2025-05 の対比表」が返るだけで、12ヶ月分の月次推移は出ない。

しかも8542321010 のセルをクリックしても詳細ポップアップが開かない。表は IBSheet という商用の JavaScript グリッドで、onclick ハンドラが TD ではなく内部の overlay 層に登録されているため、element.click()dispatchEvent で反応しない。

POST API を直接叩くアプローチも試したが、レスポンスは IBSheet の枠だけで、データ部分は別の Ajax で後から差し込まれる構造。HTML を grep してもデータが出ない。

ここで詰んだので、別ページを探した。

ItemList.screen(맞춤분석)の発見

/stat/cstat/peri/item/ItemList.screen(맞춤분석 / 품목 수출입)に行ったら、UI に 「주기(周期)」 という選択肢があり、년도별 / 분기별 / 월별 を選べる。さらに、시작〜종료で 任意期間を指定できる。

ただし2つの罠:

  • 5年制限: 종료日 - 시작日 が 5 年を超えると alert
  • 「월별」を選んでも結果は期間集計1行。例えば「2020-01〜2024-12 で 月別」を指定すると、表は「DRAM 全期間集計(5年合計)」が1行返るだけ。月ごとに分解した行は出ない

つまり「月次時系列」は直接取れない。

抜け道:시작 = 종료 = 同じ年同じ月を指定すれば、その1ヶ月だけの集計が返る。これを75回ループすれば月次時系列になる。

75ヶ月ループ取得

実装は Chrome DevTools MCP の evaluate_script で:

const fetchMonth = async (year, month) => {
  setSel('e_year', String(year));   // 終了年を先に上げる
  setSel('e_month', month);         // 終了月も上げる
  setSel('s_year', String(year));   // 開始年を合わせる
  setSel('s_month', month);         // 開始月を合わせる
  window.doSearch();
  await wait(2200);                 // IBSheet 再描画待ち
  // 8542321010 を含む行から column 5 (수출액) と column 7 (수출중량) を抽出
};

setSel の順序が重要。月を逆方向(2024→2020)に動かすと、「期間 開始 > 終了」で alert が出て検索が走らない。順方向(2020→2026 順次)かつ「終了を先に上げる→開始を合わせる」という順番だと alert なしで通る。

それでも年初(1月)への遷移時には別の race condition があって、最初の 1月だけ「累計値」が混入したので、各年の 01 月は別ルート(s_month を 12→01 に下げる別ロジック)で個別取得した。それでも 2021-01 と 2026-01 だけは k-stat 側のキャッシュ挙動か何かで取れず、最終的には前後月から interpolate した。

結果:DRAM 単体 + MCOs の二系列

DRAM 単体(HS 8542321010)75ヶ月分と、MCOs(HS 8542324000)39ヶ月分(MCOs は HS 改正前の 2020-2022 期間にコードが存在しないので 2023 年から)を取得。Vue + Chart.js で重ね描き。

そこで見えたのは DRAM 単体と MCOs の二極化

DRAM 単体 ($/kg)MCOs / HBM ($/kg)
2024-01$10,919$36,389
2024-12$15,463$39,644
2025-05$14,021$36,184
2025-12$23,725$54,011
2026-02$48,170$87,512
2026-03$55,143$64,673

DRAM 単体は 2024 年通年 10〜25k 帯で淡々と推移。MCOs(HBM等のメモリモジュール)は 2024 年初から 36k と既にDRAMの3倍水準で、2025-06 から急上昇、2026-02 にピーク $87k。

Economist が言っていた「DRAM (including modules)」の "modules" は、この MCOs (8542324000) のことだと推定が立つ。AI サーバー需要で HBM が高騰している話を、Economist は HS10桁の DRAM single と modules を合算して、あるいは modules 中心に語っていた。

⚠️ Economist の数字との比較:完全一致はしなかった

ここが本記事の核心。

Economist の元グラフでは 2025年5月で **64,000/kg** に達したと書いてある("reaching a record high of 64,000 per kg" "+18% in just ten days")。

ところが、私が k-stat から取得した同月のデータはこれ:

系列2025-05 単価
DRAM 単体(HS 8542321010)$14,021/kg
MCOs / HBM(HS 8542324000)$36,184/kg

MCOs ですら Economist の半分強。Economist の $64,000/kg を 2025-05 のデータで再現できていない

私のチャートで 64,673/kg が出るのは **2026-03 の MCOs**。これは Economist の数字「64k」と数値だけ偶然似ているが、時期が1年近くズレている。「再現できた」と言うのは正しくない。

なぜ Economist の数字に届かないか:4つの仮説

完全には特定できていないが、考えられる理由:

  1. 旬報(10日値)のスパイク: Economist の "+18% in just 10 days, May 1-10 vs April 1-30" は明らかに10日値の話。Korea Customs Service は10日ごとに「잠정」値を出している。月平均にならすと低くなる。私が取った月集計の MCOs 36k と「10日スパイク 64k」はそもそも比較対象が違う
  2. 別のHS10桁細分: もしかすると Economist は 8542321090 기타(その他DRAM、HBM単体がここに分類されている可能性)を使っている。今回未取得
  3. 特定相手国向け集計: Korea から世界全体ではなく、米国向けや特定相手国に絞ると単価が変わる。AI サーバー向けは米国比率が高いので、そこだけ抜くと高くなる
  4. 数量単位の違い: kg ではなく Unit(個数)基準で計算した可能性。HS10桁データには「수량」列があり、私は kg 列を使ったが Economist は別かもしれない

仮説1(旬報スパイク)が一番ありそう。記事の文章 "+18% in just ten days" がそれを示唆している。

残った謎と次にやること

この記事の段階で確定していること:

  • ✅ HS10桁の DRAM single(8542321010)と MCOs(8542324000)を 2020-2026 で月次取得できた
  • ✅ Economist の "DRAM (including modules)" の "modules" は MCOs(HBM 等)に相当しそう
  • ✅ MCOs の急上昇は 2025-06 以降で、AI サーバー × HBM 需要の話と整合
  • ❌ Economist 公開の "$64,000/kg in May 2025" を月次データで再現できていない

次に試したいこと:

  • 8542321090 기타 の月次取得(HBM 単体がここに入っていれば $64k に近づくかも)
  • KITA k-stat の「旬보」(10日値)UI を探す(あれば Economist の数字に直接アクセスできる)
  • 米国向けに絞った輸出データ(k-stat の「국가별」タブ、ただし会員社限定機能の m マーク付き)

副産物として記録した工程

データ取得そのものより、Korea Customs Service / KITA k-stat の構造を読み解く工程の方がワークとしては大きかった。同じ作業を再現したい人向けに、コアな手順をメモ:

  1. Chrome を --remote-debugging-port=9223 で起動しておく
  2. agent-browser で k-stat にアクセス(ログイン状態を流用するため)
  3. Chrome DevTools MCP に切り替えevaluate_script でフォーム操作と DOM 抽出
  4. ページは /stat/cstat/peri/item/ItemList.screen を使う(월별 + 同月単発で月次データが取れる)
  5. setSel の順序: 終了月 → 開始月の順で更新。月を逆方向に動かさない
  6. 年初(1月)は別ルート: s_month を 12→01 に下げてから e_month を 01 にする
  7. alert は handle_dialog で都度 accept。データは alert 発生前に DOM に乗るので拾える
  8. 75ヶ月 × 2系列 ≈ 200リクエスト。バッチサイズ12ヶ月で各バッチ約30秒、合計15分

fetchMonth の最終形:

const fetchMonth = async (year, month) => {
  if (month === '01') {
    setSel('e_year', String(year));
    setSel('s_year', String(year));
    setSel('s_month', '01');
    setSel('e_month', '01');
  } else {
    setSel('e_year', String(year));
    setSel('e_month', month);
    setSel('s_year', String(year));
    setSel('s_month', month);
  }
  window.doSearch();
  await wait(2200);
  // DOMから 8542321010 行を抽出して amt と wgt を取得
};

まとめ

The Economist のチャートを 完全再現はできなかった。でも、HS10桁まで掘ったおかげで「DRAM single(chip)と DRAM modules(HBM)は別物で、AI需要の急騰は modules 側で起きている」という構造は見えた。Economist が "including modules" と書いた一言の重みが、HS code の細分まで掘って初めてわかった。

データは公開チャートで確認できる → /blog/korea-dram-export-prices