Files
Gnuboard7/plugins/_bundled/sirsoft-gdpr/README.md
T
HeuJung 1124fad027 feat(gdpr): 필수 저장 항목 허용목록을 운영자 설정으로 이관
허용목록이 플러그인 코드 상수라, 새 확장이 저장 키를 도입할 때마다 이 플러그인을
고쳐야 했다. 고치지 않으면 그 키는 방문마다 파기되는데 예외도 로그도 남지 않아
운영자에게는 "설정이 저장되지 않는다" 는 증상만 보인다.

허용목록을 운영자 설정(necessary_storage_allowlist)으로 옮기고, 관리자 환경설정에
브라우저 저장소·세션 저장소·쿠키 세 카드를 두어 직접 편집하게 했다. 확장은 GDPR 을
알 필요가 없고 GDPR 도 확장을 알 필요가 없다 — 연결은 운영자가 화면에서 한다.
저장 키를 플러그인이 관측·수집하지 않는 것도 같은 이유다: 관측 자체가 추적이다.

판정은 서버(미들웨어)와 클라이언트 셋(인터셉터 둘 + 정리기)이 같은 설정을 같은 매칭
규칙으로 읽는다. 잠금 항목(로그인 토큰·CSRF·세션 쿠키·동의 기록)만 설정 밖에 두고
판정 시점에 합집합으로 얹는다 — 설정에 담기면 저장 요청 한 번으로 지워져 잠금이
아니게 된다. 기설치본은 업그레이드 스텝이 현재 카탈로그를 설정 파일에 못박되,
운영자가 이미 편집했으면 그대로 둔다.

함께 고친 선재 결함 셋:
- 차단 도메인 추천 목록이 응답에 실리지 않아 자동완성이 동작하지 않던 문제
- 세션 쿠키 이름을 기본값에서 바꾼 사이트에서 브라우저 측 목록의 그 항목이 죽던 문제
- 쿠키 목록에만 앞부분 매칭(`이름_*`)이 적용되지 않던 문제
2026-09-03 22:18:18 +09:00

14 KiB

GDPR

그누보드7 플러그인 · sirsoft-gdpr GDPR·개인정보보호법 대응 쿠키 동의 배너와 동의 이력 관리를 제공하는 플러그인

version 1.0.4 type 플러그인 그누보드7 >=7.0.6 license MIT


소개 · 주요 기능 · 동작 방식 · 요구 사항 · 설치 · 관리자 설정 · 사용 방법 · 다른 확장과의 연동 · 문서 · 트러블슈팅 · 변경 이력 · 라이선스


소개

GDPR(유럽 일반 데이터 보호 규정) 및 한국 개인정보보호법 대응 핵심 기능을 제공하는 플러그인입니다. 쿠키 동의 배너·동의 전 자동 차단·동의 이력 영구 보존·마이페이지 동의 철회를 한 패키지로 제공합니다.

이 플러그인이 의도적으로 하지 않는 것 하나는 게스트 → 회원 동의 자동 승계입니다. GDPR Art.6/ePrivacy Art.5(3) 관점에서 게스트(디바이스 단위)와 회원(주체 단위)은 별도 동의 모델이며, 회원가입 폼 동의로 Art.7(1) 입증 책임이 별도로 충족됩니다. 게스트 시절 동의 이력은 세션 기준 으로 보존될 뿐 회원 계정과 자동으로 이어붙지 않습니다.

주요 기능

영역 설명
쿠키 동의 배너 필수/기능/분석/마케팅 4분류(ICO·CNIL 권장 표준), 다크 모드, 4가지 위치(하단 바·좌하단·우하단·중앙 모달)
동의 전 자동 차단 외부 추적 스크립트·iframe + 기능 카테고리 1st-party 저장소(localStorage·sessionStorage·쿠키) 게이팅
동의 이력 저장 정책 버전·출처·카테고리 스냅샷을 함께 immutable 보존(GDPR Art.7(1) 입증 자료)
마이페이지 동의 관리 회원이 자신의 동의 현황을 조회·개별 철회·재동의·전체 일괄 재동의
관리자 동의 이력 조회 회원/게스트 동의 변경 이력(이메일·세션 검색, 카테고리·출처 다중 필터, 카테고리 스냅샷 표)
정책 버전 발행 정책 본문 변경 시 수동 발행으로 모든 회원에게 재동의를 트리거

동작 방식

flowchart LR
  V[방문자] -->|첫 방문| Banner[쿠키 배너 노출]
  Banner -->|동의 전| Block[외부 스크립트·iframe·1st-party 저장소 자동 차단]
  Banner -->|동의| Grant[GdprUserConsent 저장 + 훅 발행]
  Grant --> Restore[차단 해제·스크립트 로드]
  Grant --> History[(동의 이력 append-only 보존)]

  Admin[운영자] -->|정책 본문 변경| Publish[새 정책 버전 발행]
  Publish -->|다음 방문| Renew[모든 회원 재동의 안내]

동의는 부여든 철회든 상태 저장(gdpr_user_consents, mutable)과 이력 기록 (gdpr_user_consent_histories, immutable append-only)이 항상 함께 일어납니다 — "지금 동의 상태가 무엇인가"와 "언제 무엇에 동의했었는가"를 구분해서 답할 수 있어야 하기 때문입니다.

요구 사항

항목 값
그누보드7 코어 >=7.0.6
PHP ^8.2

설치

# 번들 설치 (코어에 동봉된 소스에서 설치)
php artisan plugin:install sirsoft-gdpr

# 활성화
php artisan plugin:activate sirsoft-gdpr

# 업데이트 (번들 소스 기준 강제 반영)
php artisan plugin:update sirsoft-gdpr --force

저장소: https://github.com/gnuboard/g7-plugin-sirsoft-gdpr

설치 직후 쿠키 배너는 비활성 상태입니다. 운영자가 운영 주체명·데이터 저장 위치·정책 페이지 슬러그를 입력한 뒤 "쿠키 배너 노출" 토글을 켜야 사이트에 노출됩니다.

관리자 설정

키 의미 기본값
privacy_policy_slug 개인정보처리방침 페이지 슬러그 privacy
legal_entity_name 운영 주체명 -
data_storage_location 데이터 저장 위치 -
banner_enabled 쿠키 배너 노출 true
banner_position 배너 위치 bottom_bar
blocked_domains 추적 도메인 차단 목록 {"functional":["*.crisp.chat","client.crisp.chat","*.intercom.io","widget.intercom.io","*.tawk.to","embed.tawk.to","cdn.weglot.com","*.weglot.com","*.usercentrics.eu"],"analytics":["google-analytics.com","*.google-analytics.com","googletagmanager.com","*.googletagmanager.com","ssl.google-analytics.com","*.hotjar.com","static.hotjar.com","*.mixpanel.com","cdn.mxpnl.com","*.amplitude.com","cdn.amplitude.com","*.segment.io","*.segment.com","wcs.naver.net","wcs.naver.com","*.beusable.net"],"marketing":["facebook.net","connect.facebook.net","facebook.com","*.facebook.com","doubleclick.net","*.doubleclick.net","googleadservices.com","googlesyndication.com","ads.google.com","*.criteo.com","static.criteo.net","*.adnxs.com","*.taboola.com","cdn.taboola.com","*.outbrain.com","*.kakao.com","analytics.ad.daum.net","platform.twitter.com","*.twitter.com","platform.linkedin.com","*.linkedin.com"]}
necessary_storage_allowlist 필수 저장 항목 허용목록 {"localStorage":["g7_locale","g7_color_scheme","g7_cache_version","g7_asset_url_mode*","g7_cart_key","g7-devtools-panel","g7_guest_order_token","g7_guest_order_number","g7_guest_order_expires_at","g7_devtools_*","g7_filters_*","g7_columns_*","g7_order_*","g7_admin_sidebar_collapsed","g7_filter_visibility_*","g7_dismissed_warnings","g7le.*","__sirsoftKginicisMobilePaymentReturnPending","g7.identity.redirectStash","sirsoft-verification_nhnkcp.formStash"],"sessionStorage":["g7:sirsoft-pay_kginicis:pendingClose","g7:sirsoft-pay_nhnkcp:pendingClose","g7:sirsoft-tosspayments:pendingClose","g7.identity.redirectStash","sirsoft-verification_nhnkcp.formStash","__sirsoftKginicisMobilePaymentReturnPending","g7le.*","g7_devtools_*","g7_filters_*","g7_columns_*","g7_order_*","g7_filter_visibility_*"],"cookie":["laravel_maintenance"]}
cookie_categories 쿠키 카테고리 정의 []

개발자용 상세(타입·검증·저장 위치)는 설정 스키마 를 보세요.

쿠키 배너 노출 은 마스터 토글입니다 — ON 하면 배너와 자동 차단이 함께 켜집니다. GDPR Art.6 "동의 전 처리 금지"를 강제하는 메커니즘인 자동 차단만 단독으로 끌 수 없도록 의도적으로 하나의 토글에 묶었습니다. 반대로 마이페이지 동의 관리 카드는 이 토글과 무관하게, 동의/철회 이력이 있는 회원에게는 항상 노출됩니다(Art.7(3) 철회 대칭성 보장 — 동의를 배너로 받았다면 철회도 언제든 마이페이지에서 가능해야 합니다).

데이터 저장 위치(data_storage_location)에는 IP 주소·CIDR·클라우드 리전 코드(예: ap-northeast-2)를 입력할 수 없습니다 — 보안상 자동 거부됩니다. "대한민국", "미국 (AWS)"처럼 사용자에게 안내할 국가/지역명만 입력합니다.

자동 차단 대상 도메인은 카테고리(기능/분석/마케팅)별 카탈로그로 관리하며, 기본 카탈로그(예: Google Analytics, Facebook Pixel, Kakao Pixel 등)가 시드되어 있고 운영자가 추가·삭제할 수 있습니다. 도메인 형식은 example.com 또는 와일드카드 *.example.com 만 지원하며, localhost 같은 단일 라벨과 한글 도메인(xn-- 변환)은 지원하지 않습니다.

필수 저장 항목(necessary_storage_allowlist)은 기능 쿠키에 동의하지 않은 방문자에게도 저장이 허용되는 항목 목록입니다. 이 목록 밖의 항목은 방문할 때마다 지워지므로, 새로 설치한 확장의 설정이 "저장했는데 새로고침하면 사라진다"면 그 확장이 쓰는 항목 이름을 여기에 추가하면 됩니다 — 이 플러그인을 고칠 필요가 없습니다. 항목 이름은 그 확장의 문서나 브라우저 개발자 도구(Application → Storage)에서 확인할 수 있습니다.

목록은 저장소 구분(브라우저 저장소 / 세션 저장소 / 쿠키) 셋으로 나뉘고, 이름 끝에 * 를 붙이면 앞부분이 같은 항목을 모두 포함합니다(g7_filters_* → g7_filters_orders_1). * 는 끝에만 쓸 수 있습니다 — 앞에 두면 모든 항목이 열려 동의 전 차단이 무의미해지기 때문입니다.

로그인 토큰·CSRF 토큰·세션 쿠키·쿠키 동의 기록은 잠금 항목으로 카드 위쪽에 따로 표시되며 삭제할 수 없습니다. 이 넷이 없으면 사이트가 동작하지 않습니다.

사이트 운영에 반드시 필요한 항목만 등록하세요. 추적·분석 목적의 항목을 여기 넣으면 동의 전 차단 원칙이 무너집니다.

사용 방법

자체 호스팅 추적 자원 등록: 자체 도메인에서 서빙하는 추적 스크립트·iframe·임베드는 도메인 매칭 대상이 아니므로 HTML 속성으로 분류합니다.

<script src="/js/my-analytics.js" data-gdpr-category="analytics"></script>
<iframe src="/embed/custom-tracker" data-gdpr-category="marketing"></iframe>

동의 전까지 자동 차단되고, 동의 후 자동 복원되며, 동의 철회 시 다시 차단됩니다.

정책 버전 발행: 관리자 → 플러그인 → GDPR 설정 의 "정책 버전" 카드에서 "+ 새 버전 발행"을 누르면 모든 회원이 다음 방문 시 재동의 화면을 보게 됩니다. 아래 기준으로 발행 여부를 판단합니다.

발행이 필요한 변경 발행이 필요 없는 변경
정책 본문(개인정보처리방침 페이지) 변경 차단 도메인 추가/삭제
카테고리 의미 변경 UI 라벨/설명 정정
위탁자·데이터 보관 정보 변경 운영 주체명·저장 위치 정정

발행 시 변경 사유 메모를 함께 저장합니다(GDPR Art.30 처리 기록 의무).

동의 이력 조회: 관리자 → GDPR 동의 이력 메뉴에서 이메일 부분 일치·세션 ID 로 검색하고, 카테고리·출처(banner/mypage/register/withdraw 등)·동의 액션(granted/revoked)으로 필터링합니다. 각 행을 펼치면 동의 시점의 전체 카테고리 의사 스냅샷을 확인할 수 있습니다(Art.7(1) 입증 자료).

다른 확장과의 연동

이 확장이 의존하는 확장

없음 — 코어만으로 동작합니다.

이 확장에 의존하는 확장 (이 확장을 비활성화하면 함께 영향을 받습니다)

없음.

sirsoft-page 는 소프트 의존(런타임 체크)입니다 — 미설치 시 쿠키 배너의 "자세히" 정책 링크만 자동으로 숨겨지고 나머지 기능은 정상 동작합니다. sirsoft-basic 템플릿은 배너가 주입되는 지점(_user_base.json 의 공용 확장 지점)을 제공해야 하므로, 다른 사용자 템플릿을 쓰려면 그 템플릿에도 같은 주입 지점이 있어야 배너가 정상 노출됩니다.

문서

문서 내용 상태
docs/README.md 문서 통합 목차와 실측 집계 ✅
docs/architecture.md 설계 의도·계층 지도·디렉토리 맵 ✅
docs/extension-points.md 발행/구독 훅·미들웨어·채널·스케줄 ✅
docs/data-model.md 모델·소유 테이블·마이그레이션·Enum ✅
docs/settings.md 설정 스키마·권한·메뉴·라우트·의존 관계 ✅
docs/frontend.md 레이아웃·액션 핸들러·전역 진입점·에셋 ✅
docs/editor-spec.md 레이아웃 편집기에 선언한 팔레트·컨트롤·샘플 데이터 ✅
docs/api/ API 레퍼런스 (엔드포인트별 파라미터·응답 필드) ✅
CHANGELOG.md 변경 이력 ✅

트러블슈팅

증상 원인 조치
쿠키 배너 설정을 저장했는데도 배너가 안 뜸 "쿠키 배너 노출" 마스터 토글이 꺼져 있음 관리자 설정에서 토글을 켠다 — 개별 항목 저장만으로는 배너가 켜지지 않는다
정책 페이지 링크가 배너에 안 보임 privacy_policy_slug 미설정 또는 sirsoft-page 미설치 슬러그를 입력하거나, 링크 없이 운영할지 결정한다(자동 숨김은 정상 동작)
배너에서 동의했는데 마이페이지에 이력이 안 보임 게스트 상태에서 동의 후 회원가입한 경우 — 게스트→회원 자동 승계를 제공하지 않음 의도된 동작이다(§소개 참고). 회원가입 시 별도 동의를 다시 받는다
자체 호스팅 스크립트가 동의 전에도 로드됨 data-gdpr-category 속성 누락 스크립트/iframe 태그에 카테고리 속성을 추가한다

변경 이력

CHANGELOG.md

라이선스

MIT