Skip to Content
Dev웹 클라이언트

웹 클라이언트

뮤블의 클라이언트는 웹 기반으로 동작하며, 웹용 SSR과 네이티브용 CSR를 모두 지원하는 구조로 이루어져 있습니다.

주요 사용 스택

메인 구조

  • deprecated는 추후 플러그인 및 패키지로 분리될 예정입니다.

빌드 및 개발 환경 명령어

# cwd: root pnpm build:libs # 라이브러리(plugin 및 packages) 빌드 명령어 pnpm dev:libs # 라이브러리(plugin 및 packages) watch-build 명령어 (개발 시 사용) # cwd: apps/client pnpm build # 빌드 pnpm dev # 개발 서버 실행 pnpm typecheck # 클라이언트 타입 체크 # cwd: root pnpm build:client # 빌드 pnpm dev:client # 개발 서버 실행
  • 클라이언트 개발은 대부분 뮤블 플러그인을 수정하는 과정으로 이루어집니다.
    • 플러그인 코드를 수정할 경우 디버깅에서 핫로딩을 지원하지만, IDE에서의 타이핑 및 오류 발견을 위해서는 별도의 빌드가 필요합니다.
    • 인간 개발자의 경우 pnpm dev:libs를 실행하여 뮤블 플러그인 수정이 실시간으로 빌드되게 할 수 있습니다.
      • pnpm dev:libs는 실시간 변경사항만 반영하므로, 빌드가 안 된 상태에서 사용할 경우 제대로 작동하지 않을 수 있습니다. 사용 전 pnpm build:libs를 실행하여 빌드를 해주세요.
    • AI 개발자의 경우 플러그인 및 패키지를 수정할 때마다 pnpm build:libs를 실행하여 빌드를 해주세요.
    • IDE 특성 상 빌드 직후에는 타입이나 오류가 명확히 잡히지 않을 수 있습니다. 이 경우 기다리거나 pnpm typecheck를 실행하여 직접 타입 체크를 해주세요.

개발 참고사항

  • 크로스플랫폼에 관하여

    • 뮤블은 프로젝트를 클라우드에 실시간 저장하는 옵션(cloud-first)과 로컬에 저장하는 옵션(local-only)을 제공합니다. 따라서 백엔드가 동원되는 기능을 개발할 때는 대부분 이 두 API를 모두 구현해야 합니다,
    • 클라우드 저장소 API는 apps/server에서 제공되며, packages/cloud-client에서 추상화된 API 클라이언트 클래스를 제공합니다.
    • 로컬 저장소 API는 apps/tauri-app에서 제공되며, packages/tauri-commands에서 TypeScript로 포팅된 호출 메서드를 제공합니다. 단, 특정 플러그인 기능에서만 사용하도록 분리된 Tauri API는 packages/tauri-commands에서 제공되지 않으며 각 플러그인이 직접 @tauri-apps/api를 사용하여 호출합니다.
    • packages/tauri-commandspackages/cloud-clientpackages/api-types를 공통의 타입 정의로 사용합니다.
    • 해당 프론트엔드는 tauri-app에서도 네이티브 앱 용으로 공유됩니다. 웹 배포에는 SSR을 사용하고, 네이티브 앱 배포에는 CSR을 사용합니다.
    • routes.tsroutes/에서 확인 가능하듯 CSR과 SSR용 라우트가 구분되어 있습니다.
    • 새로운 기능을 구현하거나, 데이터의 구조를 변경할 경우 apps/server, apps/tauri-apps 둘 다 구현체 변경이 필요하며, packages/api-types도 대부분의 상황에서 수정해야 합니다.
  • 뮤블 플러그인 시스템

    본 문단은 클라이언트의 뮤블 플러그인 사용 및 개발에 관한 내용만을 다룹니다. 플러그인 개발 자체에 관한 자세한 내용은 해당 문서를 참고해주세요.

    • 뮤블 플러그인 시스템은 2025년 2월부터 도입되었으며, 앞으로 추가되는 기능과 기존의 기능들은 뮤블 플러그인 시스템을 통해 구현되어야 합니다.
    • 각 기능은 독립된 플러그인 패키지로 분리되며, 각 플러그인은 @muvel-plugins/ 네임스페이스를 사용합니다.
    • 베이스 시스템이 분리되지 않아 의존성을 제거할 수 없어 현재로서는 별개 패키지로 분리하기 힘든 기능의 경우 apps/temp-plugins 폴더에 넣은 후 apps/system/plugins.ts에서 직접 임포트하여 구현할 수 있습니다. 차후 분리가 가능해질 경우 plugins 폴더로 옮겨주시면 됩니다.
    • 플러그인 사용을 위해서는 clientpackage.json에 해당 의존성을 아래와 같이 추가하여야 합니다.
    "dependencies": { "@muvel-plugins/auth": "workspace:*", "@muvel-plugins/background-sync.android": "workspace:*", }
    • 플러그인이 peerDependencies로 사용하는 라이브러리는 무조건 clientpackage.json에 의존성에 존재해야 합니다. 그렇지 않을 경우 프로덕션에서 오류가 발생할 수 있습니다.
  • 번역 키 작성

    • 뮤블은 react-i18next 라이브러리를 사용하여 번역 키를 작성합니다.
    • 사용자에게 노출되는 모든 텍스트는 번역 키로 작성하는 것이 원칙입니다.
    • 번역 키는 camelCase 형식으로 작성하는 것이 원칙입니다.
    • enum 값을 기반으로 하는 번역 키는 enum 값을 키로 사용해주세요.
    • 번역 파일은 app/locales 폴더에 있습니다.
    • 기본 언어 및 폴백 언어는 한국어(ko.ts)로 설정되어 있습니다.
    • react-i18next를 peerDependencies로 추가할 경우 같은 인스턴스가 공유되므로 번역 키를 공유할 수 있습니다.
  • 더 이상 유효하지 않은 패턴

    • 컴포넌트 등에는 Atomic Design + Feature-based 패턴을 사용합니다. 뮤블 플러그인 시스템이 도입되며, 현재 features 폴더 내의 기능들은 차차 플러그인으로 분리되며 일부 컴포넌트만 Atomic Design 패턴으로 components 폴더에 남게 됩니다.
    • 네이티브와 웹 모두를 지원해야 하므로 usePlatform hook을 이용해서 사용 환경을 분기하는 것이 핵심입니다. 환경에 따른 동적 분기가 필요한 기능은 뮤블 플러그인 시스템으로 구현하며, 더 이상 이 후크로 기능을 분기하는 것은 권장하지 않습니다.

최신 의존성 안내사항

프로젝트에서 메인으로 사용되는 최신 라이브러리에 대한 정보를 안내합니다. 아래에 설명된 라이브러리 및 프레임워크들은 구 버전과 API 구조가 크게 차이나므로 주의가 필요합니다.

  • React-Router v7 (2024년 11월 22일 출시)

  • Chakra UI v3 (2024년 10월 22일 출시)

    • 대부분의 컴포넌트 사용법이 변경되었기에 문서 참고가 필수적입니다.
    • v3 공식 문서 
    • v2에서 v3로의 마이그레이션 
    • 구 버전과 자주 헷갈리는 부분
      • 사용법이 바뀜: IconButton, toaster, colorScheme → colorPalette
      • breakpoint {base: 'value', sm: 'value'}
      • color-mode {base: 'value', _dark: }
      • HTML 표준으로 바뀜: isDisableddisabled, isLoadingloading
      • 삭제됨 Modal(삭제됨), spacing 속성(삭제됨)
      • <Divider/><Separator/>
      • sx={{...}}css={{...}}
      • 네임스페이스 방식으로 변경: Dialog, Drawer, Alert, Tag, Checkbox
      • QRCode, Combobox, Marquee, TreeView, TagsInput 등 다양한 신규 컴포넌트가 추가되었습니다.
  • motion/react v12 (2024년 1월 경 변경)

    • 기존 Framer Motion 패키지는 Motion for React라는 이름의 독립 프로젝트로 분리되었습니다.
    • 이로 인해 framer-motion 패키지는 더 이상 사용되지 않으며, motion 패키지를 설치해야 합니다.
    • import { motion } from "framer-motion"import { motion } from "motion/react"
    • motion()은 deprecated 되었습니다. motion.create()를 사용해 주세요.
    • Chakra UI v3 컴포넌트와 같이 사용할 경우 타이핑 이슈로 as={} 대신 asChild를 사용하거나 moiton.create()로 미리 만들어 둔 컴포넌트를 활용하세요.

Footnotes

  1. 해당 라이브러리는 @muvel/ui 패키지를 통해 reexport 되어 사용됩니다.

Last updated on