게이트에 별을 들이다 — 별이 건네는 한마디
어려운 일 앞에서, 또는 다 끝낸 순간에 fecit은 살짝 멈춰 세워 한 줄을 권합니다. 그 권유가 시스템 대화상자처럼 무미건조했습니다. 그래서 fecit의 별을 데려와, 별이 직접 그 한마디를 건네게 했습니다 — 곁에 있는 동무처럼.
게이트에 별을 들이다 — 별이 건네는 한마디
fecit에는 “게이트”라는 게 있습니다. 묵직한 일을 시작하려 할 때는 시작 전에 작전을 한 줄 짜보라고, 일을 다 끝냈을 때는 마무리로 회고를 한 줄 남겨보라고 — 딱 그 순간에 살짝 멈춰 세우는 작은 권유입니다. 강제는 아니고, “그냥 시작/완료”로 지나칠 수 있는 부드러운 넛지예요.
기능적으로는 잘 동작했습니다. 그런데 오래 보고 있자니 마음에 걸리는 게 있었습니다. 이 게이트가 — 아무리 부드럽게 말해도 — 시스템 경고창처럼 느껴졌습니다. 바닥에서 올라오는 카드, 작은 별 아이콘, 메시지, 버튼. 흔히 보는 “확인하시겠습니까?“의 결이었죠.
문제는 톤이었습니다. 같은 권유라도 건네는 손이 누구냐에 따라 온도가 달라집니다. 차가운 대화상자가 건네면 의무처럼 들리고, 곁의 동무가 건네면 거들어주는 말이 됩니다. fecit이 원한 건 후자였고, fecit에는 이미 그 동무가 있습니다 — 어시스턴트 탭의 별이요.
별이 직접 건네게
방향은 정해졌습니다. 게이트를 “시스템이 띄우는 알림”이 아니라 “별이 건네는 한마디”로 만들기.
첫걸음은 의외로 빼는 것이었습니다. 모달의 흰 카드 배경을 투명하게 했습니다. 그러자 별과 말풍선이 어두워진 화면 위에 둥실 떠 보였습니다. 카드 안에 갇힌 메시지가 아니라, 별이 지금 여기 와 있는 느낌. 어시스턴트 탭에서 별이 화면 한가운데 떠 있는 그 장면과 같은 언어였죠.
물론 빼기만 하니 새 문제가 생겼습니다. 별이 어두운 배경에 묻혔어요. 동그라미를 깔아봤다가, 무대 타원을 깔아봤다가 — 다 어색했습니다. 결국 답은 단순했습니다. 별 실루엣을 따라 한 톤 밝은 테두리를 두르는 것. 별보다 살짝 큰 별을 뒤에 깔아 윤곽선을 만드니, 어떤 배경에서도 또렷하게 떴습니다.
같은 별이어야 했다
여기서 한 번 멈췄습니다. 별을 회전시키고, 등장시키고, 반응하게 만들려는데 — 잠깐, 이 애니메이션 어시스턴트 별에 이미 다 있지 않나?
그렇습니다. 어시스턴트의 별은 이미 살아 있습니다. 가만히 있다가 가끔 끄덕이고 갸웃하고, 탭하면 통통 튀고, 완료를 감지하면 빙글 돌며 입자를 터뜨립니다. 그걸 게이트에서 손으로 다시 짜는 건 중복일 뿐 아니라, 두 개의 다른 별을 만드는 일이었어요.
그래서 그 별을 공용 컴포넌트로 들어냈습니다. 이제 게이트의 별과 어시스턴트의 별은 같은 존재입니다. 크기와 테두리만 옵션으로 다를 뿐, 같은 몸짓, 같은 성격. 제품 곳곳에서 마주치는 별이 매번 똑같은 동무라는 건, 단순한 코드 정리(DRY)를 넘어 제품이 하나의 인격으로 느껴지게 하는 일이었습니다.
등장의 안무
연출은 이렇게 정리됐습니다. 먼저 별이 자기 모션으로 등장합니다. 잠시 뒤, 말풍선이 별 쪽에서 바깥으로 펼쳐집니다. 별이 손에 쥔 쪽지를 건네듯이요. 닫을 때는 별과 말풍선이 함께 사라집니다(예전엔 말풍선이 먼저 사라지고 별이 잠깐 남아 어색했어요).
그리고 두 게이트를 다르게 대했습니다. 완료 게이트는 성취의 정점이에요. 다 해냈잖아요! 그 순간엔 별이 빙글 돌며 작은 폭죽을 터뜨립니다 — 화면 가득 작은 별이 사방으로 튀어요. 벌어들인 셀레브레이션이죠. 반대로 시작 게이트는 조용히 둡니다. 그건 보상이 아니라 부드러운 권유니까요. 폭죽은 끝낸 사람의 몫입니다.
과해지지 않기 — 그리고 한 가지 함정
중간에 욕심이 났습니다. 등장할 때 별을 720도 돌리고, 크기를 키우고, 입자를 뿌리고… 한꺼번에 다 했더니 화려하긴 한데 버벅였습니다. 그리고 더 중요한 건, 게이트는 자주 뜨는 인터럽트라는 점이었어요. 어시스턴트 탭은 일부러 찾아가는 목적지라 화려해도 되지만, 게이트는 흐름을 막아서는 통과의례입니다. 한 번은 즐겁고 스무 번은 거슬리죠. 신기한 애니메이션은 자주 뜨는 곳에서 빨리 늙습니다.
그래서 덜어냈습니다. 이중 회전을 한 번으로, 요란한 등장을 한 동작으로. 정체성(별이 건넨다)은 남기되, 연출 예산은 그 순간에 맞게.
버벅임의 진짜 범인은 따로 있었습니다. 별의 등장 스케일은 React Native의 Animated로, 별 자체의 몸짓은 Reanimated로 — 두 애니메이션 시스템이 같은 뷰를 동시에 건드리고 있었습니다. 둘을 겹치지 않게 분리하니 끊김이 사라졌어요. (불투명도처럼 서로 다른 속성은 괜찮지만, 같은 변형(transform)을 두 시스템이 쓰면 충돌합니다.)
교훈
- 정체성은 히어로 화면이 아니라 자잘한 순간에 산다. 넛지 하나도 “시스템이 막아서는” 자리가 아니라 “동무가 곁에 있는” 자리가 될 수 있습니다. 마찰의 순간일수록 더요.
- 같은 캐릭터를 곳곳에서 재사용하면 제품이 하나의 존재처럼 느껴진다. DRY는 코드 위생을 넘어 제품의 결을 만듭니다.
- 연출 예산은 순간의 성격에 맞춘다. 찾아가는 목적지는 화려해도 되고, 자주 뜨는 인터럽트는 절제해야 합니다.
- 한 뷰에 두 애니메이션 시스템을 겹치지 말 것.
게이트는 여전히 똑같은 일을 합니다 — 어려운 일 앞에서 한 걸음을, 끝낸 일 뒤에 한 줄을 권하죠. 달라진 건 그걸 건네는 손입니다. 시스템이 아니라, 별이.
그리고 고백하자면 — 별을 통통 튀게 하고, 빙글 돌리고, 화면 가득 작은 별을 흩뿌리게 만드는 일은, 만드는 내내 그냥 즐거웠습니다. (토마토 아이콘 하나 그리느라 한참을 헤맨 것도요. 그건 또 다른 이야기지만요.) 사용자가 그 순간 한 번이라도 피식 웃는다면, 그걸로 충분합니다.