결제 버튼을 눌렀는데 아무 일도 일어나지 않는다면, 사이트의 보안 헤더가 결제창을 막고 있는 거예요. 어디에 무엇을 넣으면 되는지 안내해요.
CSP(Content-Security-Policy, 콘텐츠 보안 정책)는 웹서버가 내보내는 보안 헤더예요. 어떤 외부 화면을 페이지 안에 띄울 수 있는지 제한하는데, 결제창도 여기에 걸려요.
CSP는 직접 켜야 동작해요. 설정한 적이 없다면 결제창은 그냥 떠요.
내 문제인지 먼저 확인해요
브라우저 개발자도구(F12) → Console 탭에 아래와 비슷한 줄이 있는지 봐요.
Refused to frame 'https://...' because it violates the following
Content Security Policy directive: "frame-src ..."이 메시지가 보이면 부트페이 장애도, 연동키(Client Key) 문제도 아니에요. 내 웹서버 설정 문제예요.
무엇을 넣나요
결제창을 막는 지시어는 frame-src 하나예요. (iframe-src 라는 지시어는 없어요.)
frame-src 를 아예 선언하지 않으면 default-src 로 폴백되므로, default-src 'self' 만 있어도 똑같이 막혀요.
script-src 처럼 원래 없던 지시어를 새로 만들면 없던 제약이 새로 생겨요. 특히 script-src 를 새로 선언하는 순간 목록에 적지 않은 스크립트가 전부 차단돼서, 사이트의 분석 도구·채팅 위젯·광고 태그가 한꺼번에 멈춰요.
해당 지시어를 이미 쓰고 있는 경우에만 아래 「이미 쓰고 있는 지시어만 병합」의 값을 합치세요.
어디에 넣나요
| 환경 | 위치 |
|---|---|
| Vercel | vercel.json 의 headers |
| Next.js | next.config.js 의 headers() 또는 middleware.ts |
| Nuxt | nuxt.config.ts 의 routeRules |
| nginx | add_header Content-Security-Policy "..." always; |
| Express | helmet.contentSecurityPolicy({ directives }) |
| 헤더를 못 만질 때 | HTML <head> 의 <meta http-equiv="Content-Security-Policy"> |
Vercel + Next.js 조합에서는 middleware.ts 가 vercel.json 과 next.config.js 를 덮어써요. 한 곳만 고치고 "왜 안 바뀌지" 하는 경우가 많아요.
실제로 나가는 값을 확인해 주세요.
curl -sI https://내도메인 | grep -i content-security-policybash기존 CSP가 이미 있다면 통째로 덮어쓰지 말고 frame-src 값만 병합하세요. 설정 파일의 다른 항목(rewrites 등)도 그대로 두어야 해요.
허용 도메인
사용하는 PG와 결제수단에 따라 필요한 값이 달라요. 어떤 PG를 쓰는지 모르겠다면 전체 목록을 그대로 넣어도 돼요.
전체 허용 값 — 그대로 복사해서 쓰세요
frame-src 'self' https://*.bootpay.co.kr https://*.lightpay.kr https://lightpay.kr https://*.nicepay.co.kr https://*.settlebank.co.kr https://settlebank.co.kr https://*.inicis.com https://*.kcp.co.kr https://*.tosspayments.com https://*.smartropay.co.kr https://*.smartro.co.kr https://*.teledit.com https://teledit.com https://*.danalpay.com https://danalpay.com https://*.danal.co.kr https://danal.co.kr https://*.payletter.com https://*.payapp.kr https://*.easypay.co.kr https://*.welcomepayments.co.kr https://welcomepayments.co.kr https://*.payco.com https://payco.com https://*.kakao.com https://*.kakaopay.com https://kakaopay.com https://*.naver.com https://*.mobilians.co.kr https://*.ksnet.co.kr https://*.kspay.co.kr https://*.jtnet.co.kr https://jtnet.co.kr https://*.paypal.com https://*.stripe.com https://*.stripe.network https://*.kbcard.com https://*.bccard.com https://*.lottecard.co.kr https://*.shinhancard.com https://*.hyundaicard.com https://*.hanacard.co.kr https://*.samsungcard.co.kr https://*.nonghyup.com https://*.wooricard.com https://dacs.wooricard.com:8886 https://*.citibank.co.kr https://*.vpay.co.kr https://vpay.co.kr https://*.daum.net https://*.daumcdn.net https://*.channel.io항상 필요해요
https://*.bootpay.co.kr
https://*.lightpay.kr
https://lightpay.kr주소 검색(다음 우편번호)이나 상담 위젯을 함께 쓴다면 아래도 필요해요.
https://*.daum.net
https://*.daumcdn.net
https://*.channel.ioPG사별
PG사별 결제창 도메인 (21개)
| PG사 | 허용 값 |
|---|---|
| 라이트페이 | https://*.lightpay.kr https://lightpay.kr⚠️ 결제 모듈이 세틀뱅크·나이스페이먼츠 로 넘어가요 — 그 값도 함께 넣으세요 |
| 나이스페이먼츠 | https://*.nicepay.co.kr |
| 세틀뱅크 (헥토파이낸셜) | https://*.settlebank.co.kr https://settlebank.co.kr |
| KG이니시스 | https://*.inicis.com |
| NHN KCP | https://*.kcp.co.kr |
| 토스페이먼츠 | https://*.tosspayments.com |
| 스마트로 | https://*.smartropay.co.kr https://*.smartro.co.kr |
| 다날 | https://*.teledit.com https://teledit.com https://*.danalpay.com https://danalpay.com https://*.danal.co.kr https://danal.co.kr |
| 페이레터 | https://*.payletter.com |
| 페이앱 | https://*.payapp.kr |
| KICC 이지페이 | https://*.easypay.co.kr |
| 웰컴페이먼츠 | https://*.welcomepayments.co.kr https://welcomepayments.co.kr※ 결제창 주소 미확정. 막히면 콘솔 도메인을 추가하세요 |
| 페이코 | https://*.payco.com https://payco.com |
| 카카오페이 | https://*.kakao.com https://*.kakaopay.com https://kakaopay.com |
| 네이버페이 | https://*.naver.com |
| KG모빌리언스 | https://*.mobilians.co.kr |
| KSNET | https://*.ksnet.co.kr https://*.kspay.co.kr |
| JTNet | https://*.jtnet.co.kr https://jtnet.co.kr※ 결제창 주소 미확정. 막히면 콘솔 도메인을 추가하세요 |
| 티페이 | https://*.settlebank.co.kr https://settlebank.co.kr※ 결제창 주소 미확정. 막히면 콘솔 도메인을 추가하세요 |
| PayPal | https://*.paypal.com |
| Stripe | https://*.stripe.com https://*.stripe.network |
샌드박스와 운영의 결제창 도메인이 다른 PG가 있어요(예: sandbox-pay.nicepay.co.kr ↔ pay.nicepay.co.kr). 위처럼 와일드카드로 넣으면 둘 다 덮이니 운영 전환 시 다시 막히지 않아요.
카드 인증(3-D Secure)
PG 결제창 안에서 카드 인증 단계로 넘어가면 카드사 자체 서버가 열려요. PG 도메인만 허용하면 "결제창은 떴는데 카드를 고르니 멈춘다" 가 돼요. 카드결제를 받는다면 아래 값이 모두 필요해요.
카드사별 인증 도메인 (11개)
| 카드사 | 허용 값 |
|---|---|
| KB국민카드 | https://*.kbcard.com |
| BC카드 | https://*.bccard.com |
| 롯데카드 | https://*.lottecard.co.kr |
| 신한카드 | https://*.shinhancard.com |
| 현대카드 | https://*.hyundaicard.com |
| 하나카드 | https://*.hanacard.co.kr |
| 삼성카드 | https://*.samsungcard.co.kr |
| NH농협카드 | https://*.nonghyup.com |
| 우리카드 | https://*.wooricard.com https://dacs.wooricard.com:8886 |
| 씨티카드 | https://*.citibank.co.kr |
| VPay (카드사 공동) | https://*.vpay.co.kr https://vpay.co.kr |
아래 카드사는 실제 인증 서버 여부를 확인하지 못해 목록에서 뺐어요. 해당 카드에서 막히면 콘솔에 찍힌 도메인을 추가하세요 — 신협 · 전북은행 · 광주은행 · 수협
CSP는 포트를 생략하면 기본 포트(443)만 허용해요. 우리카드 인증 서버는 8886 포트에서만 응답하므로 https://*.wooricard.com 만으로는 덮이지 않아요.
놓치면 다른 카드는 되는데 우리카드 사용자만 결제가 실패해요.
https://*.wooricard.com https://dacs.wooricard.com:8886본인인증
본인인증(method: 'auth')을 쓴다면 추가해요.
https://nice.checkplus.co.kr
https://*.mobile-ok.com
https://*.kmcert.com
https://*.vno.co.kr
https://*.teledit.com이미 쓰고 있는 지시어만 병합
아래 지시어를 원래 선언해 두었다면 결제 도메인을 함께 넣어야 해요. 선언한 적이 없다면 건드리지 마세요.
form-action · connect-src · script-src · img-src
form-action — KG이니시스·NHN KCP 모바일은 폼 전송으로 결제창을 전환해요
form-action 'self' https://*.bootpay.co.kr https://*.lightpay.kr https://lightpay.kr https://*.nicepay.co.kr https://*.settlebank.co.kr https://settlebank.co.kr https://*.inicis.com https://*.kcp.co.kr https://*.tosspayments.com https://*.smartropay.co.kr https://*.smartro.co.kr https://*.teledit.com https://teledit.com https://*.danalpay.com https://danalpay.com https://*.danal.co.kr https://danal.co.kr https://*.payletter.com https://*.payapp.kr https://*.easypay.co.kr https://*.welcomepayments.co.kr https://welcomepayments.co.kr https://*.payco.com https://payco.com https://*.kakao.com https://*.kakaopay.com https://kakaopay.com https://*.naver.com https://*.mobilians.co.kr https://*.ksnet.co.kr https://*.kspay.co.kr https://*.jtnet.co.kr https://jtnet.co.kr https://*.paypal.com https://*.stripe.com https://*.stripe.network https://*.kbcard.com https://*.bccard.com https://*.lottecard.co.kr https://*.shinhancard.com https://*.hyundaicard.com https://*.hanacard.co.kr https://*.samsungcard.co.kr https://*.nonghyup.com https://*.wooricard.com https://dacs.wooricard.com:8886 https://*.citibank.co.kr https://*.vpay.co.kr https://vpay.co.krconnect-src — 결제 승인·상태 조회 통신
connect-src 'self' https://*.bootpay.co.kr https://*.lightpay.kr https://lightpay.kr https://*.nicepay.co.kr https://*.settlebank.co.kr https://settlebank.co.kr https://*.inicis.com https://*.kcp.co.kr https://*.tosspayments.com https://*.smartropay.co.kr https://*.smartro.co.kr https://*.teledit.com https://teledit.com https://*.danalpay.com https://danalpay.com https://*.danal.co.kr https://danal.co.kr https://*.payletter.com https://*.payapp.kr https://*.easypay.co.kr https://*.welcomepayments.co.kr https://welcomepayments.co.kr https://*.payco.com https://payco.com https://*.kakao.com https://*.kakaopay.com https://kakaopay.com https://*.naver.com https://*.mobilians.co.kr https://*.ksnet.co.kr https://*.kspay.co.kr https://*.jtnet.co.kr https://jtnet.co.kr https://*.paypal.com https://*.stripe.com https://*.stripe.networkscript-src — 부트페이 SDK·주소 검색 스크립트
script-src 'self' 'unsafe-inline' https://*.bootpay.co.kr https://*.lightpay.kr https://lightpay.kr https://*.daum.net https://*.daumcdn.net https://*.channel.ioimg-src — 카드사 로고·QR (data: blob:)
img-src 'self' data: blob: https://*.bootpay.co.kr https://*.lightpay.kr https://lightpay.kr https://*.nicepay.co.kr https://*.settlebank.co.kr https://settlebank.co.kr https://*.inicis.com https://*.kcp.co.kr https://*.tosspayments.com https://*.smartropay.co.kr https://*.smartro.co.kr https://*.teledit.com https://teledit.com https://*.danalpay.com https://danalpay.com https://*.danal.co.kr https://danal.co.kr https://*.payletter.com https://*.payapp.kr https://*.easypay.co.kr https://*.welcomepayments.co.kr https://welcomepayments.co.kr https://*.payco.com https://payco.com https://*.kakao.com https://*.kakaopay.com https://kakaopay.com https://*.naver.com https://*.mobilians.co.kr https://*.ksnet.co.kr https://*.kspay.co.kr https://*.jtnet.co.kr https://jtnet.co.kr https://*.paypal.com https://*.stripe.com https://*.stripe.networkCSP를 건드릴 수 없다면
보안 정책이나 권한 문제로 헤더를 못 만지는 경우, 결제창을 Redirect 방식으로 열면 frame-src 를 아예 거치지 않아요. CSP와 무관하게 결제가 진행돼요.
extra: {
open_type: 'redirect',
redirect_url: 'https://내도메인/payment/result', // 필수
}javascript부트페이는 원래 Web SDK에서 Redirect를 기본값으로 권장해요. 방식별 결과 수신 차이와 서버 라우트 구성은 창 모드 문서를 참고하세요.
그래도 막힌다면
- 콘솔의
Refused to frame문구에 찍힌 도메인을 그대로 추가해요. 이 목록보다 콘솔이 정확해요 — PG와 카드사는 도메인을 바꿔요. curl -sI로 실제 나가는 헤더를 확인해요. 설정이 다른 곳에서 덮이고 있을 수 있어요.- 위를 다 했는데 모바일만 안 된다면 Redirect 방식으로 전환해요.
운영 반영 전에는 Content-Security-Policy-Report-Only 로 먼저 돌려 위반만 수집해 보는 방법도 있어요.