보안을 아예 모르는 건 아니지만, 한국 개인정보보호법 조문 기준으로 우리 DB를 제대로 줄 세워 점검해본 적은 없었어요. 그걸 Rona로 만든 스킬로 해봤습니다.
Rona는 AI를 실제 업무에 써보게 만드는 학습 플랫폼이에요. 누군가 맞춤 스킬을 한 번 만들어두면, 배우는 사람이 자기 AI 도구(클로드 코드 같은)에 원클릭으로 설치해 단계별로 따라 하는 구조죠. 핵심 가설은 "뭘 요청해야 할지도 잘 모르는 사람도, 가이드만 제대로 받으면 쓸만한 결과까지 간다"는 겁니다.
이번엔 그 가설을, 평소 어느 정도는 챙긴다고 생각하던 영역에 던져봤습니다. 개발하면서 비밀번호 해시나 토큰 관리 같은 기본은 신경 쓰는 편인데, 개인정보 유출 사고 뉴스를 보다 보니 "우리 DB 전체가 한국 개인정보보호법 기준으로 정말 괜찮은가"는 솔직히 자신이 없더라고요. 어떤 게 법적으로 고유식별정보고 어떤 게 민감정보인지, 어느 컬럼부터 어떻게 손대야 하는지를 조문 기준으로 줄 세워본 적은 없었거든요. 그래서 Rona에게 "DB 컬럼이랑 저장값을 한국 법 기준으로 점검하고 싶다"고 설명했더니, 그 점검 절차를 통째로 담은 맞춤 스킬이 만들어졌습니다. 그걸 클로드 코드에 설치해, 시키는 순서대로 따라가 봤어요. 코드는 한 줄도 직접 치지 않았습니다.
1. Rona가 만들어준 스킬은 어떤 순서로 데려갔나
혼자였다면 "민감한 컬럼 있나 한번 훑어볼까" 하고 끝났을 텐데, 스킬은 그걸 6단계로 쪼개서 데려갔습니다.
좋았던 건, 매 단계 끝에 "이대로 갈까요?"를 물어봤다는 점이에요. 제가 중간에 "분류랑 우선순위 위주로 가자"고 방향을 틀었더니, 자율주행처럼 혼자 달리지 않고 멈춰서 같이 잡아줬습니다. 역할을 나누면 이런 그림이었어요. Rona가 만들어준 스킬이 도메인 지식과 절차를, 클로드 코드가 실제 스키마 grep과 구현을, 저는 방향·판단을 맡았습니다. 여기에 예전에 만들어둔 보안 점검 스킬도 하나 같이 돌렸어요. 새 API·민감 데이터·배포 직전에 인증 가드·응답 마스킹·암호화 같은 영역을 훑어 🔴/🟡/🟢로 짚어주는 가드인데, 이번엔 DB 점검에 곁들였습니다.
⚠️ 시작하면서 선 하나는 분명히 그었습니다. 운영 DB의 실제 사용자 데이터를 통째로 뽑아보면 그 점검 행위 자체가 유출이에요. 그래서 스키마 정의만 근거로 삼고, 저장값은 형태와 샘플 수준에서만 봤습니다.
2. 안다고 생각했는데, 스킬이 체계로 다시 짚어준 것들
막연히는 "민감한 건 암호화하면 되겠지" 정도로 챙기고 있었어요. 그런데 스킬은 한국 법에선 등급마다 조치 강도가 법적으로 다르다는 걸 조문 단위로 짚어줬습니다. 그냥 "위험/안전"이 아니라요.
그리고 "고치라"고만 하지 않고, 값 성격에 따라 방법이 갈린다는 것도 알려줬어요. 토큰·결제키처럼 나중에 다시 꺼내 써야 하는 값은 양방향 암호화(AES-256-GCM), 비밀번호처럼 맞는지만 확인하면 되는 값은 단방향 해시(argon2id), 전화·이메일은 저장은 두고 화면에서만 마스킹, 그리고 memo·extra_info 같은 자유 입력 칸은 값을 따로 스캔(Presidio 등)해서 숨은 민감값을 잡는 식으로요. 이런 분기를 머리로는 알아도, 매번 빠짐없이 갈라서 적용하긴 어렵죠. 스킬이 그 체계를 대신 깔아줬습니다.
3. 점검 결과 ① — 생각보다 깨끗했다
막상 까보니 법적으로 가장 무거운 항목이 의외로 하나도 없었습니 다.
주민번호를 애초에 안 받고, 로그인이 OAuth라 비밀번호를 저장할 일이 없고, 결제도 카드 끝 4자리만 두는 구조 덕이었어요. 막연히 불안했던 게 근거로 보니 출발점은 나쁘지 않았습니다.
4. 점검 결과 ② — 그런데 함정이 하나 있었다 ⚠️
같이 돌린 그 보안 점검 스킬이 콕 집어주는 함정이 우리에게도 해당됐습니다. 바로 암호화 유틸(encrypt/decrypt)이 코드에 있어도, 실제론 로그인 토큰만 감싸고 정작 민감한 PII 필드엔 안 걸려 있는 경우예요. 함수가 있다는 사실만 보고 "우린 암호화한다"고 넘기기 쉬운데, 무엇을 감싸는지 호출처를 봐야 하더라고요. 이걸 한 줄로 확인하는 방법이 깔끔했습니다.
grep -rn "encrypt(" src | grep -iE "resident|bank|account|jumin"
# 결과가 비면 → 그 PII는 평문 (암호화 유틸이 토큰만 감싸는 중)화면 쪽 함정도 있었어요. "어드민이니까 다 보여도 된다"가 틀린 가정이라는 점입니다. 전화·이메일도 운영진/어드민 화면에서 기본 마스킹(010-****-1234)이 원칙이고, 평문이 꼭 필요하면 재인증·접근로그·권한분리를 전제로만 잠깐 보여주라는 거죠. 거기에 "누가 언제 어떤 개인정보를 봤는지" 접속기록(안전성 확보조치 제8조)도 챙기라고 짚어줬습니다.
5. 그래서 어디부터 고치면 되나
점검의 진짜 결과물은 "위험하다"가 아니라 "어느 것부터"였어요. 그 보안 점검 스킬의 🔴/🟡/🟢에 맞춰 줄을 세웠습니다.
여기서 하나 배웠습니다. 교과서적 1순위(주민번호 평문·평문 비밀번호)가 없다고 안심할 게 아니라, "우리 서비스에서 털리면 제일 아픈 값"이 무엇인지로 1순위를 다시 잡아야 한다는 것. 우리 경우엔 주민번호가 한 줄도 없으니, 가장 먼저 손볼 자리는 인증·결제 토큰을 제대로 감싸는 쪽이더라고요.
6. Rona가 깔아준 것 vs 내가 실제로 바꾼 것 (갭)
만드는 사람으로서 진짜 보고 싶었던 건, 스킬이 깔아준 기본값과 내가 실제로 적용한 것 사이의 간격이었어요. 네 군데서 갈렸습니다.
하나씩 보면 — ①은 스킬이 "안전하게 붙일 수 있는 개발 DB"를 가정했는데 우리 건 실유저 prod라, 제안대로 행을 긁었으면 점검이 곧 유출이 됐을 거예요. ②가 제일 아찔했습니다. 스킬 기준의 P0(주민번호 평문)를 그대로 읽으면 "P0 없음, 안심"으로 끝났을 텐데, 정작 우리한테 더 중요한 인증·결제 토큰 쪽을 후순위로 둘 뻔했어요. ③은 스킬이 도구 설치를 전제했지만 제 환경엔 없어서 결국 못 돌렸고, ④는 사소하지만 제가 끌어와 바꾼 부분입니다.
네 갈림의 공통점은 하나예요. 스킬이 "일반적인 프로젝트"를 가정해 깔아준 기본값을, 우리 상황(실유저 prod · 없는 도구 · 실제 위험 분포)에 맞게 제가 덮어써야 했다는 것. 그리고 그 덮어쓰기가 가능했던 건 매 단계 "이대로 갈까요?"가 있었기 때문이에요. 자율주행이었다면 psql로 prod를 그냥 긁고 "P0 없음"으로 끝냈겠죠. 만드는 입장에서 수확은 분명했습니다 — 시작할 때 맥락을 캐묻는 질문(어떤 DB인지, 어떤 도구가 깔렸는지, 우리한테 제일 아픈 값이 뭔지)을 더 세게 넣으면, 이 네 개는 처음부터 다 잡혔을 거예요. 다음 버전에 손볼 지점이 명확해졌습니다.
7. 혹시 직접 해보실 분들께
개인정보를 등급(S1~S4)으로 먼저 갈라두기 — 그래야 "어디부터"가 안 흔들립니다
암호화 유틸이 PII까지 감싸는지 한 줄로 확인:
grep -rn "encrypt(" | grep -iE "resident|bank|token"어드민 화면이라도 전화·이메일 기본 마스킹
jsonb·메모 같은 자유 입력 칸은 값을 스캔해서 숨은 민감값 잡기
그리고 점검을 일회성으로 끝내지 않으려고, 같은 기준을 다시 돌리는 검토 프롬프트로 남겼어요. 클로드 코드에 이걸 붙이면 새 컬럼이 생겨도 같은 잣대로 다시 봅니다.
<task> 아래 스키마와 샘플값을 한국 개인정보보호법 기준으로 검토해
수정할 컬럼/값, 리스크 등급(P0~P3), 수정 방안을 표로 작성한다. </task>
<checklist>
1. S1/S2/S3/S4 분류 (컬럼명 말고 샘플값으로 확정)
2. 암호화 vs 단방향 해시 — 양방향 사용=암호화, 검증만=해시
3. 최소수집·보유기간·파기 / 접근권한·접속기록
4. 자유 입력(jsonb/memo)에 숨은 민감정보 가능성
</checklist>마무리
평소 기본은 챙긴다고 해도 한국 법 기준으로 제대로 까본 적은 없던 제가, 발행할 만한 점검 결과와 우선순위까지 간 건 Rona가 만들어준 가이드 덕이었어요. Rona가 제 일을 대신 해준 게 아니라, 알지만 매번 빠짐없이 적용하긴 어려운 절차와 법적 판단 틀을 쥐여줬고 저는 거기에 우리 DB 사정을 얹었습니다. "안다고 넘기기 쉬운 영역"일수록 이렇게 체계를 대신 깔아주는 값이 크더라고요. "우리 DB 괜찮나"가 막연히 불안한 분이라면, Rona로 점검 스킬을 하나 만들어 직접 까보시길 권합니다.