터미널 광고 프라이버시: 동의와 리댁션을 먼저 설계한 방법
터미널 광고 프라이버시는 나중에 덧붙인 기능이 아니라, 저희가 출발점으로 삼은 제약이에요. Tybre.md의 내장 터미널 안에서 맥락형 광고를 실험해보기로 했을 때 첫 질문은 '어떻게 돈을 버나'가 아니라 '개발자의 시크릿이 기기를 절대 떠나지 않게 어떻게 만드나'였어요. 이 글은 그 설계에 대한 엔지니어링 해설이에요. 왜 기본값이 꺼짐인지, 2단계 동의가 어떻게 동작하는지, 그리고 한 바이트라도 나가기 전에 로컬 Rust 리댁션이 시크릿을 ▮▮▮ 로 어떻게 가리는지요.
무엇보다 먼저 솔직한 부분이요. 이 시스템은 아직 돈을 주지 않아요. 수익 적립은 계획 단계이고 아직 라이브가 아니에요. 캐시아웃은 지원되지 않고, 지금 나가는 하우스 광고는 $0을 벌어요. 돈 쪽이 아직 뼈대뿐인 지금 아키텍처를 공개하는 건, 프라이버시 설계를 부업 미끼로 파는 게 아니라 그 자체의 가치로 검토받고 싶어서예요.
언제나 기본값은 꺼짐
터미널 광고 시스템은 비활성 상태로 배포돼요. 새로 설치하면 광고도 없고, 아무것도 보내지 않고, 아무것도 수집하지 않아요. 설정에 들어가 의도적으로 켜기 전까지는 광고 파이프라인의 어떤 것도 실행되지 않아요. 텔레메트리를 켜둔 채로 끄는 스위치를 찾게 만드는 업계 기본값과 정반대예요.
기본값 꺼짐은 어떤 단일 기술적 통제보다 중요해요. 아무 결정도 하지 않았을 때 얻는 상태가 곧 안전한 상태라는 뜻이니까요. 이 글을 읽지 않고, 설정을 열지 않고, 광고를 한 번도 생각하지 않은 사용자는 설계상 완전히 프라이빗해요. 아래 내용은 전부 '의도적으로 켠' 사람에게만 적용돼요.
묻어둔 체크박스 하나가 아니라 2단계 동의
기능을 켜는 건 환경설정 어딘가에 숨은 토글 하나가 아니에요. 두 번의 의도적 단계가 필요해요. 명시적으로 활성화하는 동작, 그리고 무엇이 수집되고 무엇이 수집되지 않는지 정확히 적어둔 별도의 확인이요. 둘 다 통과해야 뭔가가 켜져요.
일부러 둘로 나눴어요. 클릭 한 번은 실수로 하기 너무 쉽고, 실수로 줄 수 있는 동의는 동의가 아니니까요. 두 번째 단계는 데이터 수집이 시작될 수 있는 순간이 약관을 눈앞에 두고 명확히 선택한 순간이 되도록 존재해요. 어느 단계든 미완이면 시스템은 기본값인 침묵 상태로 남아요.
무엇이 나가기 전에, Rust로 로컬 리댁션
이 설계의 핵심은 리댁션이 '어디서' 일어나느냐예요. 전부 네이티브 Rust 레이어, 즉 여러분 기기 안에서, 어떤 네트워크 호출보다 먼저 일어나요. 원본을 보낸 뒤 서버에서 지우는 방식이 아니에요. 마스킹은 로컬에서 먼저 돌고, 오직 마스킹된 결과만 나갈 자격을 얻어요.
구체적으로, 리댁션 패스는 수집된 입력에서 시크릿처럼 보이는 것, API 키, 토큰, 자격증명 같은 고위험 문자열을 찾아 그 자리에서 ▮▮▮ 로 바꿔요. 파이프라인이 전송할 무언가를 갖게 될 즈음엔 민감한 부분 문자열은 이미 사라지고, 복구 불가능한 불투명 블록으로 대체돼요. PTY를 소유한 바로 그 레이어인 Rust에서 이걸 한다는 건, 리댁션이 렌더링 버그가 건너뛸 수 있는 JavaScript 뒷일이 아니라 모든 게 반드시 지나야 하는 경로 위에 놓인다는 뜻이에요.
이건 앱 나머지를 관통하는 로컬 우선 철학과 같아요. 로컬 우선 마크다운 노트 글에서 설명했듯 노트가 디스크에 머무는 것처럼, 광고 시스템은 여러분 기기를 신뢰 경계로 다뤄요. 그 경계의 안쪽에서 리댁션하는 게 핵심 전부예요.
제출한 입력 줄만, 키 입력도 출력도 아님
터미널은 많은 걸 봐요. 모든 걸 캡처하는 건, 즉 모든 키 입력, 모든 명령의 출력, 스크롤되는 모든 파일을 잡는 건 사소하지만 틀린 일이에요. 저희는 그걸 일부러 하나도 수집하지 않아요. 수집 대상이 될 수 있는 건 오직 여러분이 Enter를 눌러 실제로 제출한 명령 줄이에요.
- 키 입력 아님: 치다 만 입력, 백스페이스, 포기한 명령은 절대 캡처되지 않아요. 최종적으로 Enter로 제출한 줄만 고려돼요.
- 출력 아님: 명령이 찍는 것, 로그, 파일 내용, 프로그램 결과는 어떤 것도 파이프라인에 들어가지 않아요.
- 프롬프트에 친 비밀번호 아님: 에코되지 않는 대화형 프롬프트는 제출 줄 경로 밖에 완전히 있어요.
- 제출한 줄조차 로컬에서 먼저 리댁션돼요. 토큰이 담긴 Enter 제출 명령도 뭔가 움직이기 전에 그 토큰이
▮▮▮로 가려져요.
왜 이 모양이고, 아직 무엇이 없나
아키텍처가 이렇게 생긴 이유는 맥락 관련성에는 거의 아무것도 필요 없기 때문이에요. 예컨대 Claude Code를 쓰는 개발자에게 맞는 광고를 보여주려면, 시스템은 어떤 도구를 돌리는지에 대한 거친 신호만 있으면 되고, 그건 리댁션된 제출 명령 줄로 충분해요. 키 입력도, 출력도, 시크릿도 필요 없으니 하나도 수집하지 않아요. 넓게 수집하고 잘 처신하겠다 약속하는 것보다, 수집을 최소화하는 게 더 싸고 안전했어요.
무엇이 아직 만들어지지 않았는지도 똑같이 분명히 해요. 오늘 실제 돈을 주는 라이브 수익 원장은 없고, 캐시아웃 장치도 없으며, 순환 중인 광고는 $0을 버는 하우스 광고예요. 돈 쪽이 실제가 되는 날이 온다면, 프라이버시 쪽과 똑같이 다룰 거예요. 정직하게 설명할 수 있을 때에만 배포하는 거죠. 내부 구조보다 워크플로가 궁금한 분께는 Claude Code 마크다운 워크플로 가이드가 이 딥다이브의 실용 짝꿍이에요.
자주 묻는 질문
터미널 광고 시스템이 지금 돈을 벌어주나요?
아니요. 수익 적립은 계획됐지만 라이브가 아니고, 캐시아웃은 지원되지 않으며, 현재 하우스 광고는 $0을 벌어요. 프라이버시 아키텍처를 먼저 배포했고, 지급 쪽이 아직 없다는 걸 솔직히 말해요.
광고 시스템이 기본값으로 켜져 있나요?
아니요. 완전히 꺼진 채로 배포돼요. 2단계 동의로 의도적으로 켜기 전까지는 아무것도 수집·전송되지 않아서, 설정을 건드리지 않은 사용자는 완전히 프라이빗해요.
동의하면 정확히 무엇이 수집되나요?
Enter로 제출한 명령 줄만, 그것도 로컬 Rust 리댁션이 시크릿을 블록으로 가린 뒤에만이요. 키 입력, 명령 출력, 파일 내용, 프롬프트에 친 비밀번호는 절대 수집되지 않아요.
시크릿 리댁션은 어디서 일어나나요?
여러분 기기의 네이티브 Rust 레이어에서, 어떤 네트워크 요청보다 먼저요. 시크릿은 로컬에서 불투명 블록으로 대체돼서, 원본 민감 문자열은 애초에 기기를 떠나지 않아요.