KISA 제보 취약점(KVE-2026-1914/1919/2019/2029/2041/2042/2043/2044)과 그 수정 과정에서 드러난 자격증명 전송로 결함을 함께 해소한다. globalHeaders 는 데이터소스와 apiCall 핸들러에만 적용되는데, 코어 ApiClient 를 직접 부르는 경로들이 그 사실을 모른 채 게이트된 엔드포인트를 호출하고 있었다. 서버는 정당한 사용자를 거부하고 화면은 이미 버튼을 내준 뒤라, 예외도 로그도 없이 그 자리만 비는 형태로만 드러났다. 전송로 10축을 전수 열거해 6건을 고치고, 같은 실수가 반복되지 않도록 규정과 coverage 에 등재했다. 아웃바운드 프록시가 사이트 자기 자신으로 가는 내부 요청까지 가로채 저장이 수십 초씩 걸리던 문제도 함께 고쳤다. 실패가 폴백으로 삼켜져 화면에는 지연으로만 나타났다.
5.4 KiB
NHN KCP — 프론트엔드
레이아웃·액션 핸들러·전역 진입점·에셋 · 진입점: AGENTS.md
레이아웃
레이아웃 1개 (루트: resources/layouts).
| 그룹 | 개수 |
|---|---|
admin |
1개 |
| 레이아웃 | 그룹 | 종류 | extends |
|---|---|---|---|
plugin_settings |
admin |
화면 | _admin_base |
sirsoft-pay_kginicis와 마찬가지로 이 플러그인이 소유한 화면 레이아웃은 관리자 설정 화면
하나뿐입니다 — 체크아웃·주문상세·마이페이지의 결제 UI는 이 플러그인 소유가 아니라
§레이아웃 확장(다른 확장/템플릿 레이아웃에 주입되는 조각)으로 존재합니다.
액션 핸들러
핸들러 3개 (정의: resources/js/handlers/index.ts).
| 핸들러 | 레이아웃에서 부르는 이름 |
|---|---|
requestPayment |
sirsoft-pay_nhnkcp.requestPayment |
setPaymentMethod |
sirsoft-pay_nhnkcp.setPaymentMethod |
copyToClipboard |
sirsoft-pay_nhnkcp.copyToClipboard |
sirsoft-pay_kginicis가 핸들러 1개(requestPayment)로 끝나는 것과 달리 이 플러그인은
3개입니다. setPaymentMethod가 별도로 필요한 이유는 KCP 간편결제 버튼(PAYCO/네이버페이/
카카오페이/Apple Pay)이 레이아웃 컴포넌트가 아니라 KCP 가 제공하는 DOM 을 그대로 쓰기
때문입니다 — React 상태로 선택 하이라이트를 그리는 대신 DOM 을 직접 조작해 선택된 버튼에
테두리를 입힙니다(updateEasyPayButtonStyles). Apple Pay 는 iOS 모바일이 아니면 여기서
바로 오류 모달을 띄우고 요청 자체를 막습니다 — KCP 서버까지 보냈다가 거부당하면 사용자가
결제 실패 이유를 알 수 없기 때문입니다. copyToClipboard는 가상계좌 계좌번호 복사
버튼처럼 결제와 무관한 범용 유틸리티라 KCP 고유 로직이 없습니다.
전역 진입점
| 항목 | 값 |
|---|---|
| 엔트리 파일 | resources/js/index.ts |
| 전역 객체 | window.__SirsoftNhnkcp |
| 재등록 진입점 | initPlugin() |
로케일 전환 시 코어가 이 진입점을 호출해 핸들러를 다시 등록합니다. 진입점은 핸들러 재등록만 수행하고 1회성 부팅 작업을 포함하지 않습니다.
window.__SirsoftNhnkcp로 노출되는 이유는 코어가 로케일 전환 시 이 이름으로 재등록
진입점을 찾기 때문입니다(§코어 AGENTS.md "재등록 진입점"). KCP 결제창 스크립트 자체는 이
진입점이 미리 로드하지 않습니다 — 모든 방문자가 결제 페이지에 오는 것은 아니므로 전역
부팅에서 미리 불러올 필요가 없습니다(requestPayment 핸들러가 실제 결제 시도 시점에만
동적으로 로드).
에셋
| 경로 | 구분 |
|---|---|
dist/js/plugin.iife.js |
빌드 산출물 (커밋 대상) |
editor-spec.json |
레이아웃 편집기 스펙 (manifest) |
로딩 설정: {"strategy":"global","priority":100,"dependencies":[]}
KCP 가 제공하는 payplus_web.jsp SDK 는 이 목록에 없습니다 — requestPayment 핸들러가
결제 시도 시점에 iframe 안으로 동기 로드하는 제3자 자산이라, 이 플러그인이 빌드 시
번들링하는 dist/ 산출물과는 다른 층입니다. CSS 산출물이 없는 것은 결제창 자체는 KCP 가
그리고, 이 플러그인은 간편결제 버튼·복사 버튼 같은 최소한의 UI만 코어 컴포넌트로
구성하기 때문입니다.
비회원 주문의 자격 증명
영수증·결제수단 표시는 주문 정보를 서버에서 다시 조회해 만든다. 이 요청은 레이아웃의
globalHeaders 배선을 타지 않는 직접 호출(fetch)이므로, 자격 증명을 호출부가 직접 실어야 한다.
- 회원:
Authorization: Bearer … - 비회원:
X-Guest-Order-Token: …(코어 storageHandlers 가 sessionStorage 에 저장, 전역 상태 폴백)
두 경로 모두 resources/js/guestOrderToken.ts 의 buildOrderRequestHeaders() 한 곳을 거친다.
비회원 분기를 비우면 서버는 그 주문을 찾을 수 없다고 응답하고, 화면에는 영수증 버튼이 아예
나타나지 않는다 — 예외도 콘솔 오류도 남지 않아 운영자가 원인을 알 수 없다. 서버(UserReceiptController)는
비회원을 이미 지원하므로, 이 배선이 빠지면 서버 기능이 도달 불가 상태로만 남는다.
주문 상세 화면의 경로 판정(ORDER_SHOW_RE)도 회원(/mypage/orders/{N})과
비회원(/shop/guest/orders/{N}) 두 주소를 함께 매칭해야 한다. 한쪽을 빼면 그 화면에서는
조회가 시작조차 되지 않는다.