본문으로 건너뛰기
강홍재/ James
← Work
Live2026 · Solo Builder· Started(First Commit date)

Sheen

키보드를 잠그고 닦고, 화면을 단색으로 채워 지문·먼지·데드픽셀을 드러내는 맥북 청소용 메뉴바 앱 - 권한 요청·데이터 수집 없이 샌드박스로 Mac App Store 출시.

  • Swift 6
  • AppKit / SwiftUI
  • macOS Menu Bar
  • Mac App Store
  • Zero-permission / Sandboxed
스크린샷
  • 키보드 잠금 - "닦는 동안 키가 입력되지 않습니다. 트랙패드는 그대로." 언제든 해제, 60초 자동 해제로 갇히지 않는다

  • 화면 청소 모드 - 화면을 단색으로 덮어 지문·먼지·데드픽셀을 드러낸다. 하단 6가지 검사 색을 순환

  • 물 쏟음 응급(보너스) - "SHUT DOWN NOW"를 최상단에 크게, 나머지 절차(분리·뒤집어 배수·건조)를 한 화면에 몰아 끄기 전에 읽도록. 안내일 뿐 전원을 대신 꺼주지는 않는다

Setup

Problem

맥북 키보드를 닦으려면 키가 눌려 엉뚱한 입력이나 명령이 실행된다. 화면 지문·먼지는 조명 각도를 바꿔야 겨우 보이고, 음료를 쏟으면 당황해 대처 순서를 놓쳐 메인보드까지 손상된다.

Context

개인적으로 자주 겪던 불편에서 시작. 다만 "키보드 잠금" 자체는 이미 무료 도구(KeyboardCleanTool 등)로 완벽하게 되는 5초짜리 기능이라, 잠금을 더 잘 만드는 방향으로는 이길 수 없다고 봤다. 그래서 카테고리를 "키보드 락커"에서 "맥북 청소 리추얼"로 옮기고, 잠금을 입구로 그 주변의 진짜 니즈(화면 청소·위생 습관·물 쏟음 응급)를 하나로 묶었다.

Build

What I did
  • 키보드 잠금 청소 - 전체화면 오버레이가 키 입력을 삼켜(로컬 NSEvent 모니터) 닦는 동안 어떤 키도 입력되지 않게. 트랙패드·마우스는 살아 있어 항상 해제 가능, Esc 1.5초 길게 누르기 탈출구, 60초 자동 해제로 절대 갇히지 않게
  • 화면 청소 모드 - 모든 디스플레이를 단색으로 덮어 지문·먼지·데드픽셀을 드러냄. 6가지 검사 색을 순환(각 색이 무엇을 드러내는지 라벨), 자동 숨김 툴바
  • 청소 스트릭 + 주간 리마인더 - 잠금·화면청소 세션마다 스트릭이 쌓이고(메뉴바에 표시), 선택적 주간 알림으로 습관화
  • 물 쏟음 응급 안내(보너스) - 한 번의 탭으로 젖어 오작동하는 키보드를 봉인하고, "SHUT DOWN NOW"를 최상단에 크게, 나머지 절차(분리·뒤집어 배수·건조)를 한 화면에 노출
  • 권한 제로 · 샌드박스 - 접근성·입력 모니터링 프롬프트 없이 동작(주간 알림 켤 때만 표준 알림 권한). 데이터 수집·네트워크·계정 전부 없음
Product decisions
  • "키보드 잠금"을 히어로가 아니라 입구로 - 잠금은 이미 무료로 완벽하게 되는 기능이라 이걸로는 못 이긴다고 보고, 화면 청소·습관·응급을 묶어 "맥북 청소는 이 앱 하나"로 카테고리를 옮겼다
  • 물 쏟음 응급을 히어로에서 보너스로 강등(2026-07-08 결정) - 패닉 중에 메뉴바 앱을 여는 동선이 비현실적이고, 샌드박스라 실제 전원 종료는 못 하고 안내만 가능하다는 두 가지 이유. 대신 일상 청소(잠금+화면청소+습관)를 전면에 두되, 스필이 가장 강한 차별점이었던 만큼 해자가 얕아지는 리스크를 스스로 문서에 기록했다
  • "절대 갇히지 않는다"를 잠금 UX의 1원칙으로 - 트랙패드 유지 + Esc 길게 누르기 + 60초 자동 해제, 세 겹의 탈출 경로
  • 응급 화면은 "켜둔 채로 읽게 만들면 안 된다"가 설계 원칙 - 초기엔 4단계 페이지네이션이었지만 그건 "화면 보며 대기"를 유도해 자기모순이라, SHUT DOWN NOW를 압도적으로 크게 최상단에 두고 나머지를 한 화면에 몰아 끄기 전 2초 안에 읽도록 재설계
  • 유료 단독 1회 구매 4,400원($4.99) - 무료판·구독·IAP 없이 구매=전 기능. 청소 유틸리티엔 구독이 부적합하다고 보고 소액 1회로
QA considerations
  • 키 삼킴 완전성 - 오버레이 활성 중 어떤 키도 뒤 앱으로 새지 않아야 함(accessory 포커스 누락 회귀 포함해 실측)
  • 갇힘 방지 3중 안전장치(트랙패드 유지 · Esc 롱프레스 · 60초 자동 해제)가 각각 독립적으로 동작하는가
  • 앱이 예기치 않게 종료돼도 키보드 잠금이 남지 않고 항상 풀리는가(fail-safe)
  • 다중 디스플레이에서 화면 청소 오버레이가 모든 화면을 덮고 6색 순환이 정확한가
  • 권한·샌드박스 경계 - 접근성/입력 모니터링 요청 0건, 샌드박스 컨테이너 생성·크래시 없음까지 실증

Outcome

Metrics
  • Mac App Store 정식 출시 - Utilities, macOS 13+, 4+, 유료 1회 구매 4,400원($4.99)
  • 권한 요청 0개 · 샌드박스 · 데이터 수집·네트워크·계정 없음
  • 앱 용량 346.7 KB, 메뉴바 전용(Dock 아이콘 없음)
  • 출시 직후 - 리뷰·판매·전환 지표는 측정 전

진행 과정 (기획 → 개발)

문제·가설에서 스코프·스펙(SSOT)·개발·QA 게이트·배포까지, 같은 틀로 이 앱을 어떻게 기획하고 끌고 갔는지.

문제 · 가설

맥북 키보드를 닦을 때 키가 눌리는 문제에서 출발. 다만 시장을 냉정하게 봤다 - 키보드 잠금은 이미 무료 도구로 완벽하게 되는 5초짜리 기능이라, 잠금 품질로는 못 이긴다. 그래서 "잠금을 입구로, 그 주변의 진짜 니즈(화면 청소·위생 습관·물 쏟음)를 묶는다"로 가설을 다시 세우고, 카테고리를 "키보드 락커"에서 "맥북 청소 리추얼"로 옮겼다.

역량 · 문제 정의 · 가설

스코프 · 우선순위

화면 청소(메인 차별화)·키보드 잠금(안전 탈출)·위생 스트릭·물 쏟음 응급(보너스) 네 각으로 우선순위를 매겼다. 출시 직전 물 쏟음을 히어로에서 보너스로 강등하는 리포지셔닝을 감행했고, 가장 강한 차별점을 낮추는 리스크를 문서에 남겨 스스로 추적하게 했다.

역량 · 스코핑 · 우선순위

스펙 우선 (SSOT)

SSOT.md를 코드보다 먼저 두고, 제품 방향이 바뀌면 코드가 아니라 이 문서를 먼저 고치는 규칙으로 운영. 포지셔닝·과금·배포 제약·비목표까지 "결정(RESOLVED)"과 "열린 질문"으로 나눠 적어, 혼자여도 결정이 흐트러지지 않게 했다.

역량 · 스펙 · 문서화

개발 · 이터레이션

Swift 6, XcodeGen(project.yml → .xcodeproj) 단일 빌드. AppKit 메뉴바(NSStatusItem)에 SwiftUI 오버레이를 얹은 accessory 앱. 잠금·화면청소·응급이 모두 같은 전체화면 오버레이 구조를 공유하도록 설계해 코드와 UX를 한 틀로 묶었다.

역량 · 실행 · 전달

검증 (QA 게이트)

잠금 UX의 1원칙을 "절대 갇히지 않는다"로 두고 트랙패드 유지·Esc 탈출·60초 자동 해제 세 겹을 검증. 로컬 모니터가 키를 실제로 삼키는지(accessory 앱의 포커스 누락으로 키가 새던 버그)를 실측으로 잡아 활성화 전환으로 막았다. 샌드박스 적격성은 서명 빌드가 컨테이너를 생성하며 크래시 없이 도는 것까지 확인.

역량 · 품질 · 리스크

배포

샌드박스 엔타이틀먼트(app-sandbox 하나)만으로 서명·노터라이즈 후 Mac App Store에 유료 단독 4,400원($4.99)으로 출시. 스토어 첫 스크린샷을 키보드 잠금·화면 청소로 잡아 "무료로 충분한데?"에 대한 답을 첫 화면에서 보이게 했다.

역량 · 릴리스

Tech stack
  • Swift 6
  • AppKit (NSStatusItem)
  • SwiftUI (overlays)
  • NSEvent local monitor
  • UserNotifications
  • XcodeGen
  • App Sandbox (Mac App Store)