개요
앱을 로컬에서 빌드하고 테스트하면, 배포 경로는 두 가지입니다:- 타르볼 배포 — 내부 또는 비공개 사용을 위해 특정 Twenty 서버에 앱을 직접 업로드합니다.
- npm에 게시 — 모든 워크스페이스가 검색하고 설치할 수 있도록 Twenty 마켓플레이스에 앱을 등재합니다.
앱 빌드
앱을 컴파일하고 배포 준비가 된manifest.json을 생성하려면 빌드 명령을 실행하세요:
.twenty/output/에 기록합니다. 수동 배포 또는 publish 명령을 위한 .tgz 패키지도 생성하려면 --tarball을 추가하세요.
서버에 배포(타르볼)
공개하고 싶지 않은 앱 — 독점 도구, 엔터프라이즈 전용 통합 또는 실험적 빌드 — 의 경우, 타르볼을 Twenty 서버에 직접 배포할 수 있습니다.사전 준비
배포 전에 대상 서버를 가리키도록 구성된 원격이 필요합니다. 원격은 서버 URL과 인증 자격 증명을 로컬의~/.twenty/config.json에 저장합니다.
원격 추가:
배포
앱을 한 번에 빌드하여 서버에 업로드:배포된 앱 공유
타르볼 앱은 공개 마켓플레이스에 나열되지 않으므로, 동일한 서버의 다른 워크스페이스는 탐색만으로는 이를 찾을 수 없습니다. 워크스페이스가 Enterprise 플랜을 사용 중이면, 배포된 앱을 다음과 같이 공유할 수 있습니다:- 설정 > 애플리케이션 > 등록으로 이동하여 앱을 엽니다
- Distribution 탭에서 공유 링크 복사를 클릭합니다
- 이 링크를 다른 워크스페이스의 사용자와 공유하세요 — 해당 앱의 설치 페이지로 바로 이동합니다
버전 관리
이미 배포된 타르볼 앱을 업데이트할 때, 서버는package.json의 version이 현재 배포된 버전보다 semver 순서 기준으로 엄격히 더 높아야 합니다. 동일한 버전을 다시 배포하거나 더 낮은 버전을 푸시하는 경우, 타르볼이 저장되기 전에 거부됩니다 — CLI에서 VERSION_ALREADY_EXISTS 오류가 표시됩니다.
업데이트를 릴리스하려면:
package.json의version필드를 올리세요(예:1.2.3→1.2.4,1.3.0, 또는2.0.0)yarn twenty app:publish --private(또는yarn twenty app:publish --private --remote production)를 실행합니다.- 앱을 설치한 워크스페이스는 설정에서 사용 가능한 업그레이드를 확인할 수 있습니다
프리릴리스 태그는 예상대로 동작합니다:
1.0.0-rc.1 → 1.0.0-rc.2로 올리는 것은 허용되며, 1.0.0과 같은 최종 릴리스는 1.0.0-rc.5보다 더 높은 버전으로 올바르게 인식됩니다. package.json의 버전은 유효한 semver 문자열이어야 합니다.서버 버전 호환성
앱이 특정 Twenty 서버 버전에서 도입된 기능(예: v2.3.0에 추가된 OAuth 공급자)을 사용한다면,package.json의 engines.twenty 필드를 사용하여 앱에 필요한 최소 서버 버전을 선언해야 합니다:
| 범위 | 의미 |
|---|---|
>=2.3.0 | 2.3.0 이상인 모든 서버 |
>=2.3.0 \<3.0.0 | 2.3.0 이상이지만 다음 메이저 버전 미만 |
^2.3.0 | >=2.3.0 \<3.0.0과 동일 |
engines.twenty가 설정되어 있고 대상 서버의 버전이 해당 범위를 충족하지 않으면, 배포(tarball 업로드) 또는 설치가SERVER_VERSION_INCOMPATIBLE오류와 함께 거부되며 필요한 범위와 실제 서버 버전을 모두 나타내는 메시지가 표시됩니다.engines.twenty가 설정되어 있지 않으면, 앱은 모든 서버 버전에서 허용됩니다(기존 앱과 하위 호환).- 서버에
APP_VERSION이 구성되어 있지 않으면, 검사가 생략됩니다.
서버가 최종 검증을 수행합니다 — 타르볼 업로드와 워크스페이스 설치 모두에서
engines.twenty를 검증합니다. 타르볼을 별도 경로로 배포하거나 마켓플레이스에서 설치하더라도, 서버는 여전히 호환성을 강제합니다.자동화된 CI/CD (스캐폴드된 워크플로)
create-twenty-app으로 생성된 앱은 .github/workflows/ 아래에 기본으로 두 개의 GitHub Actions 워크플로가 포함되어 있습니다. 저장소를 GitHub에 푸시하는 즉시 실행할 준비가 되어 있습니다 — CI에는 추가 설정이 필요 없고, CD에는 단 하나의 시크릿만 필요합니다.
CI — ci.yml
main으로의 푸시와 풀 리퀘스트마다 통합 테스트를 자동으로 실행합니다.
하는 일:
- 앱의 소스 코드를 체크아웃합니다.
twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main컴포지트 액션을 사용해 격리된 Twenty 테스트 인스턴스를 생성합니다(CI에서yarn twenty docker:start --test와 동등합니다).- Corepack을 활성화하고,
.nvmrc에 따라 Node.js를 설정하며,yarn install --immutable로 의존성을 설치합니다. - 생성된 인스턴스에서
TWENTY_API_URL과TWENTY_API_KEY를 전달하여 실제 서버와 통신할 수 있도록yarn test를 실행합니다.
TWENTY_VERSION(환경 변수, 기본값latest) —ci.yml에서 이 값을 수정하여 CI에서 사용하는 Twenty 서버 버전을 고정합니다.- 동시 실행은
github.ref로 그룹화되며, 새 푸시가 발생하면 진행 중인 실행을 취소합니다.
CD — cd.yml
매번 main으로 푸시될 때 구성된 Twenty 서버에 앱을 배포하며, deploy 라벨이 적용된 경우 풀 리퀘스트에서도 선택적으로 배포합니다.
하는 일:
- 라벨이 지정된 PR의 경우 PR 헤드, 아니면 푸시된 커밋을 체크아웃합니다.
twentyhq/twenty/.github/actions/deploy-twenty-app@main를 실행합니다 — CI에서의yarn twenty app:publish --private에 해당합니다.twentyhq/twenty/.github/actions/install-twenty-app@main를 실행하여 새로 배포된 버전을 대상 워크스페이스에 설치합니다.
| 설정 | 위치 | 목적 |
|---|---|---|
TWENTY_DEPLOY_URL | cd.yml의 env(기본값 http://localhost:3000) | 배포 대상 Twenty 서버입니다. 처음 사용하기 전에 실제 서버 URL로 변경하세요. |
TWENTY_DEPLOY_API_KEY | GitHub 저장소 Settings → Secrets and variables → Actions | 대상 서버에서 배포 권한이 있는 API 키입니다. |
기본
TWENTY_DEPLOY_URL 값 http://localhost:3000은 플레이스홀더이며 — GitHub 호스팅 러너에서는 아무 곳에도 도달하지 않습니다. CD를 활성화하기 전에 서버의 퍼블릭 URL로 업데이트하세요(또는 네트워크에 접근 가능한 셀프 호스티드 러너를 사용하세요).deploy 라벨을 추가하세요. cd.yml의 if: 가드는 해당 PR의 헤드 커밋을 사용해 그 PR에 대한 잡을 실행하므로, 머지 전에 대상 서버에서 변경 사항을 검증할 수 있습니다.
재사용 가능한 액션 고정하기
두 워크플로 모두@main의 재사용 가능한 액션을 참조하므로, twentyhq/twenty 저장소의 액션 업데이트가 자동으로 반영됩니다. 결정적 빌드를 원한다면, 각 uses: 줄에서 @main을 커밋 SHA 또는 릴리스 태그로 바꾸세요.
npm에 게시
npm에 게시하면 Twenty 마켓플레이스에서 앱을 찾을 수 있게 됩니다. 모든 Twenty 워크스페이스는 UI에서 바로 마켓플레이스 앱을 탐색, 설치 및 업그레이드할 수 있습니다.요구 사항
- npm 계정
package.json의keywords배열에 있는twenty-app키워드(수동으로 추가하세요 —create-twenty-app템플릿에 기본적으로 포함되어 있지 않습니다)
마켓플레이스 메타데이터
defineApplication() 구성은 마켓플레이스에서 앱이 표시되는 방식을 제어하는 선택적 필드를 지원합니다. public/ 폴더의 이미지를 참조하려면 logoUrl과 screenshots를 사용하세요:
src/application-config.ts
author, category, aboutDescription, websiteUrl, termsUrl 등)은 Building Apps 페이지의 defineApplication 아코디언을 참조하세요.
권장 스크린샷 크기
마켓플레이스는screenshots를 고정된 8:5 컨테이너에 렌더링합니다(예: 1600×1000 px).
어떤 종횡비의 스크린샷이든 전체가 표시되며 잘리지 않습니다. 그러나
8:5보다 훨씬 세로로 길거나 가로로 좁은 경우 양쪽에 빈 띠가 표시됩니다.게시
beta 또는 next)로 게시하려면:
마켓플레이스 검색 방식
Twenty 서버는 npm 레지스트리에서 마켓플레이스 카탈로그를 매시간 동기화합니다. 기다리지 않고 즉시 동기화를 트리거할 수 있습니다:defineApplication() 구성에서 가져옵니다 — displayName, description, author, category, logoUrl, screenshots, aboutDescription, websiteUrl, termsUrl 같은 필드입니다.
앱에서
defineApplication()에 aboutDescription을 정의하지 않으면, 마켓플레이스는 소개 페이지 콘텐츠로 npm에 게시된 패키지의 README.md를 자동으로 사용합니다. 즉, npm과 Twenty 마켓플레이스 모두에서 하나의 README만 관리하면 됩니다. 마켓플레이스에서 다른 설명을 사용하려면 aboutDescription을 명시적으로 설정하세요.CI 게시
모든 릴리스마다 자동으로 게시하려면 이 GitHub Actions 워크플로를 사용하세요(OIDC 사용):yarn install, yarn twenty dev:build, 그리고 .twenty/output에서 npm publish.
npm provenance는 선택 사항이지만 권장됩니다.
--provenance 옵션으로 게시하면 npm 목록에 신뢰 배지가 추가되어, 사용자가 공개 CI 파이프라인의 특정 커밋에서 패키지가 빌드되었는지 확인할 수 있습니다. 설정 방법은 npm provenance 문서를 참고하세요.앱 설치
앱이 게시(npm)되었거나 배포(타르볼)되면, 워크스페이스는 UI를 통해 이를 설치할 수 있습니다. Twenty UI의 설정 > 애플리케이션 페이지로 이동하면 마켓플레이스 앱과 타르볼로 배포된 앱을 모두 탐색하고 설치할 수 있습니다. 명령줄에서 앱을 설치할 수도 있습니다:서버는 설치 시 semver 버전 규칙을 강제하며, 배포와 동일한 규칙을 적용합니다:
- 워크스페이스에 이미 설치된 것과 동일한 버전을 설치하려고 하면
APP_ALREADY_INSTALLED오류와 함께 거부됩니다. - 현재 설치된 것보다 낮은 버전을 설치하려고 하면
CANNOT_DOWNGRADE_APPLICATION오류와 함께 거부됩니다.
yarn twenty app:install을 다시 실행하세요.