하이브리드 앱 구축 및 출시 회고 | React Native + Next.js + Supabase 조합

    반응형

    현재 출시를 목표로 만든 [로그트립] 앱이 있습니다
    출시는 되었으나 꾸준히 리팩토링 과정을 거치고 있는 중인데요
    일단 출시가 목표였기에 무작정 만들다보니 설계 부분에서 놓친것도 많고 고군분투한 과정도 참 많습니다 (앱 개발 자체도 처음)

     

    1. 설계 구조에 따른 시행착오

    하이브리드 앱 구조로 변경

    최초 설계는 오로지 React Native로만 개발해서 출시까지 했으나

    이전부터 프론트엔드 JD에 꽤 보이던 하이브리드 앱으로
    React Native 껍떼기에 내부 대부분의 기능을 WebView로 구성한 경험이 있는자를
    자격조건 또는 우대사항으로 넣는곳이 보였던 생각이 나더랍니다
    그래서 저도 공부 겸 하이브리드 앱으로 변경하게 됩니다

    프로젝트를 Monorepo 구조로 변경

    또한, 핫했던 조건 중에도 monorepo 설계 경험도 있었죠
    전 이 모든걸 실무에서 경험해본적이 없기에
    이 참에 공부 겸 해당 프로젝트를 위와 같은 구조로 싹 바꿔보자 했었어요

    하지만 생각보다 생소한 조합인 네이티브 앱 + 웹 구조의 모노레포 구조였고,
    하다보니 그닥 모노레포의 이점을 크게 누리지는 못했습니다.
    그러나 덕분에 모노레포 구조가 어떤지, 다음에는 어떤식으로 시작하면 되는지를 배울 수 있었어요

    현재 규모에서는 가장 눈에 띄게 누리고 있는 이점은
    앱과 웹을 동시에 로컬 스타트 할 수 있다는 점과
    한 코드 편집기에 왔다갔다 하면서 편집할 수 있단게 편하다는 점밖에 없네요
    (아직 공통 패키지를 구상할 정도의 규모가 아니여서 이 정도뿐인 것도 있습니다)

    로그인은 네이티브 앱에서, 인증은 웹뷰에서 처리

    그 다음 저는 또 생소하게..? React Native 단에서 로그인을 해서
    인증 토큰을 WebView에 넘겨 인증하는 과정을 거쳤습니다

    여기서 좀 시행착오가 많았어요

    일단 왜 굳이 인증 발급 절차를 네이티브쪽에 두었냐면
    UX 경험과 심사 통과를 고려한 점이 있었습니다
    저는 사용자가 소셜 로그인을 시도할때
    바로 내 폰 소셜앱 열려서 딸각 수준으로 로그인이 끝났으면 하길 바랬습니다

    그 다음 떠도는 소문으로(?) 모든 기능이 웹뷰에 있으면 심사 통과가 안된다는 소문도 있었고
    애플 로그인이 필수로 들어가야하는데
    이 부분이 웹뷰에 있어도 심사 통과가 힘들다는 이야기가 있었습니다
    그래서 로그인 기능은 모두 네이티브쪽으로 뺀 이유입니다

    사실 추측이긴 합니다만...ㅎ
    실제로 웹뷰에서 모두 구현했을때 어떨지는 잘 모르겠습니다...
    요즘 소셜 로그인측에서 지원을 많이 해줘서
    웹이든 앱이든 상관없게 강제 앱 리다이랙트 해주는게 잘 되어있기도 해서..
    암튼 2번 노가다하기 싫어서 처음부터 이렇게 구상했습니다

    페이지 전환도 네이티브 앱에서 처리

    그리고 네비게이션 탭바도 네이티브쪽에 뒀습니다...ㅋㅋㅋㅋㅋㅋ
    이 부분은 왜 그랬냐면 안드로이드, ios마다 webview 엔진이 다른데
    하단 네비게이션 탭바를 웹뷰쪽에 두면 UI가 달라질까 하는 걱정도 있었고,
    스크롤 문제도 생기지 않을까? 하는 추측도 있었습니다

    그리고 네이티브에서 제공하는 스무스한 페이지 전환 애니메이션을 누리고 싶은 생각도 있었습니다
    모든 페이지를 웹뷰로 구상할 경우 네이티브에서 누리던 스무스한 그런 애니메이션 적용이 안되거든요...
    무론 제가 수동으로 설정해도 됩니다만 귀찮았어요
    근데 이게 나중에 좀 문제가 되었습니다^^...

    데이터 캐싱 문제 직면

    앱 최초 구상 당시부터 데이터 캐싱에 대한 고민이 많았습니다
    외부 API에서 대용량 GeoJson을 받아오는데 이게 생각보다 시간이 오래 걸리더라고요
    그리고 지도를 이용하는 서비스이기에 API 호출건은 최소화 하고 싶은 마음이 있었습니다
    지도 라이브러리 자체가 무겁다고 생각했었음)
    그래서 최초에는 무작정 익수한 React Query 라이브러리를 사용해서
    해당 라이브러리의 기능들을 최대한 활용해서 잘 짜놨었습니다(?)

    근데 제가 다 개발하고 깨달은 점...!! 탭바가 네이티브쪽에 있었다고 했잖아요?
    각 탭바마다 있는 웹뷰가 서로 독립된 브라우저 형태라는걸 뒤늦게 알았던겁니다ㅠㅠㅠㅠㅠ!!!
    앱 개발이 처음이기도 했고 잘 안 알아보고 무작정 만든게 여기서 문제가 터졌습니다...
    어쩐지 A 탭에서 데이터를 업데이트 할 경우 B 탭의 데이터도 다시 받아오게 설정했더니 변화가 없더랍니다...
    그래서 그제서야 알아보니 각 탭마다 있는 웹뷰는 마치 독립된 브라우저로 걍 브라우저 여러개 띄운것과 같다고 하더라고요
    React Query는 각 브라우저 탭마다 독립적인 메모리를 사용하기에 서로 공유가 되질 않았던겁니다

    SSR, 서버 컴포넌트의 이점을 누리고 싶은 마음

    그 다음으로 어느정도 기능 개발을 완료하니
    내가 Next.js 프레임워크의 이점을 잘 활용했는가?란 고민이 들더라고요
    제가 실무에서 Next.js App Router를 사용해보긴 했으나
    규모가 작은 서비스에 구축해본 경험만 있어서 늘 아쉬운 마음이 있었습니다
    (Next.js 14버전 이전은 실무에서 주구장창 썼으나 이마저도 대부분 CSR로 구상했었음)

    그래서 이번엔 Next.js 프레임워크의 이점을 최대한 활용해보자!란 생각이 들면서
    대부분의 컴포넌트를 SSR로 전환하는 시도를 했습니다
    기존에는 빨리 출시한다고 대부분 클라이언트 컴포넌트였고 코드 분리도 잘 안되어있었거든요
    그래서 리팩토링 하면서 코드를 분리하고 역할을 분리한 다음
    클라이언트 컴포넌트, 서버 컴포넌트로 나누어 코드를 수정하기 시작했습니다

    이때까지는 React Query로 일단 구상해놨다가
    2차로 Next.js에서 제공하는 캐싱 기능을 활용하기 위해 또 대규모 수정에 들어갔습니다
    여기서 제가 Supabase을 SSR로 변경해야하는 문제가 발생했는데요
    지금까지는 네이티브에서 토큰을 보내면 웹뷰내(Next.js 프로젝트)에 설치된
    Supabase SDK에 해당 토큰을 설정하고,
    웹뷰 로컬스토리지에도 저장하는 형태로 한마디로 클라이언트용으로 사용했었습니다. 

    이걸 전환하는 과정에서 위기를 맞이합니다...
    네이티브 로그인 -> 리다이랙트 -> Next.js 미들웨어 -> 인증 설정 -> 웹뷰 로드 -> API 호출
    이 과정에서 뭔가 타이밍이 안 맞는건지 웹뷰 브라우저 쿠키에 토큰이 설정되었으나
    최초로 리다이랙트 된 A 탭에서 AP 호출시 계속 세션이 없다고 뜨거나,
    그러다 B 탭으로 이동하면 갑자기 쿠키가 인식돼서 B 탭 API는 호출된다거나,
    그래서 최초로 리다이랙트 후 페이지 리프레쉬도 해봤으나 효과가 없었고...
    뭐 등등등.... 계속 인증이 제대로 설정되질 않던 문제가 있었습니다
    여러모로 급하게 만들면서 처음으로 바이브 코딩마냥 AI에 의지를 많이 했는데
    뭔가 인증 워크플로우가 말도 안되게 꼬인 것 같다는 생각이 들었습니다

    일단, React Query를 걷어내고 데이터 캐싱을 unstable_cache API로 변경을 했었습니다
    Next.js는 서버단에서 데이터를 캐싱할 수 있게 해주는데
    그 캐싱은 프로젝트 내부 .next 폴더 내에 파일채로 저장이 됩니다
    근데 A 탭에서 데이터 업데이트 후 B 탭의 데이터를 리패칭해서 새로운 데이터를 받아와야할 경우
    이것도 어쩔땐 잘 날라가고 어쩔땐 안 날라가고... 뭐 난리였습니다 ^_ㅠ
    만약 유저의 데이터가 변경이 될 경우에는 모든 탭이 업데이트 되어야하는데
    그럴 경우 A 탭은 됐는데 B 탭은 안됐다거나...
    생각보다 리프레쉬 과정이 매우 수동적이며, 까다롭기도 하고 그랬었습니다

     

    2. 회고

    그렇게 결국 일주일동안 리팩토링한 코드를 모두 롤백했었습니다

    여기서 제 큰 문제는
    결과만 보고 달려서 과정이 어떻게 흘러가는지를 놓쳐서 그랬다는 결론에 도달했습니다
    그래서 다시 처음부터 하나하나 차근차근 시도해보기 시작했습니다

    일단 Next.js Supabase SSR부터 제대로 세팅하고, Cookie가 잘 설정 되었는지
    해당 Cookie로 User 정보를 잘 불러오는지만 집중해서 다시 SSR, 서버 컴포넌트 전환을 시도해보려고 합니다

    그 다음 캐싱 전략을 어떤식으로 가져갈지 고민하고 세팅하고,
    각 탭마다의 캐싱 동기화도 어떤식으로 가져갈지 고민해서 시도하려고 합니다
    마지막으로는 로그인 인증, 인가에 따른 보안 설정으로 마무리 해보려고 합니다

    다음글은 Next.js Supabase SSR 설정과 React Native에서 발급된 인증 토큰을 WebView내 Cookie로 저장하는 과정중 겪은 시행착오로 오겠습니다

    반응형

    댓글