글자 크기

조비엣 빌드로그 2주차: 길은 화면보다 먼저 열린다

지난주엔 UI 부품을 깎았다.
말투를 정리했다.
앱이 어떤 표정으로 “안내/경고/에러/권유”를 말할지 통일했다.

근데… 그 다음 주에는 이런 생각이 들었다.

“좋은 말투만으로는 부족하다.”

말을 어떻게 하느냐만큼 중요한 게 있다.
어디서 말을 하느냐.
그리고 그 말이 ‘어떻게 이동하느냐’.

이 주는 그래서, 화면을 더 예쁘게 만드는 주가 아니었다.
길을 만드는 주였다.
Turbo Native(iOS/Android)로 가기 위한 “내비게이션 규칙”을 코드로 박는 주.

1. “서버가 모달을 닫아준다”는 발상

웹에서 모달은 보통 자바스크립트가 닫는다.
버튼 누르면 hide() 하고 끝.

근데 Turbo Native로 갈 생각을 하면 이야기가 달라진다.
모달이 화면의 일부이면서도, 네이티브에선 “별도의 화면”처럼 취급된다.
여기서 어설프게 닫았다 열었다 하면 경험이 깨진다.

그래서 이번 주에 잡은 핵심 원칙은 이거다.

모달은 클라이언트가 닫는 게 아니라,
서버 응답이 닫는다.

구조는 단순하다.

  • 성공하면: turbo_stream.update(“modal”, “”) 로 모달을 비우고, turbo_stream.update(“flash”, …) 로 메시지 보여주고
  • 실패하면(422): 모달 안에 폼을 다시 렌더해서 그대로 수정하게 한다

즉, 모달의 열림/닫힘을 “서버의 결정”으로 표준화했다.

이게 왜 중요하냐면,
Turbo Native에서 “화면 전환”은 곧 “신뢰”라서 그렇다.
사용자가 눌렀는데 앱이 이상하게 버벅이거나, 닫힌 줄 알았는데 남아있거나,
그 순간 앱은 바로 신뢰를 잃는다.

이번 주는 그 신뢰를 지키는 쪽으로 길을 냈다.

2. 모달 프레임 표준화: report_modal → modal (하지만 호환은 유지)

현실은 늘 타협이 필요하다.
이미 report_modal이라는 레거시 프레임이 깔려 있었고,
그걸 하루아침에 다 갈아엎는 건 “가능”은 해도 “현명”하진 않다.

그래서 전략은 이랬다.

  • 새로운 표준 프레임: modal
  • 기존 레거시: report_modal 유지
  • 대신 서버가 닫을 때는 둘 다 닫는다

즉, “공존하는 동안은 둘 다 챙긴다.”

이런 방식은 개발자로서 약간 꼴사나울 때도 있는데,
나는 요즘 오히려 이런 게 성숙한 선택이라고 생각한다.

완벽주의로 크게 부수는 사람보다,
점진적으로 갈아타는 사람이 오래 간다.

3. flash도 규칙 안으로 넣기: turbo-frame “flash”

Turbo Streams로 플래시를 업데이트하려면
플래시가 “타겟”이 있어야 한다.

그래서 플래시를 그냥 렌더하는 대신,

  • <turbo-frame id="flash"> 로 감싸서
  • 서버가 turbo_stream.update("flash", ...)로 통일해서 보낼 수 있게 만들었다

이건 작은 수정 같지만, Turbo Native 관점에서는 엄청 큰 변화다.

서버가 말하는 방식(플래시)이,
네이티브에서도 동일하게 작동하는 기반이 생긴다.

즉, “웹 전용 트릭”이 아니라 “플랫폼 공용 규칙”이 된다.

4. /me 고정 URL — 딥링크 안정성의 핵심

내가 이번 주에 제일 마음에 들었던 결정은 이거다.

/me 로 고정한다.

프로필을 /users/:id로 두면,
Turbo Native에서 탭/딥링크/캐시가 점점 복잡해진다.

  • 로그인 전후에 ID가 바뀌고
  • 딥링크가 사용자마다 달라지고
  • PathConfiguration 매핑도 길어진다

반면 /me는 단순하다.

  • “내 프로필”은 항상 /me
  • 네이티브 탭도 항상 같은 URL
  • 캐시도 안정적
  • PathConfiguration도 깔끔해진다

이건 개발 편의성만의 문제가 아니다.
사용자 경험의 안정성이다.
앱이 “항상 같은 길”로 나를 데려간다는 감각.
그게 신뢰다.

5. PathConfiguration: 이제 진짜 Turbo Native가 보이기 시작했다

Turbo Native의 핵심은 결국 이 한 파일로 드러난다.

PathConfiguration.json

이 파일은 말하자면
“이 URL은 네이티브에서 어떤 방식으로 보여줄 거냐”를 정하는 지도다.

이번 주에 정리된 방향:

  • 기본 화면들: context: default — /posts, /chat_rooms, /me
  • 모달로 띄울 화면들: context: modal — 신고, 리뷰
  • 인증 계열: presentation: replace로 더 안전하게

여기서 중요한 포인트는 하나.

이제 조비엣은 “뷰”를 만드는 게 아니라 “네비게이션 규칙”을 만든다.

이 순간부터 프로젝트는
웹앱이 아니라 “앱”의 형태를 갖추기 시작한다.

6. 이번 주의 결론: “UI는 표면이고, 길은 뼈대다”

지난주엔 말투를 다듬었다.
이번 주엔 길을 냈다.

그리고 나는 요즘 이런 생각을 한다.

표면은 언제든 바꿀 수 있다.
하지만 길은 한 번 잘못 만들면 계속 돌아가게 된다.

그래서 이번 주의 작업은
겉보기엔 리팩터링이지만, 실제론 이런 선언이었다.

조비엣은 Turbo Native로 갈 수 있는 구조로 간다.
그리고 그 구조의 첫 단추는 “모달”과 “/me”와 “PathConfiguration”이다.

다음 주 예고 (3주차)

이제 남은 건 한 가지가 크다.

“이미지 확대(미디어)와 라우팅”

  • 이미지 확대가 Turbo Native에서 어떻게 뜰지
  • 모달인지, 별 화면인지
  • 캐시와 뒤로가기 경험까지

여기까지 잡히면
iOS/Android Turbo Native 템플릿을 붙일 때,
앱이 “그냥 연결되는” 느낌이 날 거다.

조비엣은 지금 그 문턱 앞에 와 있다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다