10월 29일과 30일에 걸쳐, 내가 운영하는 서비스 14곳과 소개 사이트(cmhong95.com)에 개인정보 처리방침을 올렸다. 29일에 대부분을 한꺼번에 올렸고, 30일 아침에는 쓰면서 나온 결정거리 다섯 가지를 정해 반영했다. 무엇을 어떻게 만들었고, 사이트마다 무엇을 확인했고, 어디서 막혔는지 적는다.
공통 방침 하나에서 서비스별 방침으로
10월 22일 광고를 붙이면서 소개 사이트에 공통 개인정보 처리방침을 하나 만들었고, 블로그도 그 방침을 가리켰다. 그런데 서비스마다 다루는 정보가 다르다. 시나브로 AI는 질문과 답을, 저지는 학생이 낸 코드와 채점 결과를, 축전 앱은 설문 응답을 다룬다. 그래서 10월 29일에 서비스마다 처리방침을 따로 두고, 소개 사이트의 공통 방침에는 서비스별 처리방침을 모은 표를 넣었다. 이 표는 처음 13곳이었고, 다음 날 GPU 실습실을 더해 14곳이 됐다.
생성기 하나, 사이트별 내용은 한곳에
처리방침은 사이트마다 장의 순서와 법에서 요구하는 문구가 같다. 다른 것은 그 사이트가 실제로 다루는 정보다. 같은 틀을 열다섯 번 손으로 쓰면 한 문장을 고칠 때마다 열다섯 곳을 다시 맞춰야 한다. 그래서 파이썬 생성기(build.py) 하나를 만들고, 사이트별 내용은 SITES라는 사전 하나에 모았다. 생성기는 사이트마다 privacy.html을 만들고, 모든 사이트가 같은 privacy.css를 쓴다.
CSP가 엄격한 사이트에서도 그대로 열리도록 페이지에는 인라인 스크립트와 인라인 스타일을 넣지 않았다. 검사 스크립트도 두 개 만들었다. 하나는 처리방침 페이지를 휴대폰 폭(390px)과 PC 폭(1440px)에서 열어 보고, 다른 하나는 각 사이트 첫 화면에 처리방침 링크가 실제로 있는지 확인한다. 어디에 올렸는지와 사이트마다 확인한 사실은 같은 폴더의 README에 표로 남겼다.
사이트마다 코드에서 확인한 사실
처리방침에 쓰는 숫자는 짐작하지 않고 각 서비스의 코드와 설정에서 찾았다. 몇 가지를 옮긴다.
| 서비스 | 확인한 것 |
|---|---|
| 시나브로 AI | 로그인 세션 2시간, 대화 30일, 감사 기록 90일, 체험 게스트의 IP 해시 2일 |
| 시나브로 저지 | 로그인 세션 14일, 랭킹을 로그인 없이 볼 수 있었고 이름이 보였다 |
| 해커톤 플랫폼 | 로그인 세션 14일, 웹 검색은 MDN·Google 뉴스·Bing RSS로 한다 |
| 학성고 시험 채점 | 서술형 AI 채점은 Anthropic Claude, 이름과 이메일은 보내지 않는다. 지금은 읽기 전용 |
| PyCode Racer | 진단 피드백은 Gemini(닉네임·학습 기록), 데이터는 Firestore 서울, 광고 게시자 ID가 내 것이 아니었다 |
| 시나브로 데이터 랩 | 시나브로 AI 질문·답은 30일 보관, 본인이 모두 지울 수 있고 계정을 지우면 함께 지워진다 |
뜻밖의 것도 하나 나왔다. Cloudflare가 터널로 연 사이트의 HTML에 방문 통계 스크립트(Cloudflare Web Analytics)를 자동으로 넣고 있었다. 내가 코드에 넣은 것이 아니어도 방문자의 브라우저에서 돌아가니 처리방침에 들어가야 할 내용이다. CSP가 엄격한 시나브로 AI와 사용 현황 대시보드에서는 브라우저가 이 스크립트를 막고 있었다.
표의 숫자는 처리방침의 보유 기간과 쿠키 항목에 들어간다. 예를 들어 시나브로 AI의 체험 게스트는 IP 주소를 그대로 두지 않고 해시로 바꿔 2일만 보관한다. 이런 값은 화면에서는 보이지 않아서, 코드를 읽지 않고 쓰면 틀리기 쉽다. 외부 AI도 마찬가지다. 같은 학교 서비스라도 시나브로 AI와 데이터 랩은 학교 AI 서버를 쓰고, 학성고 시험 채점은 Anthropic Claude를, PyCode Racer는 Gemini를 쓴다. 처리방침마다 어떤 정보가 어느 AI로 가는지 따로 적었다.
사이트마다 달랐던 올리는 방법
생성기는 하나지만, 만든 파일을 올리는 방법은 사이트마다 달랐다.
- 저지는 정적 파일 폴더 아래(
/static/privacy.html)에 두었다. - 해커톤 플랫폼은 서버가
.html주소를 404로 돌려줘서/privacy.htm으로 열었다. - 축전 앱은 화면 템플릿을 메모리에 캐시하고 있어서, 파일을 바꿔도 다시 시작하기 전까지는 반영되지 않았다. 다시 시작한 뒤 쌓여 있던 응답 112개가 그대로 돌아왔는지 확인했다.
- 사용 현황 대시보드는 API 서버에 주소(라우트)와 CSS 파일 허용 목록을 더하고 다시 시작했다.
- 학성고 시험 채점 사이트는 Cloud Run에서 도는 서버에 주소를 더해 새 버전으로 배포했다. 되돌릴 수 있게 이전 이미지를 기록해 두었다.
- Pico IDE와 PyCode Racer는 Firebase Hosting으로 올렸다. Pico IDE는 [더보기 → 도움말] 메뉴에, PyCode Racer는 로그인 화면에도 링크를 달았다.
- 블로그는 꼬리말 링크를 소개 사이트의 공통 방침에서 블로그 자체 방침으로 바꿨다.
- 소개 사이트의 처리방침에는 서비스별 처리방침을 표로 모으고 모두 링크했다.
Pico IDE는 배포 스크립트로 올린 뒤 화면 시험 76개를 로컬과 실제 사이트에서 다시 돌렸다. 고칠 파일은 올리기 전에 따로 백업했고, git으로 관리하지 않는 축전 앱은 파일 옆에 날짜를 붙인 사본을 두었다.
해커톤은 한 번 더 손이 갔다. 해커톤 플랫폼은 실험 저장소에서 검증한 코드를 배포 스크립트로 올린다. 이 스크립트는 운영 폴더가 기준 버전과 같은지 먼저 확인한다. 운영 파일에만 링크 한 줄을 넣으면 다음 배포가 그 확인에 걸린다. 그래서 같은 줄을 실험 저장소의 작업 브랜치에 넣고, 지금 운영과 똑같은 기준 브랜치를 새로 만들어 다음 배포의 출발점으로 정했다. 배포 미리보기는 통과했다.
처리방침은 기능과 함께 바뀐다
처리방침은 한 번 쓰고 끝나지 않는다. 10월 29일 저녁 PixelPlaza v0.3.0을 배포하면서 놀이 기능(보물 스탬프, 이름표 칭호 등)을 위한 DB 표를 더했고, 처리방침도 2판으로 올렸다. 다음 날 데이터 랩에 시나브로 AI를 붙일 때는 질문과 답을 30일 보관한다는 내용을 처리방침 2-2절로 더했다. 새 기능이 새 정보를 저장하면 처리방침도 같은 배포에 들어가야 한다.
다음 날 아침에 정한 다섯 가지
처리방침을 쓰다 보니 문장보다 먼저 정해야 할 것이 나왔다. 10월 30일 아침에 정해 반영했다.
- 저지 랭킹과 대회 점수판은 로그인한 사람만 본다. 랭킹 API는 로그인하지 않아도 이름을 보여 주고 있었다. 이대로 처리방침에 "누구나 볼 수 있다"고 적을지, 로그인 뒤로 옮길지 정해야 했다. 로그인한 사람만 보게 하고, 로그인하지 않으면 401과 안내 문구를 돌려주게 바꿨다. 격리 인스턴스에서 저지 API 시험을 모두 통과했고(v2 API 시험 48/48), 그 뒤 운영 서버를 다시 시작했다.
- 학성고 시험 채점의 AI 채점 문구는 그대로 둔다. 서술형 AI 채점에 Anthropic Claude를 쓰고, 이름과 이메일은 보내지 않는다는 문장이다.
- PyCode Racer 광고 게시자 ID를 내 것으로 통일하고
ads.txt를 더한다. 광고 항목을 쓰려고 보니 사이트에 붙은 게시자 ID가 내 것이 아니었다. 바꾼 뒤 Hosting만 다시 배포했다. - 해커톤 링크 한 줄은 실험 저장소에도 넣는다. 위에 적은 대로다.
- GPU 실습실(JupyterHub)에도 처리방침을 둔다. 10월 29일까지 GPU 실습실에는 처리방침이 없었다. JupyterHub 설정에 처리방침 페이지(
/hub/privacy)를 더하는 설정 파일 하나를 넣고, 로그인 화면 템플릿에 링크를 달았다. 고치기 전에 설정과 템플릿을 묶어 백업했다.
쓰면서 배운 것
- 처리방침은 코드를 읽어야 쓸 수 있다. 세션 길이, 보관 기간, 외부 AI에 보내는 항목은 설정 파일과 코드에 있다.
- 쓰다 보면 결정할 것이 나온다. 랭킹처럼 문장을 고치는 대신 서비스를 고친 것도 있다.
- 같은 '순위'라도 서비스마다 답이 달랐다. 저지는 순위를 로그인 뒤로 옮겼고, 데이터 탐험 카드는 순위에 이름의 가운데 글자를 가리고 이름 신고와 자동 가림을 둔다.
- 내가 넣지 않은 코드도 방문자 브라우저에서 돈다. 터널이 넣는 통계 스크립트가 그랬다.
- 자동 삭제 기능이 없는 서비스는 처리방침에 "운영자가 직접 지운다"고 적었다. 실제로 지울 날짜를 정하는 일은 아직 남아 있다.
- 생성기가 하나여도 올리는 길은 사이트 수만큼 있다. 캐시, 주소 규칙, 배포 확인 장치를 사이트마다 따로 봐야 했다.