한국형 개인정보 필터
# 한국형 개인정보 필터 API
**Korean Privacy Filter** — 한국어 텍스트에서 개인정보(PII)를 정확하게 탐지·마스킹하는 AI 모델이에요. 개인정보보호법 §24-2 고유식별정보 9 종을 포함한 17 카테고리를 다뤄요.
- **모델 ID**: `pii`
- **라이브 버전**: `pii-2026.05`
- **정확도**: 자체 2,000건 분류까지 일치 정확도 99.99% + 외부 평가 묶음 14,195건 분류까지 일치 정확도 99.99% (동음이의어 함정 3,682건 + 공인 본명 1,222건 모두 오탐 0건)
## 핵심 기능
- 주민등록번호·전화번호·이메일·주소·계좌번호 등 개인정보 자동 탐지
- 문맥 기반 PII 인식 (단순 패턴이 아닌 의미 이해 기반)
- 실시간 마스킹 / 치환 / 삭제 처리
- API 기반 입력·출력 양방향 필터링
- 로그·감사 추적 지원 (compliance 대응)
## 특징
- 한국어 특화 (이름 + 맥락 기반 식별 강점)
- 정규식 + 한국어 특화 작은 AI 모델 결합 구조로 높은 정확도
- 개인정보보호법 등 국내 규제 대응 최적화
- 빠른 응답 시간으로 실시간 서비스 적용 가능
- 다양한 포맷 (텍스트·문서·채팅) 대응
## 1. 빠른 호출
```bash
curl -X POST https://api.corepin.ai/v1/pii/redact \
-H "Authorization: Bearer $COREPIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "안녕하세요, 김민수입니다. 010-1234-5678로 연락주세요. 주민번호 900101-1234567.",
"output_mode": "redacted"
}'
```
응답:
```json
{
"text": "안녕하세요, 김민수입니다. 010-1234-5678로 연락주세요. 주민번호 900101-1234567.",
"detected_spans": [
{"label": "private_person", "start": 7, "end": 10, "text": "김민수", "placeholder": "<PRIVATE_PERSON>"},
{"label": "private_phone", "start": 16, "end": 29, "text": "010-1234-5678", "placeholder": "<PRIVATE_PHONE>"},
{"label": "kr_rrn", "start": 41, "end": 55, "text": "900101-1234567", "placeholder": "<KR_RRN>"}
],
"span_count": 3,
"by_label": {"private_person": 1, "private_phone": 1, "kr_rrn": 1},
"redacted_text": "안녕하세요, <PRIVATE_PERSON>입니다. <PRIVATE_PHONE>로 연락주세요. 주민번호 <KR_RRN>.",
"meta": {
"model_id": "pii",
"model_version": "pii-2026.05",
"processing_time_ms": 38.7,
"request_id": "4c74bd30c53e497ca8a71f05aead6012",
"quota_remaining": 99998
}
}
```
## 2. 엔드포인트
| Method | Path | 인증 | 설명 |
|---|---|:-:|---|
| GET | `/v1/pii/version` | – | 모델 버전·릴리스 노트 |
| GET | `/v1/pii/categories` | – | 17 카테고리 카탈로그 (한글 설명 포함) |
| POST | `/v1/pii/detect` | ✓ | 탐지 only — spans 배열 반환 |
| POST | `/v1/pii/redact` | ✓ | 탐지 + 마스킹된 텍스트 |
| POST | `/v1/pii/batch` | ✓ | 1 - 100 텍스트 일괄 처리 |
| GET | `/v1/pii/history` | ✓ | 본문 미저장 검출 이력 (라벨 카운트만) |
| GET | `/v1/pii/audit` | ✓ | 본문 저장 감사 로그 (audit 모드 활성화 후의 요청만) |
레거시 alias `/v1/{detect,redact,batch}` 도 그대로 작동해요. 새 통합은 `/v1/pii/*` 사용을 권해요.
### 2.1 POST `/v1/pii/detect`
**Request**:
```json
{
"text": "탐지할 텍스트 (1 ~ 32,768자)",
"categories": ["kr_rrn", "private_phone"],
"return_text": true,
"apply_policy": false
}
```
`categories` (선택) — 화이트리스트. 지정하지 않으면 17개 모두 탐지.
`return_text` (기본 true) — false 면 응답에서 `text` 필드 생략.
`apply_policy` (기본 false) — true 시 조직·테넌트의 PII 카테고리 토글 정책을
적용해서 차단(keep=false)된 카테고리의 spans만 응답에서 제외해요. 응답
`meta.policy_applied=true` 와 `meta.filtered_out` (제외된 span 수) 가 함께 와요.
정책 우선순위는 [tenants 문서 §3](/docs/tenants#3-정책-resolve-순서-호출-시점) 참조.
### 2.2 POST `/v1/pii/redact`
`/v1/pii/detect` 의 모든 필드 (`apply_policy` 포함) +
```json
{
"output_mode": "redacted",
"placeholder_template": "[{label}]"
}
```
`output_mode`:
- `redacted` — `placeholder_template` 적용 (기본 `<KR_RRN>` 등)
- `partial_mask` — span 마지막 4자 외 `*` (예: `**********4567`)
- `typed` — 마스킹 없이 spans만 반환
`placeholder_template` 변수: `{label}`, `{start}`, `{end}`, `{original}`. positional `{0}` 사용 시 422.
### 2.3 POST `/v1/pii/batch`
```json
{
"texts": ["...", "...", "..."],
"categories": [...],
"output_mode": "redacted",
"placeholder_template": null,
"return_text": true,
"apply_policy": false
}
```
각 항목당 quota 1 unit 차감. `apply_policy=true` 시 배치 전체에 동일 정책 적용
(호출당 1회 정책 resolve, 항목별 fan-out).
배치 N 개는 RPM·월 한도 모두 N 건으로 차감돼요.
### 2.4 GET `/v1/pii/history`
본문 미저장 검출 이력. 본문이나 span text는 절대 포함되지 않아요 — 라벨 카운트와 길이만 반환해요.
```bash
curl "https://api.corepin.ai/v1/pii/history?limit=50" \
-H "Authorization: Bearer $COREPIN_API_KEY"
```
응답 필드: `ts`, `request_id`, `text_length`, `summary.by_label`, `summary.span_count`. `from_ts` / `to_ts` (unix epoch sec) · `limit` (1 - 500) · `offset` 으로 페이지네이션.
### 2.5 GET `/v1/pii/audit`
본문 저장 감사 로그. **대시보드 → 설정** 에서 PII 감사 모드를 `metadata` 또는 `full` 로 켠 이후의 요청만 적재돼요. `level=full` 인 경우에만 `input_text` 가 채워지고, `metadata` 모드는 길이·라벨만 저장돼요.
```bash
curl "https://api.corepin.ai/v1/pii/audit?limit=50" \
-H "Authorization: Bearer $COREPIN_API_KEY"
```
쿼리 파라미터: `from_ts`, `to_ts` (unix epoch sec) · `blocked_only` (true/false) · `limit` (1 - 500, 기본 50) · `offset`.
응답 필드:
```ts
{
items: [
{
ts: number, // unix epoch sec
request_id: string,
key_id: string,
input_text: string | null, // level='full' 일 때만 본문
output: object, // 모델 응답 그대로
blocked: boolean,
level: "metadata" | "full",
input_length: number,
}
],
count: number, total: number, limit: number, offset: number,
model_id: "pii",
note: string
}
```
## 3. 17 카테고리
| 라벨 | 한글명 | 개인정보보호법 고유식별 |
|---|---|:-:|
| `private_person` | 이름 | |
| `private_address` | 주소 | |
| `private_email` | 이메일 | |
| `private_phone` | 전화번호 | |
| `private_url` | URL | |
| `private_date` | 날짜 (생년월일 등) | |
| `account_number` | 계좌·카드번호 | |
| `secret` | API 키·토큰·비밀번호 | |
| `kr_rrn` | 주민등록번호 | ✓ |
| `kr_foreigner_id` | 외국인등록번호 | ✓ |
| `kr_passport` | 여권번호 | ✓ |
| `kr_driver_license` | 운전면허번호 | ✓ |
| `kr_biz_no` | 사업자등록번호 | |
| `kr_corp_no` | 법인등록번호 | |
| `kr_health_insurance` | 건강보험증번호 | ✓ |
| `kr_vehicle_plate` | 차량번호 | |
| `private_ip` | IP 주소 | |
각 카테고리의 한글 설명은 `GET /v1/pii/categories` 에서 받아볼 수 있어요.
## 4. 응답 스키마
```ts
{
text: string | null,
detected_spans: {
label: string, // 17 카테고리 중 하나
start: number, // Python str index (UTF-16 unit 아님)
end: number, // exclusive
text: string, // 원문 substring
placeholder: string // 권장 마스킹 토큰
}[],
span_count: number,
by_label: { [label: string]: number },
redacted_text: string | null,
meta: {
model_id: "pii",
model_version: "pii-2026.05",
processing_time_ms: number,
request_id: string,
quota_remaining: number | null,
policy_applied: boolean, // apply_policy=true 호출 시 true
filtered_out: number // 정책에 의해 제외된 span 수 (apply_policy=true 일 때만 ≥0)
}
}
```
## 5. 개인정보 처리 안내
- 본 서비스는 입력 텍스트와 탐지 spans의 텍스트를 저장하지 않아요. 메트릭·로그·검출 이력에는 길이·라벨 카운트만 남아요.
- `pipa_sensitive: true` 카테고리(주민·외국인·여권·운전면허·건강보험증)는 개인정보보호법 §24-2 고유식별정보예요. 마스킹 후에도 별도 처리·암호화 의무가 발생할 수 있어요.
- 본 API는 **탐지기**예요. `redacted_text` 는 참고용이며 재식별 가능성이 있어요.
## 6. 변경 이력
- **pii-2026.05** (2026-04-25 학습, 2026-05 출시) — 외부 일반화 완성. 한국 개인정보 마스킹 공개 평가 셋 통합 (총 22.3만 문장, 5 회차에 걸친 학습). 자체 분류 일치 정확도 99.99% 그대로 + 외부 14,195 평가 묶음 분류 일치 정확도 99.99%. 동음이의어 함정 3,682건·공인 본명 1,222건 오탐 0건.
- **v8-20260425** — 한국 공개 학습 비중 확대 (V7 잔여 케이스 보완).
- **v7-20260425** — 한국 개인정보 마스킹 공개 평가 셋 1차 통합. 외부 14,195 평가 묶음에서 78.6 → 99.2 도약.
- **v6-20260423** — 자체 시험지 정확도 마무리. 17 카테고리, 분류 일치 정확도 99.99% (2,000건 자체 평가 묶음).
## 6.5 단가
- 무료: 60회/분 · 1,000회/월 · 카드 등록 불필요
- 유료: **₩15/호출** (배치 호출은 텍스트 개수만큼 차감)
- 연간 대량 계약 할인 가능 — <support@corepin.ai>
- 전체 요금 비교는 [`/pricing`](/pricing) 또는 [`/docs/billing`](/docs/billing)
## 7. SDK / 코드 예제
### Python
```python
from kpf_client import KPFClient
client = KPFClient(api_key="sk_live_…")
result = client.redact("홍길동 010-1234-5678")
print(result.redacted_text)
# "<PRIVATE_PERSON> <PRIVATE_PHONE>"
```
### JavaScript / TypeScript
```ts
const r = await fetch(`${BASE}/v1/pii/redact`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.COREPIN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text, output_mode: "redacted" }),
});
if (!r.ok) throw new Error((await r.json()).error.message);
const { redacted_text, detected_spans } = await r.json();
```
### Go
```go
body, _ := json.Marshal(map[string]any{"text": text, "output_mode": "redacted"})
req, _ := http.NewRequest("POST", base+"/v1/pii/redact", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("COREPIN_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
```