블로그
알림은 앱만 여는 것이 아니라 올바른 Session 으로 돌아가야 합니다
푸시 알림은 도착했다고 끝이 아닙니다. 멀티 session AI 코딩에서는 올바른 server, session, 현재 상태와 함께 도착해야 합니다. 1.6.6이 고친 것은 바로 그 맥락 복귀 경로입니다.
이 카테고리의 제품 및 엔지니어링 업데이트를 확인하세요.
카테고리 보기우리는 보통 알림을 전달 문제로 설명합니다. 도착했는가, 얼마나 빨랐는가, 잠금 화면에 보이는가. 하지만 원격 AI 코딩에서는 이 관점이 너무 얕습니다.
알림이 할 수 있는 일이 "앱을 여는 것"뿐이라면, 피드백 루프는 닫히지 않은 것입니다. 사용자는 여전히 어떤 머신인지, 어떤 session 인지, Claude가 승인을 요청하는 것인지 완료를 알리는 것인지, 지금 보고 있는 작업인지 아니면 조금 전에 백그라운드에 남겨둔 다른 session 인지 스스로 복원해야 합니다.
이건 카피 문제도, 전환 애니메이션 문제도 아닙니다. 완전한 상태 동기화 문제입니다.
왜 AI 코딩에서는 이 문제가 더 심각한가
일반적인 앱에서는 알림 하나가 보통 하나의 대상과 깔끔하게 대응합니다. 메일 한 통, 메시지 한 개, 일정 한 건. 탭했을 때 목적지도 자연스럽게 정해집니다.
원격 AI 코딩은 다릅니다.
동시에 세 개의 session 이 돌고 있을 수 있습니다.
- 하나는 모듈을 리팩터링 중
- 하나는 테스트 결과를 기다리는 중
- 또 하나는 승인 요청에서 멈춰 있는 중
이 상황에서 "Claude가 당신을 필요로 합니다"라는 문장은 아무 의미가 없습니다. 정말 중요한 것은 다음입니다.
- 어느 server 가 이 알림을 보냈는가
- 어느 session 이 이를 트리거했는가
- 그 session 이 지금 어떤 상태인가
- 사용자가 이미 그 session 을 보고 있는가
이 중 하나라도 빠지면 알림은 모호한 인터럽트로 퇴화합니다. 집중을 끊을 수는 있어도 다음에 무엇을 해야 하는지는 알려주지 못합니다.
알림은 사라져서만 실패하는 것이 아니다
대부분의 시스템은 알림 신뢰성을 "떨어뜨리지 않는 것"으로 이해합니다. 하지만 멀티 session 워크플로에는 그만큼 나쁜 다른 실패가 있습니다. 알림은 도착했지만, 사용자를 잘못된 맥락으로 돌려보내는 것입니다.
이 실패는 완전 손실보다 더 미묘하고, 종종 더 위험합니다.
사용자는 올바른 위치로 돌아왔다고 믿고, 그대로 잘못된 session 에서 작업을 이어갑니다. 원격 AI 코딩에서는 다음과 같은 실수로 이어질 수 있습니다.
- 잘못된 repository 에서 Claude 에게 응답하기
- 잘못된 task 를 승인하기
- 한 session 의 상태를 다른 session 의 상태로 오해하기
상호작용 측면에서는 평범한 이동 버그처럼 보입니다. 제품 측면에서는 원격 워크플로 전체에 대한 신뢰를 깹니다.
알림이 유용하려면 맥락이 전체 경로를 살아남아야 한다
유용한 알림은 APNs payload 하나로 성립하지 않습니다. 다음의 전체 경로를 지나며 정체성을 잃지 않아야 합니다.
- server hook event 가 만들어질 때 어떤
tmux_session이 원인인지 알아야 한다 - server 가 알림을 broadcast 할 때
session을 포함해야 한다 - push relay 가 dedupe 할 때 project 만으로 묶지 말고 session 을 구분해야 한다
- app 이 cold start 할 때 push 의 server identity 를 로컬에 저장된 server 로 다시 매핑해야 한다
- 최종 navigation 에서 올바른 server 로 돌아간 뒤 올바른 session 을 선택해야 하며, 기본 화면으로 떨어지면 안 된다
이 중 한 단계라도 "대충 추측"으로 채우면 최종 동작은 불안정해집니다.
그래서 1.6.6 의 알림 관련 변경이 iOS, Mac, server, push relay 에 흩어져 보이더라도 사실은 같은 문제를 고치고 있는 것입니다. 알림을 일반적인 리마인더가 아니라 실행 가능한 맥락 진입점으로 만드는 것입니다.
이전 모델은 정확히 어떻게 고장 났는가
문제를 추상화해 보면, 이전 모델에는 네 가지 전형적인 실패 패턴이 있었습니다.
1. source event 에는 session 이 있지만 알림에는 session 이 없다
server 의 hook event 는 특정 tmux_session 에서 왔다는 것을 알고 있었지만, 알림 broadcast 는 "알림이 있다"는 사실만 전했습니다. 그 순간 client 는 "현재 active 한 session 으로 돌아가는" 정도밖에 할 수 없게 됩니다.
위험한 점은, 탭하면 어딘가로 이동은 하므로 기능이 있는 것처럼 보인다는 점입니다. 실제로는 목적지가 자주 틀린데도 말입니다.
2. foreground 에서 동작하는 것과 cold start 에서 동작하는 것은 다른 문제다
앱이 살아 있을 때 알림 이동이 제대로 보이는 것은 흔합니다. 더 어려운 것은 cold start 입니다. app 이 아직 상태를 완전히 복원하지 못했기 때문입니다.
그 시점에는 server list 가 로딩 중일 수도 있고, navigation state 가 아직 없을 수도 있습니다. 로컬 ID 와 push payload 의 식별자도 서로 다를 수 있습니다. 너무 이른 navigation 은 대개 두 결과 중 하나를 낳습니다.
- 아무것도 열리지 않는다
- 열리긴 했지만 잘못된 server 나 session 에 도착한다
3. dedupe 가 두 개의 session 을 하나의 event 로 취급한다
push relay 의 dedupe key 가 server + project + event 만 포함하고 session 을 포함하지 않으면, 같은 project 의 두 session 이 가까운 시간에 이벤트를 발생시킬 때 뒤의 알림이 앞의 알림에 흡수될 수 있습니다.
이건 crash 처럼 보이지 않습니다. 가장 조사하기 어려운 사용자 피드백처럼 보입니다. "task 가 끝났는데 왜 알림이 안 왔죠?"
4. client 가 '보이는 session' 과 '알림의 source session' 을 혼동한다
이건 멀티 session 제품에서 매우 흔한 모델링 오류입니다. 지금 UI 가 focus 하고 있는 session 과 알림을 만든 session 은 같은 개념이 아닙니다. 상태 모델이 이 둘을 분리하지 않으면 잘못된 이동은 피할 수 없습니다.
1.6.6이 고친 것은 버튼이 아니라 경로였다
이 release 에서 중요한 것은 "알림을 탭하면 이동할 수 있습니다"라는 문장이 아닙니다. 여러 끊어진 제약이 마침내 하나의 경로로 연결되었다는 점입니다.
1. 이제 알림이 session identity 를 가진다
이전에는 session B 에서 나온 event 인데도 client 는 "어떤 알림이 생겼다"는 것만 알고 session A 로 돌아가 버릴 수 있었습니다. 1.6.6에서는 session identity 가 notification broadcast 와 push payload 전체를 통과합니다. 알림은 더 이상 단순히 "Claude가 뭔가 필요하다"가 아니라 "repo-x / session-y 가 뭔가 필요하다"를 의미합니다.
2. cold start 에서 deep link 를 덜 잃게 됐다
어려웠던 것은 UI 전환 자체가 아니었습니다. identity mapping 이었습니다. push 가 들고 오는 것은 server 측 identity 이고, app 이 저장하는 것은 로컬 object ID 입니다. cold start routing 은 이 두 identity system 을 화해시켜야 비로소 진짜가 됩니다.
즉 문제는 "어떻게 페이지를 넘길까"가 아니라 "시스템이 이것이 같은 server 라는 것을 어떻게 증명할까"였습니다.
3. push delivery 가 session 을 선택적 metadata 로 취급하지 않게 됐다
dedupe key 에 session 이 빠져 있으면 같은 project 의 다른 session 들이 서로를 지워 버릴 수 있습니다. 여기서 알 수 있는 것은 AI 워크플로에서 session 은 부가 정보가 아니라 알림 의미 자체의 일부라는 사실입니다.
4. local notification, remote push, navigation 이 마침내 같은 언어를 쓰기 시작했다
알림 파이프라인에서 최악인 것은 계층마다 의미가 어긋나는 것입니다.
-
server 는 "이건 hook event 다"라고 말하고
-
push service 는 "이건 project-level alert 다"라고 말하고
-
client 는 "그럼 현재 페이지로 돌아가자"라고 말하는 식입니다
1.6.6 의 진짜 가치는 이 계층들이 하나의 목표로 정렬되기 시작했다는 점입니다. 이벤트를 만든 server 와 session 으로 사용자를 돌려보내는 것입니다.
이것은 engineering 문제이기 전에 product 문제이기도 하다
지금까지 ID, payload, deep link 이야기처럼 들렸을 수 있습니다. 하지만 그 밑에는 더 큰 제품 판단이 있습니다.
알림은 사용자를 '의사결정이 필요한 정확한 장소'로 되돌리는 메커니즘이어야 하는가?
답이 yes 라면, 전달률만으로는 부족합니다. 알림은 동시에 세 가지를 만족해야 합니다.
- 도착해야 한다
- 올바른 곳에 떨어져야 한다
- 떨어진 순간 사용자가 바로 행동할 수 있어야 한다
이 기준으로 보면 많은 제품의 알림은 첫 번째만 만족합니다.
사용자가 실제로 느끼는 변화는 무엇인가
구현을 모두 무시하고 일상 사용만 보면, 1.6.6 은 최소한 네 가지 결과를 개선합니다.
- 알림 탭이 잘못된 session 에 떨어질 가능성이 줄어든다
- 잠금 화면이나 종료 상태에서 app 을 깨워도 맥락을 잃을 가능성이 줄어든다
- 일시적인 네트워크 오류가 알림 전체를 날려 버릴 가능성이 줄어든다
- Live Activity 의 비정상 경로 상태가 이전보다 더 믿을 만해진다. force-quit edge case 는 남아 있더라도
각각은 화려하지 않습니다. 하지만 함께 보면 더 중요한 질문에 답합니다. 여러 AI session 을 실제로 background 에 걸어 둘 만큼 제품을 신뢰할 수 있는가라는 질문입니다.
신뢰성은 경계 조건을 정직하게 쓰는 것이기도 하다
1.6.6 은 Live Activity cleanup path 도 다시 썼습니다. relaunch 시 stale activity 를 정리하고 orphan reference 를 제거하며, 짧은 끊김 뒤에 잘못된 "Finished" 상태가 나타날 가능성을 낮춥니다.
하지만 release note 에서 해결된 척하지 않은 edge case 가 하나 있습니다. 사용자가 iOS app 을 force-quit 하면 Live Activity 가 다음 launch 나 system timeout 까지 남아 있을 수 있다는 점입니다.
이 부분을 "완전 수정"이라고 써 버리면 단기적으로는 더 깔끔해 보일 수 있습니다. 하지만 장기적으로는 제품의 신뢰를 떨어뜨립니다. developer tool 에서는 특히 그렇습니다. 우리가 파는 것은 분위기가 아니라 예측 가능성이기 때문입니다.
진짜 목표는 알림을 더 많이 보내는 것이 아니다
좋은 원격 AI 제품은 알림을 받을 때마다 사용자가 "방금 무슨 일이 있었지?"를 다시 조립하게 만들어서는 안 됩니다.
알림이 정말 해야 할 일은 그 맥락 복구 작업을 미리 끝내 놓는 것입니다.
원격 AI 코딩에서 전달은 입장권일 뿐입니다. 문맥을 붙인 채로 도착하느냐가 그것이 유용한 입력이 될지, 또 하나의 인터럽트가 될지를 결정합니다.
1.6.6 은 알림도, 멀티 session 도 발명하지 않았습니다. 대신 더 기본적이고 더 가치 있는 일을 했습니다. 이 둘이 드디어 올바르게 협력하도록 만든 것입니다.