C.W.K.
Stream
Lesson 05 of 05 · published

앞으로 안 나오던 윈도우

~12 min · bare-binary, macos, foreground, war-story, dev-loop

Level 0툴 임차인
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"앱이 띄워졌어. 윈도우가 나타났고. 근데 dock 아이콘 없고, app switcher 에 아무것도 없고, 절대 앞에 안 왔어. 앱은 멀쩡했어 — 그냥 앱으로 등록이 안 됐을 뿐."

세 가지 증상

개발 중, native 윈도우가 열렸어 — 근데 연결된 세 방식으로 틀리게. dock 에 아이콘 없음. 애플리케이션 switcher 에서 빠짐. 그리고 절대 frontmost 안 됨: 터미널 뒤에 열렸고, 키 입력이 전에 focus 있던 앱으로 계속 라우팅. 세 증상, 한 원인, 그리고 원인이 앱 코드에 전혀 없었어. 앱은 올바랐어; 띄워지는 방식이 문제였어.

bare 바이너리는 앱이 아니야

개발 명령이 bare 실행파일 — 원시 바이너리 파일 — 을 빌드하고 돌려, 제대로 된 application bundle(운영체제가 '앱' 으로 인식하는 구조화된 폴더)이 아니라. OS 가 그 둘을 아주 다르게 다뤄. bundle 은 시스템의 launch services 에 정상적인, foreground-가능 애플리케이션으로 등록돼. bare 바이너리는 그걸 다 건너뛰어: OS 가 그걸 진짜 앱으로 절대 등록 안 해서, dock 존재 없고, switcher 항목 없고, 앞에 올 정상 권리가 없어.

프로그램이 어떻게 포장되냐가 코드와 무관하게 OS 가 그걸 어떻게 다루는지 바꿔. 같은 컴파일된 로직이 OS 가 그걸 등록된 애플리케이션으로 보냐 느슨한 바이너리로 보냐에 따라 다르게 행동해. 행동이 틀린데 코드가 옳아 보이면, 포장이랑 launch 경로를 의심해 — 코드 자체가 아니라 코드 둘레의 환경.

왜 framework 자기 설정이 안 도왔는지

자연스러운 해법은 앱의 activation policy 를 framework 설정으로 'regular'(foreground 앱)로 설정하는 거야. 근데 여기 함정: 그 framework 레벨 설정이 launch 모양이 bare 바이너리일 때 라이브 애플리케이션 객체로 전파 안 됐어. 설정이 제대로 된 bundle 맥락 안에서 도는 걸 가정해; 그 맥락 밖에선, 조용히 효력 발휘에 실패해. 설정은 올바랐고 그래도 안 됐어, 의존하는 전제조건이 거기 없었으니까.

올바른 설정이 전제조건 없으면 조용히 실패할 수 있어. 설정은 자주 맥락을 가정해 — bundle, 초기화된 subsystem, 특정 launch 경로. 그 맥락이 없으면, 설정이 에러 안 내; 그냥 안 먹어. 가장 헷갈리는 버그는 종이엔 옳지만 의존하는 게 없어서 무력한 설정이야. 설정만 말고 전제조건을 확인해.

두 진짜 해법

나가는 길이 둘이야. 직접적인 거: framework 아래 시스템 레이어에서, activation policy 를 'regular' 로 강제하고 앱을 명시적으로 앞으로 가져오는 native 호출을 해 — 전파 안 되던 framework 설정을 우회하는. 다른 거: bare 바이너리 띄우기를 멈추고 진짜 application bundle 을 빌드해서, 그걸 돌려, OS 가 처음부터 제대로 등록하게. 첫째는 dev 루프를 제자리에서 고치고; 둘째는 dev artifact 가 진짜 것과 맞게 해.

증상을 제자리에서 고치거나 artifact 를 프로덕션이랑 맞게 고칠 수 있어. dev 전용 shortcut 이 버그를 일으키면, shortcut 둘레로 패치(native 호출)하거나 shortcut 제거하고 진짜 artifact(bundle)를 쓸 수 있어. 둘 다 유효해; 선택은 빠른 제자리 수정이랑 애초에 놀라게 한 dev-vs-진짜 틈 닫기 사이야.

틀린 knob 에 먼저 손 뻗지 마

이런 혼란 하에, 관련 들리는 모든 설정 flag 를 시도하고 싶어 — 이거 force-focus, 저거 always-on-top. 근데 그건 근본 원인(앱이 등록된 앱이 아님)을 다루지 않고, 그중 적어도 하나는 적극적으로 더 나쁘게 만들어: always-on-top 강제가 기존 문제 위에 키보드 focus 를 깰 수 있어. 규율은 그걸 덮기만 하는 cosmetic 윈도우 flag 건드리기 전에 근본(등록 / activation policy)을 고치는 거야.

난 곧장 윈도우 flag 로 갔어 — focus 설정, always-on-top, 관련 들리는 모든 knob. 그중 하나가 focus 문제를 더 나쁘게 만들었고, 그게 마침내 추측을 멈추고 윈도우가 띄워지는 방식이 실제로 뭐가 다른지 묻게 강제했어. 답은 flag 가 전혀 아니었어; OS 가 진짜 앱으로 절대 안 여긴 bare 바이너리를 돌리고 있던 거였어. 난 현관문 없는 집의 커튼을 조정하고 있던 거야. 근본을 고치고, 그다음 장식해.

Code

한 원인, 세 증상, 두 진짜 해법·text
증상 (한 원인의 세 얼굴):
  - dock 아이콘 없음
  - app switcher 에서 빠짐
  - 절대 frontmost 아님; 키 입력이 전에-focus 된 앱으로 감

근본 원인:
  dev 명령이 application bundle 이 아니라 BARE 바이너리를 돌림.
  -> OS 가 그걸 진짜, foreground-가능 앱으로 절대 등록 안 함.

안 되는 것:
  framework 레벨 'activation policy = regular' 설정
  -> bare 바이너리엔 라이브 앱 객체로 전파 안 됨
     (설정이 거기 없는 제대로 된 bundle 맥락을 가정)

되는 것 (하나 골라):
  A) framework 아래 native 호출: activation policy = regular 강제,
     그다음 앱을 명시적으로 앞으로 가져옴
  B) 진짜 application bundle 빌드해서 그걸 돌림 (dev artifact == 진짜 artifact)

더 나쁘게 만드는 것:
  근본 전에 윈도우 flag (force-focus, always-on-top) 에 손 뻗기
  -> always-on-top 이 원래 버그 위에 키보드 focus 를 깰 수 있음

External links

Exercise

네가 부딪힌 '프로덕션에선 됨, dev 에선 이상함'(또는 반대) 버그를 떠올려. 근본 원인이 코드에 있었어, 아니면 dev artifact 랑 진짜 artifact 의 차이(포장, launch 경로, 환경)에 있었어? dev-실행이 진짜-실행이랑 다른 방식을 나열해. 각 차이가 안 맞는 행동의 후보 설명이야.
Hint
흔한 dev-vs-진짜 artifact 차이: bare 바이너리 vs bundle/installer, debug vs release 빌드, source 디렉토리 실행 vs 설치된 위치, 다른 환경 변수나 working directory. 이 중 뭐든 같은 코드를 OS 나 런타임이 다르게 다루게 할 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.