Skip to content

Repository files navigation

AI Privacy System

AI 기반 프라이버시 관리 시스템 백엔드 인프라입니다.

프로젝트 구조

ai-privacy-system/
backend/
collaboration-server/
src/
config/ # 환경변수 관리
routes/ # API 라우트 (status, masking)
db/ # PostgreSQL 연결
storage/ # MinIO 스토리지 연결
middlewares/ # HTTP 로거, JWT 인증
services/ # 마스킹 서비스
websocket/ # Socket.io 협업 처리
.env.example # 환경변수 템플릿
docker-compose.yml # 인프라 컨테이너 설정

기술 스택

분류기술
RuntimeNode.js + TypeScript
FrameworkExpress v5
WebSocketSocket.io v4
DatabasePostgreSQL 16
Object StorageMinIO (S3 호환)
CacheRedis 7
ContainerDocker

시스템 구성 (3-way 통합)

서버역할주소
Django메인 백엔드 (인증, 파일 업로드)localhost:8000
collaboration-server실시간 협업, 마스킹localhost:4000
React FE프론트엔드localhost:5173

시작하기

1. 환경변수 설정

cp backend/collaboration-server/.env.example backend/collaboration-server/.env

.env 파일을 열어 JWT_SECRET 등 값을 채워넣어.

2. 인프라 실행 (Docker 필요)

docker-compose up -d
서비스주소
PostgreSQLlocalhost:5560
MinIO APIlocalhost:9000
MinIO 콘솔http://localhost:9001
Redislocalhost:6379

MinIO 기본 계정: minioadmin / minioadmin

3. 서버 실행

cd backend/collaboration-server
npm install
npm run dev

4. 동작 확인

GET http://localhost:4000/status

응답:

{ "ok": true, "message": "collaboration-server is running" }

환경변수

변수설명기본값
PORT서버 포트4000
NODE_ENV실행 환경development
PG_HOSTPostgreSQL 호스트localhost
PG_PORTPostgreSQL 포트5432
PG_USERPostgreSQL 유저postgres
PG_PASSWORDPostgreSQL 비밀번호postgres123
PG_DATABASEPostgreSQL DB명ai_privacy
MINIO_ENDPOINTMinIO 호스트localhost
MINIO_PORTMinIO 포트9000
MINIO_ACCESS_KEYMinIO 액세스 키minioadmin
MINIO_SECRET_KEYMinIO 시크릿 키minioadmin
MINIO_BUCKET기본 버킷 이름documents
REDIS_HOSTRedis 호스트localhost
REDIS_PORTRedis 포트6379
JWT_SECRETJWT 서명 키 (Django와 동일)-

주의:JWT_SECRET은 Django 서버와 동일한 값으로 설정해야 합니다.


사용 가이드

1. 개발 환경 시작

인프라 올리기

cd C:\dev\ai-privacy-system
docker-compose up -d
docker ps
# ai-postgres, ai-minio, ai-redis 세 컨테이너가 Up 상태여야 함

서버 실행

cd backend/collaboration-server
npm install # 최초 1회
npm run dev # ts-node-dev로 핫리로드 실행

서버가 http://localhost:4000 에서 시작됩니다.


2. HTTP API 사용법

파일 업로드/다운로드는 Django 서버(:8000)에서 처리합니다.

서버 상태 확인

curl http://localhost:4000/status
# { "ok": true, "message": "collaboration-server is running" }

텍스트 마스킹

curl -X POST http://localhost:4000/masking/text \
-H "Content-Type: application/json" \
-d '{"text": "홍길동 010-1234-5678 주민번호 901010-1234567"}'

응답:

{
"original": "홍길동 010-1234-5678 주민번호 901010-1234567",
"masked": "홍길동 010-****-**** 주민번호 901010-*******",
"detections": [
{ "type": "전화번호", "original": "010-1234-5678", "masked": "010-****-****", "index": 4 },
{ "type": "주민등록번호", "original": "901010-1234567", "masked": "901010-*******", "index": 16 }
]
}

PII 탐지만 (마스킹 없이)

curl -X POST http://localhost:4000/masking/detect \
-H "Content-Type: application/json" \
-d '{"text": "이메일: user@example.com"}'

파일 마스킹

curl -X POST http://localhost:4000/masking/file \
-F "file=@/path/to/document.txt"# 마스킹된 파일 반환

지원 PII 유형: 주민등록번호, 전화번호, 이메일, 카드번호, 계좌번호, 여권번호, 운전면허번호, IP 주소


3. WebSocket 협업 사용법

Socket.io 클라이언트 기준 예시입니다.

JWT 인증 연결

WebSocket 연결 시 Django에서 발급한 JWT 토큰을 반드시 전달해야 합니다.

import{io}from"socket.io-client";constsocket=io("http://localhost:4000",{auth: {token: "Bearer eyJ..."}// Django accessToken});socket.on("connect_error",(err)=>{console.error("인증 실패:",err.message);});

룸 입장

userIduserName은 JWT에서 자동으로 추출되므로 클라이언트가 보낼 필요 없습니다.

// 룸 입장socket.emit("room:join",{roomId: "project-room-1",sessionToken: null// 재연결 시 이전 sessionToken 전달});// 입장 확인 수신socket.on("room:joined",({ users, sessionToken, isReconnect })=>{console.log("현재 룸 유저:",users);localStorage.setItem("sessionToken",sessionToken);// 재연결용 보관});

프레즌스 업데이트

// 내가 어느 영역에서 작업 중인지 알리기socket.emit("presence:update",{roomId: "project-room-1",activeArea: "section-2",status: "active"// "active" | "idle"});// 다른 유저 프레즌스 변경 수신socket.on("presence:updated",(presence)=>{console.log(`${presence.userName}${presence.activeArea} 작업 중`);});

커서 동기화

// 커서 위치 전송socket.emit("cursor:move",{roomId: "project-room-1",x: 120,y: 350,areaId: "section-2"});// 다른 유저 커서 수신socket.on("cursor:moved",({ userId, userName, x, y, areaId })=>{// 커서 렌더링});

영역 잠금 & 편집

// 영역 잠금 요청socket.emit("area:lock",{roomId: "project-room-1",areaId: "section-2"});// 잠금 결과 수신socket.on("area:locked",({ areaId, lock, denied })=>{if(denied){console.log("이미 다른 사람이 편집 중");}else{// 잠금 성공 → 편집 가능socket.emit("area:change",{roomId: "project-room-1",areaId: "section-2",changes: {content: "수정된 내용"}});}});// 편집 완료 후 잠금 해제socket.emit("area:unlock",{roomId: "project-room-1",areaId: "section-2"});

재연결 처리

socket.on("connect",()=>{consttoken=localStorage.getItem("sessionToken");if(token){socket.emit("room:join",{roomId: "project-room-1",sessionToken: token// 세션 복원 (10초 이내 재연결 시 상태 유지)});}});

4. WebSocket 이벤트 전체 목록

Room

방향이벤트페이로드
C→Sroom:join{ roomId, sessionToken? }
C→Sroom:leave{ roomId }
S→Croom:joined{ users, sessionToken, isReconnect }
S→Roomroom:user-joined{ user }
S→Roomroom:user-left{ user }
S→Roomroom:reconnected{ user }

Presence + Cursor

방향이벤트페이로드
C→Spresence:update{ roomId, activeArea, status }
C→Scursor:move{ roomId, x, y, areaId }
S→Cpresence:sync전체 프레즌스 맵
S→Roompresence:updatedpresence 객체
S→Roomcursor:moved{ userId, userName, x, y, areaId }

Area

방향이벤트페이로드
C→Sarea:lock{ roomId, areaId }
C→Sarea:unlock{ roomId, areaId }
C→Sarea:change{ roomId, areaId, changes }
S→Carea:state-sync전체 영역 상태
S→Roomarea:locked{ areaId, lock, denied? }
S→Roomarea:unlocked{ areaId }
S→Roomarea:changed{ areaId, changes, userId }

5. MinIO 콘솔 (관리 UI)

브라우저에서 http://localhost:9001 접속

  • ID: minioadmin
  • PW: minioadmin

마스킹된 파일은 documents 버킷의 masked/{document_id}/{uuid}/ 경로에 저장됩니다.


6. 자주 쓰는 개발 시나리오

상황해결
DB 테이블 확인docker exec -it ai-postgres psql -U postgres -d ai_privacy -c "\dt"
PostgreSQL 직접 접속psql -h localhost -p 5560 -U postgres -d ai_privacy
MinIO 버킷 초기화 안 됨서버 재시작 (index.ts에서 자동 생성)
서버 재시작 후 룸 상태 사라짐정상 동작 (인메모리, Redis 미연동)
WebSocket 인증 오류JWT_SECRET이 Django와 동일한지 확인
포트 충돌.env에서 PORT 변경

About

서버 관련

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages