Skip to Content
Dev뮤블 개발 가이드

뮤블 개발 가이드

뮤블 개발에 참여하게 되신 걸 환영합니다! 이 문서는 뮤블을 개발하는 생물 및 비생물체들을 위한 친절한 개발 가이드를 제공합니다. 일반 유저 분들은 이 개발 가이드가 보여도 놀라지 마세요. 어차피 저희는 공개해도 아무도 관심을 가지지 않을 이 문서를 굳이 숨기는 게 매우 귀찮아서 그렇습니다.


뮤블은 무엇인가요?

뮤블(Muvel)은 스토리 집필 특화 에디터 프로젝트입니다. React Router v7 의 프레임워크 모드를 기반으로 웹 클라이언트를 구현하며, 이를 SPA 모드로 빌드해 Tauri v2 를 통해 모바일, 데스크톱 등 크로스플랫폼으로 배포합니다.

클라우드 저장소를 우선 신뢰하는(cloud-first) 클라우드 저장 전략과 로컬 저장소를 우선 신뢰(local-only)하는 로컬 저장소 전략 두 가지를 제공합니다.

주요 사용 스택

프로젝트 구성

아래는 뮤블의 프로젝트의 주요 구조입니다. 뮤블은 패키지 매니저로 pnpm 을 사용하며, 모노레포 구조로 구성되어 있습니다.

  • package.json
  • pnpm-workspace.yaml
  • apps: pnpm monorepo 내에 위치한 앱들입니다.
    • apps/client: 사용자가 사용하는 웹 프론트엔드입니다.
    • apps/server: 뮤블 클라우드의 API와 비즈니스 로직을 담당하는 백엔드입니다.
    • apps/tauri-app: 데스크톱/모바일 환경을 위한 앱입니다. UI 요소는 client에서 가져오며, 이곳에는 주로 로컬 저장소용 비즈니스 로직이 구현되어 있습니다.
    • apps/guide: 사용 가이드북 웹사이트입니다.
  • packages: 공통으로 사용하는 기능, 타입, 또는 무거운 의존성을 가진 로직을 분리하는 용도로 사용됩니다.
    • packages/api-types: 뮤블 클라우드 API 서버와 클라이언트에서 공유하는 타입, 상수 등을 선언합니다.
    • packages/ui: 뮤블 클라이언트에서 사용하는 UI 컴포넌트를 선언합니다.
  • plugins: 주로 뮤블 클라이언트에서 사용하는 플러그인들을 선언합니다.

프로젝트에 중복으로 사용되는 의존성의 경우, 버전이 엇나가는 것을 막기 위해 루트의 pnpm-workspace.yaml 파일에 버전을 명시하는 것을 권장합니다.

packages: - packages/**/* - apps/* - plugins/**/* catalog: "@chakra-ui/react": 3.30.0 "@tanstack/react-query": 5.90.19 "@tauri-apps/api": 2.9.1 # ...

위처럼 버전을 명시할 경우 이후 의존성 설치 시, pnpm의 기능으로 자동으로 관리되며, 각 package.json에는 catalog:로 버전이 명시됩니다.

이는 peer dependency를 적극 사용하는 뮤블 플러그인뮤블 패키지에서 치명적인 오류를 막기 위해서는 필수적입니다.

메인 앱

웹 클라이언트 (apps/client)

자세한 내용은 웹 클라이언트 문서를 참고해주세요.

타우리 프로젝트 (apps/tauri-app)

자세한 내용은 타우리 앱 문서를 참고해주세요.

뮤블 클라우드 API 서버 (apps/server)

자세한 내용은 뮤블 클라우드 API 서버 문서를 참고해주세요.

가이드 웹사이트 (apps/guide)

뮤블 사용 가이드 웹사이트는 Next.js Nextra 로 구현되어 있습니다.

뮤블 점검 페이지 (apps/status)

뮤블 점검 페이지는 Next.js 로 구현되어 있으며, HTML로 빌드하여 뮤블 점검 시 대신하여 띄우는 용도로 사용됩니다.

플러그인

뮤블 플러그인은 완벽한 분리성을 유지하면서 웹 클라이언트의 기능을 확장하는 역할을 하는 핵심 시스템입니다.

자세한 내용은 뮤블 플러그인 문서를 참고해주세요.

패키지

뮤블 패키지는 공통으로 사용하는 기능, 타입, 또는 무거운 의존성을 가진 로직을 분리하는 용도로 사용됩니다.

자세한 내용은 뮤블 패키지 문서를 참고해주세요.

TypeScript 공통 규칙

뮤블의 대부분의 코드는 TypeScript로 작성되어 있습니다. 따라서 대부분의 코드는 아래 규칙을 따릅니다.

  • 특정 this 스코프가 필요한 특별한 경우가 아니라면 function 대신 화살표 함수(() => {})를 우선 사용하세요.
  • 파일명은 케밥 케이스(kebab-case)로 작성하세요.
  • Enum 작성 시 값은 Screaming Snake Case(SCREAMING_SNAKE_CASE) 대신 Pascal Case(PascalCase)를 사용하세요.
  • 특수한 경우(for 루프 등)를 제외하면 세미콜론을 사용하지 않습니다.
  • as를 사용한 Type Assertion은 최대한 자제하세요. 본 프로젝트는 Type-Safe를 매우 중시합니다.
    • 다른 방법이 없어 어쩔 수 없이 Type Assertion이 필요한 경우에는 먼저 허가받거나, 꼭 사후보고하세요.
  • Type-only import인 경우 import에 type을 꼭 표기하세요.
Last updated on