Giting.
낮의 Giting

홈 · macOS · 메뉴바 앱 · 한글 입력 · 원격 데스크탑 · Tailscale · Swift

HangulSync 대표 이미지 f2d471a (2026-07-27, 전체 25커밋)
분석 리포트실측 정보적용점원문 README

ㅎㅏㄴㄱㅡㄹ 문제

맥에서 다른 맥으로 원격 접속해 한국어를 쳐 본 사람은 안다. 로컬 맥은 한글인데 원격 맥은 영문이면, 자소가 분리돼 ㅎㅏㄴㄱㅡㄹ 처럼 풀어진다. 반대면 한글을 치려던 키가 Command 단축키로 먹힌다. 원격 데스크탑의 오래된 통증이다.

HangulSync 는 그 하나를 겨눈다. 로컬 맥과 원격 맥의 한/영 입력 소스를 실시간으로 맞춰 문제를 없애는 macOS 메뉴바 앱이다. Jump Desktop, 화면 공유, TeamViewer, AnyDesk, RustDesk 등 원격 앱이 떠 있을 때만 작동한다.

릴리스를 받아 뜯어봤다

말이 아니라 실물을 봤다. v1.0.12 릴리스 zip 을 받아 열었다.

  • 1.1MB 네이티브 Swift 앱. macOS 13+, 메뉴바에만 상주(Dock 없음)
  • ⚠️ 서명이 adhoc 이고 TeamIdentifier 가 없다. 즉 공증이 안 됐다(spctl 이 rejected). Gatekeeper 가 처음엔 막으니 우클릭 열기가 필요하다
  • 로컬 네트워크 권한(Bonjour)과 접근성 권한(입력 소스 제어)을 준다

전송 경로가 영리하다

두 맥을 어떻게 잇느냐가 이 앱의 핵심이다. 세 경로를 상황에 맞게 쓴다.

  • 같은 네트워크: Bonjour 로 서로를 찾는다(가까우면 AWDL P2P Wi-Fi 포함)
  • 다른 네트워크: Tailscale 이 켜져 있으면 같은 tailnet 의 피어를 30초마다 찾아 직결한다
  • 둘 다 없으면: ntfy.sh 공개 릴레이로 잇는다. 단 페이로드는 CryptoKit 로 암호화한다(RelayCiphertext, salt "HangulSync relay v1")

Tailscale 을 쓰는 사람이라면 실제로는 tailnet 직결로 붙어 제3자 릴레이를 거치지 않는다. 주고받는 것도 "지금 한글이냐 영문이냐"라는 저민감 신호다.

작게, 그러나 보안을 의식했다

소스는 4,508줄로 작지만 짜임새가 있다. 네트워크·보안을 ProtocolSecurity·SecureIdentity·PairingRendezvous·RelayChannel 로 나눴고, 새 직접 연결은 사용자가 승인해야 붙으며, 원격에서 적용된 변경은 되쏘지 않는다(루프 방지). 테스트는 두 개뿐인데 하필 프로토콜 보안 테스트다. 저자 1인, 스타 30, 7월 이후 조용하지만 열린 이슈가 0이고 목적이 하나라, 방치보다 완성에 가깝다.

가져올 것과 주의

  • 맥에서 맥으로 원격 접속해 한국어를 치는 사람에게 정확히 맞는다. Tailscale 을 이미 쓰면 tailnet 직결이라 붙이기도 깔끔하다
  • ⚠️ 공증이 안 됐다. Gatekeeper 가 막으니 우클릭 열기(또는 quarantine 제거)가 필요하고, 접근성·로컬 네트워크 권한을 준다
  • ⚠️ Tailscale·Bonjour 가 없는 인터넷 경로에서는 ntfy.sh 공개 서비스를 거친다(내용은 암호화). 그 경로가 싫으면 Tailscale 을 켜 두면 된다
  • 입력을 대신 바꾸고 네트워크로 주고받는 앱이라, 오픈소스로 열어 볼 수 있다는 점이 신뢰의 근거다. 4,508줄이면 읽을 만하다

실측 정보

HEAD 커밋
f2d471a (2026-07-27, 전체 25커밋)
저자 / 이력
dongri 단독 · 생성 2026-07-23 · 나흘간 집중 개발 후 조용 · 태그 15개(v1.0.0~1.0.12) · 열린 이슈 0
규모
텍스트 4,508줄 · Swift 13파일(3,117줄) · 보안 테스트 2 · 단일 목적 유틸
푸는 문제
원격 데스크탑(Jump Desktop·화면공유·TeamViewer·AnyDesk·RustDesk 등)에서 로컬·원격 맥의 입력 소스가 어긋나 생기는 자소 분리 / 단축키 오작동
전송 경로
같은 망=Bonjour(AWDL P2P 포함) · 다른 망=Tailscale tailnet 피어 직결(30초 탐지) · 둘 다 없으면 ntfy.sh 공개 릴레이. 릴레이 페이로드는 CryptoKit 로 E2E 암호화(RelayCiphertext)
실측(릴리스 해부)
v1.0.12 zip 다운로드 → HangulSync.app 1.1MB, macOS 13+, LSUIElement(메뉴바 전용). 서명은 adhoc·TeamIdentifier 없음 → spctl rejected(공증 안 됨). 로컬 네트워크·접근성 권한 필요
안전장치
새 직접 연결은 사용자 승인 후에만 · 루프 방지(원격 적용 변경 재전파 안 함) · 원격 접속 중에만 작동(항상 켜기 옵션) · 보안 파일 분리(ProtocolSecurity·SecureIdentity·PairingRendezvous)
다국어
UI·문서 8개 언어(한·영·일·중간·중번·태·러·이)
라이선스
MIT © catgarret

적용점

  • 이럴 때 유용맥에서 맥으로 원격 접속해 한국어를 치는 사람에게 정확히 맞는다. 자소 분리·단축키 오작동이 실제 통증이라면 1.1MB짜리로 그걸 없앤다. Tailscale 을 이미 쓴다면 tailnet 직결이라 제3자 릴레이도 안 탄다.
  • 이럴 땐 부적합맥이 하나거나 원격 접속을 안 하면 쓸 일이 없다. Windows·Linux 는 대상이 아니다(macOS 전용). Tailscale·Bonjour 둘 다 없는 인터넷 경로에서는 ntfy.sh 공개 토픽을 거친다(내용은 암호화되지만 제3자 서비스 의존).
  • 먼저 볼 것⚠️ 공증이 안 돼 있다. Gatekeeper 가 막으니 우클릭 열기 또는 quarantine 제거가 필요하고, 접근성·로컬 네트워크 권한을 준다. 1인·30스타·7월 이후 조용한 소규모 프로젝트다(다만 이슈 0·목적 단일이라 '방치'보다 '완성'에 가깝다). 입력 소스를 대신 바꾸고 네트워크로 주고받는 앱이니 오픈소스라는 점(4,508줄, 코드 열람 가능)이 신뢰의 근거다.
◆ 도입 후보

이건 큰 프로젝트가 아니라 통증 하나를 정확히 겨눈 유틸이다. 맥에서 맥으로 원격 접속해 한국어를 치면 입력 소스가 어긋나 ㅎㅏㄴㄱㅡㄹ 로 자소가 분리되거나, 한글을 치려다 Command 단축키가 실행된다. HangulSync 는 두 맥의 한/영 상태를 실시간으로 맞춰 그걸 없앤다. 검수는 릴리스를 받아 직접 뜯었다. v1.0.12 zip 은 1.1MB 네이티브 Swift 앱이고, 메뉴바에만 상주하며 macOS 13+ 를 요구한다. 전송 경로가 영리하다. 같은 망이면 Bonjour, 다른 망이면 Tailscale tailnet 직결, 둘 다 없으면 ntfy.sh 공개 릴레이로 잇되 그 페이로드는 CryptoKit 로 암호화한다. 코드도 보안을 의식했다. ProtocolSecurity·SecureIdentity·PairingRendezvous 로 파일을 나눴고, 연결 승인·루프 방지가 있으며, 두 개뿐인 테스트가 하필 프로토콜 보안 테스트다. 걸리는 건 셋이다. 공증이 안 돼 Gatekeeper 가 처음에 막고(우클릭 열기 필요), 접근성·로컬 네트워크 권한을 주며, 저자 1인·30스타에 7월 이후 조용하다. 다만 열린 이슈 0에 목적이 단일이라 방치라기보다 완성에 가깝고, 4,508줄 오픈소스라 무엇을 하는지 열어 볼 수 있다. 판정은 도입 후보다. 맥 간 원격으로 한국어를 치는 사람에게 이건 지금 붙여 쓸 값이 있다. 공증·권한·소규모라는 조건만 알고 들이면 된다.

원문 README

아래는 catgarret/HangulSync 저장소의 README 원문입니다(GitHub 렌더, 수집 시점 기준). 저작권은 원 프로젝트에 있으며 원 저장소의 라이선스를 따릅니다. GitHub에서 보기

README 전문 펼치기

HangulSync

HangulSync

한국어 | English | 日本語 | 简体中文 | 繁體中文 | ไทย | Русский | Italiano

Platform Swift License

HangulSync는 원격 데스크탑 사용 중 발생하는 한글 자소 분리 (ㅎㅏㄴㄱㅡㄹ)를 줄이는 macOS 메뉴바 앱입니다.

로컬 Mac과 원격 Mac의 한·영 입력 상태를 동기화합니다. 같은 네트워크에서는 Bonjour로 서로를 찾고, 다른 네트워크에서는 Tailscale을 사용할 수 있습니다.

왜 필요한가요?

원격 데스크탑을 사용할 때 두 Mac의 입력 소스가 서로 달라질 수 있습니다. 로컬 Mac은 한글이고 원격 Mac은 영문이면 자소가 분리될 수 있습니다. 반대 상황에서는 입력 대신 Command 단축키가 실행될 수 있습니다. HangulSync는 두 Mac의 입력 소스를 맞춰 이런 문제를 줄입니다.

기능

  • 실시간 양방향 동기화 한·영 전환이 즉시 전파
  • 자동 탐지
    • 같은 네트워크: Bonjour 자동 탐지 (근거리에서는 AWDL P2P Wi-Fi 포함)
    • 다른 네트워크: **Tailscale**이 켜져 있으면 같은 tailnet의 피어를 30초마다 탐지
  • 언어 기준 대체 상대 Mac에 같은 입력기가 없으면 언어가 같은 입력기를 사용
  • 루프 방지 원격에서 적용된 변경은 재전파되지 않음
  • 가볍게 상주 메뉴바에서 제어, Dock 아이콘 표시/숨김 선택 가능, 로그인 시 자동 실행 지원
  • 다국어 UI 한국어, English, 日本語, 简体中文, 繁體中文, ไทย, Русский, Italiano
  • 원격 접속 중에만 작동 Jump Desktop, 화면 공유, Screens, TeamViewer, AnyDesk, RustDesk 등 원격 데스크탑 앱이 실행 중일 때만 동기화. 메뉴에서 항상 켜기로 변경 가능
  • 연결 승인 새 직접 연결은 사용자가 승인한 뒤에만 입력 상태를 주고받음
  • 암호화된 인터넷 릴레이 페어링된 Mac은 직접 연결이 없을 때 ntfy를 통해 종단간 암호화된 상태를 주고받음

설치 (두 Mac 모두)

빌드 없이 사용하려면 Releases에서 최신 HangulSync.zip을 받아 /Applications에 넣으세요. 첫 실행 시 앱을 우클릭한 뒤 열기를 선택하세요.

빌드된 HangulSync.app을 복사해도 됩니다.

git clone https://github.com/catgarret/HangulSync.git
cd HangulSync
./install.sh

Xcode Command Line Tools 필요 (xcode-select --install).

  1. 첫 실행 시 로컬 네트워크 접근 허용 팝업에서 반드시 허용
  2. 메뉴바 ⇄한 / ⇄A 아이콘 클릭 → 로그인 시 자동 실행 체크

첫 페어링과 Keychain 안내

  1. 두 Mac에서 HangulSync를 실행합니다.
  2. 두 Mac 중 한쪽에서만 자동으로 찾기를 누릅니다. 다른 Mac에서는 버튼을 누르거나 창을 열 필요 없이 앱만 실행해 두면 됩니다.
  3. 찾는 Mac에는 진행 상태가 표시되고, 다른 Mac에는 연결 승인창이 자동으로 나타납니다.
  4. 자동으로 찾지 못하면 어느 한쪽에서 초대 코드 만들기를 누릅니다. 자동 복사된 코드를 2분 안에 다른 Mac의 초대 코드 입력에 붙여 넣습니다.
  5. 양쪽에 표시된 6자리 코드가 같은지 확인한 뒤 양쪽에서 승인합니다. 이 기기를 계속 신뢰를 켜면 이후에는 다시 확인하지 않습니다. 다음 실행부터는 두 Mac에서 앱만 켜면 자동으로 다시 연결됩니다.
  6. macOS가 로그인 Keychain 접근을 요청하면 앱 이름이 HangulSync인지 확인합니다. 현재 Mac 로그인 암호를 입력하고 항상 허용 또는 허용을 선택합니다.

암호는 HangulSync 화면에 입력하는 것이 아니라 macOS Keychain 창에만 입력합니다. 취소하면 보안 페어링과 인터넷 릴레이가 작동하지 않습니다.

메뉴바 아이콘

표시 의미
⇄한 / ⇄A 동기화 중 (현재 입력: 한글/영문)
⏸한 / ⏸A 일시정지
흐린 아이콘 대기 중 (원격 세션 없음)

메뉴에서 연결된 Mac 수를 확인할 수 있습니다. 동기화 일시정지와 재개, 원격 앱 실행 중에만 동기화, 로그인 시 자동 실행, 앱 종료를 설정할 수 있습니다.

라이선스

MIT © dongri.me · AI 바이브코딩으로 만들었습니다.

의견

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

이것도 재봤습니다

전체 리포트 →