T2Editor 9.1.0의 NSFW 필터는 브라우저 모드를 기준으로 설계되어 있으며, 내부 엔진은 NSFWJS + TensorFlow.js 조합을 사용합니다. 모델은 기본적으로 MobileNetV2Mid를 사용하고, 런타임 자산은 CDN이 아니라 vendor/ 아래의 자체 호스팅 경로에서 읽도록 구성할 수 있습니다.
파일 개요
이 문서는 T2Editor 9.1.0에서 NSFWJS 관련 구조가 어떻게 바뀌었는지, 그리고 어떤 파일이 어떤 책임을 가지는지 한 번에 이해하기 위한 안내서입니다.
기존 구조에서는 브라우저 NSFW 코드가 자체 추론 로직과 워커 처리 중심으로 설명될 수 있었지만, 9.1.0에서는 다음 원칙으로 재정리되었습니다.
- 엔진 교체: 자체 브라우저 추론 로직 →
NSFWJS - 기본 모델 교체: 커스텀 분류 흐름 →
MobileNetV2Mid - UI 유지: NSFWJS 자체 UI를 쓰지 않고 기존 이미지 업로드 UI에 결과만 연결
- 운영 방식 변경: CDN 의존 대신 self-hosted vendor 구조 지원
- 성능 전략 변경:
webgpu -> webgl -> wasm -> cpu순서 폴백
초보자와 웹마스터를 위한 이해
이 구조를 아주 간단히 보면 아래와 같습니다.
| 단계 | 설명 |
|---|---|
| 1 | 사용자가 이미지 업로드 모달에서 파일을 고릅니다. |
| 2 | image.js가 브라우저 NSFW API를 불러옵니다. |
| 3 | nsfw_api_browser.js가 NSFWJS 모델을 로드합니다. |
| 4 | 업로드 전 각 이미지가 safe / suspect / unsafe / error 중 하나로 분류됩니다. |
| 5 | 결과가 기존 미리보기 카드와 상태바에 반영됩니다. |
| 6 | 정책에 따라 업로드 허용, 경고 후 허용, 업로드 취소가 결정됩니다. |
즉, NSFWJS는 보이는 UI를 담당하지 않고 분류 엔진만 담당합니다. 사용자가 실제로 보는 경고 배지, 상태바, 경고 모달은 T2Editor의 기존 이미지 플러그인이 담당합니다.
왜 이렇게 바뀌었나요?
가장 큰 이유는 아래 세 가지입니다.
- 브라우저 추론 엔진을 유지보수하기 쉽게 만들기 위해
- 기존 UI를 버리지 않고 필터 성능과 구조를 개선하기 위해
- 서버 부하를 늘리지 않으면서 클라이언트 하드웨어를 활용하기 위해
전문 개발자를 위한 분석
전체 호출 흐름
texteditor.lib.php └─ window.T2EDITOR_NSFW_* 전역 설정 주입 └─ plugin/image/image.js ├─ getNSFWApi() │ └─ import(config/nsfw_api_browser.js) ├─ checkNSFW(file) │ └─ api.classify(file) ├─ resolveNSFWResult(imageData) └─ applyNSFWFilter(imageDataArray) └─ 업로드 허용/경고/차단 결정
핵심 파일별 책임
| 파일 | 책임 |
|---|---|
editor.lib.php | NSFW 관련 설정 상수를 JS 전역 값으로 주입합니다. |
config/nsfw_api_browser.js | NSFWJS 모델 로딩, 백엔드 선택, 이미지 분류를 담당합니다. |
plugin/image/image.js | 업로드 모달, 상태 배지, 경고 모달, 업로드 정책 적용을 담당합니다. |
plugin/image/image.css | 상태 배지, 상태바, 경고 표시의 시각 스타일을 담당합니다. |
결과 라벨 체계
9.1.0의 브라우저 NSFW 결과는 단순히 safe / nsfw 두 단계가 아니라 아래처럼 다룹니다.
| 라벨 | 의미 | 기본 처리 |
|---|---|---|
safe | 업로드 가능으로 판단 | 그대로 허용 |
suspect | 애매하거나 주의가 필요한 상태 | 설정에 따라 경고 후 허용 또는 차단 |
unsafe | 고위험 이미지로 판단 | 설정에 따라 차단 또는 경고 후 허용 |
error | 모델 로딩 또는 추론 실패 | 오류 표시 후 정책에 따라 계속 진행 |
이 라벨 체계 때문에 문서와 코드에서 의심 이미지와 명확한 위험 이미지를 구분해서 다뤄야 합니다.
성능 구조
백엔드 우선순위
기본 우선순위는 다음과 같습니다.
textwebgpu -> webgl -> wasm -> cpu
webgpu: 가장 먼저 시도하는 가속 백엔드webgl: 대부분의 브라우저에서 현실적인 폴백wasm: GPU가 어렵거나 제한될 때 사용 가능한 안전한 폴백cpu: 마지막 안전망
이 순서는 editor.lib.php에서 전역 설정으로 넘길 수 있고, nsfw_api_browser.js가 실제 선택을 수행합니다.
self-hosted 구조
운영에서는 아래 같은 구조를 권장합니다.
text/plugin/editor/t2editor/vendor/ tfjs/ tfjs-backend-webgl/ tfjs-backend-webgpu/ tfjs-backend-wasm/ nsfwjs/ nsfwjs/models/mobilenet_v2_mid/
이렇게 하면 외부 CDN 장애나 차단의 영향을 줄이고, 배포 경로를 서비스 내부에서 통제할 수 있습니다.
수정 요약
9.1.0에서 NSFWJS 관련 핵심 변화는 아래와 같습니다.
- 기존 브라우저 추론 코드 대신 NSFWJS 사용
MobileNetV2Mid모델 도입- WebGPU 우선 백엔드 선택 지원
- self-hosted vendor 자산 로딩 지원
- 기존 이미지 UI에 맞춘 결과 연동
suspect상태를 별도 정책 대상으로 추가- 업로드 직전 중복 재검사 비용 감소
자주 생기는 오해
NSFWJS를 쓰면 UI도 자동으로 바뀌나요?
아닙니다. 이 구조에서는 NSFWJS가 분류 엔진만 담당하고, 배지·모달·상태바는 기존 T2Editor 이미지 플러그인이 담당합니다.
server 모드는 완전히 사라졌나요?
완전히 삭제된 것은 아닐 수 있지만, 9.1.0의 권장 경로는 브라우저 모드입니다. 문서와 운영 기본값도 브라우저 모드를 기준으로 작성하는 것이 맞습니다.