Skip to content

Latest commit

Β 

History

History
136 lines (93 loc) Β· 6.2 KB

File metadata and controls

136 lines (93 loc) Β· 6.2 KB

μ•± μžλ™ 전달 μ •μ±…

λͺ©ν‘œ

MVP의 μžλ™ 전달은 λͺ¨λ“  앱에 λŒ€ν•œ μ™„μ „ν•œ λ„€μ΄ν‹°λΈŒ 연동이 μ•„λ‹ˆλΌ, 캑처 이미지λ₯Ό ν΄λ¦½λ³΄λ“œμ— λ³΅μ‚¬ν•œ λ’€ λŒ€μƒ 앱에 λΆ™μ—¬λ„£κΈ° 이벀트λ₯Ό λ³΄λ‚΄λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•œλ‹€.

κΈ°λ³Έ 방식

μžλ™ 전달 μˆœμ„œ:

  1. 캑처 이미지λ₯Ό NSPasteboard에 λ³΅μ‚¬ν•œλ‹€.
  2. 섀정이 μ €μž₯ 및 전달이면 캑처 이미지λ₯Ό μ €μž₯ν•œλ‹€.
  3. μ„€μ •μ˜ 전달 λŒ€μƒ 방식에 따라 λŒ€μƒμ„ κ²°μ •ν•œλ‹€.
  4. 맀번 μ•± 선택이면 μ‹€ν–‰ 쀑인 μ•± λͺ©λ‘κ³Ό μœˆλ„μš° λͺ©λ‘μ„ 보여주고 μ‚¬μš©μžκ°€ λŒ€μƒμ„ μ„ νƒν•œλ‹€.
  5. κ°€μž₯ 졜근 μ‚¬μš© 앱이면 캑처 μ‹œμž‘ 직전에 ν™œμ„±ν™”λ˜μ–΄ 있던 앱을 λŒ€μƒμœΌλ‘œ μ‚¬μš©ν•œλ‹€.
  6. μ§€μ •ν•œ 앱이면 섀정에 μ €μž₯된 앱을 λŒ€μƒμœΌλ‘œ μ‚¬μš©ν•œλ‹€.
  7. Traceκ°€ λŒ€μƒ μ•± λ˜λŠ” μ„ νƒν•œ μœˆλ„μš°λ₯Ό ν™œμ„±ν™”ν•œλ‹€.
  8. κ°€μž₯ 졜근 μ‚¬μš© μ•±μ—μ„œλŠ” 별도 μœˆλ„μš° 선택 없이 μ•± 전체 ν™œμ„±ν™”λ₯Ό μˆ˜ν–‰ν•œλ‹€.
  9. μ§€μ •ν•œ μ•±μ—μ„œλŠ” 섀정에 따라 κ°€μž₯ 졜근 μ‚¬μš© μœˆλ„μš°λ₯Ό ν™œμ„±ν™”ν•˜κ±°λ‚˜ μ§€μ • μ•±μ˜ μœˆλ„μš° 선택 창을 ν‘œμ‹œν•œλ‹€.
  10. Traceκ°€ λΆ™μ—¬λ„£κΈ° 이벀트λ₯Ό 보낸닀.
  11. μ €μž₯된 μΊ‘μ²˜κ°€ 있으면 전달 κ²°κ³Όλ₯Ό νžˆμŠ€ν† λ¦¬μ— κΈ°λ‘ν•œλ‹€.

전달 λŒ€μƒ 방식

μ„€μ •μ˜ deliveryTargetMode κ°’:

  • chooseEachTime: 캑처 ν›„ μ•±/μœˆλ„μš° 선택 창을 ν‘œμ‹œν•œλ‹€.
  • mostRecentApp: 캑처 μ‹œμž‘ μ§μ „μ˜ μ „λ©΄ 앱을 κΈ°μ–΅ν–ˆλ‹€κ°€ 선택 μ°½ 없이 ν•΄λ‹Ή μ•±μœΌλ‘œ μ „λ‹¬ν•œλ‹€.
  • fixedApp: 섀정에 μ €μž₯된 μ•±μœΌλ‘œ λ°”λ‘œ μ „λ‹¬ν•œλ‹€.

mostRecentApp은 μžλ™ μΆ”μ²œμ΄ μ•„λ‹ˆλΌ μ‚¬μš©μžκ°€ μ„€μ •μ—μ„œ λͺ…μ‹œμ μœΌλ‘œ μ„ νƒν•˜λŠ” κ³ μ • λ™μž‘μ΄λ‹€. 캑처 μ‹œμž‘ 직전 μ „λ©΄ 앱이 Trace μžμ‹ μ΄κ±°λ‚˜ 일반 앱이 μ•„λ‹ˆλ©΄ 전달 μ‹€νŒ¨λ‘œ μ²˜λ¦¬ν•œλ‹€.

fixedApp은 μ‚¬μš©μžκ°€ μ„€μ •μ—μ„œ 앱을 λͺ…μ‹œμ μœΌλ‘œ μ €μž₯ν•΄μ•Ό ν•œλ‹€. μ§€μ • 앱이 μ‹€ν–‰ 쀑이지 μ•ŠμœΌλ©΄ 앱을 μžλ™ μ‹€ν–‰ν•˜μ§€ μ•Šκ³  μ‹€νŒ¨ μ•Œλ¦Όμ„ 보낸닀.

μ§€μ • μ•±μ˜ μœˆλ„μš° 처리 방식:

  • mostRecentWindow: μ§€μ • μ•±μ˜ main windowλ₯Ό μš°μ„  ν™œμ„±ν™”ν•˜κ³ , μ—†μœΌλ©΄ μ•± 전체 ν™œμ„±ν™”λ‘œ λΆ™μ—¬λ„£κΈ°λ₯Ό 보낸닀.
  • chooseWindow: μ§€μ • μ•±μ˜ μœˆλ„μš° 선택 창을 ν‘œμ‹œν•œλ‹€.

λŒ€μƒ μ•± λͺ©λ‘

λŒ€μƒ μ•± λͺ©λ‘μ€ NSWorkspace의 μ‹€ν–‰ 쀑인 μ•± λͺ©λ‘μ„ κΈ°μ€€μœΌλ‘œ λ§Œλ“ λ‹€.

ν‘œμ‹œ κΈ°μ€€:

  • μ•± 이름이 μžˆλŠ” ν•­λͺ©λ§Œ ν‘œμ‹œν•œλ‹€.
  • λ°±κ·ΈλΌμš΄λ“œ μ „μš© ν”„λ‘œμ„ΈμŠ€λŠ” μ œμ™Έν•œλ‹€.
  • Trace μžμ‹ μ€ μ œμ™Έν•œλ‹€.
  • μ•± μ•„μ΄μ½˜κ³Ό μ•± 이름을 ν•¨κ»˜ ν‘œμ‹œν•œλ‹€.
  • ν˜„μž¬ ν™œμ„± 앱은 μš°μ„  ν‘œμ‹œν•  수 μžˆλ‹€.

λŒ€μƒ μœˆλ„μš° λͺ©λ‘

κΈ°λ³Έ 전달은 Accessibility API둜 μ„ νƒν•œ μ•±μ˜ μœˆλ„μš° λͺ©λ‘μ„ 읽어 μ‚¬μš©μžκ°€ 뢙여넣을 μœˆλ„μš°λ₯Ό κ³ λ₯΄κ²Œ ν•œλ‹€.

ν‘œμ‹œ κΈ°μ€€:

  • μš°μ„  Core Graphics μœˆλ„μš° λͺ©λ‘μœΌλ‘œ μ‹€μ œ 화면에 λ–  μžˆλŠ” 일반 μœˆλ„μš°λ₯Ό ν‘œμ‹œν•œλ‹€.
  • ν˜„μž¬ Space뿐 μ•„λ‹ˆλΌ ν˜„μž¬ μ‚¬μš©μž μ„Έμ…˜μ˜ λ‹€λ₯Έ Space에 μžˆλŠ” 일반 μœˆλ„μš°λ„ ν‘œμ‹œν•œλ‹€.
  • 각 λ³΄μ΄λŠ” μœˆλ„μš°λŠ” Accessibility hit-test둜 μ‘°μž‘ κ°€λŠ₯ν•œ μœˆλ„μš°μ™€ λ‹€μ‹œ 연결을 μ‹œλ„ν•œλ‹€.
  • Accessibilityκ°€ μΆ”κ°€λ‘œ λ…ΈμΆœν•œ μˆ¨μ€ μœˆλ„μš°λ„ μ€‘λ³΅λ˜μ§€ μ•Šκ²Œ λ³΄κ°•ν•œλ‹€.
  • 제λͺ©μ΄ μ—†λŠ” μœˆλ„μš°λ„ 선택할 수 있게 λŒ€μ²΄ 이름을 λΆ€μ—¬ν•œλ‹€.
  • 제λͺ©μ΄ μ—†λŠ” μœˆλ„μš°λŠ” λ‚΄λΆ€ 보쑰 창이 μ„žμ΄κΈ° μ‰¬μš°λ―€λ‘œ, λ„ˆλ¬΄ μž‘κ±°λ‚˜ 사싀상 투λͺ…ν•œ 창은 μ œμ™Έν•œλ‹€.
  • ν™”λ©΄ 기둝 κΆŒν•œμ΄ 있으면 ScreenCaptureKit으둜 각 μœˆλ„μš° 썸넀일을 생성해 선택 화면에 ν•¨κ»˜ ν‘œμ‹œν•œλ‹€.
  • ν˜„μž¬ 메인 μœˆλ„μš°λŠ” μš°μ„  ν‘œμ‹œν•œλ‹€.
  • μœˆλ„μš°λ³΄λ‹€ 더 κΉŠμ€ λŒ€μƒμ€ λ²”μš© κ·œμΉ™μœΌλ‘œ 닀루지 μ•Šκ³ , 앱별 전달 μ–΄λŒ‘ν„°κ°€ μ œκ³΅ν•  λ•Œλ§Œ ν‘œμ‹œν•œλ‹€.

κΆŒν•œ

μžλ™ μ „λ‹¬μ—λŠ” Accessibility κΆŒν•œμ΄ ν•„μš”ν•˜λ‹€. κΆŒν•œμ΄ μ—†μœΌλ©΄ λŒ€μƒ μ•± ν™œμ„±ν™”μ™€ λΆ™μ—¬λ„£κΈ° 이벀트 전솑을 μ‹œλ„ν•˜μ§€ μ•ŠλŠ”λ‹€.

κΆŒν•œμ΄ 없을 λ•Œμ˜ λ™μž‘:

  • μ „λ‹¬μš© ν΄λ¦½λ³΄λ“œλŠ” μœ μ§€ν•œλ‹€.
  • 섀정이 μ €μž₯을 ν¬ν•¨ν•˜λ©΄ μ €μž₯은 μœ μ§€ν•œλ‹€.
  • μ•± 전달 흐름에 처음 λ“€μ–΄κ°ˆ λ•Œ macOS μ†μ‰¬μš΄ μ‚¬μš© κΆŒν•œ μš”μ²­μ„ νŠΈλ¦¬κ±°ν•œλ‹€.
  • Trace 자체 κΆŒν•œ μ•ˆλ‚΄ 창은 ν‘œμ‹œν•˜μ§€ μ•ŠλŠ”λ‹€.
  • μ €μž₯된 μΊ‘μ²˜κ°€ 있으면 deliveryStateλŠ” failed둜 κΈ°λ‘ν•œλ‹€.

κ²°κ³Ό μƒνƒœ

deliveryState κ°’:

  • none: κΈ°λ³Έ 캑처 λͺ¨λ“œ
  • skipped: μ‚¬μš©μžκ°€ λŒ€μƒ μ•± 선택을 κ±΄λ„ˆλœ€
  • delivered: λŒ€μƒ μ•± ν™œμ„±ν™”μ™€ λΆ™μ—¬λ„£κΈ° 이벀트 전솑을 μ™„λ£Œν•¨
  • failed: κΆŒν•œ λΆ€μ‘±, μ•± ν™œμ„±ν™” μ‹€νŒ¨, 이벀트 전솑 μ‹€νŒ¨

deliveredλŠ” λΆ™μ—¬λ„£κΈ° 이벀트λ₯Ό μ„±κ³΅μ μœΌλ‘œ λ³΄λƒˆλ‹€λŠ” λœ»μ΄λ‹€. λŒ€μƒ μ•± λ‚΄λΆ€μ—μ„œ 이미지가 μ‹€μ œλ‘œ μ²¨λΆ€λ˜μ—ˆλŠ”μ§€κΉŒμ§€ 100% 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

μ‹€νŒ¨ 처리

μ‹€νŒ¨λ‘œ κΈ°λ‘ν•˜λŠ” 경우:

  • Accessibility κΆŒν•œμ΄ μ—†μŒ
  • λŒ€μƒ 앱이 이미 μ’…λ£Œλ¨
  • κ°€μž₯ 졜근 μ‚¬μš© 앱을 찾을 수 μ—†μŒ
  • μ§€μ • 앱이 μ„€μ •λ˜μ§€ μ•ŠμŒ
  • μ§€μ • 앱이 μ‹€ν–‰ 쀑이지 μ•ŠμŒ
  • λŒ€μƒ μ•± ν™œμ„±ν™” μ‹€νŒ¨
  • λΆ™μ—¬λ„£κΈ° 이벀트 전솑 μ‹€νŒ¨

μ‹€νŒ¨ μ‹œ μ‚¬μš©μžμ—κ²Œ μ œκ³΅ν•  행동:

  • 직접 λΆ™μ—¬λ„£κΈ° μ•ˆλ‚΄
  • Finderμ—μ„œ 파일 보기

MVP 검증 λŒ€μƒ μ•±

MVPμ—μ„œλŠ” λŒ€ν‘œ μ•±μ—μ„œ λΆ™μ—¬λ„£κΈ° 기반 전달을 κ²€μ¦ν•œλ‹€.

μš°μ„  λŒ€μƒ:

  • Slack
  • Notion
  • TextEdit
  • Mail

λŒ€μƒ μ•±λ§ˆλ‹€ λΆ™μ—¬λ„£κΈ° 수용 방식이 λ‹€λ₯Ό 수 μžˆμœΌλ―€λ‘œ, μžλ™ 전달은 앱별 μ»€μŠ€ν…€ κ·œμΉ™ 없이 best-effort λ°©μ‹μœΌλ‘œ 닀룬닀.

앱별 전달 μ–΄λŒ‘ν„°

MVP 이후 ν™•μž₯의 첫 μ˜ˆμ™Έλ‘œ cmuxλŠ” μ „μš© μ–΄λŒ‘ν„°λ₯Ό λ‘”λ‹€.

  • κΈ°λ³Έ μ•± 전달은 macOS μœˆλ„μš°κΉŒμ§€λ§Œ μ„ νƒν•œλ‹€.
  • cmuxλŠ” 자체 CLIλ₯Ό μ‚¬μš©ν•΄ window -> workspace -> pane -> surface 계측을 μ½λŠ”λ‹€.
  • cmux λŒ€μƒ 선택 ν™”λ©΄μ—λŠ” surface λ‹¨μœ„ λŒ€μƒμ„ μΆ”κ°€λ‘œ ν‘œμ‹œν•œλ‹€.
  • μ‚¬μš©μžκ°€ surfaceλ₯Ό κ³ λ₯΄λ©΄ Traceκ°€ cmux CLI의 surface.focusλ₯Ό ν˜ΈμΆœν•œ λ’€ λΆ™μ—¬λ„£κΈ°λ₯Ό 보낸닀.
  • cmux CLIλ₯Ό 찾을 수 μ—†κ±°λ‚˜ socket 접근이 λ§‰ν˜€ 있으면 μ „μš© λŒ€μƒμ€ ν‘œμ‹œν•˜μ§€ μ•Šκ³ , κΈ°λ³Έ μœˆλ„μš° μ„ νƒλ§Œ μœ μ§€ν•œλ‹€.

MVP 이후 ν™•μž₯

  • 자주 μ“°λŠ” μ•± 즐겨찾기
  • μΆ”κ°€ 앱별 전달 μ–΄λŒ‘ν„°
  • νŠΉμ • μ•±μ˜ 첨뢀 API λ˜λŠ” URL scheme 연동
  • 전달 성곡 μ—¬λΆ€λ₯Ό μ•±λ³„λ‘œ 더 μ •ν™•νžˆ ν™•μΈν•˜λŠ” 방식