🔒 보안

PIMS

Personal Information Management System

개인정보보호 관리체계 인증제도. 조직이 개인정보를 체계적으로 보호하고 관리하는지 검증하는 국내 인증으로, 현재 ISMS와 통합된 ISMS-P로 운영됩니다.

📖 상세 설명

PIMS(Personal Information Management System)는 한국인터넷진흥원(KISA)이 운영하던 개인정보보호 관리체계 인증제도입니다. 2018년 11월부터 정보보호 관리체계(ISMS)와 통합되어 ISMS-P(정보보호 및 개인정보보호 관리체계)로 운영됩니다. PIMS의 핵심 요소들은 ISMS-P의 개인정보 처리 단계별 요구사항으로 계승되었습니다. 개인정보보호법과 정보통신망법의 의무사항을 체계적으로 이행하기 위한 프레임워크입니다.

PIMS/ISMS-P의 개인정보보호 영역은 개인정보 생명주기 전체를 다룹니다. 수집 단계에서는 적법한 동의 획득, 최소 수집 원칙을 검증합니다. 이용/제공 단계에서는 목적 범위 내 처리, 제3자 제공 절차를 확인합니다. 보관/파기 단계에서는 보유기간 관리, 안전한 파기 절차를 평가합니다. 이러한 체계적 관리를 통해 개인정보 침해 사고를 예방합니다.

인증 획득 과정은 서류 심사와 현장 심사로 구성됩니다. 조직은 개인정보보호 정책, 처리 절차, 기술적/물리적 보호조치를 문서화해야 합니다. 심사원이 실제 운영 상태를 현장에서 확인하며, 결함이 발견되면 보완 후 재심사를 받습니다. 인증 유효기간은 3년이며, 매년 사후관리 심사를 통해 지속적인 이행 여부를 검증합니다.

AI 시스템에서 PIMS/ISMS-P는 더욱 중요합니다. ML 모델 학습에 개인정보가 사용되면 수집 동의, 목적 제한, 안전한 처리가 필수입니다. AI 기반 개인화 서비스는 프로파일링 동의와 자동화된 의사결정 고지 의무가 있습니다. EU의 GDPR과 달리 국내법 중심이지만, 해외 진출 시 GDPR, CCPA와의 정합성도 고려해야 합니다.

💻 코드 예제

# PIMS/ISMS-P 준수 개인정보 처리 클래스
import hashlib
import logging
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from enum import Enum

class ConsentType(Enum):
    REQUIRED = "required"      # 필수 동의
    OPTIONAL = "optional"      # 선택 동의
    MARKETING = "marketing"    # 마케팅 동의
    THIRD_PARTY = "third_party"  # 제3자 제공 동의

class PIIMSCompliantProcessor:
    """PIMS/ISMS-P 준수 개인정보 처리기"""

    def __init__(self, retention_days: int = 365):
        self.retention_days = retention_days
        self.logger = logging.getLogger("pims_audit")

    def collect_personal_info(
        self,
        data: Dict[str, Any],
        consents: Dict[ConsentType, bool],
        collection_purpose: str
    ) -> Optional[Dict[str, Any]]:
        """개인정보 수집 (최소 수집 원칙 적용)"""

        # 필수 동의 확인
        if not consents.get(ConsentType.REQUIRED, False):
            self.logger.warning("필수 동의 없이 수집 시도")
            raise ValueError("필수 동의가 필요합니다")

        # 최소 수집 원칙 - 목적에 필요한 항목만 수집
        required_fields = self._get_required_fields(collection_purpose)
        collected_data = {
            k: v for k, v in data.items()
            if k in required_fields
        }

        # 수집 이력 로깅 (감사 추적)
        self.logger.info(
            f"개인정보 수집 | 목적: {collection_purpose} | "
            f"항목: {list(collected_data.keys())} | "
            f"동의: {[c.value for c, v in consents.items() if v]}"
        )

        # 보유기간 설정
        collected_data["_retention_until"] = (
            datetime.now() + timedelta(days=self.retention_days)
        ).isoformat()
        collected_data["_collection_purpose"] = collection_purpose
        collected_data["_consents"] = {c.value: v for c, v in consents.items()}

        return collected_data

    def pseudonymize(self, data: Dict[str, Any], fields: list) -> Dict[str, Any]:
        """가명처리 (식별자 해시화)"""
        result = data.copy()
        for field in fields:
            if field in result:
                # SHA-256 + Salt로 가명처리
                salt = "pims_salt_2024"  # 실제로는 안전하게 관리
                original = str(result[field])
                result[field] = hashlib.sha256(
                    (original + salt).encode()
                ).hexdigest()[:16]

        self.logger.info(f"가명처리 완료 | 대상 필드: {fields}")
        return result

    def check_retention_and_destroy(self, records: list) -> int:
        """보유기간 만료 데이터 파기"""
        destroyed_count = 0
        now = datetime.now()

        for record in records:
            retention_until = datetime.fromisoformat(
                record.get("_retention_until", "2099-12-31")
            )
            if now > retention_until:
                self._secure_destroy(record)
                destroyed_count += 1

        self.logger.info(f"개인정보 파기 완료 | 파기 건수: {destroyed_count}")
        return destroyed_count

    def _secure_destroy(self, record: Dict[str, Any]):
        """안전한 파기 (복구 불가능하게)"""
        # 실제 구현에서는 DB에서 삭제 + 백업에서도 삭제
        pass

    def _get_required_fields(self, purpose: str) -> set:
        """목적별 필요 수집 항목 정의"""
        purpose_fields = {
            "회원가입": {"email", "password", "name"},
            "본인인증": {"name", "phone", "birth_date"},
            "배송": {"name", "address", "phone"},
            "마케팅": {"email"},  # 최소한만
        }
        return purpose_fields.get(purpose, set())


# 사용 예시
processor = PIIMSCompliantProcessor(retention_days=365)

user_data = {
    "email": "user@example.com",
    "name": "홍길동",
    "phone": "010-1234-5678",
    "address": "서울시 강남구",
    "hobby": "독서"  # 불필요한 항목
}

consents = {
    ConsentType.REQUIRED: True,
    ConsentType.MARKETING: False
}

# 회원가입 목적으로 수집 (최소 항목만)
collected = processor.collect_personal_info(
    user_data, consents, "회원가입"
)
print(f"수집된 항목: {[k for k in collected if not k.startswith('_')]}")
# 출력: ['email', 'name'] - hobby, address는 목적에 불필요하므로 제외
# ISMS-P 개인정보보호 인증 체크리스트 (자동화 점검용)
# 참고: KISA ISMS-P 인증기준 개인정보 처리 단계별 요구사항

isms_p_checklist:
  version: "2024.1"
  organization: "Example Corp"
  audit_date: "2026-01-26"

  # 1. 개인정보 수집 시 보호조치
  collection:
    items:
      - id: "PI-001"
        requirement: "개인정보 수집 시 동의 획득"
        controls:
          - "수집 목적 명시"
          - "수집 항목 명시"
          - "보유 기간 명시"
          - "동의 거부권 안내"
        evidence:
          - "개인정보 수집 동의서"
          - "회원가입 화면 캡처"
        status: "compliant"  # compliant / non_compliant / partial

      - id: "PI-002"
        requirement: "최소 수집 원칙"
        controls:
          - "목적에 필요한 항목만 수집"
          - "민감정보 수집 시 별도 동의"
        evidence:
          - "개인정보 처리방침"
          - "수집항목 검토 보고서"
        status: "compliant"

  # 2. 개인정보 이용 및 제공
  usage_and_provision:
    items:
      - id: "PI-003"
        requirement: "목적 범위 내 이용"
        controls:
          - "수집 목적과 이용 목적 일치 확인"
          - "목적 외 이용 시 별도 동의"
        evidence:
          - "개인정보 이용 현황"
          - "접근 로그"
        status: "compliant"

      - id: "PI-004"
        requirement: "제3자 제공 절차"
        controls:
          - "제공받는 자 명시"
          - "제공 목적 명시"
          - "제공 항목 명시"
          - "제공받는 자의 보유기간"
        evidence:
          - "제3자 제공 동의서"
          - "위탁계약서"
        status: "partial"
        remediation: "위탁계약서 갱신 필요 (2026-03-01까지)"

  # 3. 개인정보 보관 및 파기
  retention_and_destruction:
    items:
      - id: "PI-005"
        requirement: "보유기간 관리"
        controls:
          - "법정 보유기간 준수"
          - "보유기간 경과 시 지체없이 파기"
        evidence:
          - "개인정보 파기 이력"
          - "보유기간 관리 대장"
        status: "compliant"

      - id: "PI-006"
        requirement: "안전한 파기"
        controls:
          - "복구 불가능한 방법으로 파기"
          - "파기 확인 및 기록"
        evidence:
          - "파기 증명서"
          - "디스크 완전삭제 확인서"
        status: "compliant"

  # 4. 기술적 보호조치
  technical_measures:
    items:
      - id: "PI-007"
        requirement: "접근 권한 관리"
        controls:
          - "개인정보 처리자 지정"
          - "최소 권한 부여"
          - "접근 권한 변경 이력 관리"
        evidence:
          - "접근 권한 관리 대장"
          - "계정 생성/변경 로그"
        status: "compliant"

      - id: "PI-008"
        requirement: "암호화"
        controls:
          - "비밀번호 일방향 암호화"
          - "주민번호 등 고유식별정보 암호화"
          - "전송 구간 암호화 (TLS)"
        evidence:
          - "암호화 적용 현황"
          - "암호화 솔루션 설정"
        status: "compliant"

  # 종합 평가
  summary:
    total_items: 8
    compliant: 7
    partial: 1
    non_compliant: 0
    compliance_rate: 87.5%
    next_audit: "2026-07-26"
-- PIMS/ISMS-P 준수 개인정보 보존 및 파기 관리 SQL

-- 1. 개인정보 테이블 (보유기간 관리 포함)
CREATE TABLE personal_info (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id VARCHAR(50) NOT NULL,

    -- 개인정보 항목 (암호화 저장)
    name_encrypted VARBINARY(256),           -- AES 암호화
    email_encrypted VARBINARY(256),
    phone_encrypted VARBINARY(256),
    ssn_encrypted VARBINARY(256),            -- 주민번호 (수집 최소화)

    -- PIMS 관리 메타데이터
    collection_purpose VARCHAR(100) NOT NULL,
    consent_required BOOLEAN DEFAULT TRUE,
    consent_marketing BOOLEAN DEFAULT FALSE,
    consent_third_party BOOLEAN DEFAULT FALSE,

    -- 보유기간 관리
    collected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    retention_period_days INT NOT NULL DEFAULT 365,
    retention_expires_at TIMESTAMP AS (DATE_ADD(collected_at, INTERVAL retention_period_days DAY)),
    is_destroyed BOOLEAN DEFAULT FALSE,
    destroyed_at TIMESTAMP NULL,

    -- 감사 추적
    last_accessed_at TIMESTAMP NULL,
    access_count INT DEFAULT 0,

    INDEX idx_retention (retention_expires_at, is_destroyed),
    INDEX idx_purpose (collection_purpose)
);

-- 2. 개인정보 접근 로그 (감사 추적)
CREATE TABLE pi_access_log (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    personal_info_id BIGINT NOT NULL,
    accessor_id VARCHAR(50) NOT NULL,
    accessor_role VARCHAR(50),
    access_type ENUM('READ', 'UPDATE', 'EXPORT', 'DELETE') NOT NULL,
    access_purpose VARCHAR(200),
    accessed_fields TEXT,  -- JSON: ["name", "email"]
    access_ip VARCHAR(45),
    accessed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_personal_info (personal_info_id),
    INDEX idx_accessor (accessor_id),
    INDEX idx_accessed_at (accessed_at)
);

-- 3. 보유기간 만료 데이터 파기 프로시저
DELIMITER //

CREATE PROCEDURE destroy_expired_personal_info()
BEGIN
    DECLARE destroyed_count INT DEFAULT 0;

    -- 트랜잭션 시작
    START TRANSACTION;

    -- 만료된 개인정보 파기 (복구 불가능하게 NULL 처리)
    UPDATE personal_info
    SET
        name_encrypted = NULL,
        email_encrypted = NULL,
        phone_encrypted = NULL,
        ssn_encrypted = NULL,
        is_destroyed = TRUE,
        destroyed_at = CURRENT_TIMESTAMP
    WHERE
        retention_expires_at < CURRENT_TIMESTAMP
        AND is_destroyed = FALSE;

    SET destroyed_count = ROW_COUNT();

    -- 파기 이력 기록
    INSERT INTO pi_destruction_log (
        destruction_date,
        destroyed_count,
        destruction_method,
        performed_by
    ) VALUES (
        CURRENT_TIMESTAMP,
        destroyed_count,
        'AUTO_RETENTION_EXPIRY',
        'SYSTEM'
    );

    COMMIT;

    SELECT destroyed_count AS '파기된 개인정보 건수';
END //

DELIMITER ;

-- 4. 일별 자동 파기 이벤트 (MySQL Event Scheduler)
CREATE EVENT IF NOT EXISTS daily_pi_destruction
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_DATE + INTERVAL 1 DAY + INTERVAL 3 HOUR  -- 매일 새벽 3시
DO
    CALL destroy_expired_personal_info();

-- 5. 개인정보 접근 시 로깅 트리거
DELIMITER //

CREATE TRIGGER log_pi_access
AFTER SELECT ON personal_info
FOR EACH ROW
BEGIN
    -- 접근 횟수 증가 및 마지막 접근 시간 업데이트
    UPDATE personal_info
    SET
        access_count = access_count + 1,
        last_accessed_at = CURRENT_TIMESTAMP
    WHERE id = NEW.id;
END //

DELIMITER ;

-- 6. 개인정보 현황 리포트 (ISMS-P 심사용)
SELECT
    collection_purpose AS '수집목적',
    COUNT(*) AS '보유건수',
    SUM(CASE WHEN is_destroyed = TRUE THEN 1 ELSE 0 END) AS '파기건수',
    AVG(retention_period_days) AS '평균보유기간(일)',
    MIN(collected_at) AS '최초수집일',
    SUM(CASE
        WHEN retention_expires_at < DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 30 DAY)
        AND is_destroyed = FALSE
        THEN 1 ELSE 0
    END) AS '30일내파기예정'
FROM personal_info
GROUP BY collection_purpose;

-- 7. 동의 현황 리포트
SELECT
    '필수동의' AS '동의유형',
    SUM(consent_required) AS '동의',
    COUNT(*) - SUM(consent_required) AS '미동의'
FROM personal_info WHERE is_destroyed = FALSE
UNION ALL
SELECT
    '마케팅동의',
    SUM(consent_marketing),
    COUNT(*) - SUM(consent_marketing)
FROM personal_info WHERE is_destroyed = FALSE
UNION ALL
SELECT
    '제3자제공동의',
    SUM(consent_third_party),
    COUNT(*) - SUM(consent_third_party)
FROM personal_info WHERE is_destroyed = FALSE;

🗣️ 실무에서 이렇게 말하세요

💬 인증 준비 회의에서
"ISMS-P 인증 심사 3개월 전이에요. 개인정보 처리 현황 파악부터 시작합시다. 어떤 개인정보를 어디서 수집하고, 누가 접근하고, 언제 파기하는지 전수 조사가 필요해요. 수집 동의서도 최신 법률에 맞게 업데이트해야 합니다."
💬 AI 프로젝트 데이터 검토에서
"ML 모델 학습에 고객 데이터를 쓰려면 ISMS-P 개인정보 보호조치를 먼저 확인하세요. 학습 목적이 수집 동의 범위에 포함되는지, 가명처리가 필요한지, 학습 완료 후 원본 데이터 파기 절차는 어떻게 되는지 문서화해야 심사 대응이 됩니다."
💬 보안 감사 대응에서
"ISMS-P 사후관리 심사에서 개인정보 접근 로그 요청이 왔어요. 누가 언제 어떤 개인정보에 접근했는지 최소 6개월 로그를 제출해야 해요. 접근 권한 변경 이력, 비인가 접근 시도 탐지 현황도 준비해주세요."

⚠️ 주의사항 & 베스트 프랙티스

동의 없는 개인정보 수집

개인정보보호법 위반으로 과태료 및 형사처벌 대상입니다. 수집 전 반드시 목적, 항목, 보유기간을 명시하고 동의를 획득하세요. 만 14세 미만은 법정대리인 동의가 필수입니다.

보유기간 경과 후 미파기

보유기간이 지난 개인정보는 지체없이(5일 이내) 파기해야 합니다. 자동 파기 시스템을 구축하고, 파기 이력을 3년간 보관하세요. 백업 데이터도 파기 대상입니다.

목적 외 이용

수집 목적과 다른 용도로 개인정보를 이용하면 안 됩니다. AI 학습, 마케팅, 제3자 제공은 별도 동의가 필요합니다. 가명처리 후 활용하더라도 재식별 위험을 평가하세요.

PIMS/ISMS-P 베스트 프랙티스

개인정보 처리 현황을 주기적으로 점검하고, 접근 권한은 최소한으로 부여하세요. 개인정보처리방침을 웹사이트에 상시 공개하고, 변경 시 정보주체에게 통지하세요. 연 1회 이상 개인정보보호 교육을 실시하세요.

🔗 관련 용어

📚 더 배우기