Giting.
낮의 Giting

홈 · Swift · macOS · 메뉴 막대 앱 · 스크린샷

comfyScreen 대표 이미지 b6498b4 (2026-10-16) · 첫 커밋 하나
분석 리포트실측 정보적용점

구조와 기능

ScreenshotRouter 는 macOS 메뉴 막대에 사는 작은 앱이다. 영역을 캡처하면 창이 뜨고, 미리 등록한 폴더 중 하나를 고르면 그곳에 저장한다.

  • 폴더 고르기: Cmd+1~9 로 바로, 또는 위아래 화살표와 Return
  • 저장한 이미지는 클립보드에도 복사된다(PNG 와 파일 경로 둘 다)
  • 같은 이름이 있으면 덮어쓰지 않고 번호를 붙인다
  • 한국어 · 영어 화면, 시스템 언어를 따라간다

소스는 7파일 1,078줄이고 외부 패키지가 없다. 화면은 SwiftUI, 창 띄우기와 폴더 고르기만 AppKit 이다.

comfyScreen 이 캡처 한 장을 어떻게 다루는지, 코드를 읽고 확인한 순서 그대로 Giting 이 다시 그린 그림입니다. 실제 앱 화면이 아니라 흐름을 옮긴 것이고, 「파일은 지금 어디에」는 그 순간 파일이 있는 폴더입니다. 두 경우를 눌러 보세요.

    파일은 지금 어디에
    시스템 스크린샷 폴더보통 바탕화면
    앱 임시 폴더저장 대기
    고른 폴더버그 제보/

    근거: 캡처 직후 원본을 앱 임시 폴더로 옮기고(CaptureFiles.stage), 새 캡처가 들어오면 저장 안 한 앞 캡처를 먼저 지운다(replacePending → discardPending). 앱을 다시 켤 때도 남은 캡처를 찾자마자 지운다(recover). 커밋 b6498b4 기준이며, 코드를 읽어 확인했고 실행해서 재현하지는 않았습니다.

    하이라이트

    할 일만 하는 코드

    화면을 직접 읽지 않는다. 캡처는 macOS 기본 명령 /usr/sbin/screencapture -i 를 불러서 하고, 시스템 스크린샷 폴더(com.apple.screencapture 설정, 없으면 바탕화면)를 지켜보다가 새 파일이 생기면 앱의 임시 폴더로 옮긴다. 소스 어디에도 URLSession · http · 소켓 같은 외부 통신 코드가 없다.

    키보드 감시는 한 조합만

    Cmd+Shift+4 를 잡으려고 손쉬운 사용 권한으로 키 입력 이벤트를 받는다. 이 권한은 모든 키를 볼 수 있어 조심스러운 권한인데, 코드(CaptureShortcutMonitor.swift, 44줄)는 키 코드 21 에 Cmd+Shift 가 눌린 경우만 가로채고 나머지는 그대로 돌려보낸다. 키를 저장하거나 기록하는 코드는 없다.

    저장 자체는 조심스럽다

    저장할 때는 대상 폴더에 복사가 끝난 다음에야 임시 파일을 지운다. 같은 이름이 있으면 번호를 붙여 피한다. 저장 버튼을 누른 캡처는 잃지 않는다.

    주의점

    저장하지 않은 캡처가 사라지는 것이 첫째 주의점이다. 새 캡처가 들어오면 앱은 원본을 시스템 스크린샷 폴더에서 자기 임시 폴더로 옮긴다(CaptureFiles.stage, renamex_np 로 이동). 그런데 다음 캡처가 들어오면 replacePending 이 먼저 discardPending 을 불러 저장하지 않은 앞 캡처 파일을 지우고, 앱을 다시 켤 때도 남은 캡처를 찾자마자(recover) 지운다(discardPending). 원본은 이미 옮겨졌으니 어디에도 남지 않는다. Esc 는 「저장하지 않고 창 숨기기」라서, 닫아 두고 다음 캡처를 찍으면 앞의 것이 사라진다. 설계 문서(DESIGN.md)는 「캡처를 순서대로 줄 세우고, 사용자 데이터를 지우지 않는다」고 적고 있어 코드와 다르다. 이 동작은 코드를 읽고 확인한 것이고 실행해서 재현하지는 않았다.

    설치 경로가 둘째 주의점이다. 저장소에 빌드된 ScreenshotRouter.app(실행 파일 977,856바이트)이 들어 있고, Install ScreenshotRouter.command 와 curl … | sh 원클릭 설치는 소스를 빌드하지 않고 이 파일을 복사해 실행한다. CI 는 빌드와 테스트만 확인하고 결과를 올리지 않으니, 이 파일이 공개된 소스로 만든 것인지 확인할 길이 없다. Giting 맥미니에서 소스를 직접 빌드해 보니 7.3초에 성공했고 크기는 976,032바이트로 거의 같았지만, 빌드는 매번 똑같은 바이트로 나오지 않아 같은지 다른지 단정할 수 없다.

    서명은 자체 서명(ad-hoc)이라 처음 실행할 때 Gatekeeper 를 「확인 없이 열기」로 넘겨야 하고, 그 뒤 화면 기록과 손쉬운 사용 두 권한을 준다. 그래서 이 앱은 소스로 직접 빌드해 쓰는 것을 권한다.

    설계 문서와 동작이 한 군데 다르다. DESIGN.md 는 시스템 Cmd+Shift+4 를 건드리지 않는다고 쓰지만, 손쉬운 사용 권한을 주면 앱이 그 단축키를 가로채 자체 캡처를 띄운다. 권한을 주지 않으면 메뉴 막대의 「영역 캡처」로만 쓴다.

    첫 커밋이 2026-10-16 하나뿐인 새 저장소라, 활동이나 이슈 응답 같은 운영 지표는 아직 없다. 이 리포트는 코드를 열어 본 기록이다.

    실측 정보

    HEAD 커밋
    b6498b4 (2026-10-16) · 첫 커밋 하나
    무엇
    macOS 메뉴 막대 앱 ScreenshotRouter. 영역 캡처 → 폴더 고르기 → 저장 + 클립보드 복사
    규모
    Swift 소스 7파일 1,078줄 · 테스트 7개 · 가장 큰 파일 RouterViews.swift
    의존성
    외부 패키지 없음(SwiftUI · AppKit)
    요구 환경
    Apple Silicon · macOS 14 이상
    권한
    화면 기록 · 손쉬운 사용(Cmd+Shift+4 감지)
    CI
    GitHub Actions: release 빌드 + 테스트 (빌드 결과는 올리지 않음)
    직접 빌드
    swift build -c release 7.3초 성공 (Giting 맥미니, 2026-10-16)

    적용점

    • 쓴다면캡처할 때마다 바로 폴더를 골라 저장한다. Esc 로 창만 닫고 다음 캡처를 찍으면 앞의 캡처가 사라진다(코드 기준). 설치는 git clone 후 swift build -c release 로 직접 빌드한다. 저장소의 ScreenshotRouter.app 이나 curl … | sh 원클릭 설치는 내가 확인할 수 없는 실행 파일을 깐다.
    • 이럴 때 유용캡처를 프로젝트 폴더마다 바로 나눠 담고 싶을 때. 스크린샷을 찍자마자 붙여 넣어야 하는 일(디자인 피드백, 버그 제보, AI 에게 화면 보여 주기)에 클립보드 복사까지 같이 된다.
    • 만드는 쪽이라면설계 문서대로 저장 안 한 캡처를 줄 세워 두고(지우지 말고) 하나씩 보여 주면 첫째 문제가 풀린다. 그리고 빌드된 앱은 저장소에서 빼고, CI 가 빌드한 결과를 릴리스로 올리면 설치 경로가 소스와 이어진다. 공증(Developer ID)까지 하면 Gatekeeper 안내도 필요 없다.
    • 설계 문서와 다른 곳DESIGN.md 는 「시스템 Cmd+Shift+4 동작을 그대로 둔다」고 쓰지만, 코드는 손쉬운 사용 권한이 있으면 그 단축키를 가로채 자체 캡처를 띄운다. 쓰는 사람이 알아 둘 차이다.
    ◈ 참고용

    참고용. 두 가지가 고쳐지면 도입 후보다. 스크린샷을 「일단 바탕화면에 쌓고 나중에 정리」하던 사람에게 딱 맞는 작은 도구이고, 코드가 그 일만 한다. 외부 통신 코드가 없고, 캡처는 시스템 screencapture 를 부르고, 키보드 감시는 Cmd+Shift+4 하나만 가로채 나머지는 그대로 흘려보낸다. 걸리는 건 둘이다. 첫째, 코드대로라면 저장하지 않은 캡처는 다음 캡처가 들어오거나 앱을 다시 켤 때 지워진다. 캡처 직후 원본을 시스템 폴더에서 옮겨 오기 때문에 어디에도 남지 않는다. 둘째, 설치다. 원클릭 설치가 저장소에 들어 있는 빌드된 앱을 그대로 깔고, 그 파일은 CI 가 만든 것이 아니라 소스와 같은지 확인할 길이 없다. 서명도 자체 서명이라 Gatekeeper 를 넘겨야 한다. 소스로 빌드하면 7초면 되니 그쪽을 권한다.

    의견

    판정에 대한 반론, 도입 경험, 정정 제보를 환영합니다. GitHub 계정으로 참여합니다.

    이것도 재봤습니다

    전체 리포트 →