diff --git a/package-lock.json b/package-lock.json
index 8bb1642..2f10041 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"axios": "^1.8.1",
+ "chart.js": "^4.4.8",
"cra-template": "1.2.0",
"react": "^19.0.0",
"react-cookie": "^7.2.2",
@@ -2998,6 +2999,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@kurkle/color": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
+ "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
+ "license": "MIT"
+ },
"node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
@@ -5506,6 +5513,18 @@
"node": ">=10"
}
},
+ "node_modules/chart.js": {
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz",
+ "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==",
+ "license": "MIT",
+ "dependencies": {
+ "@kurkle/color": "^0.3.0"
+ },
+ "engines": {
+ "pnpm": ">=8"
+ }
+ },
"node_modules/check-types": {
"version": "11.2.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz",
diff --git a/package.json b/package.json
index f0fa293..0a9c901 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"axios": "^1.8.1",
+ "chart.js": "^4.4.8",
"cra-template": "1.2.0",
"react": "^19.0.0",
"react-cookie": "^7.2.2",
diff --git a/src/App.js b/src/App.js
index a205814..8ad93e9 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,6 +1,6 @@
-import React from 'react';
-import AppRoutes from './appRoutes/routes'
-import { BrowserRouter } from 'react-router-dom';
+import React from "react";
+import AppRoutes from "./appRoutes/routes";
+import { BrowserRouter } from "react-router-dom";
import { UserProvider } from "./contexts/UserContext"; // UserProvider 추가
function App() {
diff --git a/src/components/Dashboard.jsx b/src/components/Dashboard.jsx
index 4b96854..8278ebd 100644
--- a/src/components/Dashboard.jsx
+++ b/src/components/Dashboard.jsx
@@ -1,45 +1,826 @@
-import React, { useEffect, useState } from "react"; // useEffect를 import
-import { useNavigate } from "react-router-dom"; // useNavigate를 import
-//import axios from "axios";
+import React, { useEffect, useState, useRef } from "react";
+import { useNavigate } from "react-router-dom";
+import { useUser } from "../contexts/UserContext"; // UserContext 추가
import styles from "../styles/Dashboard.module.css";
import NavBar from "./NavBar";
+import Chart from "chart.js/auto";
const Dashboard = () => {
const navigate = useNavigate();
- //const [user, setUser] = useState(null);
+ const { user } = useUser(); // UserContext에서 user 가져오기
const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const chartRef = useRef(null);
+ const chartInstance = useRef(null);
+ const checklistChartRef = useRef(null);
+ const checklistChartInstance = useRef(null);
+ const monthlyChartRef = useRef(null);
+ const monthlyChartInstance = useRef(null);
+ const [monthlyRiskData, setMonthlyRiskData] = useState([]);
+ const monthlyRiskChartRef = useRef(null);
+ const monthlyRiskChartInstance = useRef(null);
+ const [sensitiveInfoData, setSensitiveInfoData] = useState([]);
+ const sensitiveInfoChartRef = useRef(null);
+ const sensitiveInfoChartInstance = useRef(null);
- const securityData = [
- { type: "주소", count: 150 },
- { type: "전화번호", count: 120 },
- { type: "이메일", count: 100 },
- { type: "주민번호", count: 80 },
- { type: "신용카드", count: 50 },
- ];
+ // 월간 데이터 상태
+ const [monthlyData, setMonthlyData] = useState({
+ totalCount: 0,
+ dateData: [],
+ });
- useEffect(() => {
- // 로그인 상태 확인
- const token = localStorage.getItem("token");
- const storedUser = localStorage.getItem("user");
+ // 체크리스트 상태
+ const [checklistData, setChecklistData] = useState([]);
+ const [checklistInput, setChecklistInput] = useState("");
+
+ // 서버에서 가져온 데이터를 저장할 상태
+ const [dashboardData, setDashboardData] = useState({
+ today: {
+ detectedCount: 0,
+ sensitiveTypes: [],
+ lastExecutionDate: null,
+ lastExecutionCount: 0,
+ changeRate: 0,
+ },
+ monthly: {
+ thisMonth: 0,
+ lastMonth: 0,
+ changePercent: 0,
+ },
+ safetyScore: 85,
+ globalPercentile: 15,
+ });
- if (!token || !storedUser) {
+ // 안전 점수 데이터
+ const [safetyData, setSafetyData] = useState({
+ currentScore: 0,
+ previousScore: 0,
+ scoreDifference: 0,
+ percentile: 0,
+ });
+
+ useEffect(() => {
+ // 로그인 상태 확인 - useUser 훅 사용
+ if (!user) {
alert("로그인이 필요합니다.");
navigate("/login");
return;
}
- //setUser(JSON.parse(storedUser));
- setIsLoading(false);
+ // 사용자 이메일 가져오기
+ const userEmail = user.email;
+
+ // 대시보드 데이터 가져오기
+ fetchDashboardData(userEmail);
+
+ // 안전 점수 데이터 가져오기
+ fetchSafetyData(userEmail);
+
+ // 체크리스트 데이터 로드 (localStorage)
+ loadChecklistData();
+
+ // 월간 데이터 가져오기
+ fetchMonthlyData(userEmail);
+
+ // 월간 위험 감지 데이터 가져오기
+ fetchMonthlyRiskData(userEmail);
+
+ // 유형별 민감 정보 데이터 가져오기
+ fetchSensitiveInfoData(userEmail);
+
+ return () => {
+ // 컴포넌트 언마운트 시 차트 정리
+ if (chartInstance.current) {
+ chartInstance.current.destroy();
+ }
+ if (checklistChartInstance.current) {
+ checklistChartInstance.current.destroy();
+ }
+ if (monthlyChartInstance.current) {
+ monthlyChartInstance.current.destroy();
+ }
+
+ if (monthlyRiskChartInstance.current) {
+ monthlyRiskChartInstance.current.destroy();
+ }
+
+ if (sensitiveInfoChartInstance.current) {
+ sensitiveInfoChartInstance.current.destroy();
+ }
+ };
+ }, [user, navigate]); // user 상태 추가
+
+ // 월간 데이터 가져오기
+ // 1. fetchMonthlyData 함수 수정
+ // fetchMonthlyData 함수 수정
+ const fetchMonthlyData = async (email) => {
+ try {
+ const response = await fetch(
+ `http://localhost:5000/api/dashboard/monthly-data?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!response.ok) {
+ throw new Error("월간 데이터를 가져오는데 실패했습니다.");
+ }
+
+ const data = await response.json();
+ console.log("월간 데이터 API 응답:", data);
+
+ if (data.success) {
+ // API 응답 데이터 형식에 맞게 조정 (한 번만 호출)
+ setMonthlyData({
+ totalCount: data.data.totalCount || 0,
+ dateData: data.data.dailyData || [],
+ });
+ } else {
+ throw new Error(data.message || "월간 데이터 로드 실패");
+ }
+ } catch (error) {
+ console.error("월간 데이터 로드 오류:", error);
+ setMonthlyData({
+ totalCount: 0,
+ dateData: [],
+ });
+ }
+ };
+
+ // 2. 월간 차트 생성 부분 수정
+ // 월간 차트 생성 및 업데이트
+ useEffect(() => {
+ // 로드 중이거나 오류가 있다면 차트를 그리지 않음
+ if (isLoading || error) return;
+
+ // 약간의 지연을 두어 DOM이 완전히 렌더링된 후 차트 생성
+ const timer = setTimeout(() => {
+ if (!monthlyChartRef.current) {
+ console.log("차트 ref가 없습니다 - 지연 후 체크");
+ return;
+ }
+
+ console.log("월간 차트 useEffect 실행:", monthlyData);
+
+ // 기존 차트가 있으면 파괴
+ if (monthlyChartInstance.current) {
+ monthlyChartInstance.current.destroy();
+ }
+
+ // 데이터 준비
+ const labels = monthlyData.dateData.map((item) => item.date);
+ const values = monthlyData.dateData.map((item) => item.detection_count);
+
+ console.log("차트 데이터:", { labels, values });
+
+ // 차트 생성
+ const ctx = monthlyChartRef.current.getContext("2d");
+ monthlyChartInstance.current = new Chart(ctx, {
+ // 기존 차트 옵션 유지
+ type: "bar",
+ data: {
+ labels: labels,
+ datasets: [
+ {
+ data: values,
+ backgroundColor: "rgba(104, 132, 245, 0.7)",
+ borderColor: "rgba(104, 132, 245, 1)",
+ borderWidth: 1,
+ },
+ ],
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ display: false,
+ },
+ },
+ scales: {
+ x: {
+ grid: {
+ display: false,
+ },
+ ticks: {
+ color: "#94a3b8",
+ },
+ },
+ y: {
+ grid: {
+ display: false,
+ },
+ beginAtZero: true,
+ ticks: {
+ color: "#94a3b8",
+ },
+ },
+ },
+ },
+ });
+ }, 100); // 100ms 지연
+
+ return () => clearTimeout(timer);
+ }, [monthlyData, isLoading, error]);
+
+ // 월간 위험 감지 차트 생성 및 업데이트
+ useEffect(() => {
+ if (isLoading || error || !monthlyRiskChartRef.current) return;
+
+ // 데이터가 비어있는지 확인
+ if (!monthlyRiskData.length) return;
+
+ // 약간의 지연을 두어 DOM이 완전히 렌더링된 후 차트 생성
+ const timer = setTimeout(() => {
+ // 기존 차트가 있으면 파괴
+ if (monthlyRiskChartInstance.current) {
+ monthlyRiskChartInstance.current.destroy();
+ }
+
+ // 데이터 준비 - 월 표시를 더 읽기 쉽게 변환 (YYYY-MM -> YYYY년 MM월)
+ const labels = monthlyRiskData.map((item) => {
+ const [year, month] = item.month.split("-");
+ return `${year}년 ${month}월`;
+ });
+ const values = monthlyRiskData.map((item) => item.count);
+
+ // 차트 생성
+ const ctx = monthlyRiskChartRef.current.getContext("2d");
+ monthlyRiskChartInstance.current = new Chart(ctx, {
+ type: "line",
+ data: {
+ labels: labels,
+ datasets: [
+ {
+ label: "감지 건수",
+ data: values,
+ borderColor: "#818cf8",
+ backgroundColor: "rgba(129, 140, 248, 0.2)",
+ borderWidth: 2,
+ pointRadius: 4,
+ fill: true,
+ tension: 0.4, // 곡선 형태로 표시
+ },
+ ],
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ callbacks: {
+ title: function (tooltipItems) {
+ return tooltipItems[0].label;
+ },
+ label: function (context) {
+ return `감지 건수: ${context.parsed.y}건`;
+ },
+ },
+ },
+ },
+ scales: {
+ x: {
+ grid: {
+ display: false,
+ },
+ ticks: {
+ color: "#94a3b8",
+ },
+ },
+ y: {
+ grid: {
+ display: false,
+ },
+ beginAtZero: true,
+ ticks: {
+ color: "#94a3b8",
+ },
+ },
+ },
+ },
+ });
+ }, 100);
+
+ return () => clearTimeout(timer);
+ }, [monthlyRiskData, isLoading, error]);
+
+ // 월간 위험 감지 데이터 가져오기 함수
+ const fetchMonthlyRiskData = async (email) => {
+ try {
+ const response = await fetch(
+ `http://localhost:5000/api/dashboard/monthly-risk?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!response.ok) {
+ throw new Error("월간 위험 감지 데이터를 가져오는데 실패했습니다.");
+ }
+
+ const data = await response.json();
+ console.log("월간 위험 감지 API 응답:", data);
+
+ if (data.success) {
+ setMonthlyRiskData(data.data || []);
+ } else {
+ throw new Error(data.message || "월간 위험 감지 데이터 로드 실패");
+ }
+ } catch (error) {
+ console.error("월간 위험 감지 데이터 로드 오류:", error);
+ setMonthlyRiskData([]);
+ }
+ };
+
+ // 유형별 민감 정보 데이터 가져오기 함수
+ const fetchSensitiveInfoData = async (email) => {
+ try {
+ const response = await fetch(
+ `http://localhost:5000/api/dashboard/sensitive-info?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!response.ok) {
+ throw new Error("유형별 민감 정보를 가져오는데 실패했습니다.");
+ }
+
+ const data = await response.json();
+ console.log("유형별 민감 정보 API 응답:", data);
+
+ if (data.success) {
+ setSensitiveInfoData(data.data || []);
+ } else {
+ throw new Error(data.message || "유형별 민감 정보 로드 실패");
+ }
+ } catch (error) {
+ console.error("유형별 민감 정보 로드 오류:", error);
+ setSensitiveInfoData([]);
+ }
+ };
+
+ // 유형별 민감 정보 차트 생성 및 업데이트
+ useEffect(() => {
+ if (isLoading || error || !sensitiveInfoChartRef.current) return;
+
+ // 데이터가 비어있는지 확인
+ if (!sensitiveInfoData.length) return;
+
+ // 약간의 지연을 두어 DOM이 완전히 렌더링된 후 차트 생성
+ const timer = setTimeout(() => {
+ // 기존 차트가 있으면 파괴
+ if (sensitiveInfoChartInstance.current) {
+ sensitiveInfoChartInstance.current.destroy();
+ }
+
+ // 데이터 준비
+ const labels = sensitiveInfoData.map((item) => item.content_type);
+ const values = sensitiveInfoData.map((item) => item.count);
+
+ // 배경색 배열
+ const backgroundColors = [
+ "rgba(104, 132, 245, 0.8)",
+ "rgba(235, 87, 87, 0.8)",
+ "rgba(240, 180, 41, 0.8)",
+ "rgba(46, 213, 115, 0.8)",
+ "rgba(156, 136, 255, 0.8)",
+ ];
+
+ // 차트 생성
+ const ctx = sensitiveInfoChartRef.current.getContext("2d");
+ sensitiveInfoChartInstance.current = new Chart(ctx, {
+ type: "pie",
+ data: {
+ labels: labels,
+ datasets: [
+ {
+ data: values,
+ backgroundColor: backgroundColors.slice(0, labels.length),
+ borderWidth: 1,
+ borderColor: "rgba(255, 255, 255, 0.2)",
+ },
+ ],
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ position: "bottom",
+ labels: {
+ color: "#94a3b8",
+ font: { size: 12 },
+ padding: 15,
+ },
+ },
+ tooltip: {
+ callbacks: {
+ label: function (context) {
+ const label = context.label || "";
+ const value = context.parsed || 0;
+ const total = context.dataset.data.reduce((a, b) => a + b, 0);
+ const percentage = ((value / total) * 100).toFixed(1);
+ return `${label}: ${value}건 (${percentage}%)`;
+ },
+ },
+ },
+ },
+ },
+ });
+ }, 100);
+
+ return () => clearTimeout(timer);
+ }, [sensitiveInfoData, isLoading, error]);
+
+ // 안전 점수 차트 생성 및 업데이트
+ useEffect(() => {
+ if (!chartRef.current) return;
+
+ // 기존 차트가 있으면 파괴
+ if (chartInstance.current) {
+ chartInstance.current.destroy();
+ }
+
+ // 중앙 텍스트 플러그인 등록
+ const centerTextPlugin = {
+ id: "centerText",
+ beforeDraw(chart) {
+ const { width, height } = chart;
+ const { ctx } = chart;
+ const text = chart.options.plugins.centerText.text || "0";
+
+ ctx.save();
+ ctx.font = "bold 40px Arial";
+ ctx.fillStyle = "#ffffff"; // 흰색 텍스트 (다크 테마)
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(text, width / 2, height / 2);
+ ctx.restore();
+ },
+ };
+
+ // 차트 생성
+ const ctx = chartRef.current.getContext("2d");
+ chartInstance.current = new Chart(ctx, {
+ type: "doughnut",
+ data: {
+ datasets: [
+ {
+ data: [safetyData.currentScore, 100 - safetyData.currentScore],
+ backgroundColor: ["#3B82F6", "rgba(255, 255, 255, 0.1)"], // 파란색, 투명 흰색 (다크 테마)
+ },
+ ],
+ },
+ options: {
+ responsive: true,
+ plugins: {
+ tooltip: {
+ callbacks: {
+ label: function (context) {
+ return context.label + ": " + context.parsed + "%";
+ },
+ },
+ },
+ centerText: {
+ text: safetyData.currentScore.toString(),
+ },
+ legend: {
+ display: false, // 범례 숨김
+ },
+ },
+ cutout: "80%",
+ },
+ plugins: [centerTextPlugin],
+ });
+ }, [safetyData.currentScore]);
+
+ // 체크리스트 차트 생성 및 업데이트
+ useEffect(() => {
+ if (!checklistChartRef.current) return;
+
+ // 기존 차트가 있으면 파괴
+ if (checklistChartInstance.current) {
+ checklistChartInstance.current.destroy();
+ }
+
+ // 차트 중앙에 완료/전체 항목 수를 표시하는 커스텀 플러그인
+ const centerTextPlugin = {
+ id: "centerTextChecklist",
+ afterDraw: (chart) => {
+ const { ctx, width, height } = chart;
+ ctx.save();
+ const completedCount = checklistData.filter(
+ (item) => item.completed
+ ).length;
+ const totalCount = checklistData.length;
+ const text = totalCount ? `${completedCount}/${totalCount}` : `0/0`;
+ ctx.font = "bold 20px Arial";
+ ctx.fillStyle = "#ffffff"; // 흰색 텍스트 (다크 테마)
+ ctx.textBaseline = "middle";
+ ctx.textAlign = "center";
+ ctx.fillText(text, width / 2, height / 2);
+ ctx.restore();
+ },
+ };
+
+ const completedCount = checklistData.filter(
+ (item) => item.completed
+ ).length;
+ const totalCount = checklistData.length;
+ const uncompletedCount = totalCount - completedCount;
+
+ // 체크리스트 차트 생성
+ const ctx = checklistChartRef.current.getContext("2d");
+ checklistChartInstance.current = new Chart(ctx, {
+ type: "doughnut",
+ data: {
+ labels: ["완료", "미완료"],
+ datasets: [
+ {
+ data: [completedCount, uncompletedCount],
+ backgroundColor: ["#3B82F6", "rgba(255, 255, 255, 0.1)"], // 파란색, 투명 흰색 (다크 테마)
+ borderWidth: 0,
+ },
+ ],
+ },
+ options: {
+ cutout: "70%",
+ plugins: {
+ legend: { display: false },
+ tooltip: { enabled: false },
+ },
+ },
+ plugins: [centerTextPlugin],
+ });
+ }, [checklistData]);
+
+ // 체크리스트 데이터 로드
+ const loadChecklistData = () => {
+ try {
+ const savedData = localStorage.getItem("securityChecklist");
+ if (savedData) {
+ setChecklistData(JSON.parse(savedData));
+ }
+ } catch (error) {
+ console.error("체크리스트 데이터 로드 오류:", error);
+ }
+ };
+
+ // 체크리스트 데이터 저장
+ const saveChecklistData = (data) => {
+ try {
+ localStorage.setItem("securityChecklist", JSON.stringify(data));
+ } catch (error) {
+ console.error("체크리스트 데이터 저장 오류:", error);
+ }
+ };
+
+ // 체크리스트 항목 추가 핸들러
+ const handleAddChecklistItem = (e) => {
+ e.preventDefault();
+ const trimmedInput = checklistInput.trim();
+
+ if (trimmedInput) {
+ // 한 줄씩 입력 (공백 제거)
+ const lines = trimmedInput.split("\n");
+ const newItems = lines
+ .map((line) => line.trim())
+ .filter((line) => line !== "")
+ .map((line) => ({
+ text: line,
+ completed: false,
+ }));
+
+ const updatedList = [...checklistData, ...newItems];
+ setChecklistData(updatedList);
+ saveChecklistData(updatedList);
+ setChecklistInput("");
+ }
+ };
+
+ // 체크리스트 항목 상태 변경 핸들러
+ const handleToggleChecklistItem = (index) => {
+ const updatedList = [...checklistData];
+ updatedList[index].completed = !updatedList[index].completed;
+ setChecklistData(updatedList);
+ saveChecklistData(updatedList);
+ };
+
+ // 체크리스트 항목 삭제 핸들러
+ const handleDeleteChecklistItem = (index) => {
+ const updatedList = checklistData.filter((_, i) => i !== index);
+ setChecklistData(updatedList);
+ saveChecklistData(updatedList);
+ };
+
+ // 안전 점수 계산 함수
+ const calculateSafetyScore = (leakData) => {
+ const sensitivityWeights = { 낮음: 0.1, 중간: 0.3, 높음: 0.7 };
+
+ // 카테고리별 유출 개수 집계
+ let categoryCounts = {};
+ let categoryWeights = {};
+
+ leakData.forEach(({ content_type, sensitivity_level, count }) => {
+ categoryCounts[content_type] =
+ (categoryCounts[content_type] || 0) + count;
+ categoryWeights[content_type] =
+ sensitivityWeights[sensitivity_level] || 0.3; // 기본값 중간
+ });
+
+ const categories = Object.keys(categoryCounts);
+ const counts = Object.values(categoryCounts);
+ const weights = categories.map((cat) => categoryWeights[cat]);
+
+ const N = counts.reduce((acc, val) => acc + val, 0);
+ const w_total = 0.05 + Math.min(0.02 * N, 2);
+
+ let weightedSum = 0;
+ for (let i = 0; i < categories.length; i++) {
+ weightedSum += weights[i] * counts[i];
+ }
+
+ const logTerm = Math.log(1 + w_total * N);
+ const S = 100 - weightedSum * logTerm;
+
+ return Math.min(100, Math.max(0, Math.floor(S)));
+ };
+
+ // 안전 점수 데이터 가져오기
+ const fetchSafetyData = async (email) => {
+ try {
+ // 실제로는 API 요청을 보내서 데이터를 가져와야 함
+ // 여기서는 대시보드 데이터로 계산
+
+ // 이전 유출 기록 (어제까지의 데이터)
+ const previousLeaksResponse = await fetch(
+ `http://localhost:5000/api/dashboard/previous-leaks?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!previousLeaksResponse.ok) {
+ throw new Error("이전 유출 기록을 가져오는데 실패했습니다.");
+ }
+
+ const previousLeaksData = await previousLeaksResponse.json();
+ const previousScore = calculateSafetyScore(previousLeaksData.data || []);
+
+ // 현재 유출 기록 (오늘 데이터)
+ const currentLeaksResponse = await fetch(
+ `http://localhost:5000/api/dashboard/current-leaks?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!currentLeaksResponse.ok) {
+ throw new Error("현재 유출 기록을 가져오는데 실패했습니다.");
+ }
+
+ const currentLeaksData = await currentLeaksResponse.json();
+ const currentScore = calculateSafetyScore(currentLeaksData.data || []);
+
+ // 전체 사용자 데이터
+ const allUsersResponse = await fetch(
+ `http://localhost:5000/api/dashboard/all-users-leaks`
+ );
+
+ if (!allUsersResponse.ok) {
+ throw new Error("전체 사용자 데이터를 가져오는데 실패했습니다.");
+ }
+
+ const allUsersData = await allUsersResponse.json();
+
+ // 각 사용자별 안전 점수 계산
+ const allScores = allUsersData.data.map((user) => {
+ return {
+ email: user.email,
+ score: calculateSafetyScore(user.leaks || []),
+ };
+ });
+
+ // 현재 사용자보다 점수가 높은 사용자 수
+ const higherScores = allScores.filter(
+ (item) => item.score > currentScore
+ ).length;
+
+ // 백분위 계산
+ const percentile =
+ allScores.length > 0
+ ? Math.round((higherScores / allScores.length) * 100)
+ : 50; // 데이터가 없을 경우 기본값
+
+ setSafetyData({
+ currentScore,
+ previousScore,
+ scoreDifference: currentScore - previousScore,
+ percentile,
+ });
+ } catch (error) {
+ console.error("안전 점수 데이터 로드 오류:", error);
+ // 오류 발생 시 기본 데이터
+ setSafetyData({
+ currentScore: dashboardData.safetyScore,
+ previousScore:
+ dashboardData.safetyScore -
+ parseInt(dashboardData.monthly.changePercent),
+ scoreDifference: parseInt(dashboardData.monthly.changePercent),
+ percentile: dashboardData.globalPercentile,
+ });
+ }
+ };
+
+ // 대시보드 데이터 가져오기
+ const fetchDashboardData = async (email) => {
+ try {
+ setIsLoading(true);
+ setError(null);
- // 토큰 유효성 검증 (선택적)
- // 서버에 토큰 검증 요청을 보내고 유효하지 않으면 로그아웃 처리
- }, [navigate]);
+ const response = await fetch(
+ `http://localhost:5000/api/dashboard/summary?email=${encodeURIComponent(
+ email
+ )}`
+ );
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ console.error("API 응답:", errorText);
+ throw new Error("대시보드 데이터를 불러오는데 실패했습니다.");
+ }
+
+ const data = await response.json();
+ console.log("받은 대시보드 데이터:", data);
+
+ if (data.success) {
+ setDashboardData(data.data);
+
+ // 백엔드 API가 없는 경우 대시보드 데이터로 안전 점수 설정
+ setSafetyData({
+ currentScore: data.data.safetyScore,
+ previousScore:
+ data.data.safetyScore - parseInt(data.data.monthly.changePercent),
+ scoreDifference: parseInt(data.data.monthly.changePercent),
+ percentile: data.data.globalPercentile,
+ });
+ } else {
+ throw new Error(data.message || "데이터 로드 실패");
+ }
+ } catch (error) {
+ console.error("데이터 로드 오류:", error);
+ setError(error.message);
+
+ // 오류 발생 시 기본 데이터 설정
+ setDashboardData({
+ today: {
+ detectedCount: 0,
+ sensitiveTypes: [],
+ lastExecutionDate: null,
+ lastExecutionCount: 0,
+ changeRate: 0,
+ },
+ monthly: {
+ thisMonth: 0,
+ lastMonth: 0,
+ changePercent: 0,
+ },
+ safetyScore: 100,
+ globalPercentile: 15,
+ });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // 증가/감소에 따른 색상 및 기호 반환
+ const getChangeStyle = (value) => {
+ const numValue = parseFloat(value);
+ if (numValue > 0) {
+ return { color: "#FF4D4F", symbol: "↑", text: "증가" };
+ } else if (numValue < 0) {
+ return { color: "#52C41A", symbol: "↓", text: "감소" };
+ } else {
+ return { color: "#8C8C8C", symbol: "-", text: "변동 없음" };
+ }
+ };
if (isLoading) {
return
로딩 중...
;
}
- const maxCount = Math.max(...securityData.map((item) => item.count));
+ // 가장 높은 감지 횟수 계산 (프로그레스 바용)
+ const maxCount =
+ dashboardData.today.sensitiveTypes.length > 0
+ ? Math.max(
+ ...dashboardData.today.sensitiveTypes.map((item) => item.count)
+ )
+ : 1; // 0으로 나누는 것을 방지
+
+ // 최근 실행일 변화 스타일
+ const dailyChangeStyle = getChangeStyle(dashboardData.today.changeRate);
+
+ // 안전 점수 변화 스타일
+ const safetyScoreChangeStyle = getChangeStyle(safetyData.scoreDifference);
return (
@@ -48,56 +829,154 @@ const Dashboard = () => {
개인 안전 대시보드
+ {error && {error}
}
+
+ {/* 민감 텍스트 카드 (HTML 내용을 React 컴포넌트로 변환) */}
-
감지된 위험 텍스트
-
523
-
지난 30일 동안
+
오늘 감지된 위험 텍스트
+
+ {dashboardData.today.detectedCount}
+
+ {dashboardData.today.lastExecutionDate ? (
+
+ 최근 실행일({dashboardData.today.lastExecutionDate}) 대비{" "}
+
+ {dailyChangeStyle.symbol}{" "}
+ {Math.abs(dashboardData.today.changeRate)}%
+
+
+ ) : (
+
오늘 하루 동안
+ )}
+
+ {/* 유형별 목록 */}
+ {dashboardData.today.sensitiveTypes.length > 0 && (
+
+ {dashboardData.today.sensitiveTypes.map((type, index) => (
+
+ {type.type} ({type.count}건)
+
+ ))}
+
+ )}
+ {/* 안전 점수 카드 (차트로 표시) */}
안전 점수
-
85/100
-
전월 대비 3% 상승
+
+
+
+
+ 이전 대비{" "}
+
+ {safetyScoreChangeStyle.symbol}{" "}
+ {Math.abs(safetyData.scoreDifference)}점
+
+
+ {/* 체크리스트 카드 */}
-
전세계 평균 대비
-
상위 15%
-
안전한 수준입니다
+
보안 점검 체크리스트
+
+
+
+
+ {/* 체크리스트 추가 폼 */}
+
+
+ {/* 체크리스트 목록 */}
+
+ {/* 한 달간 감지된 민감 텍스트 (새로 추가된 부분) */}
+
+
+
한 달간 감지된 민감 텍스트
+
+
+
+ {monthlyData.totalCount}건
+
+
이번 달 총 감지 건수
+
+
+
+
+
+
+
+
+ {/* 두 번째 행: 월간 위험 감지와 유형별 민감 정보 차트 */}
+ {/* 월간 위험 감지 차트 */}
-
민감 정보 유형별 감지 횟수
-
-
-
- | 유형 |
- 횟수 |
-
- 분포
- |
-
-
-
- {securityData.map((item) => (
-
- | {item.type} |
- {item.count} |
-
-
- |
-
- ))}
-
-
+
월간 위험 감지 추이
+
+
+
+
+
+ {/* 유형별 민감 정보 차트 */}
+
diff --git a/src/components/HeroPage.jsx b/src/components/HeroPage.jsx
index 496ce90..19d5f6e 100644
--- a/src/components/HeroPage.jsx
+++ b/src/components/HeroPage.jsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from "react";
-import { useNavigate, useLocation } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
import styles from "../styles/HeroPage.module.css";
import NavBar from "./NavBar";
@@ -46,7 +46,6 @@ const FeatureCard = ({ icon, title, description, delay }) => {
// Main Hero Page Component
const HeroPage = () => {
const navigate = useNavigate();
- const location = useLocation();
const [scrolled, setScrolled] = useState(false);
const [copied, setCopied] = useState(false);
const [user, setUser] = useState(null);
@@ -124,7 +123,9 @@ const HeroPage = () => {
};
// 북마크릿 코드 - 로그인 시에만 실제 코드를 보여줄 것임
- const bookmarkletCode = `일단 비워둠`;
+ const bookmarkletCode =
+ `javascript:%28function%28%29%20%7B%0A%0A%20%20%20%20const%20USER_EMAIL%20%3D%20%22%24%7BuserEmail%7D%22%3B%0A%20%20%20%20%0A%20%20%20%20%2F%2F%20%EC%9E%85%EB%A0%A5%EC%B0%BD%20%EC%B0%BE%EA%B8%B0%0A%20%20%20%20let%20inputBox%20%3D%20document.querySelector%28%22div%5Bcontenteditable%3D%27true%27%5D%22%29%3B%0A%20%20%20%20if%20%28%21inputBox%29%20%7B%0A%20%20%20%20%20%20alert%28%22%E2%9D%8C%20%EC%9E%85%EB%A0%A5%EC%B0%BD%EC%9D%84%20%EC%B0%BE%EC%9D%84%20%EC%88%98%20%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4.%20GPT%20%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90%EC%84%9C%20%EC%8B%A4%ED%96%89%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94%21%22%29%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%0A%20%20%20%20%2F%2F%20%ED%8C%A8%ED%84%B4%EC%9D%84%20%EC%9D%B4%EC%9A%A9%ED%95%9C%20%EA%B8%B0%EB%B3%B8%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EA%B0%90%EC%A7%80%20%28%EC%9D%B4%EB%A6%84%20%EA%B0%90%EC%A7%80%20%EC%B6%94%EA%B0%80%29%0A%20%20%20%20function%20localCheckSensitiveInfo%28text%29%20%7B%0A%20%20%20%20%20%20%20%20const%20patterns%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%9D%B4%EB%A9%94%EC%9D%BC%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cb%5BA-Za-z0-9._%25%2B-%5D%2B%40%5BA-Za-z0-9.-%5D%2B%5C.%5BA-Z%7Ca-z%5D%7B2%2C%7D%5Cb%2F%2C%20type%3A%20%27EMAIL%27%20%7D%2C%20%20%2F%2F%20%EA%B8%B0%EB%B3%B8%20%EC%9D%B4%EB%A9%94%EC%9D%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Ba-zA-Z0-9_.%2B-%5D%2B%40%5Ba-zA-Z0-9-%5D%2B%5C.%5Ba-zA-Z0-9-.%5D%2B%2F%2C%20type%3A%20%27EMAIL%27%20%7D%2C%20%20%2F%2F%20%EB%8D%94%20%EB%84%93%EC%9D%80%20%EB%B2%94%EC%9C%84%EC%9D%98%20%EC%9D%B4%EB%A9%94%EC%9D%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Ba-zA-Z0-9_.%2B-%5D%2B%28%3F%3A%5Cs%2B%29%3F%40%28%3F%3A%5Cs%2B%29%3F%5Ba-zA-Z0-9-%5D%2B%5C.%2B%5Ba-zA-Z0-9-.%5D%2B%2F%2C%20type%3A%20%27EMAIL%27%20%7D%2C%20%20%2F%2F%20%EC%9D%B4%EB%A9%94%EC%9D%BC%20%EA%B3%B5%EB%B0%B1%20%ED%97%88%EC%9A%A9%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Ba-zA-Z0-9_.%2B-%5D%2B%5C%28at%5C%29%5Ba-zA-Z0-9-%5D%2B%5C.%5Ba-zA-Z0-9-.%5D%2B%2F%2C%20type%3A%20%27EMAIL%27%20%7D%2C%20%20%2F%2F%20at%20%EA%B5%AC%EB%AC%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Ba-zA-Z0-9_.%2B-%5D%2B%28%3F%3A%5B%5C%5B%5C%28%5Dat%5B%5C%5D%5C%29%5D%29%5Ba-zA-Z0-9-%5D%2B%5C.%5Ba-zA-Z0-9-.%5D%2B%2F%2C%20type%3A%20%27EMAIL%27%20%7D%2C%20%20%2F%2F%20%EA%B4%84%ED%98%B8%20%EA%B5%AC%EB%AC%B8%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A3%BC%EB%AF%BC%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%20%28%EC%A0%95%ED%99%95%ED%95%9C%20%EA%B5%AC%EB%B6%84%EC%9D%84%20%EC%9C%84%ED%95%B4%20%EC%88%98%EC%A0%95%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cb%5Cd%7B6%7D-%5Cd%7B7%7D%5Cb%28%3F%21%5B%5Cd%5Cs%5C.%5C-%2F%5D%29%2F%2C%20type%3A%20%27SSN%27%20%7D%2C%20%20%2F%2F%20%EC%A3%BC%EB%AF%BC%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%20%ED%98%95%EC%8B%9D%20%286%EC%9E%90%EB%A6%AC-7%EC%9E%90%EB%A6%AC%29%20-%20%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8%EB%A1%9C%20%EC%9D%B8%EC%8B%9D%EB%90%98%EC%A7%80%20%EC%95%8A%EB%8F%84%EB%A1%9D%20%EB%B3%B4%EC%A0%95%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%8B%A0%EC%9A%A9%EC%B9%B4%EB%93%9C%20%EB%B2%88%ED%98%B8%20%28%EB%8B%A4%EC%96%91%ED%95%9C%20%EC%B9%B4%EB%93%9C%EC%82%AC%20%ED%98%95%EC%8B%9D%20%EC%A7%80%EC%9B%90%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cb%5Cd%7B4%7D-%5Cd%7B4%7D-%5Cd%7B4%7D-%5Cd%7B4%7D%5Cb%2F%2C%20type%3A%20%27CREDIT_DEBIT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EA%B8%B0%EB%B3%B8%20%EC%8B%A0%EC%9A%A9%EC%B9%B4%EB%93%9C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B3%2C4%7D%2F%2C%20type%3A%20%27CREDIT_DEBIT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EA%B8%B0%EB%B3%B8%20%EC%8B%A0%EC%9A%A9%EC%B9%B4%EB%93%9C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F3%5B47%5D%5Cd%7B2%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B6%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B5%7D%2F%2C%20type%3A%20%27CREDIT_DEBIT_NUMBER%27%20%7D%2C%20%20%2F%2F%20American%20Express%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F6%28%3F%3A011%7C5%5Cd%7B2%7D%29%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27CREDIT_DEBIT_NUMBER%27%20%7D%2C%20%20%2F%2F%20Discover%20%EC%B9%B4%EB%93%9C%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%ED%95%9C%EA%B5%AD%EC%96%B4%20%EC%9D%B4%EB%A6%84%20%ED%8C%A8%ED%84%B4%20%EC%B6%94%EA%B0%80%20%282-4%EC%9E%90%EC%9D%98%20%ED%95%9C%EA%B8%80%20%EC%9D%B4%EB%A6%84%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5E%28%5B%EA%B0%80-%ED%9E%A3%5D%7B2%2C4%7D%29%28%3F%3A%5Cs%3F%28%3F%3A%EB%8B%98%7C%EC%94%A8%7C%EC%9D%B4%7C%EA%B0%80%7C%EA%BB%98%29%3F%29%5Cs%3F%28%3F%3D%5B%EA%B0%80-%ED%9E%A3%7C%5Cs%5D%2A%24%29%2F%2C%20type%3A%20%27NAME%27%20%7D%2C%20%20%2F%2F%20%ED%95%9C%EA%B8%80%20%EC%9D%B4%EB%A6%84%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%98%81%EB%AC%B8%20%EC%9D%B4%EB%A6%84%20%ED%8C%A8%ED%84%B4%20-%20%EC%84%B1%2B%EC%9D%B4%EB%A6%84%20%ED%98%95%ED%83%9C%EC%9D%98%20%ED%8C%A8%ED%84%B4%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cb%5BA-Z%5D%5Ba-z%5D%2B%5Cs%5BA-Z%5D%5Ba-z%5D%2B%5Cb%2F%2C%20type%3A%20%27NAME%27%20%7D%2C%20%20%2F%2F%20%EC%98%81%EB%AC%B8%20%EC%9D%B4%EB%A6%84%20%28%EC%84%B1%2B%EC%9D%B4%EB%A6%84%29%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%97%AC%EA%B6%8C%20%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2FM%5Cd%7B8%7D%7CM%5B0-9A-Z%5D%7B8%7D%2F%2C%20type%3A%20%27PASSPORT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EC%97%AC%EA%B6%8C%20%EB%B2%88%ED%98%B8%20%28%EA%B8%B0%EA%B3%84%ED%8C%90%EB%8F%85%EC%8B%9D%2C%20%EC%98%81%EB%AC%B8%20%ED%8F%AC%ED%95%A8%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5BA-Z%5D%7B2%7D%5Cd%7B7%7D%2F%2C%20type%3A%20%27PASSPORT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EC%9D%BC%EB%B0%98%20%EC%97%AC%EA%B6%8C%20%ED%98%95%EC%8B%9D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%28%3F%3ABS%7CUS%7CDG%7CGB%7CGN%7CGJ%7CDJ%7CIC%7CSO%7CSJ%7CSW%7CCH%7CKW%7CTJ%7CHJ%7CHD%7CPS%29%5Cd%7B7%7D%2F%2C%20type%3A%20%27PASSPORT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EC%A7%80%EC%97%AD%20%EC%BD%94%EB%93%9C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5BA-Z%5D%7B1%2C2%7D%5Cd%7B7%2C8%7D%2F%2C%20type%3A%20%27PASSPORT_NUMBER%27%20%7D%2C%20%20%2F%2F%20%EA%B8%B0%ED%83%80%20%EA%B5%AD%EA%B0%80%20%EC%97%AC%EA%B6%8C%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%20%28%EC%A3%BC%EB%AF%BC%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%EC%99%80%EC%9D%98%20%ED%98%BC%EB%8F%99%EC%9D%84%20%EB%A7%89%EA%B8%B0%20%EC%9C%84%ED%95%B4%20%EA%B5%AC%EC%B2%B4%ED%99%94%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F01%5B0-9%5D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B3%2C4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EA%B5%AD%EB%82%B4%20%ED%9C%B4%EB%8C%80%ED%8F%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5C%2B82%5B%5Cs%5C-%5C.%5D%3F1%5B0-9%5D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B3%2C4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EA%B5%AD%EC%A0%9C%20%ED%98%95%EC%8B%9D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F0%5Cd%7B1%2C2%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B3%2C4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EC%A7%80%EC%97%AD%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F01%5B0-9%5D%5B%5Cs%5D%2A%5Cd%7B4%7D%5B%5Cs%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EA%B3%B5%EB%B0%B1%20%EA%B5%AC%EB%B6%84%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F050%5Cd%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B3%2C4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EC%9D%B8%ED%84%B0%EB%84%B7%EC%A0%84%ED%99%94%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F070%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%5B%5Cs%5C-%5C.%2F%5D%2A%5Cd%7B4%7D%2F%2C%20type%3A%20%27PHONE%27%20%7D%2C%20%20%2F%2F%20%EC%9D%B8%ED%84%B0%EB%84%B7%EC%A0%84%ED%99%94%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A3%BC%EC%86%8C%20%ED%8C%A8%ED%84%B4%20%28%EB%8D%94%20%EB%A7%8E%EC%9D%80%20%ED%98%95%EC%8B%9D%20%EC%B6%94%EA%B0%80%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%28%3F%3A%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EC%8B%9C%7C%EB%8F%84%29%5Cs%2A%29%3F%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EC%8B%9C%7C%EA%B5%B0%7C%EA%B5%AC%29%5Cs%2A%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EC%9D%8D%7C%EB%A9%B4%7C%EB%8F%99%7C%EA%B0%80%7C%EB%A1%9C%7C%EA%B8%B8%29%5Cs%2A%28%3F%3A%5Cd%2B%28%3F%3A-%5Cd%2B%29%3F%29%3F%2F%2C%20type%3A%20%27ADDRESS%27%20%7D%2C%20%20%2F%2F%20%EB%B3%B5%ED%95%A9%20%EC%A3%BC%EC%86%8C%20%ED%98%95%EC%8B%9D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EC%95%84%ED%8C%8C%ED%8A%B8%7C%EB%B9%8C%EB%9D%BC%7C%EC%98%A4%ED%94%BC%EC%8A%A4%ED%85%94%29%5Cs%2A%5Cd%2B%EB%8F%99%5Cs%2A%5Cd%2B%ED%98%B8%2F%2C%20type%3A%20%27ADDRESS%27%20%7D%2C%20%20%2F%2F%20%EC%95%84%ED%8C%8C%ED%8A%B8%20%EC%A3%BC%EC%86%8C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EB%A1%9C%7C%EA%B8%B8%29%5Cs%2A%5Cd%2B%28%3F%3A-%5Cd%2B%29%3F%2F%2C%20type%3A%20%27ADDRESS%27%20%7D%2C%20%20%2F%2F%20%EB%8F%84%EB%A1%9C%EB%AA%85%20%EC%A3%BC%EC%86%8C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%27%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%3F%3A%EC%95%84%ED%8C%8C%ED%8A%B8%7C%EB%B9%8C%EB%9D%BC%7C%EC%98%A4%ED%94%BC%EC%8A%A4%ED%85%94%7C%ED%83%80%EC%9B%8C%7C%EB%A7%A8%EC%85%98%29%5Cs%2A%5Cd%2B%EB%8F%99%5Cs%2A%5Cd%2B%ED%98%B8%27%2C%20type%3A%20%27ADDRESS%27%20%7D%2C%20%20%2F%2F%20%EC%B6%94%EA%B0%80%20%EC%A3%BC%EC%86%8C%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%28%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%EC%8B%9C%7C%EB%8F%84%7C%EA%B5%B0%7C%EA%B5%AC%7C%EC%9D%8D%7C%EB%A9%B4%7C%EB%8F%99%29%29%5Cs%28%5B%EA%B0%80-%ED%9E%A3%5D%2B%28%EA%B5%AC%7C%EB%A1%9C%7C%EA%B8%B8%7C%EB%8F%99%29%29%5Cs%3F%28%5Cd%2B%28%3F%3A-%5Cd%2B%29%3F%29%3F%2F%2C%20type%3A%20%27ADDRESS%27%20%7D%2C%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%9A%B4%EC%A0%84%EB%A9%B4%ED%97%88%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B2%7D%5B-%5Cs%5D%3F%5Cd%7B2%7D%5B-%5Cs%5D%3F%5Cd%7B6%7D%5B-%5Cs%5D%3F%5Cd%7B2%7D%2F%2C%20type%3A%20%27DRIVER_LICENSE%27%20%7D%2C%20%20%2F%2F%20%EC%9A%B4%EC%A0%84%EB%A9%B4%ED%97%88%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B12%7D%2F%2C%20type%3A%20%27DRIVER_LICENSE%27%20%7D%2C%20%20%2F%2F%2012%EC%9E%90%EB%A6%AC%20%EC%9A%B4%EC%A0%84%EB%A9%B4%ED%97%88%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%EC%84%9C%EC%9A%B8%7C%EB%B6%80%EC%82%B0%7C%EB%8C%80%EA%B5%AC%7C%EC%9D%B8%EC%B2%9C%7C%EA%B4%91%EC%A3%BC%7C%EB%8C%80%EC%A0%84%7C%EC%9A%B8%EC%82%B0%7C%EC%84%B8%EC%A2%85%7C%EA%B2%BD%EA%B8%B0%7C%EA%B0%95%EC%9B%90%7C%EC%B6%A9%EB%B6%81%7C%EC%B6%A9%EB%82%A8%7C%EC%A0%84%EB%B6%81%7C%EC%A0%84%EB%82%A8%7C%EA%B2%BD%EB%B6%81%7C%EA%B2%BD%EB%82%A8%7C%EC%A0%9C%EC%A3%BC%7C%EA%B0%95%EC%9B%90%5B-%5Cs%5D%3F%5Cd%7B8%7D%2F%2C%20type%3A%20%27DRIVER_LICENSE%27%20%7D%2C%20%20%2F%2F%20%EC%A7%80%EC%97%AD%EB%AA%85%20%2B%208%EC%9E%90%EB%A6%AC%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%99%B8%EA%B5%AD%EC%9D%B8%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B6%7D%5B%5Cs%5C-%5C.%2F%5D%2B%5B5-8%5D%5Cd%7B6%7D%2F%2C%20type%3A%20%27FOREIGN_REGISTRATION%27%20%7D%2C%20%20%2F%2F%20%EC%99%B8%EA%B5%AD%EC%9D%B8%20%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5BA-Z%5D%5Cd%7B5%7D%5B0-9A-Z%5D%7B2%7D%2F%2C%20type%3A%20%27FOREIGN_REGISTRATION%27%20%7D%2C%20%20%2F%2F%20%EC%99%B8%EA%B5%AD%EC%9D%B8%20%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EA%B1%B4%EA%B0%95%EB%B3%B4%ED%97%98%EB%B2%88%ED%98%B8%20%ED%8C%A8%ED%84%B4%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B2%7D%5B-%5Cs%5D%3F%5Cd%7B8%7D%5B-%5Cs%5D%3F%5Cd%7B2%7D%2F%2C%20type%3A%20%27HEALTH_INSURANCE%27%20%7D%2C%20%20%2F%2F%20%EA%B1%B4%EA%B0%95%EB%B3%B4%ED%97%98%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20pattern%3A%20%2F%5Cd%7B2%7D%5B-%5Cs%5D%3F%5Cd%7B10%7D%2F%2C%20type%3A%20%27HEALTH_INSURANCE%27%20%7D%20%20%2F%2F%20%EA%B1%B4%EA%B0%95%EB%B3%B4%ED%97%98%EB%B2%88%ED%98%B8%0A%20%20%20%20%20%20%20%20%5D%3B%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20const%20matches%20%3D%20%5B%5D%3B%0A%20%20%20%20%20%20for%20%28let%20item%20of%20patterns%29%20%7B%0A%20%20%20%20%20%20%20%20const%20regex%20%3D%20new%20RegExp%28item.pattern%2C%20%27g%27%29%3B%0A%20%20%20%20%20%20%20%20let%20match%3B%0A%20%20%20%20%20%20%20%20while%20%28%28match%20%3D%20regex.exec%28text%29%29%20%21%3D%3D%20null%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%9D%B4%EB%A6%84%20%ED%8C%A8%ED%84%B4%EC%9D%98%20%EA%B2%BD%EC%9A%B0%20%EA%B7%B8%EB%A3%B9%201%EB%A7%8C%20%EC%B6%94%EC%B6%9C%20%28%EC%9D%B4%EB%A6%84%20%EB%B6%80%EB%B6%84%EB%A7%8C%29%0A%20%20%20%20%20%20%20%20%20%20const%20value%20%3D%20item.type%20%3D%3D%3D%20%27NAME%27%20%26%26%20match%5B1%5D%20%3F%20match%5B1%5D%20%3A%20match%5B0%5D%3B%0A%20%20%20%20%20%20%20%20%20%20matches.push%28%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20item.type%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20value%3A%20value%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20index%3A%20match.index%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20length%3A%20value.length%0A%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EC%A4%91%EB%B3%B5%20%EC%A0%9C%EA%B1%B0%20%28%EA%B0%99%EC%9D%80%20%EA%B0%92%EA%B3%BC%20%ED%83%80%EC%9E%85%EC%9D%B4%20%EC%97%AC%EB%9F%AC%EB%B2%88%20%EA%B0%90%EC%A7%80%EB%90%9C%20%EA%B2%BD%EC%9A%B0%29%0A%20%20%20%20%20%20const%20uniqueMatches%20%3D%20%5B%5D%3B%0A%20%20%20%20%20%20const%20seen%20%3D%20new%20Set%28%29%3B%0A%20%20%20%20%20%20for%20%28const%20match%20of%20matches%29%20%7B%0A%20%20%20%20%20%20%20%20const%20key%20%3D%20%60%24%7Bmatch.type%7D%3A%24%7Bmatch.value%7D%60%3B%0A%20%20%20%20%20%20%20%20if%20%28%21seen.has%28key%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20seen.add%28key%29%3B%0A%20%20%20%20%20%20%20%20%20%20uniqueMatches.push%28match%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20return%20uniqueMatches%3B%0A%20%20%20%20%7D%0A%20%20%20%20%2F%2F%20%ED%85%8D%EC%8A%A4%ED%8A%B8%20%EC%9D%B5%EB%AA%85%ED%99%94%20%ED%95%A8%EC%88%98%0A%20%20%20%20function%20anonymizeText%28text%2C%20type%29%20%7B%0A%20%20%20%20%20%20%20%20switch%28type%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20case%20%27PHONE%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5Cd%2Fg%2C%20%27%2A%27%29.replace%28%2F%5C%2A%7B3%2C4%7D-%5C%2A%7B3%2C4%7D-%5C%2A%7B4%7D%2F%2C%20%27%2A%2A%2A-%2A%2A%2A%2A-%2A%2A%2A%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27EMAIL%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%5Busername%2C%20domain%5D%20%3D%20text.split%28%27%40%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20username.substring%280%2C%202%29%20%2B%20%27%2A%2A%2A%2A%40%27%20%2B%20domain%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27SSN%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.substr%280%2C%208%29%20%2B%20%27%2A%2A%2A%2A%2A%2A%27%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27CREDIT_DEBIT_NUMBER%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5Cd%7B4%7D-%5Cd%7B4%7D-%5Cd%7B4%7D-%5Cd%7B4%7D%2F%2C%20%27%2A%2A%2A%2A-%2A%2A%2A%2A-%2A%2A%2A%2A-%2A%2A%2A%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27NAME%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28text.length%20%3C%3D%202%29%20return%20%27%2A%2A%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.charAt%280%29%20%2B%20%27%2A%27.repeat%28text.length%20-%201%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27ADDRESS%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20parts%20%3D%20text.split%28%27%20%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20parts.map%28%28part%2C%20index%29%20%3D%3E%20index%20%3D%3D%3D%200%20%3F%20part%20%3A%20%27%2A%2A%2A%27%29.join%28%27%20%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27PASSPORT_NUMBER%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5BA-Za-z0-9%5D%2Fg%2C%20%27%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27DRIVER_LICENSE%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5Cd%2Fg%2C%20%27%2A%27%29.replace%28%2F.%7B4%2C%7D%2F%2C%20%27%2A%2A%2A%2A-%2A%2A%2A%2A-%2A%2A%2A%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27FOREIGN_REGISTRATION%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5Cd%2Fg%2C%20%27%2A%27%29.replace%28%2F.%7B5%2C%7D%2F%2C%20%27%2A%2A%2A%2A%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20case%20%27HEALTH_INSURANCE%27%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20text.replace%28%2F%5Cd%2Fg%2C%20%27%2A%27%29.replace%28%2F.%7B10%2C%7D%2F%2C%20%27%2A%2A%2A%2A%2A%2A%2A%2A%2A%2A%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20default%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%27%2A%2A%2A%2A%2A%2A%27%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%2F%2F%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EC%B2%98%EB%A6%AC%EB%A5%BC%20%EC%9C%84%ED%95%9C%20%EC%84%B8%EB%A0%A8%EB%90%9C%20%EB%AA%A8%EB%8B%AC%20%0A%20%20%20%20function%20createSimpleModal%28matches%29%20%7B%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%EC%9D%B4%20%EC%9D%B4%EB%AF%B8%20%EC%A1%B4%EC%9E%AC%ED%95%98%EB%A9%B4%20%EC%A0%9C%EA%B1%B0%0A%20%20%20%20%20%20let%20existingModal%20%3D%20document.querySelector%28%27.pii-simple-modal%27%29%3B%0A%20%20%20%20%20%20if%20%28existingModal%29%20existingModal.remove%28%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EC%8A%A4%ED%83%80%EC%9D%BC%20%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0%0A%20%20%20%20%20%20const%20alertStyles%20%3D%20window.getComputedStyle%28%0A%20%20%20%20%20%20%20%20document.querySelector%28%27.text-base%27%29%20%7C%7C%20%0A%20%20%20%20%20%20%20%20document.querySelector%28%27.flex.items-center%27%29%20%7C%7C%20%0A%20%20%20%20%20%20%20%20document.body%0A%20%20%20%20%20%20%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EB%B0%B0%EA%B2%BD%0A%20%20%20%20%20%20const%20modalBackground%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20modalBackground.className%20%3D%20%27pii-modal-background%27%3B%0A%20%20%20%20%20%20modalBackground.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20position%3A%20fixed%3B%0A%20%20%20%20%20%20%20%20top%3A%200%3B%0A%20%20%20%20%20%20%20%20left%3A%200%3B%0A%20%20%20%20%20%20%20%20width%3A%20100%25%3B%0A%20%20%20%20%20%20%20%20height%3A%20100%25%3B%0A%20%20%20%20%20%20%20%20z-index%3A%209999%3B%0A%20%20%20%20%20%20%20%20display%3A%20flex%3B%0A%20%20%20%20%20%20%20%20justify-content%3A%20center%3B%0A%20%20%20%20%20%20%20%20align-items%3A%20flex-start%3B%0A%20%20%20%20%20%20%20%20padding-top%3A%20100px%3B%0A%20%20%20%20%20%20%20%20background-color%3A%20rgba%280%2C%200%2C%200%2C%200.0%29%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EC%83%9D%EC%84%B1%0A%20%20%20%20%20%20const%20modal%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20modal.className%20%3D%20%27pii-simple-modal%27%3B%0A%20%20%20%20%20%20modal.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20background-color%3A%20rgb%28255%2C%20255%2C%20255%29%3B%0A%20%20%20%20%20%20%20%20color%3A%20%24%7BalertStyles.color%20%7C%7C%20%27black%27%7D%3B%0A%20%20%20%20%20%20%20%20padding%3A%2024px%3B%0A%20%20%20%20%20%20%20%20border-radius%3A%2012px%3B%0A%20%20%20%20%20%20%20%20border%20%3A%202px%20solid%20%234285F4%3B%0A%20%20%20%20%20%20%20%20box-shadow%3A%200%204px%2020px%20rgba%280%2C0%2C0%2C0.15%29%3B%0A%20%20%20%20%20%20%20%20width%3A%20420px%3B%0A%20%20%20%20%20%20%20%20max-width%3A%2090%25%3B%0A%20%20%20%20%20%20%20%20font-family%3A%20%24%7BalertStyles.fontFamily%20%7C%7C%20%27Arial%2C%20sans-serif%27%7D%3B%0A%20%20%20%20%20%20%20%20animation%3A%20modal-slide-down%200.3s%20ease-out%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98%20%EC%8A%A4%ED%83%80%EC%9D%BC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20const%20styleElement%20%3D%20document.createElement%28%27style%27%29%3B%0A%20%20%20%20%20%20styleElement.textContent%20%3D%20%60%0A%20%20%20%20%20%20%20%20%40keyframes%20modal-slide-down%20%7B%0A%20%20%20%20%20%20%20%20%20%20from%20%7B%20transform%3A%20translateY%28-50px%29%3B%20opacity%3A%200%3B%20%7D%0A%20%20%20%20%20%20%20%20%20%20to%20%7B%20transform%3A%20translateY%280%29%3B%20opacity%3A%201%3B%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.pii-simple-modal%20ul%20%7B%0A%20%20%20%20%20%20%20%20%20%20max-height%3A%20200px%3B%0A%20%20%20%20%20%20%20%20%20%20overflow-y%3A%20auto%3B%0A%20%20%20%20%20%20%20%20%20%20padding-left%3A%2020px%3B%0A%20%20%20%20%20%20%20%20%20%20margin%3A%2015px%200%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.pii-simple-modal%20li%20%7B%0A%20%20%20%20%20%20%20%20%20%20margin-bottom%3A%208px%3B%0A%20%20%20%20%20%20%20%20%20%20line-height%3A%201.5%3B%0A%20%20%20%20%20%20%20%20%20%20display%3A%20flex%3B%0A%20%20%20%20%20%20%20%20%20%20justify-content%3A%20space-between%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.pii-simple-modal%20li%20span.type%20%7B%0A%20%20%20%20%20%20%20%20%20%20background-color%3A%20%23f0f0f0%3B%0A%20%20%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%0A%20%20%20%20%20%20%20%20%20%20padding%3A%202px%206px%3B%0A%20%20%20%20%20%20%20%20%20%20font-size%3A%200.85em%3B%0A%20%20%20%20%20%20%20%20%20%20margin-right%3A%208px%3B%0A%20%20%20%20%20%20%20%20%20%20color%3A%20%23666%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.pii-simple-modal%20button%3Ahover%20%7B%0A%20%20%20%20%20%20%20%20%20%20opacity%3A%200.9%3B%0A%20%20%20%20%20%20%20%20%20%20transform%3A%20translateY%28-1px%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.pii-simple-modal%20button%3Aactive%20%7B%0A%20%20%20%20%20%20%20%20%20%20transform%3A%20translateY%281px%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20document.head.appendChild%28styleElement%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%ED%97%A4%EB%8D%94%0A%20%20%20%20%20%20const%20header%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20header.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20display%3A%20flex%3B%0A%20%20%20%20%20%20%20%20align-items%3A%20center%3B%0A%20%20%20%20%20%20%20%20margin-bottom%3A%2016px%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EA%B2%BD%EA%B3%A0%20%EC%95%84%EC%9D%B4%EC%BD%98%0A%20%20%20%20%20%20const%20warningIcon%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20warningIcon.innerHTML%20%3D%20%60%0A%20%20%20%20%20%20%20%20%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M12%2022C6.477%2022%202%2017.523%202%2012C2%206.477%206.477%202%2012%202C17.523%202%2022%206.477%2022%2012C22%2017.523%2017.523%2022%2012%2022ZM12%2020C16.418%2020%2020%2016.418%2020%2012C20%207.582%2016.418%204%2012%204C7.582%204%204%207.582%204%2012C4%2016.418%207.582%2020%2012%2020ZM11%2015H13V17H11V15ZM11%207H13V13H11V7Z%22%20fill%3D%22%23FF9800%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fsvg%3E%0A%20%20%20%20%20%20%60%3B%0A%0A%20%20%20%20%20%20const%20title%20%3D%20document.createElement%28%27h3%27%29%3B%0A%20%20%20%20%20%20title.textContent%20%3D%20%27%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EA%B0%90%EC%A7%80%EB%90%A8%27%3B%0A%20%20%20%20%20%20title.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20margin%3A%200%200%200%2010px%3B%0A%20%20%20%20%20%20%20%20font-size%3A%2018px%3B%0A%20%20%20%20%20%20%20%20font-weight%3A%20600%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20header.appendChild%28warningIcon%29%3B%0A%20%20%20%20%20%20header.appendChild%28title%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EC%84%A4%EB%AA%85%20%ED%85%8D%EC%8A%A4%ED%8A%B8%0A%20%20%20%20%20%20const%20description%20%3D%20document.createElement%28%27p%27%29%3B%0A%20%20%20%20%20%20description.textContent%20%3D%20%27%EB%8B%A4%EC%9D%8C%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%EA%B0%80%20%EC%9E%85%EB%A0%A5%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4.%20%EC%9D%B5%EB%AA%85%ED%99%94%ED%95%98%EC%8B%9C%EA%B2%A0%EC%8A%B5%EB%8B%88%EA%B9%8C%3F%27%3B%0A%20%20%20%20%20%20description.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20margin%3A%200%200%2015px%200%3B%0A%20%20%20%20%20%20%20%20font-size%3A%2014px%3B%0A%20%20%20%20%20%20%20%20color%3A%20%24%7BalertStyles.color%20%7C%7C%20%27%23666%27%7D%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EA%B0%90%EC%A7%80%EB%90%9C%20%ED%95%AD%EB%AA%A9%20%EB%A6%AC%EC%8A%A4%ED%8A%B8%0A%20%20%20%20%20%20const%20list%20%3D%20document.createElement%28%27ul%27%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20matches.forEach%28%28match%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20item%20%3D%20document.createElement%28%27li%27%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%ED%83%80%EC%9E%85%20%ED%91%9C%EC%8B%9C%0A%20%20%20%20%20%20%20%20const%20typeSpan%20%3D%20document.createElement%28%27span%27%29%3B%0A%20%20%20%20%20%20%20%20typeSpan.className%20%3D%20%27type%27%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20let%20typeText%20%3D%20%27%27%3B%0A%20%20%20%20%20%20%20%20let%20sensitivityLevel%20%3D%20%27%EB%82%AE%EC%9D%8C%27%3B%20%2F%2F%20%EA%B8%B0%EB%B3%B8%EA%B0%92%20%EC%84%A4%EC%A0%95%0A%0A%20%20%20%20%20%20%20%20switch%28match.type%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27PHONE%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27EMAIL%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%9D%B4%EB%A9%94%EC%9D%BC%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27SSN%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%A3%BC%EB%AF%BC%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EB%86%92%EC%9D%8C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27CREDIT_DEBIT_NUMBER%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%B9%B4%EB%93%9C%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EB%86%92%EC%9D%8C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27NAME%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%9D%B4%EB%A6%84%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EB%82%AE%EC%9D%8C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27ADDRESS%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%A3%BC%EC%86%8C%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27PASSPORT_NUMBER%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%97%AC%EA%B6%8C%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EB%86%92%EC%9D%8C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27DRIVER_LICENSE%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%9A%B4%EC%A0%84%EB%A9%B4%ED%97%88%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27FOREIGN_REGISTRATION%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EC%99%B8%EA%B5%AD%EC%9D%B8%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20%27HEALTH_INSURANCE%27%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EA%B1%B4%EA%B0%95%EB%B3%B4%ED%97%98%EB%B2%88%ED%98%B8%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EC%A4%91%EA%B0%84%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20default%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20typeText%20%3D%20%22%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%22%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sensitivityLevel%20%3D%20%22%EB%82%AE%EC%9D%8C%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%A4%80%EB%B9%84%0A%20%20%20%20%20%20%20%20let%20logData%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20email%3A%20email%2C%20%20%2F%2F%20%EC%9D%B4%EB%A9%94%EC%9D%BC%20%EA%B0%92%EC%9D%80%20%EB%AF%B8%EB%A6%AC%20%EC%9E%85%EB%A0%A5%EB%B0%9B%EC%95%98%EB%8B%A4%EA%B3%A0%20%EA%B0%80%EC%A0%95%0A%20%20%20%20%20%20%20%20%20%20%20%20content_type%3A%20typeText%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sensitivity_level%3A%20sensitivityLevel%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20input_date%3A%20new%20Date%28%29.toISOString%28%29.split%28%27T%27%29%5B0%5D%20%20%2F%2F%20%EC%98%A4%EB%8A%98%20%EB%82%A0%EC%A7%9C%20%28YYYY-MM-DD%29%0A%20%20%20%20%20%20%20%20%7D%3B%0A%0A%20%20%20%20%2F%2F%20%EC%B5%9C%EC%A2%85%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%B6%9C%EB%A0%A5%20%28%EC%84%9C%EB%B2%84%EB%A1%9C%20%EB%B3%B4%EB%82%B4%EA%B8%B0%20%EC%A0%84%EC%97%90%20%ED%99%95%EC%9D%B8%EC%9A%A9%29%0A%20%20%20%20%20%20%20%20console.log%28logData%29%3B%0A%0A%20%20%20%20%20%20%20%20typeSpan.textContent%20%3D%20typeText%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EA%B0%92%20%ED%91%9C%EC%8B%9C%0A%20%20%20%20%20%20%20%20const%20valueSpan%20%3D%20document.createElement%28%27span%27%29%3B%0A%20%20%20%20%20%20%20%20valueSpan.className%20%3D%20%27value%27%3B%0A%20%20%20%20%20%20%20%20valueSpan.textContent%20%3D%20match.value%3B%0A%20%20%20%20%20%20%20%20valueSpan.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20flex-grow%3A%201%3B%0A%20%20%20%20%20%20%20%20text-overflow%3A%20ellipsis%3B%0A%20%20%20%20%20%20%20%20overflow%3A%20hidden%3B%0A%20%20%20%20%20%20%20%20white-space%3A%20nowrap%3B%0A%20%20%20%20%20%20%20%20margin-left%3A%208px%3B%0A%20%20%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20item.appendChild%28typeSpan%29%3B%0A%20%20%20%20%20%20%20%20item.appendChild%28valueSpan%29%3B%0A%20%20%20%20%20%20%20%20list.appendChild%28item%29%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2Furl%EB%A1%9C%20%EC%A0%95%EB%B3%B4%20%EB%B3%B4%EB%82%B4%EA%B8%B0%0A%0A%20%20%20%20%20%20%20%20logData%20%3D%20sendDataToService%28logData%29%3B%0A%20%20%20%20%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20%20%20%20%20function%20sendDataToService%28logData%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20params%20%3D%20new%20URLSearchParams%28logData%29.toString%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20console.log%28params%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%84%9C%EB%B9%84%EC%8A%A4%20URL%20%28%EC%84%9C%EB%B2%84%20URL%EC%97%90%20%EB%A7%9E%EA%B2%8C%20%EC%88%98%EC%A0%95%29%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20serviceUrl%20%3D%20%27http%3A%2F%2Flocalhost%3A5000%2Fapi%2Fdashboard%2Fgetdata%3F%27%20%2B%20params%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20console.log%28%22%F0%9F%94%97%20%EC%9A%94%EC%B2%AD%20URL%3A%22%2C%20serviceUrl%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%83%88%20%EC%B0%BD%EC%97%90%EC%84%9C%20%EC%84%9C%EB%B9%84%EC%8A%A4%20%ED%8E%98%EC%9D%B4%EC%A7%80%20%EC%97%B4%EA%B8%B0%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20window.open%28serviceUrl%2C%20%27_blank%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20console.log%28%27%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%A0%84%EC%86%A1%20%EC%99%84%EB%A3%8C%21%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%5B%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%EC%9D%BC%EC%A0%95%20%EA%B0%84%EA%B2%A9%EC%9C%BC%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC%20%EC%88%98%EC%A7%91%ED%95%98%EA%B3%A0%20%EC%A0%84%EC%86%A1%ED%95%98%EB%8A%94%20%EA%B8%B0%EB%8A%A5%0A%20%20%20%20%20%20%20%20function%20startDataCollection%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20intervalMinutes%20%3D%205%3B%20%20%2F%2F%205%EB%B6%84%20%EA%B0%84%EA%B2%A9%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20maxRepetitions%20%3D%2012%3B%20%20%2F%2F%20%EC%B5%9C%EB%8C%80%2012%ED%9A%8C%20%281%EC%8B%9C%EA%B0%84%20%EB%8F%99%EC%95%88%20%EB%B0%98%EB%B3%B5%29%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20currentRepetition%20%3D%201%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%9E%90%EB%8F%99%20%EC%88%98%EC%A7%91%20%EC%83%81%ED%83%9C%20%ED%91%9C%EC%8B%9C%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20statusDiv%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.id%20%3D%20%27data-collection-status%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.style%20%3D%20%27position%3Afixed%3Btop%3A10px%3Bright%3A10px%3Bbackground%3Argba%280%2C0%2C0%2C0.7%29%3Bcolor%3Awhite%3Bpadding%3A10px%3Bz-index%3A9999%3Bborder-radius%3A5px%3Bfont-family%3AArial%3B%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.innerHTML%20%3D%20%60%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%ED%99%9C%EC%84%B1%ED%99%94%20%28%24%7BintervalMinutes%7D%EB%B6%84%20%EA%B0%84%EA%B2%A9%29%3Cbr%3E%EC%A7%84%ED%96%89%3A%201%2F%24%7BmaxRepetitions%7D%60%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20document.body.appendChild%28statusDiv%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A3%BC%EA%B8%B0%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%88%98%EC%A7%91%20%EB%B0%8F%20%EC%A0%84%EC%86%A1%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20intervalId%20%3D%20setInterval%28%28%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentRepetition%2B%2B%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28currentRepetition%20%3C%3D%20maxRepetitions%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createSimpleModal%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.innerHTML%20%3D%20%60%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%9E%90%EB%8F%99%20%EC%88%98%EC%A7%91%20%ED%99%9C%EC%84%B1%ED%99%94%20%28%24%7BintervalMinutes%7D%EB%B6%84%20%EA%B0%84%EA%B2%A9%29%3Cbr%3E%EC%A7%84%ED%96%89%3A%20%24%7BcurrentRepetition%7D%2F%24%7BmaxRepetitions%7D%60%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A7%80%EC%A0%95%EB%90%9C%20%EB%B0%98%EB%B3%B5%20%ED%9A%9F%EC%88%98%20%EC%99%84%EB%A3%8C%20%ED%9B%84%20%EC%A4%91%EC%A7%80%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearInterval%28intervalId%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.innerHTML%20%3D%20%27%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%88%98%EC%A7%91%20%EC%99%84%EB%A3%8C%21%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setTimeout%28%28%29%20%3D%3E%20statusDiv.remove%28%29%2C%203000%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%20intervalMinutes%20%2A%2060%20%2A%201000%29%3B%20%20%2F%2F%205%EB%B6%84%20%EA%B0%84%EA%B2%A9%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A4%91%EC%A7%80%20%EB%B2%84%ED%8A%BC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20stopButton%20%3D%20document.createElement%28%27button%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20stopButton.textContent%20%3D%20%27%EC%A4%91%EC%A7%80%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20stopButton.style%20%3D%20%27margin-top%3A5px%3Bpadding%3A3px%208px%3B%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20stopButton.onclick%20%3D%20function%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearInterval%28intervalId%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.innerHTML%20%3D%20%27%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%88%98%EC%A7%91%EC%9D%B4%20%EC%A4%91%EC%A7%80%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4.%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setTimeout%28%28%29%20%3D%3E%20statusDiv.remove%28%29%2C%203000%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.appendChild%28document.createElement%28%27br%27%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20statusDiv.appendChild%28stopButton%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20startDataCollection%28%29%3B%0A%20%20%20%20%20%20%2F%2F%20%EB%B2%84%ED%8A%BC%20%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%0A%20%20%20%20%20%20const%20buttonContainer%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20buttonContainer.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20display%3A%20flex%3B%0A%20%20%20%20%20%20%20%20justify-content%3A%20space-between%3B%0A%20%20%20%20%20%20%20%20margin-top%3A%2020px%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EC%9D%B5%EB%AA%85%ED%99%94%20%EB%B2%84%ED%8A%BC%0A%20%20%20%20%20%20const%20anonymizeAllBtn%20%3D%20document.createElement%28%27button%27%29%3B%0A%20%20%20%20%20%20anonymizeAllBtn.textContent%20%3D%20%27%EB%AA%A8%EB%91%90%20%EC%9D%B5%EB%AA%85%ED%99%94%27%3B%0A%20%20%20%20%20%20anonymizeAllBtn.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20padding%3A%2010px%2016px%3B%0A%20%20%20%20%20%20%20%20background-color%3A%20%234285F4%3B%0A%20%20%20%20%20%20%20%20color%3A%20white%3B%0A%20%20%20%20%20%20%20%20border%3A%20none%3B%0A%20%20%20%20%20%20%20%20border-radius%3A%206px%3B%0A%20%20%20%20%20%20%20%20cursor%3A%20pointer%3B%0A%20%20%20%20%20%20%20%20font-weight%3A%20500%3B%0A%20%20%20%20%20%20%20%20font-size%3A%2014px%3B%0A%20%20%20%20%20%20%20%20transition%3A%20all%200.2s%3B%0A%20%20%20%20%20%20%20%20flex-grow%3A%201%3B%0A%20%20%20%20%20%20%20%20margin-right%3A%2010px%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20anonymizeAllBtn.onclick%20%3D%20%28%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20let%20text%20%3D%20inputBox.innerText%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%93%A0%20%EB%A7%A4%EC%B9%98%20%ED%95%AD%EB%AA%A9%20%EC%9D%B5%EB%AA%85%ED%99%94%0A%20%20%20%20%20%20%20%20matches.forEach%28match%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20const%20anonymized%20%3D%20anonymizeText%28match.value%2C%20match.type%29%3B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20%EC%A0%95%ED%99%95%ED%95%9C%20%EB%8C%80%EC%B2%B4%EB%A5%BC%20%EC%9C%84%ED%95%B4%20%EC%A0%95%EA%B7%9C%EC%8B%9D%20%EC%82%AC%EC%9A%A9%0A%20%20%20%20%20%20%20%20%20%20const%20regex%20%3D%20new%20RegExp%28escapeRegExp%28match.value%29%2C%20%27g%27%29%3B%0A%20%20%20%20%20%20%20%20%20%20text%20%3D%20text.replace%28regex%2C%20anonymized%29%3B%0A%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%EB%B3%80%EA%B2%BD%EB%90%9C%20%ED%85%8D%EC%8A%A4%ED%8A%B8%20%EC%A0%81%EC%9A%A9%0A%20%20%20%20%20%20%20%20inputBox.innerText%20%3D%20text%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20modalBackground.remove%28%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20%ED%86%A0%EC%8A%A4%ED%8A%B8%20%EB%A9%94%EC%8B%9C%EC%A7%80%20%ED%91%9C%EC%8B%9C%0A%20%20%20%20%20%20%20%20showToast%28%27%E2%9C%85%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%EA%B0%80%20%EC%9D%B5%EB%AA%85%ED%99%94%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4%27%29%3B%0A%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AC%B4%EC%8B%9C%20%EB%B2%84%ED%8A%BC%0A%20%20%20%20%20%20const%20ignoreBtn%20%3D%20document.createElement%28%27button%27%29%3B%0A%20%20%20%20%20%20ignoreBtn.textContent%20%3D%20%27%EB%AC%B4%EC%8B%9C%ED%95%98%EA%B8%B0%27%3B%0A%20%20%20%20%20%20ignoreBtn.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20padding%3A%2010px%2016px%3B%0A%20%20%20%20%20%20%20%20background-color%3A%20transparent%3B%0A%20%20%20%20%20%20%20%20color%3A%20%23666%3B%0A%20%20%20%20%20%20%20%20border%3A%201px%20solid%20%23ddd%3B%0A%20%20%20%20%20%20%20%20border-radius%3A%206px%3B%0A%20%20%20%20%20%20%20%20cursor%3A%20pointer%3B%0A%20%20%20%20%20%20%20%20font-weight%3A%20500%3B%0A%20%20%20%20%20%20%20%20font-size%3A%2014px%3B%0A%20%20%20%20%20%20%20%20transition%3A%20all%200.2s%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20ignoreBtn.onclick%20%3D%20%28%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20modalBackground.remove%28%29%3B%0A%20%20%20%20%20%20%20%20showToast%28%27%E2%9A%A0%EF%B8%8F%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EC%B2%98%EB%A6%AC%EB%A5%BC%20%EB%AC%B4%EC%8B%9C%ED%96%88%EC%8A%B5%EB%8B%88%EB%8B%A4%27%29%3B%0A%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%B2%84%ED%8A%BC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20buttonContainer.appendChild%28anonymizeAllBtn%29%3B%0A%20%20%20%20%20%20buttonContainer.appendChild%28ignoreBtn%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EC%A1%B0%EB%A6%BD%0A%20%20%20%20%20%20modal.appendChild%28header%29%3B%0A%20%20%20%20%20%20modal.appendChild%28description%29%3B%0A%20%20%20%20%20%20modal.appendChild%28list%29%3B%0A%20%20%20%20%20%20modal.appendChild%28buttonContainer%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EB%B0%B0%EA%B2%BD%EC%97%90%20%EB%AA%A8%EB%8B%AC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20modalBackground.appendChild%28modal%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%20%EB%B0%B0%EA%B2%BD%20%ED%81%B4%EB%A6%AD%20%EC%8B%9C%20%EB%8B%AB%EA%B8%B0%20%28%EB%AA%A8%EB%8B%AC%20%EC%9E%90%EC%B2%B4%EB%8A%94%20%ED%81%B4%EB%A6%AD%20%EC%9D%B4%EB%B2%A4%ED%8A%B8%20%EC%A0%84%ED%8C%8C%20%EC%A4%91%EC%A7%80%29%0A%20%20%20%20%20%20modalBackground.addEventListener%28%27click%27%2C%20%28e%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20if%20%28e.target%20%3D%3D%3D%20modalBackground%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20modalBackground.remove%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20modal.addEventListener%28%27click%27%2C%20%28e%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20e.stopPropagation%28%29%3B%0A%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EB%AC%B8%EC%84%9C%EC%97%90%20%EB%AA%A8%EB%8B%AC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20document.body.appendChild%28modalBackground%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20ESC%20%ED%82%A4%EB%A1%9C%20%EB%AA%A8%EB%8B%AC%20%EB%8B%AB%EA%B8%B0%0A%20%20%20%20%20%20function%20handleKeyDown%28e%29%20%7B%0A%20%20%20%20%20%20%20%20if%20%28e.key%20%3D%3D%3D%20%27Escape%27%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20modalBackground.remove%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20document.removeEventListener%28%27keydown%27%2C%20handleKeyDown%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20document.addEventListener%28%27keydown%27%2C%20handleKeyDown%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%2F%2F%20%EC%A0%95%EA%B7%9C%EC%8B%9D%20%ED%8A%B9%EC%88%98%EB%AC%B8%EC%9E%90%20%EC%9D%B4%EC%8A%A4%EC%BC%80%EC%9D%B4%ED%94%84%20%ED%95%A8%EC%88%98%0A%20%20%20%20function%20escapeRegExp%28string%29%20%7B%0A%20%20%20%20%20%20return%20string.replace%28%2F%5B.%2A%2B%3F%5E%24%7B%7D%28%29%7C%5B%5C%5D%5C%5C%5D%2Fg%2C%20%27%5C%5C%24%26%27%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%2F%2F%20%ED%86%A0%EC%8A%A4%ED%8A%B8%20%EB%A9%94%EC%8B%9C%EC%A7%80%20%ED%91%9C%EC%8B%9C%20%ED%95%A8%EC%88%98%0A%20%20%20%20function%20showToast%28message%29%20%7B%0A%20%20%20%20%20%20%2F%2F%20%EA%B8%B0%EC%A1%B4%20%ED%86%A0%EC%8A%A4%ED%8A%B8%20%EC%A0%9C%EA%B1%B0%0A%20%20%20%20%20%20const%20existingToast%20%3D%20document.querySelector%28%27.pii-toast%27%29%3B%0A%20%20%20%20%20%20if%20%28existingToast%29%20existingToast.remove%28%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%ED%86%A0%EC%8A%A4%ED%8A%B8%20%EC%83%9D%EC%84%B1%0A%20%20%20%20%20%20const%20toast%20%3D%20document.createElement%28%27div%27%29%3B%0A%20%20%20%20%20%20toast.className%20%3D%20%27pii-toast%27%3B%0A%20%20%20%20%20%20toast.textContent%20%3D%20message%3B%0A%20%20%20%20%20%20toast.style.cssText%20%3D%20%60%0A%20%20%20%20%20%20%20%20position%3A%20fixed%3B%0A%20%20%20%20%20%20%20%20bottom%3A%2030px%3B%0A%20%20%20%20%20%20%20%20left%3A%2050%25%3B%0A%20%20%20%20%20%20%20%20transform%3A%20translateX%28-50%25%29%3B%0A%20%20%20%20%20%20%20%20background-color%3A%20rgba%280%2C0%2C0%2C0.8%29%3B%0A%20%20%20%20%20%20%20%20color%3A%20white%3B%0A%20%20%20%20%20%20%20%20padding%3A%2012px%2020px%3B%0A%20%20%20%20%20%20%20%20border-radius%3A%208px%3B%0A%20%20%20%20%20%20%20%20font-size%3A%2014px%3B%0A%20%20%20%20%20%20%20%20font-weight%3A%20500%3B%0A%20%20%20%20%20%20%20%20z-index%3A%2010000%3B%0A%20%20%20%20%20%20%20%20animation%3A%20toast-fade-in%200.3s%2C%20toast-fade-out%200.3s%202.5s%3B%0A%20%20%20%20%20%20%20%20animation-fill-mode%3A%20forwards%3B%0A%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%20%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98%20%EC%8A%A4%ED%83%80%EC%9D%BC%20%EC%B6%94%EA%B0%80%0A%20%20%20%20%20%20if%20%28%21document.querySelector%28%27style.toast-style%27%29%29%20%7B%0A%20%20%20%20%20%20%20%20const%20style%20%3D%20document.createElement%28%27style%27%29%3B%0A%20%20%20%20%20%20%20%20style.className%20%3D%20%27toast-style%27%3B%0A%20%20%20%20%20%20%20%20style.textContent%20%3D%20%60%0A%20%20%20%20%20%20%20%20%20%20%40keyframes%20toast-fade-in%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%20opacity%3A%200%3B%20transform%3A%20translate%28-50%25%2C%2020px%29%3B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%20opacity%3A%201%3B%20transform%3A%20translate%28-50%25%2C%200%29%3B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%40keyframes%20toast-fade-out%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%20opacity%3A%201%3B%20transform%3A%20translate%28-50%25%2C%200%29%3B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%20opacity%3A%200%3B%20transform%3A%20translate%28-50%25%2C%2020px%29%3B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%60%3B%0A%20%20%20%20%20%20%20%20document.head.appendChild%28style%29%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20document.body.appendChild%28toast%29%3B%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%2F%2F%203%EC%B4%88%20%ED%9B%84%20%ED%86%A0%EC%8A%A4%ED%8A%B8%20%EC%A0%9C%EA%B1%B0%0A%20%20%20%20%20%20setTimeout%28%28%29%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20toast.remove%28%29%3B%0A%20%20%20%20%20%20%7D%2C%203000%29%3B%0A%20%20%20%20%7D%0A%0A%2F%2F%20%EC%9E%85%EB%A0%A5%EC%B0%BD%EC%9D%98%20%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%A5%BC%20%EC%B2%98%EB%A6%AC%0Aasync%20function%20processText%28%29%20%7B%0A%20%20%20%20const%20text%20%3D%20inputBox.innerText%3B%0A%0A%20%20%20%20%2F%2F%20%ED%85%8D%EC%8A%A4%ED%8A%B8%EA%B0%80%20%EB%B9%84%EC%96%B4%EC%9E%88%EC%9C%BC%EB%A9%B4%20%EC%B2%98%EB%A6%AC%ED%95%98%EC%A7%80%20%EC%95%8A%EC%9D%8C%0A%20%20%20%20if%20%28%21text.trim%28%29%29%20return%3B%0A%0A%20%20%20%20%2F%2F%20%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C%201%EC%B0%A8%20%EA%B2%80%EC%82%AC%0A%20%20%20%20const%20localMatches%20%3D%20localCheckSensitiveInfo%28text%29%3B%0A%0A%20%20%20%20if%20%28localMatches.length%20%3E%200%29%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20%EB%AA%A8%EB%8B%AC%EB%A1%9C%20%EC%95%8C%EB%A6%BC%0A%20%20%20%20%20%20%20%20createSimpleModal%28localMatches%29%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%20%20%20%20%2F%2F%20%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%20%ED%95%A8%EC%88%98%0A%20%20%20%20function%20debounce%28func%2C%20wait%29%20%7B%0A%20%20%20%20%20%20%20%20let%20timeout%3B%0A%20%20%20%20%20%20%20%20return%20function%28...args%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20clearTimeout%28timeout%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20timeout%20%3D%20setTimeout%28%28%29%20%3D%3E%20func.apply%28this%2C%20args%29%2C%20wait%29%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%20%EC%9D%B4%EB%B2%A4%ED%8A%B8%20%EB%A6%AC%EC%8A%A4%EB%84%88%20%EC%84%A4%EC%A0%95%0A%20%20%20%20const%20debouncedProcess%20%3D%20debounce%28processText%2C%20500%29%3B%0A%20%20%20%20inputBox.addEventListener%28%22input%22%2C%20debouncedProcess%29%3B%0A%0A%20%20%20%20%2F%2F%20%EC%B4%88%EA%B8%B0%ED%99%94%20%EC%99%84%EB%A3%8C%20%EB%A9%94%EC%8B%9C%EC%A7%80%0A%20%20%20%20alert%28%22%E2%9C%85%20%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%20%EA%B0%90%EC%A7%80%20%EB%B0%8F%20%EC%9D%B5%EB%AA%85%ED%99%94%20%EA%B8%B0%EB%8A%A5%EC%9D%B4%20%ED%99%9C%EC%84%B1%ED%99%94%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4%21%22%29%3B%0A%0A%20%20%20%20%2F%2F%20%EC%9D%B4%EB%A9%94%EC%9D%BC%20%EC%9E%85%EB%A0%A5%EC%9D%84%20%EB%B0%9B%EB%8A%94%20%EC%B0%BD%20%EB%9D%84%EC%9A%B0%EA%B8%B0%0A%20%20%20%20var%20email%20%3D%20prompt%28%22privaShield%EC%97%90%20%EA%B0%80%EC%9E%85%ED%95%9C%20%EC%9D%B4%EB%A9%94%EC%9D%BC%EC%9D%84%20%EC%9E%85%EB%A0%A5%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94%3A%22%29%3B%0A%0A%20%20%20%20%2F%2F%20%EC%9D%B4%EB%A9%94%EC%9D%BC%EC%9D%B4%20%EC%9E%85%EB%A0%A5%EB%90%98%EC%97%88%EB%8A%94%EC%A7%80%20%ED%99%95%EC%9D%B8%0A%20%20%20%20if%20%28email%29%20%7B%0A%20%20%20%20%20%20%20%20console.log%28%22%EC%9E%85%EB%A0%A5%EB%90%9C%20%EC%9D%B4%EB%A9%94%EC%9D%BC%3A%20%22%20%2B%20email%29%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20%EC%97%AC%EA%B8%B0%EC%97%90%20%EC%9D%B4%EB%A9%94%EC%9D%BC%EC%9D%84%20%EC%B2%98%EB%A6%AC%ED%95%98%EB%8A%94%20%EB%A1%9C%EC%A7%81%EC%9D%84%20%EC%B6%94%EA%B0%80%ED%95%A0%20%EC%88%98%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4.%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20console.log%28%22%EC%9D%B4%EB%A9%94%EC%9D%BC%EC%9D%B4%20%EC%9E%85%EB%A0%A5%EB%90%98%EC%A7%80%20%EC%95%8A%EC%95%98%EC%8A%B5%EB%8B%88%EB%8B%A4.%22%29%3B%0A%20%20%20%20%7D%0A%7D%29%28%29%3B
+ `;
return (
<>
@@ -135,15 +136,15 @@ const HeroPage = () => {
개인정보 보호
- AI 기반
+ 패턴분석 기반
실시간 감지
- AI 기반 민감정보 보호
+ 패턴분석 기반 민감정보 보호
더 안전한 데이터 관리
- PrivaShield의 강력한 AI 엔진으로 중요한 데이터를 안전하게
+ PrivaShield의 강력한 패턴분석으로 중요한 데이터를 안전하게
보호하세요. 실시간 모니터링과 자동화된 보안 시스템으로 당신의
정보를 지켜드립니다.
@@ -154,7 +155,7 @@ const HeroPage = () => {
- 100% 안심 : PrivaShield는 분석한 개인 민감 정보를 절대 저장하지 않습니다.
+ 100% 안심 : PrivaShield는 분석한 개인 민감 정보를 절대 저장하지 않습니다. 대시보드 통계를 위한 카테고리 정보만을 수집합니다.