Files
Gnuboard7/plugins/_bundled/sirsoft-gdpr
HeuJung 90f154ecc0 fix(security): 배포본 소스맵 노출 차단 + 관리자 설정 탭 지연로딩 + 동반 결함 수정
## 소스맵 노출 차단 (공개 이슈 )

배포본에 .map 이 포함돼 원본 TS/TSX 전문(sourcesContent, 한글 주석 포함)이
그대로 노출됐다. 생성·서빙·저장소 유입 3계층을 모두 막는다.

- 빌드 config 15곳(코어 3 + _bundled 12): sourcemap 하드코딩 제거.
 G7_BUILD_SOURCEMAP 판정식으로 교체 — 미설정(로컬 npm run build)이면 생성해
 개발 디버깅 경험을 보존하고, 0 이면 미생성.
- Build{Core,Module,Plugin,Template}Command: 죽어 있던 --production 플래그 복구.
 $productionMode 를 콘솔 문자열에만 쓰고 npm 프로세스에 env 를 넘기지 않아
 산출물이 개발 빌드와 동일했다. runNpmCommand 에 $env 를 추가해 주입
 (--watch 에는 미주입). Symfony Process 는 부모 환경에 병합하므로 PATH 유실 없음.
- Allowed{Module,Plugin}FileType / {Module,Plugin}Service::getMimeType:
 허용 확장자 map 제거 — 익명 200 서빙 차단(템플릿은 원래 미허용, 3종 정책 일치).
- ExtensionBundleService: CSS 번들의 /*# sourceMappingURL=... */ strip 추가.
 CSS 는 블록 주석이라 JS 의 //# 패턴으로는 검출되지 않던 구멍.
- 추적 .map 13개 삭제 + .gitignore 전역 *.map 규칙(경로 한정 시 새 확장에서 누락).

실측: 산출 JS 의 sourceMappingURL 13 → 0, 추적 .map 13 → 0,
확장 디렉토리 npm run build 는 여전히 map 생성(개발 경험 회귀 없음).

## 관리자 환경설정 탭 지연 로딩

코어/이커머스/게시판 환경설정 화면이 진입 즉시 전 탭의 데이터소스를 한꺼번에
호출했다. 각 데이터소스에 활성 탭 조건(if)을 걸어 해당 탭에서만 fetch 하도록
변경하고, 결제 플러그인 3종의 테스트모드 상태 조회도 주문설정 탭으로 한정.

## 동반 결함 수정 (무관 결함 — 재발 방지 목적으로 같은 세션 처리)

- 나이스페이먼츠: 체크아웃 캐시 프리페치가 라우트를 가리지 않아 플러그인 번들이
 로드되는 모든 페이지(홈/게시판/로그인)에서 주문서를 조회 → 비회원 매번 422.
 형제 플러그인(kginicis)의 기존 가드 패턴을 적용해 체크아웃 경로로 한정.
- admin smoke 8건: 대부분 구현이 아니라 테스트 결함이었다 — URL 오타(단수 board),
 존재하지 않는 권한키, 앱 로케일이 en 인데 한국어 라벨 로케이터, DataGrid 버튼을
 먼저 잡던 휴리스틱 로케이터. 레이아웃에는 sticky className / 안정 id 를 부여.
- PHPDoc ↔ Pint 충돌 3건: 설명 없는 @param 은 no_superfluous_phpdoc_tags 가
 삭제해 audit phpdoc-public-method 와 무한 충돌. 한국어 설명을 붙여 양쪽 충족
 (리스너 3종의 설명 누락 메서드도 전수 보강).
- Log::spy 500 3건: spy 가 Log::channel('activity') 를 null 로 만들고
 logActivity 가 null->info 로 \Error → 같은 줄 catch(\Exception) 은 못 잡아
 통과. 운영에선 채널이 항상 로거이므로 제품 무결 → 테스트에 activity 채널
 보존 헬퍼 추가.
- NhnKcpApiServiceTest 5건: 스텁이 Unix 바이너리만 만들어 Windows 분기
 (pp_cli_exe.exe)에서만 실패. #!/bin/sh 는 Windows 실행 불가 → 파일 내 기존
 컨벤션대로 skip 가드.

## 테스트

- 소스맵 범위 130 passed (신규: BuildCommandSourcemapEnv, NoSourcemapArtifacts,
 ExtensionBundleService CSS strip, Allowed*FileType 반전, 자산 서빙 거부)
- 결제 3플러그인 505 passed / 0 failed (skipped 9 = Windows 전용 CLI, 사유 명시)
- 나이스페이먼츠 프론트 38 passed (가드 제거 시 red 실증 후 복원)
- E2E: production-sourcemap-exposure.spec.ts 6건 + 시나리오 매니페스트

버전: sirsoft-admin_basic 1.0.2 → 1.0.3, sirsoft-board 1.0.1 → 1.0.2
(각 manifest/package/lock/composer 동기화). 코어 7.0.4 는 미출시 누적.
2026-07-14 12:50:23 +09:00
..
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00
2026-07-01 10:30:32 +09:00

GDPR Plugin for G7

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

핵심 기능

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

설치

php artisan plugin:install sirsoft-gdpr
php artisan plugin:activate sirsoft-gdpr

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

설정

관리자 → 플러그인 → GDPR 설정 에서 구성합니다.

운영 정보

항목 설명
운영 주체명 (legal_entity_name) 쿠키 배너 푸터·마이페이지 동의 카드에 노출되는 사이트 운영 주체 (예: "(주)홍길동컴퍼니")
데이터 저장 위치 (data_storage_location) 사용자에게 안내할 데이터 저장 국가 (예: "대한민국", "미국 (AWS)"). IP 주소·CIDR·클라우드 리전 코드(예: ap-northeast-2)는 보안상 자동 거부됩니다
개인정보처리방침 슬러그 (privacy_policy_slug) sirsoft-page 플러그인에 등록된 처리방침 페이지의 슬러그. 비어있으면 쿠키 배너의 정책 링크가 자동 숨겨집니다

쿠키 배너

항목 설명
쿠키 배너 노출 (banner_enabled) 마스터 토글 — ON 시 배너 + 자동 차단 + 마이페이지 동의 관리 카드가 일괄 활성화됩니다. GDPR Art.6 "동의 전 처리 금지" 의 강제 메커니즘인 자동 차단을 단독 OFF 할 수 없도록 단일 토글로 통합되어 있습니다
배너 위치 (banner_position) 하단 바 / 좌하단 팝업 / 우하단 팝업 / 중앙 모달

자동 차단 정책

쿠키 배너가 ON 일 때 다음 카테고리의 외부 도메인 리소스가 동의 전까지 자동 차단됩니다. 카탈로그 기본값이 시드되어 있으며, 운영자가 카테고리별로 추가·삭제할 수 있습니다.

카테고리 기본 카탈로그 예시
기능 (functional) Crisp, Intercom, Tawk.to, Weglot 등
분석 (analytics) Google Analytics, Hotjar, Mixpanel, 네이버 프리미엄 로그분석 등
마케팅 (marketing) Facebook Pixel, Google Ads, Kakao Pixel, YouTube embed 등

도메인 형식: example.com 또는 와일드카드 *.example.com. localhost 같은 단일 라벨, 한글 도메인(xn-- 변환)은 미지원.

자체 호스팅 추적 자원 분류

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

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

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

정책 버전 발행

관리자 → 플러그인 → GDPR 설정 의 「정책 버전」 카드에서 「+ 새 버전 발행」 을 클릭합니다. 발행 즉시 모든 회원이 다음 방문 시 재동의 화면(amber 안내 박스 + 「최신 정책으로 갱신」 버튼)을 보게 됩니다.

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

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

동의 이력 조회

관리자 → GDPR 동의 이력 메뉴에서 회원/게스트의 모든 동의 변경 이력을 조회할 수 있습니다.

  • 검색: 이메일 부분 일치, 세션 ID
  • 필터: 카테고리(필수/기능/분석/마케팅), 출처(banner/mypage/register/withdraw 등), 동의 액션(granted/revoked)
  • 카테고리 스냅샷: 각 행 펼침에서 동의 시점의 전체 카테고리 의사 표를 immutable 보존 (GDPR Art.7(1) 입증 자료)

가용 훅 (Hook)

다른 확장에서 본 플러그인의 동의 이벤트를 구독할 수 있습니다.

액션 훅

훅 이름 시점 인수
sirsoft-gdpr.consent.granted 동의 부여 시 GdprUserConsent $consent, string $source
sirsoft-gdpr.consent.revoked 동의 철회 시 GdprUserConsent $consent, string $source

$source 값: banner / mypage / mypage_renew_all / register / withdraw.

훅 등록 예시

use App\Extension\HookManager;

HookManager::addAction(
    'sirsoft-gdpr.consent.granted',
    function ($consent, string $source) {
        // 예: 분석 동의 부여 시 외부 분석 도구에 사용자 식별 전송
        if ($consent->consent_key === 'cookie_analytics' && $consent->is_consented) {
            AnalyticsService::identify($consent->user_id);
        }
    },
    priority: 10
);

데이터베이스

테이블 용도 보존 정책
gdpr_user_consents 회원 현재 동의 상태 (mutable) 사용자 삭제 시 명시 삭제
gdpr_user_consent_histories 동의 변경 이력 (immutable append-only) 사용자 삭제 시 user_id/IP/UA 만 NULL 익명화하여 행 보존 (GDPR Art.17 + Art.7(1) 양립)
gdpr_policy_versions 정책 버전 발행 이력 (불변) 영구 보존 (Art.30 처리 기록)

플러그인 제거 시 위 3 테이블이 자동 DROP 됩니다.

게스트 → 회원 동의 승계

본 플러그인은 게스트 → 회원 동의 자동 승계를 제공하지 않습니다. GDPR Art.6/ePrivacy Art.5(3) 관점에서 게스트(디바이스 단위)와 회원(주체 단위)은 별도 동의 모델이며, 글로벌 CMP 대부분도 자동 승계를 기본으로 제공하지 않습니다. 회원가입 폼 동의로 Art.7(1) 입증 책임이 충족되며, 게스트 시절 동의 이력은 세션 기준으로 보존됩니다.

의존성

대상 의존 수준 미설치 시 동작
sirsoft-page 모듈 소프트 (런타임 체크) 배너 "자세히" 링크만 자동 숨김. 나머지 정상
sirsoft-basic 템플릿 주입 지점 의존 다른 사용자 템플릿 사용 시 해당 템플릿에도 _user_base.json 의 공용 확장 지점이 있어야 정상 동작

테스트 실행

# 백엔드
php vendor/bin/phpunit plugins/_bundled/sirsoft-gdpr/tests

# 프론트엔드
cd plugins/_bundled/sirsoft-gdpr
npm run test:run

라이선스

MIT