i18n - docs translations (#17434)
Created by Github action Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
committed by
GitHub
parent
2353bc62cc
commit
e0d4492013
+11
-11
@@ -1,22 +1,22 @@
|
||||
---
|
||||
title: Best Practices
|
||||
title: 모범 사례
|
||||
---
|
||||
|
||||
This document outlines the best practices you should follow when working on the backend.
|
||||
이 문서는 백엔드 작업 시 따를 모범 사례를 설명합니다.
|
||||
|
||||
## Follow a modular approach
|
||||
## 모듈형 접근법 따르기
|
||||
|
||||
The backend follows a modular approach, which is a fundamental principle when working with NestJS. Make sure you break down your code into reusable modules to maintain a clean and organized codebase.
|
||||
Each module should encapsulate a particular feature or functionality and have a well-defined scope. This modular approach enables clear separation of concerns and removes unnecessary complexities.
|
||||
백엔드는 NestJS로 작업할 때 기본 원칙 중 하나인 모듈형 접근법을 따릅니다. 코드베이스를 깔끔하고 체계적으로 유지하려면 코드를 재사용 가능한 모듈로 분리하십시오.
|
||||
각 모듈은 특정 기능을 캡슐화하고 명확하게 정의된 범위를 가져야 합니다. 이 모듈형 접근법은 관심사의 명확한 분리를 가능하게 하고 불필요한 복잡성을 제거합니다.
|
||||
|
||||
## Expose services to use in modules
|
||||
## 모듈에서 사용할 서비스를 노출시키십시오.
|
||||
|
||||
Always create services that have a clear and single responsibility, which enhances code readability and maintainability. Name the services descriptively and consistently.
|
||||
항상 명확하고 단일한 책임을 가진 서비스를 생성하여 코드 가독성과 유지보수성을 향상시킵니다. 서비스의 이름을 일관되게 설명적으로 지정하십시오.
|
||||
|
||||
You should also expose services that you want to use in other modules. Exposing services to other modules is possible through NestJS's powerful dependency injection system, and promotes loose coupling between components.
|
||||
다른 모듈에서 사용하고자 하는 서비스를 노출해야 합니다. 다른 모듈에 서비스를 노출하는 것은 NestJS의 강력한 의존성 주입 시스템을 통해 가능하며, 구성 요소 간의 느슨한 결합을 촉진합니다.
|
||||
|
||||
## Avoid using `any` type
|
||||
## `any` 타입 사용 피하기
|
||||
|
||||
When you declare a variable as `any`, TypeScript's type checker doesn't perform any type checking, making it possible to assign any type of values to the variable. TypeScript uses type inference to determine the type of variable based on the value. By declaring it as `any`, TypeScript can no longer infer the type. This makes it hard to catch type-related errors during development, leading to runtime errors and makes the code less maintainable, less reliable, and harder to understand for others.
|
||||
변수를 `any`로 선언하면 TypeScript의 타입 검사자가 타입 검사를 수행하지 않으므로 변수에 모든 유형의 값을 할당할 수 있게 됩니다. TypeScript는 값에 따라 변수의 타입을 추론하기 위해 타입 추론을 사용합니다. 이를 `any`로 선언하면 TypeScript는 더 이상 타입을 추론할 수 없습니다. 이는 개발 중 타입 관련 오류를 잡기 어렵게 만들어 런타임 오류로 이어지고, 코드의 유지보수성과 신뢰성이 떨어지며, 다른 사람이 이해하기도 어려워집니다.
|
||||
|
||||
This is why everything should have a type. So if you create a new object with a first name and last name, you should create an interface or type that contains a first name and last name that defines the shape of the object you are manipulating.
|
||||
이것이 모든 것이 타입을 가져야 하는 이유입니다. 따라서 이름(first name)과 성(last name)을 가진 새 개체를 만든다면, 다루는 개체의 구조를 정의하는 이름과 성을 포함한 인터페이스나 타입을 만들어야 합니다.
|
||||
|
||||
+15
-15
@@ -1,39 +1,39 @@
|
||||
---
|
||||
title: Custom Objects
|
||||
title: 사용자 지정 개체
|
||||
---
|
||||
|
||||
Objects are structures that allow you to store data (records, attributes, and values) specific to an organization. Twenty provides both standard and custom objects.
|
||||
개체는 조직 고유의 데이터(레코드, 속성 및 값)를 저장할 수 있는 구조입니다. Twenty에는 표준 개체와 사용자 지정 개체가 모두 제공됩니다.
|
||||
|
||||
Standard objects are in-built objects with a set of attributes available for all users. Examples of standard objects in Twenty include Company and Person. Standard objects have standard fields that are also available for all Twenty users, like Company.displayName.
|
||||
표준 개체는 모든 사용자에게 제공되는 속성이 있는 내장 개체입니다. Twenty의 표준 개체 예시로는 Company(회사)와 Person(사람)이 있습니다. 표준 개체는 모든 Twenty 사용자에게 제공되는 표준 필드를 가지고 있으며, 예를 들어 Company.displayName과 같습니다.
|
||||
|
||||
Custom objects are objects that you can create to store information that is unique to your organization. They are not built-in; members of your workspace can create and customize custom objects to hold information that standard objects aren't suitable for.
|
||||
사용자 지정 개체는 조직 고유의 정보를 저장하기 위해 생성할 수 있는 개체입니다. 이들은 내장되어 있지 않으며, 워크스페이스의 구성원이 표준 개체로는 적합하지 않은 정보를 보관하기 위해 사용자 지정 개체를 생성하고 사용자 정의할 수 있습니다.
|
||||
|
||||
## High-level schema
|
||||
## 고급 스키마
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/server/custom-object-schema.png" alt="High level schema" />
|
||||
<img src="/images/docs/server/custom-object-schema.png" alt="고급 스키마" />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
## How it works
|
||||
## 작동 원리
|
||||
|
||||
Custom objects come from metadata tables that determine the shape, name, and type of the objects. All this information is present in the metadata schema database, consisting of tables:
|
||||
사용자 지정 개체는 개체의 형태, 이름 및 유형을 결정하는 메타데이터 테이블에서 비롯됩니다. 이 모든 정보는 테이블로 구성된 메타데이터 스키마 데이터베이스에 있습니다.
|
||||
|
||||
* **DataSource**: Details where the data is present.
|
||||
* **Object**: Describes the object and links to a DataSource.
|
||||
* **Field**: Outlines an Object's fields and connects to the Object.
|
||||
* **DataSource**: 데이터가 존재하는 위치를 설명합니다.
|
||||
* **Object**: 개체를 설명하고 DataSource와 연결됩니다.
|
||||
* **Field**: 개체의 필드를 설명하고 개체와 연결됩니다.
|
||||
|
||||
To add a custom object, the workspaceMember will query the /metadata API. This updates the metadata accordingly and computes a GraphQL schema based on the metadata, storing it in a GQL cache for later use.
|
||||
사용자 지정 개체를 추가하려면 /metadata API를 쿼리하십시오. 이는 메타데이터를 해당 API에 따라 업데이트하고, 메타데이터를 기반으로 GraphQL 스키마를 계산하여 나중에 사용할 수 있도록 GQL 캐시에 저장합니다.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/server/add-custom-objects.jpeg" alt="Query the /metadata API to add custom objects" />
|
||||
<img src="/images/docs/server/add-custom-objects.jpeg" alt="/metadata API를 쿼리하여 사용자 지정 개체를 추가하십시오." />
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
To fetch data, the process involves making queries through the /graphql endpoint and passing them through the Query Resolver.
|
||||
데이터를 가져오려면 /graphql 엔드포인트를 통해 쿼리를 수행하고 Query Resolver를 통해 전달하는 과정이 포함됩니다.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/server/custom-object-schema.png" alt="Query the /graphql endpoint to fetch data" />
|
||||
<img src="/images/docs/server/custom-object-schema.png" alt="/graphql 엔드포인트를 쿼리하여 데이터를 가져오십시오." />
|
||||
</div>
|
||||
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: Feature Flags
|
||||
title: 기능 플래그
|
||||
---
|
||||
|
||||
Feature flags are used to hide experimental features. For Twenty, they are set on workspace level and not on a user level.
|
||||
기능 플래그는 실험적 기능을 숨기는 데 사용됩니다. Twenty의 경우, 사용자 수준이 아니라 워크스페이스 수준에서 설정됩니다.
|
||||
|
||||
## Adding a new feature flag
|
||||
## 새로운 기능 플래그 추가
|
||||
|
||||
In `FeatureFlagKey.ts` add the feature flag:
|
||||
`FeatureFlagKey.ts`에 기능 플래그 추가:
|
||||
|
||||
```ts
|
||||
type FeatureFlagKey =
|
||||
@@ -14,7 +14,7 @@ type FeatureFlagKey =
|
||||
| ...;
|
||||
```
|
||||
|
||||
Also add it to the enum in `feature-flag.entity.ts`:
|
||||
또한 `feature-flag.entity.ts`의 열거형에 추가하십시오:
|
||||
|
||||
```ts
|
||||
enum FeatureFlagKeys {
|
||||
@@ -23,7 +23,7 @@ enum FeatureFlagKeys {
|
||||
}
|
||||
```
|
||||
|
||||
To apply a feature flag on a **backend** feature use:
|
||||
**백엔드** 기능에 기능 플래그를 적용하려면 다음을 사용하십시오:
|
||||
|
||||
```ts
|
||||
@Gate({
|
||||
@@ -31,16 +31,16 @@ To apply a feature flag on a **backend** feature use:
|
||||
})
|
||||
```
|
||||
|
||||
To apply a feature flag on a **frontend** feature use:
|
||||
**프론트엔드** 기능에 기능 플래그를 적용하려면 다음을 사용하십시오:
|
||||
|
||||
```ts
|
||||
const isFeatureNameEnabled = useIsFeatureEnabled('IS_FEATURENAME_ENABLED');
|
||||
```
|
||||
|
||||
## Configure feature flags for the deployment
|
||||
## 배포를 위한 기능 플래그 구성
|
||||
|
||||
Change the corresponding record in the Table `core.featureFlag`:
|
||||
테이블 `core.featureFlag`의 해당 레코드 변경:
|
||||
|
||||
| id | key | workspaceId | value |
|
||||
| ------ | ------------------------ | ----------- | ------ |
|
||||
| Random | `IS_FEATURENAME_ENABLED` | WorkspaceID | `true` |
|
||||
| id | 키 | workspaceId | 값 |
|
||||
| -- | ------------------------ | ----------- | --- |
|
||||
| 임의 | `IS_FEATURENAME_ENABLED` | WorkspaceID | `참` |
|
||||
|
||||
+40
-40
@@ -1,9 +1,9 @@
|
||||
---
|
||||
title: Folder Architecture
|
||||
info: A detailed look into our server folder architecture
|
||||
title: 폴더 아키텍처
|
||||
info: 서버 폴더 아키텍처에 대한 상세 분석
|
||||
---
|
||||
|
||||
The backend directory structure is as follows:
|
||||
백엔드 디렉토리 구조는 다음과 같습니다:
|
||||
|
||||
```
|
||||
server
|
||||
@@ -21,37 +21,37 @@ server
|
||||
└───utils
|
||||
```
|
||||
|
||||
## Ability
|
||||
## 권한
|
||||
|
||||
Defines permissions and includes handlers for each entity.
|
||||
각 엔티티에 대한 권한을 정의하고 핸들러를 포함합니다.
|
||||
|
||||
## Decorators
|
||||
## 데코레이터
|
||||
|
||||
Defines custom decorators in NestJS for added functionality.
|
||||
추가 기능을 위한 NestJS 커스텀 데코레이터를 정의합니다.
|
||||
|
||||
See [custom decorators](https://docs.nestjs.com/custom-decorators) for more details.
|
||||
자세한 내용은 [커스텀 데코레이터](https://docs.nestjs.com/custom-decorators)를 참조하세요.
|
||||
|
||||
## Filters
|
||||
## 필터
|
||||
|
||||
Includes exception filters to handle exceptions that might occur in GraphQL endpoints.
|
||||
GraphQL 엔드포인트에서 발생할 수 있는 예외를 처리하기 위한 예외 필터를 포함합니다.
|
||||
|
||||
## Guards
|
||||
## 가드
|
||||
|
||||
See [guards](https://docs.nestjs.com/guards) for more details.
|
||||
자세한 내용은 [가드](https://docs.nestjs.com/guards)를 참조하세요.
|
||||
|
||||
## Health
|
||||
## 상태
|
||||
|
||||
Includes a publicly available REST API (healthz) that returns a JSON to confirm whether the database is working as expected.
|
||||
데이터베이스가 예상대로 작동하는지 확인하기 위해 JSON을 반환하는 공개 API(healthz)를 포함합니다.
|
||||
|
||||
## Metadata
|
||||
## 메타데이터
|
||||
|
||||
Defines custom objects and makes available a GraphQL API (graphql/metadata).
|
||||
커스텀 객체를 정의하고 GraphQL API (graphql/metadata)를 제공합니다.
|
||||
|
||||
## Workspace
|
||||
## 워크스페이스
|
||||
|
||||
Generates and serves custom GraphQL schema based on the metadata.
|
||||
메타데이터 기반의 커스텀 GraphQL 스키마를 생성하고 제공합니다.
|
||||
|
||||
### Workspace Directory Structure
|
||||
### 워크스페이스 디렉터리 구조
|
||||
|
||||
```
|
||||
workspace
|
||||
@@ -83,43 +83,43 @@ workspace
|
||||
└───workspace.factory.ts
|
||||
```
|
||||
|
||||
The root of the workspace directory includes the `workspace.factory.ts`, a file containing the `createGraphQLSchema` function. This function generates workspace-specific schema by using the metadata to tailor a schema for individual workspaces. By separating the schema and resolver construction, we use the `makeExecutableSchema` function, which combines these discrete elements.
|
||||
작업 공간 디렉토리의 루트에는 개별 작업 공간을 위한 스키마를 맞춤화하는 `createGraphQLSchema` 함수가 포함된 `workspace.factory.ts` 파일이 있습니다. 이 함수는 메타데이터를 사용하여 작업 공간별 스키마를 생성합니다. 스키마와 리졸버 구조를 분리하여, 이러한 개별 요소를 결합하는 `makeExecutableSchema` 함수를 사용합니다.
|
||||
|
||||
This strategy is not just about organization, but also helps with optimization, such as caching generated type definitions to enhance performance and scalability.
|
||||
이 전략은 조직화뿐만 아니라 성능 및 확장성을 향상시키기 위해 생성된 타입 정의를 캐시하는 최적화에도 기여합니다.
|
||||
|
||||
### Workspace Schema builder
|
||||
### 작업 공간 스키마 빌더
|
||||
|
||||
Generates the GraphQL schema, and includes:
|
||||
GraphQL 스키마를 생성하며 다음을 포함합니다:
|
||||
|
||||
#### Factories:
|
||||
#### 팩토리:
|
||||
|
||||
Specialised constructors to generate GraphQL-related constructs.
|
||||
GraphQL 관련 구성 요소를 생성하는 특수 생성자입니다.
|
||||
|
||||
* The type.factory translates field metadata into GraphQL types using `TypeMapperService`.
|
||||
* The type-definition.factory creates GraphQL input or output objects derived from `objectMetadata`.
|
||||
* type.factory는 `TypeMapperService`를 사용하여 필드 메타데이터를 GraphQL 타입으로 변환합니다.
|
||||
* type-definition.factory는 `objectMetadata`에서 파생된 GraphQL 입력 또는 출력 객체를 만듭니다.
|
||||
|
||||
#### GraphQL Types
|
||||
#### GraphQL 타입
|
||||
|
||||
Includes enumerations, inputs, objects, and scalars, and serves as the building blocks for the schema construction.
|
||||
열거형, 입력, 객체, 스칼라를 포함하며, 스키마 구축의 기초로 사용됩니다.
|
||||
|
||||
#### Interfaces and Object Definitions
|
||||
#### 인터페이스 및 객체 정의
|
||||
|
||||
Contains the blueprints for GraphQL entities, and includes both predefined and custom types like `MONEY` or `URL`.
|
||||
GraphQL 엔티티를 위한 청사진을 포함하며, `MONEY`나 `URL`과 같은 사전 정의와 커스텀 타입을 포함합니다.
|
||||
|
||||
#### Services
|
||||
#### 서비스
|
||||
|
||||
Contains the service responsible for associating FieldMetadataType with its appropriate GraphQL scalar or query modifiers.
|
||||
FieldMetadataType과 적절한 GraphQL 스칼라 또는 쿼리 수정자를 연결하는 서비스가 포함되어 있습니다.
|
||||
|
||||
#### Storage
|
||||
#### 저장소
|
||||
|
||||
Includes the `TypeDefinitionsStorage` class that contains reusable type definitions, preventing duplication of GraphQL types.
|
||||
GraphQL 타입의 중복을 방지하기 위해 재사용 가능한 타입 정의를 포함하는 `TypeDefinitionsStorage` 클래스를 포함합니다.
|
||||
|
||||
### Workspace Resolver Builder
|
||||
### 작업 공간 리졸버 빌더
|
||||
|
||||
Creates resolver functions for querying and mutating the GraphQL schema.
|
||||
GraphQL 스키마를 쿼리하고 변경하기 위한 리졸버 함수를 만듭니다.
|
||||
|
||||
Each factory in this directory is responsible for producing a distinct resolver type, such as the `FindManyResolverFactory`, designed for adaptable application across various tables.
|
||||
이 디렉토리의 각 팩토리는 다양한 테이블에 걸쳐 적응 가능한 `FindManyResolverFactory`와 같은 명확한 리졸버 타입을 생성할 책임이 있습니다.
|
||||
|
||||
### Workspace Query Runner
|
||||
### 작업 공간 쿼리 실행기
|
||||
|
||||
Runs the generated queries on the database and parses the result.
|
||||
데이터베이스에서 생성된 쿼리를 실행하고 결과를 구문 분석합니다.
|
||||
|
||||
+10
-10
@@ -1,20 +1,20 @@
|
||||
---
|
||||
title: Message Queue
|
||||
title: 메시지 큐
|
||||
---
|
||||
|
||||
Queues facilitate async operations to be performed. They can be used for performing background tasks such as sending a welcome email on register.
|
||||
Each use case will have its own queue class extended from `MessageQueueServiceBase`.
|
||||
큐는 비동기 작업을 수행할 수 있게 합니다. 이들은 회원 가입 시 환영 이메일 보내기와 같은 백그라운드 작업을 수행하는 데 사용될 수 있습니다.
|
||||
각 사용 사례는 `MessageQueueServiceBase`로부터 확장된 자체 큐 클래스를 가집니다.
|
||||
|
||||
Currently, we only support `bull-mq`[bull-mq](https://bullmq.io/) as the queue driver.
|
||||
현재, 큐 드라이버로 `bull-mq`[bull-mq](https://bullmq.io/)만 지원합니다.
|
||||
|
||||
## Steps to create and use a new queue
|
||||
## 새 큐를 생성하고 사용하는 단계
|
||||
|
||||
1. Add a queue name for your new queue under enum `MESSAGE_QUEUES`.
|
||||
2. Provide the factory implementation of the queue with the queue name as the dependency token.
|
||||
3. Inject the queue that you created in the required module/service with the queue name as the dependency token.
|
||||
4. Add worker class with token based injection just like producer.
|
||||
1. 새 큐에 대한 큐 이름을 열거형 `MESSAGE_QUEUES`에 추가합니다.
|
||||
2. 큐 이름을 종속성 토큰으로 하여 큐의 팩토리 구현을 제공합니다.
|
||||
3. 생성한 큐를 큐 이름을 종속성 토큰으로 하여 필요한 모듈/서비스에 주입합니다.
|
||||
4. 프로듀서와 마찬가지로 토큰 기반 주입을 사용하는 워커 클래스를 추가합니다.
|
||||
|
||||
### Example usage
|
||||
### 사용 예시
|
||||
|
||||
```ts
|
||||
class Resolver {
|
||||
|
||||
+28
-29
@@ -1,19 +1,19 @@
|
||||
---
|
||||
title: Backend Commands
|
||||
title: 백엔드 명령어
|
||||
---
|
||||
|
||||
## Useful commands
|
||||
## 유용한 명령어
|
||||
|
||||
These commands should be executed from packages/twenty-server folder.
|
||||
From any other folder you can run `npx nx {command} twenty-server` (or `npx nx run twenty-server:{command}`).
|
||||
이 명령어들은 packages/twenty-server 폴더에서 실행되어야 합니다.
|
||||
다른 폴더에서 `npx nx {command} twenty-server` (또는 `npx nx run twenty-server:{command}`)를 실행할 수 있습니다.
|
||||
|
||||
### First time setup
|
||||
### 최초 설정
|
||||
|
||||
```
|
||||
npx nx database:reset twenty-server # setup the database with dev seeds
|
||||
```
|
||||
|
||||
### Starting the server
|
||||
### 서버 시작
|
||||
|
||||
```
|
||||
npx nx run twenty-server:start
|
||||
@@ -22,80 +22,79 @@ npx nx run twenty-server:start
|
||||
### Lint
|
||||
|
||||
```
|
||||
npx nx run twenty-server:lint # pass --fix to fix lint errors
|
||||
npx nx run twenty-server:lint # lint 오류를 수정하려면 --fix를 사용
|
||||
```
|
||||
|
||||
### Test
|
||||
### 테스트
|
||||
|
||||
```
|
||||
npx nx run twenty-server:test:unit # run unit tests
|
||||
npx nx run twenty-server:test:integration # run integration tests
|
||||
```
|
||||
|
||||
Note: you can run `npx nx run twenty-server:test:integration:with-db-reset` in case you need to reset the database before running the integration tests.
|
||||
참고: 데이터베이스를 재설정한 뒤 통합 테스트를 실행해야 하는 경우 `npx nx run twenty-server:test:integration:with-db-reset`을 실행할 수 있습니다.
|
||||
|
||||
### Resetting the database
|
||||
### 데이터베이스 재설정
|
||||
|
||||
If you want to reset and seed the database, you can run the following command:
|
||||
데이터베이스를 재설정하고 시드 하려면 다음 명령어를 실행하십시오:
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:database:reset
|
||||
```
|
||||
|
||||
### Migrations
|
||||
### 마이그레이션
|
||||
|
||||
#### For objects in Core/Metadata schemas (TypeORM)
|
||||
#### Core/Metadata 스키마의 객체용 (TypeORM)
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### For Workspace objects
|
||||
#### 워크스페이스 객체용
|
||||
|
||||
There are no migrations files, migration are generated automatically for each workspace,
|
||||
stored in the database, and applied with this command
|
||||
마이그레이션 파일이 없으며, 각 작업 공간에 대해 자동 생성되고 데이터베이스에 저장되어 이 명령으로 적용됩니다.
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
This will drop the database and re-run the migrations and seed.
|
||||
이 작업은 데이터베이스를 삭제하고 마이그레이션과 시드를 다시 실행합니다.
|
||||
|
||||
Make sure to back up any data you want to keep before running this command.
|
||||
이 명령을 실행하기 전에 유지하고 싶은 데이터를 백업하십시오.
|
||||
</Warning>
|
||||
|
||||
## Tech Stack
|
||||
## 기술 스택
|
||||
|
||||
Twenty primarily uses NestJS for the backend.
|
||||
Twenty는 주로 NestJS를 백엔드에 사용합니다.
|
||||
|
||||
Prisma was the first ORM we used. But in order to allow users to create custom fields and custom objects, a lower-level made more sense as we need to have fine-grained control. The project now uses TypeORM.
|
||||
Prisma가 우리가 처음으로 사용한 ORM이었습니다. 그러나 사용자들이 사용자 지정 필드와 사용자 지정 객체를 만들 수 있도록 하려면 세밀하게 제어할 수 있어야 하므로 더 낮은 수준이 더 합리적이었습니다. 현재 프로젝트는 TypeORM을 사용합니다.
|
||||
|
||||
Here's what the tech stack now looks like.
|
||||
다음은 현재 기술 스택의 모습입니다.
|
||||
|
||||
**Core**
|
||||
**코어**
|
||||
|
||||
* [NestJS](https://nestjs.com/)
|
||||
* [TypeORM](https://typeorm.io/)
|
||||
* [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server)
|
||||
|
||||
**Database**
|
||||
**데이터베이스**
|
||||
|
||||
* [Postgres](https://www.postgresql.org/)
|
||||
|
||||
**Third-party integrations**
|
||||
**서드파티 연동**
|
||||
|
||||
* [Sentry](https://sentry.io/welcome/) for tracking bugs
|
||||
* 버그 추적을 위한 [Sentry](https://sentry.io/welcome/)
|
||||
|
||||
**Testing**
|
||||
**테스트**
|
||||
|
||||
* [Jest](https://jestjs.io/)
|
||||
|
||||
**Tooling**
|
||||
**도구**
|
||||
|
||||
* [Yarn](https://yarnpkg.com/)
|
||||
* [ESLint](https://eslint.org/)
|
||||
|
||||
**Development**
|
||||
**개발**
|
||||
|
||||
* [AWS EKS](https://aws.amazon.com/eks/)
|
||||
|
||||
+20
-20
@@ -1,18 +1,18 @@
|
||||
---
|
||||
title: Zapier App
|
||||
title: Zapier 앱
|
||||
---
|
||||
|
||||
Effortlessly sync Twenty with 3000+ apps using [Zapier](https://zapier.com/). Automate tasks, boost productivity, and supercharge your customer relationships!
|
||||
[Zapier](https://zapier.com/)을 사용하여 Twenty를 3000개 이상의 앱과 손쉽게 동기화하세요. 작업을 자동화하고 생산성을 높여 고객 관계를 강화하세요!
|
||||
|
||||
## About Zapier
|
||||
## Zapier 소개
|
||||
|
||||
Zapier is a tool that allows you to automate workflows by connecting the apps that your team uses every day. The fundamental concept of Zapier is automation workflows, called Zaps, and include triggers and actions.
|
||||
Zapier는 팀이 매일 사용하는 앱을 연결하여 워크플로우를 자동화할 수 있게 하는 도구입니다. Zapier의 기본 개념은 자동화 워크플로우인 Zaps이며, 이는 트리거와 액션을 포함합니다.
|
||||
|
||||
You can learn more about how Zapier works [here](https://zapier.com/how-it-works).
|
||||
Zapier 작동 방식에 대해 [여기](https://zapier.com/how-it-works)에서 더 알아볼 수 있습니다.
|
||||
|
||||
## Setup
|
||||
## 설정
|
||||
|
||||
### Step 1: Install Zapier packages
|
||||
### 1단계: Zapier 패키지 설치
|
||||
|
||||
```bash
|
||||
cd packages/twenty-zapier
|
||||
@@ -20,33 +20,33 @@ cd packages/twenty-zapier
|
||||
yarn
|
||||
```
|
||||
|
||||
### Step 2: Login with the CLI
|
||||
### 2단계: CLI로 로그인
|
||||
|
||||
Use your Zapier credentials to log in using the CLI:
|
||||
Zapier 자격 증명을 사용하여 CLI로 로그인하세요:
|
||||
|
||||
```bash
|
||||
zapier login
|
||||
```
|
||||
|
||||
### Step 3: Set environment variables
|
||||
### 3단계: 환경 변수 설정
|
||||
|
||||
From the `packages/twenty-zapier` folder, run:
|
||||
`packages/twenty-zapier` 폴더에서 아래 명령을 실행하세요:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Run the application locally, go to [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks), and generate an API key.
|
||||
애플리케이션을 로컬로 실행하고, [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks)에 접속하여 API 키를 생성하세요.
|
||||
|
||||
Replace the **YOUR_API_KEY** value in the `.env` file with the API key you just generated.
|
||||
.env 파일의 **YOUR_API_KEY** 값을 방금 생성한 API 키로 바꾸세요.
|
||||
|
||||
## Development
|
||||
## 개발
|
||||
|
||||
<Warning>
|
||||
Make sure to run `yarn build` before any `zapier` command.
|
||||
`zapier` 명령어를 실행하기 전에 반드시 `yarn build`를 실행하세요.
|
||||
</Warning>
|
||||
|
||||
### Test
|
||||
### 테스트
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
@@ -58,25 +58,25 @@ yarn test
|
||||
yarn format
|
||||
```
|
||||
|
||||
### Watch and compile as you edit code
|
||||
### 코드를 편집할 때 감시 및 컴파일
|
||||
|
||||
```bash
|
||||
yarn watch
|
||||
```
|
||||
|
||||
### Validate your Zapier app
|
||||
### Zapier 앱 검증
|
||||
|
||||
```bash
|
||||
yarn validate
|
||||
```
|
||||
|
||||
### Deploy your Zapier app
|
||||
### Zapier 앱 배포
|
||||
|
||||
```bash
|
||||
yarn deploy
|
||||
```
|
||||
|
||||
### List all Zapier CLI commands
|
||||
### 모든 Zapier CLI 명령 목록
|
||||
|
||||
```bash
|
||||
zapier
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
---
|
||||
title: Bugs, Requests & Pull Requests
|
||||
info: Report issues, request features, and contribute code
|
||||
title: 버그, 요청 및 Pull Request
|
||||
info: 이슈를 보고하고, 기능을 요청하고, 코드에 기여하세요
|
||||
---
|
||||
|
||||
## Reporting Bugs
|
||||
## 버그 신고
|
||||
|
||||
To report a bug, please [create an issue on GitHub](https://github.com/twentyhq/twenty/issues/new).
|
||||
버그를 보고하려면 [GitHub에서 이슈를 생성해 주세요](https://github.com/twentyhq/twenty/issues/new).
|
||||
|
||||
You can also ask for help on [Discord](https://discord.gg/cx5n4Jzs57).
|
||||
[Discord](https://discord.gg/cx5n4Jzs57)에서 도움을 요청할 수도 있습니다.
|
||||
|
||||
## Feature Requests
|
||||
## 기능 요청
|
||||
|
||||
If you're not sure if it's a bug, and you feel it's closer to a feature request, then you should probably [open a discussion instead](https://github.com/twentyhq/twenty/discussions/new).
|
||||
버그인지 확신이 없고 기능 요청에 더 가깝다고 느끼신다면, 대신 [토론을 열어 주세요](https://github.com/twentyhq/twenty/discussions/new).
|
||||
|
||||
## Submit a Pull Request
|
||||
## Pull Request 제출하기
|
||||
|
||||
Contributing code to Twenty starts with a pull request (PR).
|
||||
Twenty에 코드로 기여하는 첫 단계는 Pull Request(PR)입니다.
|
||||
|
||||
### Before You Start
|
||||
### 시작하기 전에
|
||||
|
||||
1. Check [existing issues](https://github.com/twentyhq/twenty/issues) for related work
|
||||
2. For new features, open an issue first to discuss
|
||||
3. Review our [Code of Conduct](https://github.com/twentyhq/twenty/blob/main/CODE_OF_CONDUCT.md)
|
||||
1. 관련 작업이 있는지 [기존 이슈](https://github.com/twentyhq/twenty/issues)를 확인하세요
|
||||
2. 새 기능의 경우 먼저 이슈를 열어 논의하세요
|
||||
3. 우리의 [행동 강령](https://github.com/twentyhq/twenty/blob/main/CODE_OF_CONDUCT.md)을 검토하세요
|
||||
|
||||
### Fork and Clone
|
||||
### 포크하고 클론하기
|
||||
|
||||
1. Fork the repository on GitHub
|
||||
2. Clone your fork:
|
||||
1. GitHub에서 저장소를 포크하세요
|
||||
2. 포크한 저장소를 클론하세요:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/twenty.git
|
||||
cd twenty
|
||||
```
|
||||
|
||||
3. Add upstream remote:
|
||||
3. upstream 원격을 추가하세요:
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/twentyhq/twenty.git
|
||||
```
|
||||
|
||||
### Create a Branch
|
||||
### 브랜치 만들기
|
||||
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
Use descriptive branch names:
|
||||
알기 쉬운 브랜치 이름을 사용하세요:
|
||||
|
||||
* `feature/add-export-button`
|
||||
* `fix/login-redirect-issue`
|
||||
* `docs/update-api-guide`
|
||||
|
||||
### Make Your Changes
|
||||
### 변경 사항 적용하기
|
||||
|
||||
1. Write clean, well-documented code
|
||||
2. Follow existing code style
|
||||
3. Add tests for new functionality
|
||||
4. Update documentation if needed
|
||||
1. 깔끔하고 문서화가 잘 된 코드를 작성하세요
|
||||
2. 기존 코드 스타일을 따르세요
|
||||
3. 새 기능에 대한 테스트를 추가하세요
|
||||
4. 필요하다면 문서를 업데이트하세요
|
||||
|
||||
### Submit Your PR
|
||||
### PR 제출하기
|
||||
|
||||
1. Push your branch:
|
||||
1. 브랜치를 푸시하세요:
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
2. Open a PR on GitHub
|
||||
3. Fill in the PR template
|
||||
4. Link related issues
|
||||
2. GitHub에서 PR을 열어 주세요
|
||||
3. PR 템플릿을 작성하세요
|
||||
4. 관련 이슈를 연결하세요
|
||||
|
||||
### PR Checklist
|
||||
### PR 체크리스트
|
||||
|
||||
* [ ] Code follows project style guidelines
|
||||
* [ ] Tests pass locally
|
||||
* [ ] Documentation is updated
|
||||
* [ ] PR description explains the changes
|
||||
* [ ] 코드가 프로젝트 스타일 가이드라인을 따릅니다
|
||||
* [ ] 로컬에서 테스트가 통과합니다
|
||||
* [ ] 문서가 업데이트되었습니다
|
||||
* [ ] PR 설명이 변경 사항을 설명합니다
|
||||
|
||||
+65
-65
@@ -1,19 +1,19 @@
|
||||
---
|
||||
title: Best Practices
|
||||
title: 모범 사례
|
||||
---
|
||||
|
||||
This document outlines the best practices you should follow when working on the frontend.
|
||||
이 문서는 프론트엔드 작업 시 따라야 할 모범 사례를 설명합니다.
|
||||
|
||||
## State management
|
||||
## 상태 관리
|
||||
|
||||
React and Recoil handle state management in the codebase.
|
||||
React와 Recoil은 코드베이스에서 상태 관리를 처리합니다.
|
||||
|
||||
### Use `useRecoilState` to store state
|
||||
### `useRecoilState`로 상태 저장하기
|
||||
|
||||
It's good practice to create as many atoms as you need to store your state.
|
||||
상태를 저장하는 데 필요한 만큼의 atom을 만드는 것이 좋은 습관입니다.
|
||||
|
||||
<Warning>
|
||||
It's better to use extra atoms than trying to be too concise with props drilling.
|
||||
프롭스 드릴링에 너무 많은 노력을 기울이기보다는 추가 아톰을 사용하는 것이 좋습니다.
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
@@ -36,31 +36,31 @@ export const MyComponent = () => {
|
||||
}
|
||||
```
|
||||
|
||||
### Do not use `useRef` to store state
|
||||
### 상태 저장에 `useRef`를 사용하지 마십시오
|
||||
|
||||
Avoid using `useRef` to store state.
|
||||
상태 저장에 `useRef`를 사용하지 않도록 주의하십시오.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
|
||||
See [how to manage re-renders](#managing-re-renders) if you feel like you need `useRef` to prevent some re-renders from happening.
|
||||
일부 리렌더링을 방지하기 위해 `useRef`가 필요하다고 느낄 경우 [리렌더링 관리 방법](#managing-re-renders)을 참조하십시오.
|
||||
|
||||
## Managing re-renders
|
||||
## 리렌더링 관리
|
||||
|
||||
Re-renders can be hard to manage in React.
|
||||
리액트에서 리렌더링은 관리하기 어려울 수 있습니다.
|
||||
|
||||
Here are some rules to follow to avoid unnecessary re-renders.
|
||||
불필요한 리렌더링을 피하기 위해 따라야 할 몇 가지 규칙이 있습니다.
|
||||
|
||||
Keep in mind that you can **always** avoid re-renders by understanding their cause.
|
||||
리렌더링의 원인을 이해하면 항상 리렌더링을 피할 수 있다는 점을 명심하십시오.
|
||||
|
||||
### Work at the root level
|
||||
### 루트 레벨에서 작업하기
|
||||
|
||||
Avoiding re-renders in new features is now made easy by eliminating them at the root level.
|
||||
새 기능에서 리렌더링을 피하는 것은 이제 루트 수준에서 문제를 제거함으로써 쉬워졌습니다.
|
||||
|
||||
The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.
|
||||
|
||||
That way you know that there's just one place that can trigger a re-render.
|
||||
그렇게 하면 리렌더링을 트리거할 수 있는 곳이 오직 한 곳뿐이라는 것을 알 수 있습니다.
|
||||
|
||||
### Always think twice before adding `useEffect` in your codebase
|
||||
### 코드베이스에 `useEffect`를 추가하기 전에 항상 신중히 고려하세요.
|
||||
|
||||
Re-renders are often caused by unnecessary `useEffect`.
|
||||
|
||||
@@ -68,13 +68,13 @@ You should think whether you need `useEffect`, or if you can move the logic in a
|
||||
|
||||
You'll find it generally easy to move the logic in a `handleClick` or `handleChange` function.
|
||||
|
||||
You can also find them in libraries like Apollo: `onCompleted`, `onError`, etc.
|
||||
Apollo와 같은 라이브러리에서 `onCompleted`, `onError` 등을 찾을 수 있습니다.
|
||||
|
||||
### Use a sibling component to extract `useEffect` or data fetching logic
|
||||
|
||||
If you feel like you need to add a `useEffect` in your root component, you should consider extracting it in a sidecar component.
|
||||
|
||||
You can apply the same for data fetching logic, with Apollo hooks.
|
||||
Apollo 훅을 사용하여 데이터 페칭 로직에 동일한 규칙을 적용할 수 있습니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
@@ -129,43 +129,43 @@ export const App = () => (
|
||||
);
|
||||
```
|
||||
|
||||
### Use recoil family states and recoil family selectors
|
||||
### Recoil 가족 상태 및 Recoil 가족 선택자 사용하기
|
||||
|
||||
Recoil family states and selectors are a great way to avoid re-renders.
|
||||
Recoil 가족 상태와 선택자는 리렌더링을 피하기 위한 훌륭한 방법입니다.
|
||||
|
||||
They are useful when you need to store a list of items.
|
||||
항목 목록을 저장해야 할 때 유용합니다.
|
||||
|
||||
### You shouldn't use `React.memo(MyComponent)`
|
||||
### `React.memo(MyComponent)`를 사용하지 마십시오
|
||||
|
||||
Avoid using `React.memo()` because it does not solve the cause of the re-render, but instead breaks the re-render chain, which can lead to unexpected behavior and make the code very hard to refactor.
|
||||
`React.memo()`를 사용하지 마십시오. 이것은 리렌더링의 원인을 해결하지 않으며, 대신 리렌더 체인을 끊어 의도치 않은 동작을 유발하고 코드 리팩토링을 매우 어렵게 만듭니다.
|
||||
|
||||
### Limit `useCallback` or `useMemo` usage
|
||||
### `useCallback` 또는 `useMemo` 사용 제한
|
||||
|
||||
They are often not necessary and will make the code harder to read and maintain for a gain of performance that is unnoticeable.
|
||||
이들은 종종 필요하지 않으며, 성능 향상을 위해 코드 읽기와 유지보수를 어렵게 만듭니다.
|
||||
|
||||
## Console.logs
|
||||
|
||||
`console.log` statements are valuable during development, offering real-time insights into variable values and code flow. But, leaving them in production code can lead to several issues:
|
||||
`console.log` 문은 개발 중에 변수 값과 코드 흐름에 대한 실시간 정보를 제공합니다. 그러나 생산 코드에 남아 있으면 여러 문제를 일으킬 수 있습니다.
|
||||
|
||||
1. **Performance**: Excessive logging can affect the runtime performance, especially on client-side applications.
|
||||
1. **성능**: 과도한 로깅은 특히 클라이언트 측 애플리케이션의 경우 런타임 성능에 영향을 미칠 수 있습니다.
|
||||
|
||||
2. **Security**: Logging sensitive data can expose critical information to anyone who inspects the browser's console.
|
||||
2. **보안**: 민감한 데이터 로깅은 브라우저 콘솔을 검사하는 누구나 중요한 정보를 노출할 수 있습니다.
|
||||
|
||||
3. **Cleanliness**: Filling up the console with logs can obscure important warnings or errors that developers or tools need to see.
|
||||
3. **깔끔함**: 콘솔을 로그로 가득 채우면 개발자나 도구가 필요한 중요한 경고나 오류를 가릴 수 있습니다.
|
||||
|
||||
4. **Professionalism**: End users or clients checking the console and seeing a myriad of log statements might question the code's quality and polish.
|
||||
4. **전문성**: 사용자가 콘솔을 확인하고 수많은 로그를 보면 코드의 품질과 정교함을 의심할 수 있습니다.
|
||||
|
||||
Make sure you remove all `console.logs` before pushing the code to production.
|
||||
생산 환경에 코드를 올리기 전에 모든 `console.logs`를 제거해야 합니다.
|
||||
|
||||
## Naming
|
||||
## 이름 지정
|
||||
|
||||
### Variable Naming
|
||||
### 변수 이름 지정
|
||||
|
||||
Variable names ought to precisely depict the purpose or function of the variable.
|
||||
변수 이름은 변수의 목적이나 기능을 정확히 설명해야 합니다.
|
||||
|
||||
#### The issue with generic names
|
||||
#### 일반적인 이름의 문제
|
||||
|
||||
Generic names in programming are not ideal because they lack specificity, leading to ambiguity and reduced code readability. Such names fail to convey the variable or function's purpose, making it challenging for developers to understand the code's intent without deeper investigation. This can result in increased debugging time, higher susceptibility to errors, and difficulties in maintenance and collaboration. Meanwhile, descriptive naming makes the code self-explanatory and easier to navigate, enhancing code quality and developer productivity.
|
||||
프로그래밍에서 일반적인 이름은 특수성이 부족하여 모호성을 유발하고 코드 가독성을 감소시킵니다. 이름이 변수나 함수의 목적을 전달하지 않으면 개발자가 코드의 의도를 깊이 조사해야 합니다. 이로 인해 디버깅 시간이 증가하고 오류에 더 많이 노출되며 유지보수와 협업에 어려움이 생길 수 있습니다. 반면에 설명적인 이름을 사용하면 코드가 자가 설명적이 되고 탐색하기 쉬워져 코드 품질과 개발자 생산성을 향상시킵니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, uses a generic name that doesn't communicate its
|
||||
@@ -178,13 +178,13 @@ const [value, setValue] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
```
|
||||
|
||||
#### Some words to avoid in variable names
|
||||
#### 변수 이름에서 피해야 할 단어들
|
||||
|
||||
* dummy
|
||||
* 더미
|
||||
|
||||
### Event handlers
|
||||
### 이벤트 핸들러
|
||||
|
||||
Event handler names should start with `handle`, while `on` is a prefix used to name events in components props.
|
||||
이벤트 핸들러 이름은 `handle`로 시작해야 하고, `on`은 컴포넌트 속성의 이벤트 이름 지정에 사용됩니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
@@ -200,13 +200,13 @@ const handleEmailChange = (val: string) => {
|
||||
};
|
||||
```
|
||||
|
||||
## Optional Props
|
||||
## 선택적 Props
|
||||
|
||||
Avoid passing the default value for an optional prop.
|
||||
선택적 프로퍼티에 대한 기본값 전달을 피하십시오.
|
||||
|
||||
**EXAMPLE**
|
||||
**예시**
|
||||
|
||||
Take the`EmailField` component defined below:
|
||||
다음과 같은 `EmailField` 컴포넌트를 보십시오:
|
||||
|
||||
```tsx
|
||||
type EmailFieldProps = {
|
||||
@@ -219,7 +219,7 @@ const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
|
||||
);
|
||||
```
|
||||
|
||||
**Usage**
|
||||
**사용법**
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, passing in the same value as the default value adds no value
|
||||
@@ -231,11 +231,11 @@ const Form = () => <EmailField value="username@email.com" disabled={false} />;
|
||||
const Form = () => <EmailField value="username@email.com" />;
|
||||
```
|
||||
|
||||
## Component as props
|
||||
## 프로퍼티로써 컴포넌트
|
||||
|
||||
Try as much as possible to pass uninstantiated components as props, so children can decide on their own of what props they need to pass.
|
||||
가능한 한, 인스턴스화되지 않은 컴포넌트를 prop으로 전달하여 자식이 필요한 prop을 스스로 결정할 수 있도록 하세요.
|
||||
|
||||
The most common example for that is icon components:
|
||||
가장 일반적인 예는 아이콘 컴포넌트입니다.
|
||||
|
||||
```tsx
|
||||
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;
|
||||
@@ -252,25 +252,25 @@ const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
|
||||
};
|
||||
```
|
||||
|
||||
For React to understand that the component is a component, you need to use PascalCase, to later instantiate it with `<MyIcon>`
|
||||
React가 컴포넌트를 컴포넌트로 인식하려면, PascalCase를 사용하여 나중에 `<MyIcon>`으로 인스턴스화해야 합니다.
|
||||
|
||||
## Prop Drilling: Keep It Minimal
|
||||
## Prop 드릴링: 최소화하기
|
||||
|
||||
Prop drilling, in the React context, refers to the practice of passing state variables and their setters through many component layers, even if intermediary components don't use them. While sometimes necessary, excessive prop drilling can lead to:
|
||||
React에서 prop 드릴링은 상태 변수 및 그 설정자를 중간 컴포넌트가 사용하지 않더라도 여러 컴포넌트 계층에 걸쳐 전달하는 관행을 의미합니다. 가끔 필요할 수 있지만, 과도한 prop 드릴링은 다음과 같은 문제를 초래할 수 있습니다:
|
||||
|
||||
1. **Decreased Readability**: Tracing where a prop originates or where it's utilized can become convoluted in a deeply nested component structure.
|
||||
1. **읽기 어려움**: prop이 어디서 시작되었고 어디에서 사용되는지를 추적하는 것이 깊게 중첩된 컴포넌트 구조에서는 복잡해질 수 있습니다.
|
||||
|
||||
2. **Maintenance Challenges**: Changes in one component's prop structure might require adjustments in several components, even if they don't directly use the prop.
|
||||
2. **유지보수의 어려움**: 한 컴포넌트의 prop 구조의 변화는, 해당 prop을 직접 사용하지 않더라도 여러 컴포넌트에서의 조정이 필요할 수 있습니다.
|
||||
|
||||
3. **Reduced Component Reusability**: A component receiving a lot of props solely for passing them down becomes less general-purpose and harder to reuse in different contexts.
|
||||
3. **컴포넌트 재사용성 감소**: 많은 prop을 전달하기 위한 컴포넌트는 그 용도가 덜 일반적이게 되며, 다양한 컨텍스트에서 재사용하기 어려워집니다.
|
||||
|
||||
If you feel that you are using excessive prop drilling, see [state management best practices](#state-management).
|
||||
과도한 prop 드릴링을 사용하고 있다고 느껴진다면, [상태 관리 최적 관행](#state-management)을 참조하세요.
|
||||
|
||||
## Imports
|
||||
## 가져오기
|
||||
|
||||
When importing, opt for the designated aliases rather than specifying complete or relative paths.
|
||||
가져올 때는, 지정된 별칭을 사용하고 전체나 상대 경로를 지정하지 않도록 하세요.
|
||||
|
||||
**The Aliases**
|
||||
**별칭 처리**
|
||||
|
||||
```js
|
||||
{
|
||||
@@ -282,7 +282,7 @@ When importing, opt for the designated aliases rather than specifying complete o
|
||||
}
|
||||
```
|
||||
|
||||
**Usage**
|
||||
**사용법**
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, specifies the entire relative path
|
||||
@@ -300,9 +300,9 @@ import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
```
|
||||
|
||||
## Schema Validation
|
||||
## 스키마 유효성 검사
|
||||
|
||||
[Zod](https://github.com/colinhacks/zod) is the schema validator for untyped objects:
|
||||
[Zod](https://github.com/colinhacks/zod)는 타이핑되지 않은 객체를 위한 스키마 유효성 검사기입니다:
|
||||
|
||||
```js
|
||||
const validationSchema = z
|
||||
@@ -320,6 +320,6 @@ const validationSchema = z
|
||||
type Form = z.infer<typeof validationSchema>;
|
||||
```
|
||||
|
||||
## Breaking Changes
|
||||
## 파괴적 변경
|
||||
|
||||
Always perform thorough manual testing before proceeding to guarantee that modifications haven’t caused disruptions elsewhere, given that tests have not yet been extensively integrated.
|
||||
테스트가 아직 광범위하게 통합되지 않았으므로, 변경 사항이 다른 부분에 문제를 일으키지 않았는지 철저한 수동 테스트를 통해 보장하세요.
|
||||
|
||||
+36
-36
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: Folder Architecture
|
||||
info: A detailed look into our folder architecture
|
||||
title: 폴더 아키텍처
|
||||
info: 우리의 폴더 아키텍처를 자세히 살펴보기
|
||||
---
|
||||
|
||||
In this guide, you will explore the details of the project directory structure and how it contributes to the organization and maintainability of Twenty.
|
||||
이 가이드에서는 프로젝트 디렉토리 구조의 세부 사항과 그것이 Twenty의 구조화와 유지관리성에 어떻게 기여하는지 살펴봅니다.
|
||||
|
||||
By following this folder architecture convention, it's easier to find the files related to specific features and ensure that the application is scalable and maintainable.
|
||||
이 폴더 아키텍처 관례를 따르면 특정 기능과 관련된 파일을 더 쉽게 찾을 수 있고, 애플리케이션의 확장성과 유지관리성을 보장하기가 쉬워집니다.
|
||||
|
||||
```
|
||||
front
|
||||
@@ -22,14 +22,14 @@ front
|
||||
└───...
|
||||
```
|
||||
|
||||
## Pages
|
||||
## 페이지
|
||||
|
||||
Includes the top-level components defined by the application routes. They import more low-level components from the modules folder (more details below).
|
||||
애플리케이션 라우트로 정의된 최상위 컴포넌트를 포함합니다. 모듈 폴더에서 더 하위 수준의 컴포넌트를 가져옵니다(자세한 내용은 아래를 참조하세요).
|
||||
|
||||
## Modules
|
||||
## 모듈
|
||||
|
||||
Each module represents a feature or a group of feature, comprising its specific components, states, and operational logic.
|
||||
They should all follow the structure below. You can nest modules within modules (referred to as submodules) and the same rules will apply.
|
||||
각 모듈은 특정 컴포넌트, 상태 및 운영 로직을 포함하는 기능 또는 기능 그룹을 나타냅니다.
|
||||
모두 아래 구조를 따라야 합니다. 모듈 안에 모듈을 중첩할 수 있으며(이를 서브모듈이라고 하며), 동일한 규칙이 적용됩니다.
|
||||
|
||||
```
|
||||
module1
|
||||
@@ -50,60 +50,60 @@ module1
|
||||
└───utils
|
||||
```
|
||||
|
||||
### Contexts
|
||||
### 컨텍스트
|
||||
|
||||
A context is a way to pass data through the component tree without having to pass props down manually at every level.
|
||||
컨텍스트는 각 레벨에서 수동으로 props를 전달하지 않고, 컴포넌트 트리를 통해 데이터를 전달할 수 있는 방법입니다.
|
||||
|
||||
See [React Context](https://react.dev/reference/react#context-hooks) for more details.
|
||||
자세한 내용은 [React Context](https://react.dev/reference/react#context-hooks)를 참조하세요.
|
||||
|
||||
### GraphQL
|
||||
|
||||
Includes fragments, queries, and mutations.
|
||||
프래그먼트, 쿼리 및 뮤테이션이 포함됩니다.
|
||||
|
||||
See [GraphQL](https://graphql.org/learn/) for more details.
|
||||
자세한 내용은 [GraphQL](https://graphql.org/learn/)을 참조하세요.
|
||||
|
||||
* Fragments
|
||||
* 프래그먼트
|
||||
|
||||
A fragment is a reusable piece of a query, which you can use in different places. By using fragments, it's easier to avoid duplicating code.
|
||||
프래그먼트는 쿼리의 재사용 가능한 조각으로, 여러 장소에서 사용할 수 있습니다. 프래그먼트를 사용하면 코드 중복을 피하기가 더 쉬워집니다.
|
||||
|
||||
See [GraphQL Fragments](https://graphql.org/learn/queries/#fragments) for more details.
|
||||
자세한 내용은 [GraphQL 프래그먼트](https://graphql.org/learn/queries/#fragments)를 참조하세요.
|
||||
|
||||
* Queries
|
||||
* 쿼리
|
||||
|
||||
See [GraphQL Queries](https://graphql.org/learn/queries/) for more details.
|
||||
자세한 내용은 [GraphQL 쿼리](https://graphql.org/learn/queries/)를 참조하세요.
|
||||
|
||||
* Mutations
|
||||
* 뮤테이션
|
||||
|
||||
See [GraphQL Mutations](https://graphql.org/learn/queries/#mutations) for more details.
|
||||
자세한 내용은 [GraphQL 뮤테이션](https://graphql.org/learn/queries/#mutations)을 참조하세요.
|
||||
|
||||
### Hooks
|
||||
### 훅
|
||||
|
||||
See [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) for more details.
|
||||
자세한 내용은 [훅](https://react.dev/learn/reusing-logic-with-custom-hooks)을 참조하세요.
|
||||
|
||||
### States
|
||||
### 상태
|
||||
|
||||
Contains the state management logic. [RecoilJS](https://recoiljs.org) handles this.
|
||||
상태 관리 로직이 포함되어 있습니다. [RecoilJS](https://recoiljs.org)가 이것을 처리합니다.
|
||||
|
||||
* Selectors: See [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) for more details.
|
||||
* 셀렉터: 자세한 내용은 [RecoilJS 셀렉터](https://recoiljs.org/docs/basic-tutorial/selectors)를 참조하세요.
|
||||
|
||||
React's built-in state management still handles state within a component.
|
||||
React의 내장 상태 관리는 구성 요소 내에서의 상태를 여전히 처리합니다.
|
||||
|
||||
### Utils
|
||||
### 유틸
|
||||
|
||||
Should just contain reusable pure functions. Otherwise, create custom hooks in the `hooks` folder.
|
||||
재사용 가능한 순수 함수를 포함해야 합니다. 그렇지 않으면 `hooks` 폴더에 커스텀 훅을 만들어야 합니다.
|
||||
|
||||
## UI
|
||||
|
||||
Contains all the reusable UI components used in the application.
|
||||
애플리케이션에서 사용되는 모든 재사용 가능한 UI 컴포넌트를 포함합니다.
|
||||
|
||||
This folder can contain sub-folders, like `data`, `display`, `feedback`, and `input` for specific types of components. Each component should be self-contained and reusable, so that you can use it in different parts of the application.
|
||||
이 폴더는 `data`, `display`, `feedback`, `input`과 같은 특정 유형의 컴포넌트에 대한 하위 폴더를 포함할 수 있습니다. 각 컴포넌트는 자기 완결적이고 재사용 가능해야 하며, 애플리케이션의 다른 부분에서 사용할 수 있어야 합니다.
|
||||
|
||||
By separating the UI components from the other components in the `modules` folder, it's easier to maintain a consistent design and to make changes to the UI without affecting other parts (business logic) of the codebase.
|
||||
`modules` 폴더의 다른 컴포넌트에서 UI 컴포넌트를 분리함으로써 일관된 디자인을 유지하고, 코드베이스의 다른 부분(비즈니스 로직)에 영향을 주지 않고 UI를 변경하기가 더 쉬워집니다.
|
||||
|
||||
## Interface and dependencies
|
||||
## 인터페이스 및 종속성
|
||||
|
||||
You can import other module code from any module except for the `ui` folder. This will keep its code easy to test.
|
||||
`ui` 폴더를 제외한 모든 모듈에서 다른 모듈 코드를 가져올 수 있습니다. 이렇게 하면 코드를 쉽게 테스트할 수 있습니다.
|
||||
|
||||
### Internal
|
||||
### 내부
|
||||
|
||||
Each part (hooks, states, ...) of a module can have an `internal` folder, which contains parts that are just used within the module.
|
||||
각 부분(훅, 상태, ...) 모듈의 각 부분은 모듈 내에서만 사용하는 `internal` 폴더를 가질 수 있습니다.
|
||||
|
||||
+23
-23
@@ -1,41 +1,41 @@
|
||||
---
|
||||
title: Frontend Commands
|
||||
title: 프론트엔드 명령어
|
||||
---
|
||||
|
||||
## Useful commands
|
||||
## 유용한 명령어
|
||||
|
||||
### Starting the app
|
||||
### 앱 시작하기
|
||||
|
||||
```bash
|
||||
npx nx start twenty-front
|
||||
```
|
||||
|
||||
### Regenerate graphql schema based on API graphql schema
|
||||
### API GraphQL 스키마를 기반으로 GraphQL 스키마 재생성
|
||||
|
||||
```bash
|
||||
npx nx run twenty-front:graphql:generate --configuration=metadata
|
||||
```
|
||||
|
||||
OR
|
||||
또는
|
||||
|
||||
```bash
|
||||
npx nx run twenty-front:graphql:generate
|
||||
```
|
||||
|
||||
### Lint
|
||||
### 린트
|
||||
|
||||
```bash
|
||||
npx nx run twenty-front:lint # pass --fix to fix lint errors
|
||||
```
|
||||
|
||||
## Translations
|
||||
## 번역
|
||||
|
||||
```bash
|
||||
npx nx run twenty-front:lingui:extract
|
||||
npx nx run twenty-front:lingui:compile
|
||||
```
|
||||
|
||||
### Test
|
||||
### 테스트
|
||||
|
||||
```bash
|
||||
npx nx run twenty-front:test # run jest tests
|
||||
@@ -44,11 +44,11 @@ npx nx run twenty-front:storybook:test # run tests # (needs yarn storybook:serve
|
||||
npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to be running)
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
## 기술 스택
|
||||
|
||||
The project has a clean and simple stack, with minimal boilerplate code.
|
||||
프로젝트는 최소한의 보일러플레이트 코드로 깔끔하고 단순한 스택을 가지고 있습니다.
|
||||
|
||||
**App**
|
||||
**앱**
|
||||
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
@@ -56,35 +56,35 @@ The project has a clean and simple stack, with minimal boilerplate code.
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testing**
|
||||
**테스트**
|
||||
|
||||
* [Jest](https://jestjs.io/)
|
||||
* [Storybook](https://storybook.js.org/)
|
||||
|
||||
**Tooling**
|
||||
**도구**
|
||||
|
||||
* [Yarn](https://yarnpkg.com/)
|
||||
* [Craco](https://craco.js.org/docs/)
|
||||
* [ESLint](https://eslint.org/)
|
||||
|
||||
## Architecture
|
||||
## 아키텍처
|
||||
|
||||
### Routing
|
||||
### 라우팅
|
||||
|
||||
[React Router](https://reactrouter.com/) handles the routing.
|
||||
[React Router](https://reactrouter.com/)가 라우팅을 처리합니다.
|
||||
|
||||
To avoid unnecessary [re-renders](/l/ko/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`.
|
||||
|
||||
### State Management
|
||||
### 상태 관리
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) handles state management.
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts)이 상태 관리를 처리합니다.
|
||||
|
||||
See [best practices](/l/ko/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) for more information on state management.
|
||||
상태 관리에 대한 자세한 정보는 [최고의 관례](/l/ko/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)를 참조하십시오.
|
||||
|
||||
## Testing
|
||||
## 테스트
|
||||
|
||||
[Jest](https://jestjs.io/) serves as the tool for unit testing while [Storybook](https://storybook.js.org/) is for component testing.
|
||||
[Jest](https://jestjs.io/)는 유닛 테스트 도구로 사용되고 [Storybook](https://storybook.js.org/)은 컴포넌트 테스트에 사용됩니다.
|
||||
|
||||
Jest is mainly for testing utility functions, and not components themselves.
|
||||
Jest는 주로 유틸리티 함수 테스트에 사용되며, 직접 컴포넌트를 테스트하지는 않습니다.
|
||||
|
||||
Storybook is for testing the behavior of isolated components, as well as displaying the design system.
|
||||
Storybook은 개별 컴포넌트의 동작을 테스트하고 디자인 시스템을 표시하는 데 사용됩니다.
|
||||
|
||||
+34
-34
@@ -1,42 +1,42 @@
|
||||
---
|
||||
title: Hotkeys
|
||||
title: 단축키
|
||||
---
|
||||
|
||||
## Introduction
|
||||
## 소개
|
||||
|
||||
When you need to listen to a hotkey, you would normally use the `onKeyDown` event listener.
|
||||
단축키를 들으려면 일반적으로 `onKeyDown` 이벤트 리스너를 사용합니다.
|
||||
|
||||
In `twenty-front` however, you might have conflicts between same hotkeys that are used in different components, mounted at the same time.
|
||||
그러나 `twenty-front`에서는 동일한 시점에 장착된 다른 구성 요소에서 사용되는 같은 단축키 간에 충돌이 발생할 수 있습니다.
|
||||
|
||||
For example, if you have a page that listens for the Enter key, and a modal that listens for the Enter key, with a Select component inside that modal that listens for the Enter key, you might have a conflict when all are mounted at the same time.
|
||||
예를 들어, Enter 키를 듣는 페이지가 있고, Enter 키를 듣는 모달이 있으며, 그 모달 내에서 Enter 키를 듣는 Select 구성요소가 있다면, 모두 동시에 마운트될 때 충돌이 발생할 수 있습니다.
|
||||
|
||||
## The `useScopedHotkeys` hook
|
||||
## `useScopedHotkeys` 훅
|
||||
|
||||
To handle this problem, we have a custom hook that makes it possible to listen to hotkeys without any conflict.
|
||||
이 문제를 해결하기 위해, 우리는 충돌 없이 단축키를 들을 수 있게 하는 커스텀 훅을 만들었습니다.
|
||||
|
||||
You place it in a component, and it will listen to the hotkeys only when the component is mounted AND when the specified **hotkey scope** is active.
|
||||
이를 구성 요소에 배치하면 구성 요소가 마운트될 때 및 지정한 **단축키 스코프**가 활성화될 때만 단축키를 듣습니다.
|
||||
|
||||
## How to listen for hotkeys in practice?
|
||||
## 실제로 단축키를 감지하려면 어떻게 하나요?
|
||||
|
||||
There are two steps involved in setting up hotkey listening :
|
||||
단축키 청취를 설정하는 데 두 가지 단계가 있습니다:
|
||||
|
||||
1. Set the [hotkey scope](#what-is-a-hotkey-scope-) that will listen to hotkeys
|
||||
2. Use the `useScopedHotkeys` hook to listen to hotkeys
|
||||
1. 단축키를 들을 [단축키 스코프](#what-is-a-hotkey-scope-)를 설정합니다.
|
||||
2. 단축키를 듣기 위해 `useScopedHotkeys` 훅을 사용합니다.
|
||||
|
||||
Setting up hotkey scopes is required even in simple pages, because other UI elements like left menu or command menu might also listen to hotkeys.
|
||||
기본 페이지에서도 단축키 스코프를 설정해야 합니다. 왼쪽 메뉴나 명령 메뉴와 같은 다른 UI 요소도 단축키를 들을 수 있기 때문입니다.
|
||||
|
||||
## Use cases for hotkeys
|
||||
## 단축키 사용 사례
|
||||
|
||||
In general, you'll have two use cases that require hotkeys :
|
||||
일반적으로, 두 가지 단축키를 필요로 하는 사용 사례가 있습니다:
|
||||
|
||||
1. In a page or a component mounted in a page
|
||||
2. In a modal-type component that takes the focus due to a user action
|
||||
1. 페이지 또는 페이지에 마운트된 구성 요소
|
||||
2. 사용자 작업으로 인해 포커스를 차지하는 모달 형 구성 요소
|
||||
|
||||
The second use case can happen recursively : a dropdown in a modal for example.
|
||||
두 번째 사용 사례는 재귀적으로 발생할 수 있습니다: 예를 들어, 모달의 드롭다운.
|
||||
|
||||
### Listening to hotkeys in a page
|
||||
### 페이지에서 단축키 듣기
|
||||
|
||||
Example :
|
||||
예시:
|
||||
|
||||
```tsx
|
||||
const PageListeningEnter = () => {
|
||||
@@ -71,11 +71,11 @@ const PageListeningEnter = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Listening to hotkeys in a modal-type component
|
||||
### 모달 형 구성 요소에서 단축키 듣기
|
||||
|
||||
For this example we'll use a modal component that listens for the Escape key to tell its parent to close it.
|
||||
이 예시에서는 부모에게 모달을 닫으라고 알리기 위해 Escape 키를 듣는 모달 구성 요소를 사용합니다.
|
||||
|
||||
Here the user interaction is changing the scope.
|
||||
여기서 사용자 상호작용은 범위를 변경합니다.
|
||||
|
||||
```tsx
|
||||
const ExamplePageWithModal = () => {
|
||||
@@ -108,7 +108,7 @@ const ExamplePageWithModal = () => {
|
||||
};
|
||||
```
|
||||
|
||||
Then in the modal component :
|
||||
그러면 모달 구성 요소에서:
|
||||
|
||||
```tsx
|
||||
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
|
||||
@@ -131,15 +131,15 @@ It's important to use this pattern when you're not sure that just using a useEff
|
||||
|
||||
Those conflicts can be hard to debug, and it might happen more often than not with useEffects.
|
||||
|
||||
## What is a hotkey scope?
|
||||
## 단축키 스코프란 무엇인가요?
|
||||
|
||||
A hotkey scope is a string that represents a context in which the hotkeys are active. It is generally encoded as an enum.
|
||||
단축키 스코프는 단축키가 활성 상태인 컨텍스트를 나타내는 문자열입니다. 일반적으로 열거형으로 인코딩됩니다.
|
||||
|
||||
When you change the hotkey scope, the hotkeys that are listening to this scope will be enabled and the hotkeys that are listening to other scopes will be disabled.
|
||||
단축키 스코프를 변경하면 해당 스코프를 듣고 있는 단축키는 활성화되고 다른 스코프를 듣고 있는 단축키는 비활성화됩니다.
|
||||
|
||||
You can set only one scope at a time.
|
||||
한 번에 하나의 스코프만 설정할 수 있습니다.
|
||||
|
||||
As an example, the hotkey scopes for each page are defined in the `PageHotkeyScope` enum:
|
||||
예를 들어 각 페이지의 단축키 스코프는 `PageHotkeyScope` 열거형에 정의되어 있습니다:
|
||||
|
||||
```tsx
|
||||
export enum PageHotkeyScope {
|
||||
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Internally, the currently selected scope is stored in a Recoil state that is shared across the application :
|
||||
내부적으로, 현재 선택한 스코프는 애플리케이션 전반에 걸쳐 공유되는 Recoil 상태에 저장됩니다:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
But this Recoil state should never be handled manually ! We'll see how to use it in the next section.
|
||||
하지만 이 Recoil 상태는 수동으로 처리해서는 안 됩니다! 다음 섹션에서 사용하는 방법을 배웁니다.
|
||||
|
||||
## How is it working internally?
|
||||
## 내부적으로 어떻게 작동합니까?
|
||||
|
||||
We made a thin wrapper on top of [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) that makes it more performant and avoids unnecessary re-renders.
|
||||
[react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) 위에 얇은 래퍼를 만들어 성능을 높이고 불필요한 재랜더링을 방지합니다.
|
||||
|
||||
We also create a Recoil state to handle the hotkey scope state and make it available everywhere in the application.
|
||||
또한 핫키 스코프 상태를 처리하고 애플리케이션 전반에서 사용할 수 있도록 한 Recoil 상태를 만듭니다.
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
---
|
||||
title: Storybook
|
||||
description: Browse Twenty's UI component library
|
||||
description: Twenty의 UI 컴포넌트 라이브러리 둘러보기
|
||||
---
|
||||
|
||||
View our complete component library and documentation in Storybook.
|
||||
스토리북에서 완전한 컴포넌트 라이브러리와 문서를 확인하세요.
|
||||
|
||||
[Open Storybook →](https://storybook.twenty.com)
|
||||
[Storybook 열기 →](https://storybook.twenty.com)
|
||||
|
||||
+61
-61
@@ -1,24 +1,24 @@
|
||||
---
|
||||
title: Style Guide
|
||||
title: 스타일 가이드
|
||||
---
|
||||
|
||||
This document includes the rules to follow when writing code.
|
||||
이 문서에는 코드 작성 시 따라야 할 규칙이 포함되어 있습니다.
|
||||
|
||||
The goal here is to have a consistent codebase, which is easy to read and easy to maintain.
|
||||
여기서 목표는 읽기 쉽고 유지 관리가 쉬운 일관된 코드베이스를 갖는 것입니다.
|
||||
|
||||
For this, it's better to be a bit more verbose than to be too concise.
|
||||
이를 위해서는 너무 간결하기보다는 약간 더 장황한 것이 낫습니다.
|
||||
|
||||
Always keep in mind that people read code more often than they write it, specially on an open source project, where anyone can contribute.
|
||||
항상 사람들이 코드를 작성하는 것보다 더 자주 읽는다는 점을 염두에 두십시오. 특히 누구나 기여할 수 있는 오픈 소스 프로젝트에서 그렇습니다.
|
||||
|
||||
There are a lot of rules that are not defined here, but that are automatically checked by linters.
|
||||
여기에 정의되지 않은 많은 규칙이 있지만 린터에 의해 자동으로 확인됩니다.
|
||||
|
||||
## React
|
||||
## 리액트
|
||||
|
||||
### Use functional components
|
||||
### 함수형 컴포넌트 사용
|
||||
|
||||
Always use TSX functional components.
|
||||
항상 TSX 함수형 컴포넌트를 사용하십시오.
|
||||
|
||||
Do not use default `import` with `const`, because it's harder to read and harder to import with code completion.
|
||||
기본 `import`를 `const`와 함께 사용하지 마십시오. 읽기 어렵고 코드 자동 완성으로 import하기 어렵습니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, harder to read, harder to import with code completion
|
||||
@@ -34,11 +34,11 @@ export function MyComponent() {
|
||||
};
|
||||
```
|
||||
|
||||
### Props
|
||||
### 프로퍼티
|
||||
|
||||
Create the type of the props and call it `(ComponentName)Props` if there's no need to export it.
|
||||
props의 유형을 만들고 내보낼 필요가 없으면 `(ComponentName)Props`라고 명명하십시오.
|
||||
|
||||
Use props destructuring.
|
||||
props 구조 분해를 사용하십시오.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, no type
|
||||
@@ -52,7 +52,7 @@ type MyComponentProps = {
|
||||
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
|
||||
```
|
||||
|
||||
#### Refrain from using `React.FC` or `React.FunctionComponent` to define prop types
|
||||
#### prop 유형을 정의하기 위해 `React.FC` 또는 `React.FunctionComponent`를 사용하지 마십시오.
|
||||
|
||||
```tsx
|
||||
/* ❌ - Bad, defines the component type annotations with `FC`
|
||||
@@ -67,10 +67,10 @@ const EmailField: React.FC<{
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* ✅ - Good, a separate type (OwnProps) is explicitly defined for the
|
||||
* component's props
|
||||
* - This method doesn't automatically include the children prop. If
|
||||
* you want to include it, you have to specify it in OwnProps.
|
||||
/* ✅ - 좋음, 별도의 타입(OwnProps)을 명시적으로 정의합니다
|
||||
* 컴포넌트의 props에 대해
|
||||
* - 이 방법은 children prop을 자동으로 포함하지 않습니다. 포함하려면
|
||||
* OwnProps에 명시해야 합니다.
|
||||
*/
|
||||
type EmailFieldProps = {
|
||||
value: string;
|
||||
@@ -81,9 +81,9 @@ const EmailField = ({ value }: EmailFieldProps) => (
|
||||
);
|
||||
```
|
||||
|
||||
#### No Single Variable Prop Spreading in JSX Elements
|
||||
#### JSX 요소에서 단일 변수 prop 확산 방지
|
||||
|
||||
Avoid using single variable prop spreading in JSX elements, like `{...props}`. This practice often results in code that is less readable and harder to maintain because it's unclear which props the component is receiving.
|
||||
JSX 요소에서 `{...props}`와 같은 단일 변수 prop 확산을 피하십시오. 이 관행은 구성 요소가 수신되는 props를 명확하게 하지 않아 가독성과 유지 관리가 어려운 코드를 생성하는 경우가 많습니다.
|
||||
|
||||
```tsx
|
||||
/* ❌ - Bad, spreads a single variable prop into the underlying component
|
||||
@@ -94,23 +94,23 @@ const MyComponent = (props: OwnProps) => {
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* ✅ - Good, Explicitly lists all props
|
||||
* - Enhances readability and maintainability
|
||||
/* ✅ - 좋음, 모든 props를 명시적으로 나열합니다
|
||||
* - 가독성과 유지 보수성을 향상합니다
|
||||
*/
|
||||
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
|
||||
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
|
||||
};
|
||||
```
|
||||
|
||||
Rationale:
|
||||
이유:
|
||||
|
||||
* At a glance, it's clearer which props the code passes down, making it easier to understand and maintain.
|
||||
* It helps to prevent tight coupling between components via their props.
|
||||
* Linting tools make it easier to identify misspelled or unused props when you list props explicitly.
|
||||
* 한눈에 코드가 전달하는 props를 명확하게 하여 이해하고 유지하기 쉽습니다.
|
||||
* 이것은 구성 요소가 각자의 props로 긴밀하게 결합되는 것을 방지하는 데 도움이 됩니다.
|
||||
* props를 명시적으로 나열하면 Linting 도구에서 잘못된 철자나 사용되지 않는 props를 쉽게 식별할 수 있습니다.
|
||||
|
||||
## JavaScript
|
||||
## 자바스크립트
|
||||
|
||||
### Use nullish-coalescing operator `??`
|
||||
### nullish 병합 연산자 `??` 사용
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, can return 'default' even if value is 0 or ''
|
||||
@@ -120,21 +120,21 @@ const value = process.env.MY_VALUE || 'default';
|
||||
const value = process.env.MY_VALUE ?? 'default';
|
||||
```
|
||||
|
||||
### Use optional chaining `?.`
|
||||
### 옵셔널 체이닝 `?.` 사용
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
// ❌ 나쁨
|
||||
onClick && onClick();
|
||||
|
||||
// ✅ Good
|
||||
// ✅ 좋음
|
||||
onClick?.();
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
## 타입스크립트
|
||||
|
||||
### Use `type` instead of `interface`
|
||||
### `interface` 대신 `type` 사용
|
||||
|
||||
Always use `type` instead of `interface`, because they almost always overlap, and `type` is more flexible.
|
||||
항상 `interface` 대신 `type`을 사용하십시오. 두 개의 기능은 거의 항상 중첩되며, `type`이 더 유연합니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
@@ -148,11 +148,11 @@ type MyType = {
|
||||
};
|
||||
```
|
||||
|
||||
### Use string literals instead of enums
|
||||
### 열거형 대신 문자열 리터럴 사용
|
||||
|
||||
[String literals](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) are the go-to way to handle enum-like values in TypeScript. They are easier to extend with Pick and Omit, and offer a better developer experience, specially with code completion.
|
||||
[String literals](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types)는 TypeScript에서 열거형과 같은 값을 처리하는 주요 방법입니다. 그들은 Pick와 Omit으로 확장하기 쉬우며, 특히 코드 완성 기능을 사용할 때 더 나은 사용자 경험을 제공합니다.
|
||||
|
||||
You can see why TypeScript recommends avoiding enums [here](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
|
||||
타입스크립트가 열거형 사용을 피하도록 권장하는 이유는 [여기](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums)에서 확인할 수 있습니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, utilizes an enum
|
||||
@@ -171,13 +171,13 @@ let color = Color.Red;
|
||||
let color: "red" | "green" | "blue" = "red";
|
||||
```
|
||||
|
||||
#### GraphQL and internal libraries
|
||||
#### GraphQL 및 내부 라이브러리
|
||||
|
||||
You should use enums that GraphQL codegen generates.
|
||||
GraphQL 코드 생성기가 생성한 열거형을 사용해야 합니다.
|
||||
|
||||
It's also better to use an enum when using an internal library, so the internal library doesn't have to expose a string literal type that is not related to the internal API.
|
||||
내부 라이브러리를 사용할 때도 열거형을 사용하는 것이 좋으며, 내부 API와 관련이 없는 문자열 리터럴 유형을 노출할 필요가 없습니다.
|
||||
|
||||
Example:
|
||||
예시:
|
||||
|
||||
```TSX
|
||||
const {
|
||||
@@ -190,11 +190,11 @@ setHotkeyScopeAndMemorizePreviousScope(
|
||||
);
|
||||
```
|
||||
|
||||
## Styling
|
||||
## 스타일링
|
||||
|
||||
### Use StyledComponents
|
||||
### StyledComponents 사용
|
||||
|
||||
Style the components with [styled-components](https://emotion.sh/docs/styled).
|
||||
[styled-components](https://emotion.sh/docs/styled)로 구성 요소를 스타일링하십시오.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
@@ -208,7 +208,7 @@ const StyledTitle = styled.div`
|
||||
`;
|
||||
```
|
||||
|
||||
Prefix styled components with "Styled" to differentiate them from "real" components.
|
||||
스타일드 컴포넌트 앞에 "Styled"를 붙여 실제 컴포넌트와 구분하십시오.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
@@ -224,17 +224,17 @@ const StyledTitle = styled.div`
|
||||
`;
|
||||
```
|
||||
|
||||
### Theming
|
||||
### 테마
|
||||
|
||||
Utilizing the theme for the majority of component styling is the preferred approach.
|
||||
대부분의 구성 요소 스타일링에는 테마를 활용하는 것이 선호되는 접근 방식입니다.
|
||||
|
||||
#### Units of measurement
|
||||
#### 측정 단위
|
||||
|
||||
Avoid using `px` or `rem` values directly within the styled components. The necessary values are generally already defined in the theme, so it’s recommended to make use of the theme for these purposes.
|
||||
스타일드 컴포넌트 내에서 `px` 또는 `rem` 값을 직접 사용하는 것을 피하십시오. 필요한 값은 일반적으로 테마에 이미 정의되어 있으므로 이러한 목적으로 테마를 활용하는 것이 좋습니다.
|
||||
|
||||
#### Colors
|
||||
#### 색상
|
||||
|
||||
Refrain from introducing new colors; instead, use the existing palette from the theme. Should there be a situation where the palette does not align, please leave a comment so that the team can rectify it.
|
||||
새로운 색상을 도입하지 말고 테마에서 기존 팔레트를 사용하십시오. 팔레트가 맞지 않는 경우가 있다면 팀이 수정할 수 있도록 댓글을 남겨야 합니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad, directly specifies style values without utilizing the theme
|
||||
@@ -258,9 +258,9 @@ const StyledButton = styled.button`
|
||||
`;
|
||||
```
|
||||
|
||||
## Enforcing No-Type Imports
|
||||
## No-Type Import 강제 실행
|
||||
|
||||
Avoid type imports. To enforce this standard, an ESLint rule checks for and reports any type imports. This helps maintain consistency and readability in the TypeScript code.
|
||||
타입 import를 피하십시오. 이 표준을 강화하기 위해 ESLint 규칙이 모든 타입 import를 확인하고 보고합니다. 이는 TypeScript 코드의 일관성과 가독성을 유지하는 데 도움이 됩니다.
|
||||
|
||||
```tsx
|
||||
// ❌ Bad
|
||||
@@ -273,18 +273,18 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
```
|
||||
|
||||
### Why No-Type Imports
|
||||
### No-Type Import의 이유
|
||||
|
||||
* **Consistency**: By avoiding type imports and using a single approach for both type and value imports, the codebase remains consistent in its module import style.
|
||||
* **일관성**: 타입 import를 피하고, 타입과 값 import 모두의 단일 접근 방식을 사용하여 모듈 import 스타일의 일관성을 유지합니다.
|
||||
|
||||
* **Readability**: No-type imports improve code readability by making it clear when you're importing values or types. This reduces ambiguity and makes it easier to understand the purpose of imported symbols.
|
||||
* **가독성**: No-Type Import는 값을 가져오거나 타입을 가져오는 것을 명확히 하여 코드 가독성을 향상시킵니다. 이는 모호성을 줄이고 가져온 기호의 목적을 이해하기 쉽게 만듭니다.
|
||||
|
||||
* **Maintainability**: It enhances codebase maintainability because developers can identify and locate type-only imports when reviewing or modifying code.
|
||||
* **유지관리성**: 이는 코드베이스 유지관리를 향상시킵니다. 개발자가 코드를 검토하거나 수정할 때 타입 전용 import를 식별하고 찾을 수 있습니다.
|
||||
|
||||
### ESLint Rule
|
||||
### ESLint 규칙
|
||||
|
||||
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. This rule will generate errors or warnings for any type import violations.
|
||||
ESLint 규칙인 `@typescript-eslint/consistent-type-imports`는 타입 없는 import 표준을 강제합니다. 이 규칙은 모든 타입 import 위반에 대해 오류나 경고를 생성합니다.
|
||||
|
||||
Please note that this rule specifically addresses rare edge cases where unintentional type imports occur. TypeScript itself discourages this practice, as mentioned in the [TypeScript 3.8 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.
|
||||
이 규칙은 의도치 않은 타입 import가 발생하는 드문 경계 사례를 구체적으로 다룹니다. 타입스크립트 자체는 [TypeScript 3.8 릴리스 노트](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html)에서 이 관행을 권장하지 않습니다. 대부분의 상황에서 타입 전용 import를 사용할 필요가 없습니다.
|
||||
|
||||
To ensure your code complies with this rule, make sure to run ESLint as part of your development workflow.
|
||||
이 규칙을 준수하는 코드를 보장하기 위해 ESLint를 개발 워크플로의 일부로 실행하십시오.
|
||||
|
||||
+32
-33
@@ -1,59 +1,58 @@
|
||||
---
|
||||
title: Work with Figma
|
||||
info: Learn how you can collaborate with Twenty's Figma
|
||||
title: Figma와 함께 작업하기
|
||||
info: Twenty의 Figma와 협업하는 방법을 배우기
|
||||
---
|
||||
|
||||
Figma is a collaborative interface design tool that aids in bridging the communication barrier between designers and developers.
|
||||
This guide explains how you can collaborate with Figma.
|
||||
Figma는 디자이너와 개발자 간의 소통 장벽을 허무는 협업 인터페이스 디자인 도구입니다.
|
||||
이 가이드는 Figma와 협업하는 방법을 설명합니다.
|
||||
|
||||
## Access
|
||||
## 접근하기
|
||||
|
||||
1. **Access the shared link:** You can access the project's Figma file [here](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty).
|
||||
2. **Sign in:** If you're not already signed in, Figma will prompt you to do so.
|
||||
Key features are only available to logged-in users, such as the developer mode and the ability to select a dedicated frame.
|
||||
1. **공유 링크에 접근:** 프로젝트의 Figma 파일에 [여기서](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty) 접근할 수 있습니다.
|
||||
2. **로그인:** 이미 로그인하지 않은 경우, Figma에서 로그인 하라는 요청을 받을 것입니다.
|
||||
전문 모드 및 전용 프레임 선택 기능과 같이 로그인한 사용자에게만 제공되는 주요 기능이 있습니다.
|
||||
|
||||
<Warning>
|
||||
You will not be able to collaborate effectively without an account.
|
||||
계정 없이는 효과적으로 협업할 수 없습니다.
|
||||
</Warning>
|
||||
|
||||
## Figma structure
|
||||
## Figma 구조
|
||||
|
||||
On the left sidebar, you can access the different pages of Twenty's Figma. This is how they're organized:
|
||||
왼쪽 사이드바에서 Twenty의 Figma의 다양한 페이지에 접근할 수 있습니다. 이들은 이렇게 구성되어 있습니다:
|
||||
|
||||
* **Components page:** This is the first page. The designer uses it to create and organize the reusable design elements used throughout the design file. For example, buttons, icons, symbols, or any other reusable components. It serves to maintain consistency across the design.
|
||||
* **Main page:** The second page is the main page, which shows the complete user interface of the project. You can press ***Play*** to use the full app prototype.
|
||||
* **Features pages:** The other pages are typically dedicated to features in progress. They contain the design of specific features or modules of the application or website. They are typically still in progress.
|
||||
* **구성 요소 페이지:** 첫 번째 페이지입니다. 디자이너는 디자인 파일 전반에 걸쳐 재사용 가능한 디자인 요소를 생성하고 조직하는 데 사용합니다. 예를 들어, 버튼, 아이콘, 심벌 또는 기타 재사용 가능한 구성 요소가 있습니다. 디자인 전체에서 일관성을 유지하는 역할을 합니다.
|
||||
* **메인 페이지:** 두 번째 페이지는 프로젝트의 완전한 사용자 인터페이스를 보여주는 메인 페이지입니다. 전체 앱 프로토타입을 사용하려면 ***재생*** 버튼을 누르세요.
|
||||
* **기능 페이지:** 다른 페이지는 일반적으로 진행중인 기능에 전용되어 있습니다. 이 페이지들은 애플리케이션이나 웹사이트의 특정 기능 또는 모듈의 디자인을 포함하고 있습니다. 일반적으로 아직 진행 중인 상태입니다.
|
||||
|
||||
## Useful Tips
|
||||
## 유용한 팁
|
||||
|
||||
With read-only access, you can't edit the design, but you can access all features that will be useful to convert the designs into code.
|
||||
읽기 전용 접근 권한으로는 디자인을 편집할 수 없지만, 디자인을 코드로 변환하는 데 유용한 모든 기능에 접근할 수 있습니다.
|
||||
|
||||
### Use the Dev mode
|
||||
### 개발 모드 사용
|
||||
|
||||
Figma's Dev Mode enhances developers' productivity by providing easy design navigation, effective asset management, efficient communication tools, toolbox integrations, quick code snippets, and key layer information, bridging the gap between design and development. You can learn more about Dev Mode [here](https://www.figma.com/dev-mode/).
|
||||
Figma의 Dev Mode는 쉬운 디자인 탐색, 효과적인 자산 관리, 효율적인 통신 도구, 도구 상자 통합, 빠른 코드 스니펫, 주요 레이어 정보를 제공하여 디자이너와 개발자 간의 격차를 줄입니다. Dev Mode에 대해 더 알고 싶으시면 [여기](https://www.figma.com/dev-mode/)를 방문하세요.
|
||||
|
||||
Switch to the "Developer" mode in the right part of the toolbar to see design specs, copy CSS, and access assets.
|
||||
툴바의 오른쪽에서 "개발자" 모드로 전환하여 디자인 사양을 보고 CSS를 복사하고 자산에 접근하세요.
|
||||
|
||||
### Use the Prototype
|
||||
### 프로토타입 사용
|
||||
|
||||
Click on any element on the canvas and press the “Play” button at the top right edge of the interface to access the prototype view. Prototype mode allows you to interact with the design as if it were the final product. It demonstrates the flow between screens and how interface elements like buttons, links, or menus behave when interacted with.
|
||||
캔버스의 아무 요소나 클릭하고 인터페이스의 오른쪽 상단 모서리에 있는 "재생" 버튼을 눌러 프로토타입 보기에 접근하세요. 프로토타입 모드는 디자인을 최종 제품처럼 상호작용할 수 있게 합니다. 이를 통해 화면 간의 흐름과 버튼, 링크, 메뉴 등과 같은 인터페이스 요소가 상호작용할 때 어떻게 작동하는지 보여줍니다.
|
||||
|
||||
1. **Understanding transitions and animations:** In the Prototype mode, you can view any transitions or animations added by a designer between screens or UI elements, providing clear visual instructions to developers on the intended behavior and style.
|
||||
2. **Implementation clarification:** A prototype can also help reduce ambiguities. Developers can interact with it to gain a better understanding of the functionality or appearance of particular elements.
|
||||
1. **전환 및 애니메이션 이해하기:** 프로토타입 모드에서는 디자이너가 화면 또는 UI 요소 간에 추가한 전환이나 애니메이션을 볼 수 있어 개발자에게 의도된 동작 및 스타일에 대한 명확한 시각적 지침을 제공합니다.
|
||||
2. **실행 명확화:** 프로토타입은 모호성을 줄이는 데 도움을 줄 수 있습니다. 개발자는 특정 요소의 기능이나 모양을 보다 잘 이해하기 위해 이를 상호작용할 수 있습니다.
|
||||
|
||||
For more comprehensive details and guidance on learning the Figma platform, you can visit the official [Figma Documentation](https://help.figma.com/hc/en-us).
|
||||
Figma 플랫폼 학습에 대한 포괄적인 세부 정보와 지침을 얻으시려면 [공식 Figma 문서](https://help.figma.com/hc/en-us)를 방문하세요.
|
||||
|
||||
### Measure distances
|
||||
### 거리 측정
|
||||
|
||||
Select an element, hold `Option` key (Mac) or `Alt` key (Windows), then hover over another element to see the distance between them.
|
||||
요소를 선택하고 `Option` 키(Mac) 또는 `Alt` 키(Windows)를 누른 상태에서 다른 요소 위에 마우스를 올리면 요소 간 거리를 확인할 수 있습니다.
|
||||
|
||||
### Figma extension for VSCode (Recommended)
|
||||
### VSCode용 Figma 확장 프로그램 (추천)
|
||||
|
||||
[Figma for VS Code](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension)
|
||||
lets you navigate and inspect design files, collaborate with designers, track changes, and speed up implementation - all without leaving your text editor.
|
||||
It's part of our recommended extensions.
|
||||
[VS Code용 Figma](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension) 확장 프로그램은 텍스트 편집기에서 벗어나지 않고 디자인 파일 탐색 및 점검, 디자이너와의 협업, 변경 사항 추적, 구현 속도 향상을 가능하게 합니다.
|
||||
추천하는 확장 프로그램의 일부입니다.
|
||||
|
||||
## Collaboration
|
||||
## 협업
|
||||
|
||||
1. **Using Comments:** You are welcome to use the comment feature by clicking on the bubble icon in the left part of the toolbar.
|
||||
2. **Cursor chat:** A nice feature of Figma is the Cursor chat. Just press `;` on Mac and `/` on Windows to send a message if you see someone else using Figma as the same time as you.
|
||||
1. **댓글 사용하기:** 툴바 왼쪽의 말풍선 아이콘을 클릭하여 댓글 기능을 사용할 수 있습니다.
|
||||
2. **커서 채팅:** Figma의 멋진 기능 중 하나는 커서 채팅입니다. Figma를 다른 누군가와 동시에 사용하는 것을 보면 `;` (Mac)이나 `/` (Windows) 키를 눌러 메시지를 보낼 수 있습니다.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: Local Setup
|
||||
description: The guide for contributors (or curious developers) who want to run Twenty locally.
|
||||
title: 로컬 설정
|
||||
description: 콘트리뷰터(기여자)나 호기심 많은 개발자를 위한 가이드로서, Twenty를 로컬에서 실행하고자 하는 분들에게 드리는 안내입니다.
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
## 사전 준비
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Linux and MacOS">
|
||||
Before you can install and use Twenty, make sure you install the following on your computer:
|
||||
<Tab title="리눅스 및 맥OS">
|
||||
Twenty를 설치하고 사용하기 전에, 먼저 컴퓨터에 다음을 설치하세요:
|
||||
|
||||
* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
|
||||
* [Node v24.5.0](https://nodejs.org/en/download)
|
||||
@@ -15,25 +15,25 @@ description: The guide for contributors (or curious developers) who want to run
|
||||
* [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md)
|
||||
|
||||
<Warning>
|
||||
`npm` won't work, you should use `yarn` instead. Yarn is now shipped with Node.js, so you don't need to install it separately.
|
||||
You only have to run `corepack enable` to enable Yarn if you haven't done it yet.
|
||||
`npm`은 사용할 수 없으며, 대신 `yarn`을 사용해야 합니다. Yarn은 이제 Node.js와 함께 제공되기 때문에 별도로 설치할 필요가 없습니다.
|
||||
아직 하지 않았다면 `corepack enable`을 실행하여 Yarn을 사용할 수 있도록 설정하세요.
|
||||
</Warning>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Windows (WSL)">
|
||||
1. Install WSL
|
||||
Open PowerShell as Administrator and run:
|
||||
<Tab title="윈도우 (WSL)">
|
||||
1. WSL 설치
|
||||
PowerShell을 관리자 권한으로 열고 다음을 실행하세요:
|
||||
|
||||
```powershell
|
||||
wsl --install
|
||||
```
|
||||
|
||||
You should now see a prompt to restart your computer. If not, restart it manually.
|
||||
이제 컴퓨터를 재시작하라는 프롬프트가 나타날 것입니다. 그렇지 않으면 수동으로 재시작하세요.
|
||||
|
||||
Upon restart, a powershell window will open and install Ubuntu. This may take up some time.
|
||||
You'll see a prompt to create a username and password for your Ubuntu installation.
|
||||
재시작 후, powershell 창이 열리고 Ubuntu가 설치됩니다. 이 작업은 다소 시간이 걸릴 수 있습니다.
|
||||
Ubuntu 설치 시 사용자 이름과 암호를 만드는 프롬프트가 나타납니다.
|
||||
|
||||
2. Install and configure git
|
||||
2. Git 설치 및 구성
|
||||
|
||||
```bash
|
||||
sudo apt-get install git
|
||||
@@ -43,10 +43,10 @@ description: The guide for contributors (or curious developers) who want to run
|
||||
git config --global user.email "youremail@domain.com"
|
||||
```
|
||||
|
||||
3. Install nvm, node.js and yarn
|
||||
3. nvm, node.js 및 yarn 설치
|
||||
|
||||
<Warning>
|
||||
Use `nvm` to install the correct `node` version. The `.nvmrc` ensures all contributors use the same version.
|
||||
적절한 `node` 버전을 설치하기 위해 `nvm`을 사용하세요. `.nvmrc`는 모든 기여자가 동일한 버전을 사용하도록 보장합니다.
|
||||
</Warning>
|
||||
|
||||
```bash
|
||||
@@ -55,7 +55,7 @@ description: The guide for contributors (or curious developers) who want to run
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
|
||||
```
|
||||
|
||||
Close and reopen your terminal to use nvm. Then run the following commands.
|
||||
nvm을 사용하려면 터미널을 닫았다가 다시 여세요. 그런 다음 다음 명령어를 실행하세요.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -70,13 +70,13 @@ description: The guide for contributors (or curious developers) who want to run
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Git Clone
|
||||
## 1단계: Git 복제
|
||||
|
||||
In your terminal, run the following command.
|
||||
터미널에서 다음 명령어를 실행하세요.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="SSH (Recommended)">
|
||||
If you haven't already set up SSH keys, you can learn how to do so [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh).
|
||||
<Tab title="SSH (권장)">
|
||||
아직 SSH 키를 설정하지 않은 경우, [여기](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh)를 참조하여 설정하는 방법을 배우세요.
|
||||
|
||||
```bash
|
||||
git clone git@github.com:twentyhq/twenty.git
|
||||
@@ -90,36 +90,36 @@ In your terminal, run the following command.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Step 2: Position yourself at the root
|
||||
## 2단계: 루트 위치 설정
|
||||
|
||||
```bash
|
||||
cd twenty
|
||||
```
|
||||
|
||||
You should run all commands in the following steps from the root of the project.
|
||||
다음 단계의 모든 명령어는 프로젝트 루트에서 실행하세요.
|
||||
|
||||
## Step 3: Set up a PostgreSQL Database
|
||||
## 3단계: PostgreSQL 데이터베이스 설정
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Linux">
|
||||
**Option 1 (preferred):** To provision your database locally:
|
||||
Use the following link to install Postgresql on your Linux machine: [Postgresql Installation](https://www.postgresql.org/download/linux/)
|
||||
<Tab title="리눅스">
|
||||
**옵션 1 (권장):** 데이터베이스를 로컬에서 프로비저닝하려면:
|
||||
Linux 기기에 Postgresql을 설치하려면 다음 링크를 사용하십시오: [Postgresql 설치](https://www.postgresql.org/download/linux/)
|
||||
|
||||
```bash
|
||||
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
|
||||
```
|
||||
|
||||
Note: You might need to add `sudo -u postgres` to the command before `psql` to avoid permission errors.
|
||||
참고: 권한 오류를 피하기 위해 `psql` 명령어 앞에 `sudo -u postgres`를 추가해야 할 수 있습니다.
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
|
||||
```bash
|
||||
make postgres-on-docker
|
||||
make -C packages/twenty-docker postgres-on-docker
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Mac OS">
|
||||
**Option 1 (preferred):** To provision your database locally with `brew`:
|
||||
<Tab title="맥 OS">
|
||||
**옵션 1 (권장):** `brew`로 로컬에서 데이터베이스를 프로비저닝하려면:
|
||||
|
||||
```bash
|
||||
brew install postgresql@16
|
||||
@@ -128,16 +128,17 @@ You should run all commands in the following steps from the root of the project.
|
||||
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
|
||||
```
|
||||
|
||||
You can verify if the PostgreSQL server is running by executing:
|
||||
PostgreSQL 서버가 실행 중인지 확인하려면 다음을 실행하세요:
|
||||
|
||||
```bash
|
||||
brew services list
|
||||
```
|
||||
|
||||
The installer might not create the `postgres` user by default when installing
|
||||
via Homebrew on MacOS. Instead, it creates a PostgreSQL role that matches your macOS
|
||||
username (e.g., "john").
|
||||
To check and create the `postgres` user if necessary, follow these steps:
|
||||
설치 시 기본적으로 `postgres` 사용자가 생성되지 않을 수 있습니다.
|
||||
macOS에서 Homebrew로 설치할 경우, 설치 시스템 계정과 일치하는 PostgreSQL 역할이 생성됩니다(예: "john"). 대신 사용자의 macOS
|
||||
사용자 이름(예: "john")과 일치하는 PostgreSQL 역할을 생성합니다.# PostgreSQL 접속psql postgres
|
||||
또는
|
||||
psql -U $(whoami) -d postgres
|
||||
|
||||
```bash
|
||||
# Connect to PostgreSQL
|
||||
@@ -146,14 +147,14 @@ You should run all commands in the following steps from the root of the project.
|
||||
psql -U $(whoami) -d postgres
|
||||
```
|
||||
|
||||
Once at the psql prompt (postgres=#), run:
|
||||
psql 프롬프트에서(postgres=#), 다음을 실행하세요:
|
||||
|
||||
```bash
|
||||
# List existing PostgreSQL roles
|
||||
\du
|
||||
```
|
||||
|
||||
You'll see output similar to:
|
||||
출력은 다음과 비슷해야 합니다:
|
||||
|
||||
```bash
|
||||
Role name | Attributes | Member of
|
||||
@@ -161,98 +162,98 @@ You should run all commands in the following steps from the root of the project.
|
||||
john | Superuser | {}
|
||||
```
|
||||
|
||||
If you do not see a `postgres` role listed, proceed to the next step.
|
||||
Create the `postgres` role manually:
|
||||
`postgres` 역할이 나열되지 않으면 다음 단계를 계속하십시오.
|
||||
`postgres` 역할을 수동으로 만드세요:
|
||||
|
||||
```bash
|
||||
CREATE ROLE postgres WITH SUPERUSER LOGIN;
|
||||
```
|
||||
|
||||
This creates a superuser role named `postgres` with login access.
|
||||
이는 로그인 액세스가 있는 슈퍼유저 역할 `postgres`를 생성합니다.
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
|
||||
```bash
|
||||
make postgres-on-docker
|
||||
make -C packages/twenty-docker postgres-on-docker
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Windows (WSL)">
|
||||
All the following steps are to be run in the WSL terminal (within your virtual machine)
|
||||
<Tab title="윈도우 (WSL)">
|
||||
다음 단계는 모두 WSL 터미널(가상 머신 내)에서 실행됩니다.
|
||||
|
||||
**Option 1:** To provision your Postgresql locally:
|
||||
Use the following link to install Postgresql on your Linux virtual machine: [Postgresql Installation](https://www.postgresql.org/download/linux/)
|
||||
**옵션 1:** Postgresql을 로컬에서 프로비저닝하려면:
|
||||
Linux 가상 머신에 Postgresql을 설치하려면 다음 링크를 사용하세요: [Postgresql 설치](https://www.postgresql.org/download/linux/)
|
||||
|
||||
```bash
|
||||
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
|
||||
```
|
||||
|
||||
Note: You might need to add `sudo -u postgres` to the command before `psql` to avoid permission errors.
|
||||
참고: 권한 오류를 피하기 위해 `psql` 명령어 앞에 `sudo -u postgres`를 추가해야 할 수 있습니다.
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
Running Docker on WSL adds an extra layer of complexity.
|
||||
Only use this option if you are comfortable with the extra steps involved, including turning on [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl).
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
WSL에서 Docker를 실행하면 추가적인 복잡성이 발생합니다.
|
||||
이 옵션은 [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl)를 켠 상태에서의 추가 설정 단계를 수반할 수 있다는 점에서 편안할 때만 사용하십시오.
|
||||
|
||||
```bash
|
||||
make postgres-on-docker
|
||||
make -C packages/twenty-docker postgres-on-docker
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
You can now access the database at [localhost:5432](localhost:5432), with user `postgres` and password `postgres` .
|
||||
이제 [localhost:5432](localhost:5432)에서 데이터베이스에 액세스할 수 있으며, 사용자 `postgres`와 비밀번호 `postgres` 를 사용합니다.
|
||||
|
||||
## Step 4: Set up a Redis Database (cache)
|
||||
## 4단계: Redis 데이터베이스 (캐시) 설정
|
||||
|
||||
Twenty requires a redis cache to provide the best performance
|
||||
Twenty는 최상의 성능을 제공하기 위해 redis 캐시가 필요합니다.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Linux">
|
||||
**Option 1:** To provision your Redis locally:
|
||||
Use the following link to install Redis on your Linux machine: [Redis Installation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
|
||||
<Tab title="리눅스">
|
||||
**옵션 1:** Redis를 로컬에서 프로비저닝하려면:
|
||||
리눅스 기기에 Redis를 설치하려면 다음 링크를 사용하십시오: [Redis 설치](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
|
||||
```bash
|
||||
make redis-on-docker
|
||||
make -C packages/twenty-docker redis-on-docker
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Mac OS">
|
||||
**Option 1 (preferred):** To provision your Redis locally with `brew`:
|
||||
<Tab title="맥 OS">
|
||||
**옵션 1 (권장):** `brew`로 Redis를 로컬에서 프로비저닝하려면:
|
||||
|
||||
```bash
|
||||
brew install redis
|
||||
```
|
||||
|
||||
Start your redis server:
|
||||
redis 서버를 시작하세요:
|
||||
`brew services start redis`
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
|
||||
```bash
|
||||
make redis-on-docker
|
||||
make -C packages/twenty-docker redis-on-docker
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Windows (WSL)">
|
||||
**Option 1:** To provision your Redis locally:
|
||||
Use the following link to install Redis on your Linux virtual machine: [Redis Installation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
|
||||
<Tab title="윈도우 (WSL)">
|
||||
**옵션 1:** Redis를 로컬에서 프로비저닝하려면:
|
||||
Linux 가상 머신에 Redis를 설치하려면 다음 링크를 사용하세요: [Redis 설치](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
|
||||
|
||||
**Option 2:** If you have docker installed:
|
||||
**옵션 2:** 도커가 설치된 경우:
|
||||
|
||||
```bash
|
||||
make redis-on-docker
|
||||
make -C packages/twenty-docker redis-on-docker
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
If you need a Client GUI, we recommend [redis insight](https://redis.io/insight/) (free version available)
|
||||
클라이언트 GUI가 필요한 경우에는 [redis insight](https://redis.io/insight/) (무료 버전 제공)을 권장합니다.
|
||||
|
||||
## Step 5: Setup environment variables
|
||||
## 5단계: 환경 변수 설정
|
||||
|
||||
Use environment variables or `.env` files to configure your project. More info [here](/l/ko/developers/self-host/capabilities/setup)
|
||||
프로젝트를 구성하기 위해 환경 변수나 `.env` 파일을 사용하세요. 자세한 내용은 [여기](/l/ko/developers/self-host/capabilities/setup)에서 확인하세요.
|
||||
|
||||
Copy the `.env.example` files in `/front` and `/server`:
|
||||
`/front`와 `/server`의 `.env.example` 파일을 복사하세요:
|
||||
|
||||
```bash
|
||||
cp ./packages/twenty-front/.env.example ./packages/twenty-front/.env
|
||||
@@ -260,48 +261,48 @@ cp ./packages/twenty-server/.env.example ./packages/twenty-server/.env
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Multi-Workspace Mode:** By default, Twenty runs in single-workspace mode where only one workspace can be created. To enable multi-workspace support (useful for testing subdomain-based features), set `IS_MULTIWORKSPACE_ENABLED=true` in your server `.env` file. See [Multi-Workspace Mode](/l/ko/developers/self-host/capabilities/setup#multi-workspace-mode) for details.
|
||||
**멀티 워크스페이스 모드:** 기본적으로 Twenty는 하나의 워크스페이스만 생성할 수 있는 단일 워크스페이스 모드로 실행됩니다. 멀티 워크스페이스 지원을 활성화하려면(서브도메인 기반 기능을 테스트할 때 유용합니다), 서버의 `.env` 파일에서 `IS_MULTIWORKSPACE_ENABLED=true`로 설정하세요. 자세한 내용은 [멀티 워크스페이스 모드](/l/ko/developers/self-host/capabilities/setup#multi-workspace-mode)를 참조하세요.
|
||||
</Info>
|
||||
|
||||
## Step 6: Installing dependencies
|
||||
## 6단계: 의존성 설치
|
||||
|
||||
To build Twenty server and seed some data into your database, run the following command:
|
||||
Twenty 서버를 빌드하고 데이터베이스에 몇 가지 데이터를 시드하기 위해, 다음 명령어를 실행하세요:
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
Note that `npm` or `pnpm` won't work
|
||||
`npm`이나 `pnpm`은 작동하지 않음을 주의하세요.
|
||||
|
||||
## Step 7: Running the project
|
||||
## 7단계: 프로젝트 실행
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Linux">
|
||||
Depending on your Linux distribution, Redis server might be started automatically.
|
||||
If not, check the [Redis installation guide](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) for your distro.
|
||||
<Tab title="리눅스">
|
||||
리눅스 배포판에 따라 Redis 서버가 자동으로 시작될 수 있습니다.
|
||||
시작되지 않는다면, 각 배포판에 맞는 [Redis 설치 가이드](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/)를 확인하세요.
|
||||
</Tab>
|
||||
|
||||
<Tab title="Mac OS">
|
||||
Redis should already be running. If not, run:
|
||||
<Tab title="맥 OS">
|
||||
Redis가 이미 실행 중이어야 합니다. 그렇지 않으면 다음을 실행하세요:
|
||||
|
||||
```bash
|
||||
brew services start redis
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Windows (WSL)">
|
||||
Depending on your Linux distribution, Redis server might be started automatically.
|
||||
If not, check the [Redis installation guide](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) for your distro.
|
||||
<Tab title="윈도우 (WSL)">
|
||||
리눅스 배포판에 따라 Redis 서버가 자동으로 시작될 수 있습니다.
|
||||
시작되지 않는다면, 각 배포판에 맞는 [Redis 설치 가이드](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/)를 확인하세요.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Set up your database with the following command:
|
||||
다음 명령어로 데이터베이스를 설정하세요:
|
||||
|
||||
```bash
|
||||
npx nx database:reset twenty-server
|
||||
```
|
||||
|
||||
Start the server, the worker and the frontend services:
|
||||
서버, 워커 및 프론트엔드 서비스를 시작하세요:
|
||||
|
||||
```bash
|
||||
npx nx start twenty-server
|
||||
@@ -309,25 +310,25 @@ npx nx worker twenty-server
|
||||
npx nx start twenty-front
|
||||
```
|
||||
|
||||
Alternatively, you can start all services at once:
|
||||
또한, 모든 서비스를 한 번에 시작할 수도 있습니다:
|
||||
|
||||
```bash
|
||||
npx nx start
|
||||
```
|
||||
|
||||
## Step 8: Use Twenty
|
||||
## 8단계: Twenty 사용하기
|
||||
|
||||
**Frontend**
|
||||
**프론트엔드**
|
||||
|
||||
Twenty's frontend will be running at [http://localhost:3001](http://localhost:3001).
|
||||
You can log in using the default demo account: `tim@apple.dev` (password: `tim@apple.dev`)
|
||||
Twenty의 프론트엔드는 [http://localhost:3001](http://localhost:3001)에서 실행됩니다.
|
||||
기본 데모 계정을 사용하여 로그인할 수 있습니다: `tim@apple.dev` (비밀번호: `tim@apple.dev`)
|
||||
|
||||
**Backend**
|
||||
**백엔드**
|
||||
|
||||
* Twenty's server will be up and running at [http://localhost:3000](http://localhost:3000)
|
||||
* The GraphQL API can be accessed at [http://localhost:3000/graphql](http://localhost:3000/graphql)
|
||||
* The REST API can be reached at [http://localhost:3000/rest](http://localhost:3000/rest)
|
||||
* Twenty의 서버는 [http://localhost:3000](http://localhost:3000)에서 실행됩니다.
|
||||
* GraphQL API는 [http://localhost:3000/graphql](http://localhost:3000/graphql)에서 액세스할 수 있습니다
|
||||
* REST API는 [http://localhost:3000/rest](http://localhost:3000/rest)에서 액세스할 수 있습니다
|
||||
|
||||
## Troubleshooting
|
||||
## 문제 해결
|
||||
|
||||
If you encounter any problem, check [Troubleshooting](/l/ko/developers/self-host/capabilities/troubleshooting) for solutions.
|
||||
문제가 발생하면 [문제 해결](/l/ko/developers/self-host/capabilities/troubleshooting)에서 해결책을 확인하십시오.
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
---
|
||||
title: Contribute
|
||||
description: Contribute to Twenty's open-source development.
|
||||
title: 기여
|
||||
description: Twenty의 오픈 소스 개발에 기여하세요.
|
||||
---
|
||||
|
||||
<Frame>
|
||||
<img src="/images/user-guide/github/github-header.png" alt="AI" />
|
||||
</Frame>
|
||||
|
||||
## Overview
|
||||
## 개요
|
||||
|
||||
Twenty is open-source and welcomes contributions from the community. Whether you're fixing bugs, adding features, or improving documentation, your contributions help make Twenty better for everyone.
|
||||
Twenty는 오픈 소스로, 커뮤니티의 기여를 환영합니다. 버그를 수정하든, 기능을 추가하든, 문서를 개선하든, 여러분의 기여는 모두에게 더 나은 Twenty를 만드는 데 도움이 됩니다.
|
||||
|
||||
## Ways to Contribute
|
||||
## 기여 방법
|
||||
|
||||
* **Report bugs**: Help identify and document issues
|
||||
* **Submit features**: Propose and implement new functionality
|
||||
* **Improve documentation**: Make our docs clearer and more helpful
|
||||
* **Frontend development**: Work on the React-based UI
|
||||
* **Backend development**: Contribute to the NestJS server
|
||||
* **버그 신고**: 문제를 식별하고 문서화하는 데 도움을 주세요
|
||||
* **기능 제안**: 새로운 기능을 제안하고 구현하세요
|
||||
* **문서 개선**: 문서를 더 명확하고 유용하게 만드세요
|
||||
* **프런트엔드 개발**: React 기반 UI 작업에 참여하세요
|
||||
* **백엔드 개발**: NestJS 서버에 기여하세요
|
||||
|
||||
## Getting Started
|
||||
## 시작하기
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Bug Reports & Requests" icon="bug" href="/l/ko/developers/contribute/capabilities/bug-and-requests">
|
||||
Report issues or request features
|
||||
<Card title="버그 보고 및 요청" icon="bug" href="/l/ko/developers/contribute/capabilities/bug-and-requests">
|
||||
문제를 보고하거나 기능을 요청하세요
|
||||
</Card>
|
||||
|
||||
<Card title="Frontend Development" icon="browser" href="/l/ko/developers/contribute/capabilities/frontend-development">
|
||||
Contribute to the UI
|
||||
<Card title="프론트엔드 개발" icon="browser" href="/l/ko/developers/contribute/capabilities/frontend-development">
|
||||
UI에 기여하세요
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
---
|
||||
title: APIs
|
||||
description: Query and modify your CRM data programmatically using REST or GraphQL.
|
||||
title: API
|
||||
description: REST 또는 GraphQL을 사용해 프로그래밍 방식으로 CRM 데이터를 쿼리하고 수정하세요.
|
||||
---
|
||||
|
||||
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
|
||||
Twenty was built to be developer-friendly, offering powerful APIs that adapt to your custom data model. We provide four distinct API types to meet different integration needs.
|
||||
Twenty는 개발자 친화적으로 설계되어 있으며, 맞춤형 데이터 모델에 적합한 강력한 API를 제공합니다. 우리는 여러 통합 요구에 맞는 네 가지 고유한 API 유형을 제공합니다.
|
||||
|
||||
## Developer-First Approach
|
||||
## 개발자 우선 접근 방식
|
||||
|
||||
Twenty generates APIs specifically for your data model:
|
||||
Twenty는 귀하의 데이터 모델에 맞는 API를 특별히 생성합니다:
|
||||
|
||||
* **No long IDs required**: Use your object and field names directly in endpoints
|
||||
* **Standard and custom objects treated equally**: Your custom objects get the same API treatment as built-in ones
|
||||
* **Dedicated endpoints**: Each object and field gets its own API endpoint
|
||||
* **Custom documentation**: Generated specifically for your workspace's data model
|
||||
* **긴 ID가 필요하지 않습니다**: 객체 및 필드 이름을 직접 엔드포인트에 사용합니다.
|
||||
* **표준 및 사용자 정의 객체가 동등하게 처리됩니다**: 내장된 객체와 동일한 API 처리를 사용자 정의 객체에도 제공합니다.
|
||||
* **전용 엔드포인트**: 각 객체와 필드에 자체 API 엔드포인트가 할당됩니다.
|
||||
* **맞춤형 문서**: 작업 공간의 데이터 모델에 맞게 특별히 생성됩니다.
|
||||
|
||||
<Note>
|
||||
Your personalized API documentation is available under **Settings → API & Webhooks** after creating an API key. Since Twenty generates APIs that match your custom data model, the documentation is unique to your workspace.
|
||||
맞춤형 API 문서는 API 키 생성 후 **설정 → API 및 웹훅**에서 확인할 수 있습니다. Twenty가 사용자 지정 데이터 모델에 맞는 API를 생성하므로, 문서는 귀하의 워크스페이스에 고유합니다.
|
||||
</Note>
|
||||
|
||||
## The Two API Types
|
||||
## 두 가지 API 유형
|
||||
|
||||
### Core API
|
||||
|
||||
Accessed on `/rest/` or `/graphql/`
|
||||
`/rest/` 또는 `/graphql/`에서 접근할 수 있습니다.
|
||||
|
||||
Work with your actual **records** (the data):
|
||||
실제 **레코드**(데이터)로 작업합니다:
|
||||
|
||||
* Create, read, update, delete People, Companies, Opportunities, etc.
|
||||
* Query and filter data
|
||||
* Manage record relationships
|
||||
* People, Companies, Opportunities 등을 생성, 조회, 업데이트, 삭제합니다.
|
||||
* 데이터를 쿼리하고 필터링합니다
|
||||
* 데이터 기록의 관계를 관리합니다.
|
||||
|
||||
### Metadata API
|
||||
### 메타데이터 API
|
||||
|
||||
Accessed on `/rest/metadata/` or `/metadata/`
|
||||
`/rest/metadata/` 또는 `/metadata/`에서 접근할 수 있습니다.
|
||||
|
||||
Manage your **workspace and data model**:
|
||||
**워크스페이스와 데이터 모델** 관리:
|
||||
|
||||
* Create, modify, or delete objects and fields
|
||||
* Configure workspace settings
|
||||
* Define relationships between objects
|
||||
* 객체 및 필드를 생성, 수정 또는 삭제합니다.
|
||||
* 작업 공간 설정을 구성합니다.
|
||||
* 객체 간 관계를 정의합니다
|
||||
|
||||
## REST vs GraphQL
|
||||
## REST와 GraphQL
|
||||
|
||||
Both Core and Metadata APIs are available in REST and GraphQL formats:
|
||||
코어 및 메타데이터 API는 REST와 GraphQL 형식으로 제공됩니다:
|
||||
|
||||
| Format | Available Operations |
|
||||
| ----------- | ---------------------------------------------------------- |
|
||||
| **REST** | CRUD, batch operations, upserts |
|
||||
| **GraphQL** | Same + **batch upserts**, relationship queries in one call |
|
||||
| 형식 | 사용 가능한 작업 |
|
||||
| ----------- | ------------------------------- |
|
||||
| **REST** | CRUD, 배치 작업, 업서트 |
|
||||
| **GraphQL** | 동일 + **배치 업서트**, 한 번의 호출로 관계 쿼리 |
|
||||
|
||||
Choose based on your needs — both formats access the same data.
|
||||
필요에 따라 선택하세요 — 두 형식 모두 동일한 데이터에 접근합니다.
|
||||
|
||||
## API Endpoints
|
||||
## API 엔드포인트
|
||||
|
||||
| Environment | Base URL |
|
||||
| --------------- | ------------------------- |
|
||||
| **Cloud** | `https://api.twenty.com/` |
|
||||
| **Self-Hosted** | `https://{your-domain}/` |
|
||||
| 환경 | 기본 URL |
|
||||
| ---------- | ------------------------- |
|
||||
| **클라우드** | `https://api.twenty.com/` |
|
||||
| **셀프 호스팅** | `https://{your-domain}/` |
|
||||
|
||||
## Authentication
|
||||
## 인증
|
||||
|
||||
Every API request requires an API key in the header:
|
||||
모든 API 요청에는 헤더에 API 키가 필요합니다:
|
||||
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
### Create an API Key
|
||||
### API 키 생성
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks**
|
||||
2. Click **+ Create key**
|
||||
3. Configure:
|
||||
* **Name**: Descriptive name for the key
|
||||
* **Expiration Date**: When the key expires
|
||||
4. Click **Save**
|
||||
5. **Copy immediately** — the key is only shown once
|
||||
1. **설정 → API 및 웹훅**으로 이동하세요
|
||||
2. **+ 키 생성**을 클릭하세요
|
||||
3. 구성:
|
||||
* **이름**: 키를 설명하는 이름
|
||||
* **만료 날짜**: 키가 만료되는 시점
|
||||
4. **저장** 클릭
|
||||
5. **즉시 복사** — 키는 한 번만 표시됩니다
|
||||
|
||||
<VimeoEmbed videoId="928786722" title="Creating API key" />
|
||||
<VimeoEmbed videoId="928786722" title="API 키 생성" />
|
||||
|
||||
<Warning>
|
||||
Your API key grants access to sensitive data. Don't share it with untrusted services. If compromised, disable it immediately and generate a new one.
|
||||
API 키는 민감한 데이터에 대한 액세스를 부여합니다. 신뢰할 수 없는 서비스와 공유하지 마세요. 유출되었으면 즉시 비활성화하고 새 키를 생성하세요.
|
||||
</Warning>
|
||||
|
||||
### Assign a Role to an API Key
|
||||
### API 키에 역할 할당
|
||||
|
||||
For better security, assign a specific role to limit access:
|
||||
보안을 강화하려면 액세스를 제한할 특정 역할을 할당하세요:
|
||||
|
||||
1. Go to **Settings → Roles**
|
||||
2. Click on the role to assign
|
||||
3. Open the **Assignment** tab
|
||||
4. Under **API Keys**, click **+ Assign to API key**
|
||||
5. Select the API key
|
||||
1. **설정 → 역할**로 이동
|
||||
2. 할당할 역할을 클릭하세요
|
||||
3. **배정** 탭 열기
|
||||
4. **API 키**에서 **+ API 키에 할당**을 클릭하세요
|
||||
5. API 키를 선택하세요
|
||||
|
||||
The key will inherit that role's permissions. See [Permissions](/l/ko/user-guide/permissions-access/capabilities/permissions) for details.
|
||||
키가 해당 역할의 권한을 상속받습니다. 자세한 내용은 [권한](/l/ko/user-guide/permissions-access/capabilities/permissions)을 참조하세요.
|
||||
|
||||
### Manage API Keys
|
||||
### API 키 관리
|
||||
|
||||
**Regenerate**: Settings → APIs & Webhooks → Click key → **Regenerate**
|
||||
**재생성**: 설정 → API 및 웹훅 → 키 클릭 → **재생성**
|
||||
|
||||
**Delete**: Settings → APIs & Webhooks → Click key → **Delete**
|
||||
**삭제**: 설정 → API 및 웹훅 → 키 클릭 → **삭제**
|
||||
|
||||
## API Playground
|
||||
## API 플레이그라운드
|
||||
|
||||
Test your APIs directly in the browser with our built-in playground — available for both **REST** and **GraphQL**.
|
||||
내장 플레이그라운드를 사용해 브라우저에서 직접 API를 테스트하세요 — **REST**와 **GraphQL** 모두에 대해 사용할 수 있습니다.
|
||||
|
||||
### Access the Playground
|
||||
### 플레이그라운드에 액세스
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks**
|
||||
2. Create an API key (required)
|
||||
3. Click on **REST API** or **GraphQL API** to open the playground
|
||||
1. **설정 → API 및 웹훅**으로 이동하세요
|
||||
2. API 키 생성(필수)
|
||||
3. 플레이그라운드를 열려면 **REST API** 또는 **GraphQL API**를 클릭하세요
|
||||
|
||||
### What You Get
|
||||
### 얻을 수 있는 내용
|
||||
|
||||
* **Interactive documentation**: Generated for your specific data model
|
||||
* **Live testing**: Execute real API calls against your workspace
|
||||
* **Schema explorer**: Browse available objects, fields, and relationships
|
||||
* **Request builder**: Construct queries with autocomplete
|
||||
* **대화형 문서**: 귀하의 특정 데이터 모델에 맞게 생성됩니다
|
||||
* 워크스페이스를 대상으로 실제 API 호출을 실행합니다
|
||||
* **스키마 탐색기**: 사용 가능한 객체, 필드 및 관계를 탐색합니다
|
||||
* **요청 빌더**: 자동 완성을 통해 쿼리를 구성합니다
|
||||
|
||||
The playground reflects your custom objects and fields, so documentation is always accurate for your workspace.
|
||||
플레이그라운드는 사용자 지정 객체와 필드를 반영하므로 문서는 항상 워크스페이스에 대해 정확합니다.
|
||||
|
||||
## Batch Operations
|
||||
## 배치 작업
|
||||
|
||||
Both REST and GraphQL support batch operations:
|
||||
REST와 GraphQL 모두 배치 작업을 지원합니다:
|
||||
|
||||
* **Batch size**: Up to 60 records per request
|
||||
* **Operations**: Create, update, delete multiple records
|
||||
* **배치 크기**: 요청당 최대 60개의 기록
|
||||
* **작업**: 여러 기록을 생성, 업데이트, 삭제합니다
|
||||
|
||||
**GraphQL-only features:**
|
||||
**GraphQL 전용 기능:**
|
||||
|
||||
* **Batch Upsert**: Create or update in one call
|
||||
* Use plural object names (e.g., `CreateCompanies` instead of `CreateCompany`)
|
||||
* **배치 업서트**: 한 번의 호출로 생성하거나 업데이트합니다
|
||||
* 복수형 객체 이름을 사용하세요(예: `CreateCompanies` 대신 `CreateCompany`)
|
||||
|
||||
## Rate Limits
|
||||
## 속도 제한
|
||||
|
||||
API requests are throttled to ensure platform stability:
|
||||
플랫폼 안정성을 위해 API 요청에는 제한이 적용됩니다:
|
||||
|
||||
| Limit | Value |
|
||||
| -------------- | -------------------- |
|
||||
| **Requests** | 100 calls per minute |
|
||||
| **Batch size** | 60 records per call |
|
||||
| 제한 | 값 |
|
||||
| --------- | ---------- |
|
||||
| **요청** | 분당 100회 호출 |
|
||||
| **배치 크기** | 호출당 기록 60개 |
|
||||
|
||||
<Tip>
|
||||
Use batch operations to maximize throughput — process up to 60 records in a single API call instead of making individual requests.
|
||||
처리량을 극대화하려면 배치 작업을 사용하세요 — 개별 요청 대신 단일 API 호출로 최대 60개의 기록을 처리할 수 있습니다.
|
||||
</Tip>
|
||||
|
||||
@@ -1,81 +1,88 @@
|
||||
---
|
||||
title: Twenty Apps
|
||||
description: Build and manage Twenty customizations as code.
|
||||
title: Twenty 앱
|
||||
description: Twenty 맞춤설정을 코드로 구축하고 관리하세요.
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Apps are currently in alpha testing. The feature is functional but still evolving.
|
||||
앱은 현재 알파 테스트 중입니다. 해당 기능은 작동하지만 아직 발전 중입니다.
|
||||
</Warning>
|
||||
|
||||
## What Are Apps?
|
||||
## 앱이란 무엇인가요?
|
||||
|
||||
Apps let you build and manage Twenty customizations **as code**. Instead of configuring everything through the UI, you define your data model and serverless functions in code — making it faster to build, maintain, and roll out to multiple workspaces.
|
||||
앱을 사용하면 Twenty 맞춤설정을 **코드로** 구축하고 관리할 수 있습니다. 모든 것을 UI에서 구성하는 대신, 데이터 모델과 서버리스 함수를 코드로 정의합니다 — 이를 통해 더 빠르게 구축·유지 관리하고 여러 워크스페이스에 배포할 수 있습니다.
|
||||
|
||||
**What you can do today:**
|
||||
**현재 가능한 작업:**
|
||||
|
||||
* Define custom objects and fields as code (managed data model)
|
||||
* Build serverless functions with custom triggers
|
||||
* Deploy the same app across multiple workspaces
|
||||
* 사용자 정의 객체와 필드를 코드로 정의하기(관리형 데이터 모델)
|
||||
* 사용자 정의 트리거를 사용하여 서버리스 함수를 구축
|
||||
* 동일한 앱을 여러 워크스페이스에 배포
|
||||
|
||||
**Coming soon:**
|
||||
**곧 제공 예정:**
|
||||
|
||||
* Custom UI layouts and components
|
||||
* 사용자 정의 UI 레이아웃 및 컴포넌트
|
||||
|
||||
## Prerequisites
|
||||
## 사전 준비
|
||||
|
||||
* Node.js 24+ and Yarn 4
|
||||
* A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
|
||||
* Node.js 24+ 및 Yarn 4
|
||||
* Twenty 워크스페이스와 API 키(https://app.twenty.com/settings/api-webhooks에서 생성)
|
||||
|
||||
## Getting Started
|
||||
## 시작하기
|
||||
|
||||
Create a new app using the official scaffolder, then authenticate and start developing:
|
||||
공식 스캐폴더를 사용해 새 앱을 만든 다음, 인증하고 개발을 시작하세요:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Scaffold a new app
|
||||
# 새 앱 초기 구조 생성
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
cd my-twenty-app
|
||||
|
||||
# Authenticate using your API key (you'll be prompted)
|
||||
yarn auth
|
||||
# yarn@4를 사용하지 않는 경우
|
||||
corepack enable
|
||||
yarn install
|
||||
|
||||
# Start dev mode: automatically syncs local changes to your workspace
|
||||
yarn dev
|
||||
# API 키로 인증합니다(입력하라는 메시지가 표시됩니다)
|
||||
yarn auth:login
|
||||
|
||||
# 개발 모드 시작: 로컬 변경 사항이 워크스페이스와 자동으로 동기화됩니다
|
||||
yarn app:dev
|
||||
```
|
||||
|
||||
From here you can:
|
||||
여기에서 다음 작업을 수행할 수 있습니다:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Add a new entity to your application (guided)
|
||||
yarn create-entity
|
||||
yarn app:create-entity
|
||||
|
||||
# Generate a typed Twenty client and workspace entity types
|
||||
yarn generate
|
||||
yarn app:generate
|
||||
|
||||
# Run a one‑time sync (instead of watch mode)
|
||||
yarn sync
|
||||
yarn app:sync
|
||||
|
||||
# Watch your application's functions logs
|
||||
yarn logs
|
||||
yarn function:logs
|
||||
|
||||
# Execute a function by name
|
||||
yarn function:execute -n my-function -p '{"name": "test"}'
|
||||
|
||||
# Uninstall the application from the current workspace
|
||||
yarn uninstall
|
||||
yarn app:uninstall
|
||||
|
||||
# Display commands' help
|
||||
yarn help
|
||||
yarn app:help
|
||||
```
|
||||
|
||||
See also: the CLI reference pages for [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) and [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
|
||||
참고: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) 및 [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk)의 CLI 참고 페이지도 확인하세요.
|
||||
|
||||
## Project structure (scaffolded)
|
||||
## 프로젝트 구조(스캐폴딩됨)
|
||||
|
||||
When you run `npx create-twenty-app@latest my-twenty-app`, the scaffolder:
|
||||
`npx create-twenty-app@latest my-twenty-app`를 실행하면, 스캐폴더가 다음을 수행합니다:
|
||||
|
||||
* Copies a minimal base application into `my-twenty-app/`
|
||||
* Adds a local `twenty-sdk` dependency and Yarn 4 configuration
|
||||
* Creates config files and scripts wired to the `twenty` CLI
|
||||
* Generates a default application config and a default function role
|
||||
* `my-twenty-app/`에 최소한의 기본 애플리케이션을 복사합니다
|
||||
* 로컬 `twenty-sdk` 종속성과 Yarn 4 구성을 추가합니다
|
||||
* `twenty` CLI와 연결된 설정 파일과 스크립트를 생성합니다
|
||||
* 기본 애플리케이션 구성과 기본 함수 역할을 생성합니다
|
||||
|
||||
A freshly scaffolded app looks like this:
|
||||
새로 스캐폴딩된 앱은 다음과 같습니다:
|
||||
|
||||
```text filename="my-twenty-app/"
|
||||
my-twenty-app/
|
||||
@@ -85,79 +92,144 @@ my-twenty-app/
|
||||
.nvmrc
|
||||
.yarnrc.yml
|
||||
.yarn/
|
||||
releases/
|
||||
yarn-4.9.2.cjs
|
||||
install-state.gz
|
||||
eslint.config.mjs
|
||||
tsconfig.json
|
||||
README.md
|
||||
src/
|
||||
application.config.ts
|
||||
role.config.ts
|
||||
// your entities, actions, and other app files
|
||||
app/
|
||||
application.config.ts # Required - main application configuration
|
||||
default-function.role.ts # Default role for serverless functions
|
||||
// your entities (*.object.ts, *.function.ts, *.role.ts)
|
||||
utils/ # Optional - handler implementations & utilities
|
||||
```
|
||||
|
||||
At a high level:
|
||||
### 설정보다 관례
|
||||
|
||||
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall`, and `auth` that delegate to the local `twenty` CLI.
|
||||
* **.gitignore**: Ignores common artifacts such as `node_modules`, `.yarn`, `generated/` (typed client), `dist/`, `build/`, coverage folders, log files, and `.env*` files.
|
||||
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Lock and configure the Yarn 4 toolchain used by the project.
|
||||
* **.nvmrc**: Pins the Node.js version expected by the project.
|
||||
* **eslint.config.mjs** and **tsconfig.json**: Provide linting and TypeScript configuration for your app’s TypeScript sources.
|
||||
* **README.md**: A short README in the app root with basic instructions.
|
||||
* **src/**: The main place where you define your application-as-code:
|
||||
* `application.config.ts`: Global configuration for your app (metadata and runtime wiring). See “Application config” below.
|
||||
* `role.config.ts`: Default function role used by your serverless functions. See “Default function role” below.
|
||||
* Future entities, actions/functions, and any supporting code you add.
|
||||
애플리케이션은 파일 접미사로 엔티티를 감지하는 **관례 우선** 접근 방식을 사용합니다. 이를 통해 `src/app/` 폴더 내에서 유연하게 구성할 수 있습니다:
|
||||
|
||||
Later commands will add more files and folders:
|
||||
| 파일 접미사 | 엔티티 유형 |
|
||||
| --------------- | ------------ |
|
||||
| `*.object.ts` | 사용자 정의 객체 정의 |
|
||||
| `*.function.ts` | 서버리스 함수 정의 |
|
||||
| `*.role.ts` | 역할 정의 |
|
||||
|
||||
* `yarn generate` will create a `generated/` folder (typed Twenty client + workspace types).
|
||||
* `yarn create-entity` will add entity definition files under `src/` for your custom objects.
|
||||
### 지원되는 폴더 구성 방식
|
||||
|
||||
## Authentication
|
||||
엔티티를 다음 패턴 중 어느 것으로든 구성할 수 있습니다:
|
||||
|
||||
The first time you run `yarn auth`, you'll be prompted for:
|
||||
**전통적(유형별):**
|
||||
|
||||
* API URL (defaults to http://localhost:3000 or your current workspace profile)
|
||||
* API key
|
||||
```text
|
||||
src/app/
|
||||
├── application.config.ts
|
||||
├── objects/
|
||||
│ └── postCard.object.ts
|
||||
├── functions/
|
||||
│ └── createPostCard.function.ts
|
||||
└── roles/
|
||||
└── admin.role.ts
|
||||
```
|
||||
|
||||
Your credentials are stored per-user in `~/.twenty/config.json`. You can maintain multiple profiles and switch using `--workspace <name>`.
|
||||
**기능 기반:**
|
||||
|
||||
Examples:
|
||||
```text
|
||||
src/app/
|
||||
├── application.config.ts
|
||||
└── post-card/
|
||||
├── postCard.object.ts
|
||||
├── createPostCard.function.ts
|
||||
└── postCardAdmin.role.ts
|
||||
```
|
||||
|
||||
**플랫:**
|
||||
|
||||
```text
|
||||
src/app/
|
||||
├── application.config.ts
|
||||
├── postCard.object.ts
|
||||
├── createPostCard.function.ts
|
||||
└── admin.role.ts
|
||||
```
|
||||
|
||||
개요:
|
||||
|
||||
* **package.json**: 앱 이름, 버전, 엔진(Node 24+, Yarn 4)을 선언하고, `twenty-sdk`와 함께 `dev`, `sync`, `generate`, `create-entity`, `logs`, `uninstall`, `auth` 같은 스크립트를 추가합니다. 이 스크립트들은 로컬 `twenty` CLI에 위임됩니다.
|
||||
* **.gitignore**: `node_modules`, `.yarn`, `generated/`(타입드 클라이언트), `dist/`, `build/`, 커버리지 폴더, 로그 파일, `.env*` 파일 등의 일반 산출물을 무시합니다.
|
||||
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: 프로젝트에서 사용하는 Yarn 4 툴체인을 고정하고 구성합니다.
|
||||
* **.nvmrc**: 프로젝트에서 예상하는 Node.js 버전을 고정합니다.
|
||||
* **eslint.config.mjs** 및 **tsconfig.json**: 앱의 TypeScript 소스에 대한 린팅 및 TypeScript 구성을 제공합니다.
|
||||
* **README.md**: 앱 루트에 기본 안내를 담은 간단한 README입니다.
|
||||
* **src/app/**: 애플리케이션을 코드로 정의하는 주요 위치:
|
||||
* `application.config.ts`: 앱의 전역 구성(메타데이터 및 런타임 연결)입니다. 아래의 "Application config"를 참조하세요.
|
||||
* `*.role.ts`: 서버리스 함수에서 사용하는 역할 정의. 아래의 "Default function role"을 참조하세요.
|
||||
* `*.object.ts`: 사용자 정의 객체 정의.
|
||||
* `*.function.ts`: 서버리스 함수 정의.
|
||||
* **src/utils/**: 핸들러 구현 및 유틸리티를 위한 선택적 폴더.
|
||||
|
||||
이후 명령을 실행하면 더 많은 파일과 폴더가 추가됩니다:
|
||||
|
||||
* `yarn app:generate`는 `generated/` 폴더를 생성합니다(타입드 Twenty 클라이언트 + 워크스페이스 타입).
|
||||
* `yarn app:create-entity`는 사용자 정의 객체, 함수, 역할에 대한 엔티티 정의 파일을 `src/app/` 아래에 추가합니다.
|
||||
l
|
||||
|
||||
## 인증
|
||||
|
||||
처음 `yarn auth:login`을 실행하면 다음을 입력하라는 프롬프트가 표시됩니다:
|
||||
|
||||
* API URL(기본값은 http://localhost:3000 또는 현재 워크스페이스 프로필)
|
||||
* API 키
|
||||
|
||||
자격 증명은 사용자별로 `~/.twenty/config.json`에 저장됩니다. 여러 프로필을 유지하고 프로필 간에 전환할 수 있습니다.
|
||||
|
||||
### 작업 공간 관리
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Login interactively (recommended)
|
||||
yarn auth
|
||||
yarn auth:login
|
||||
|
||||
# Use a specific workspace profile
|
||||
yarn auth --workspace my-custom-workspace
|
||||
# Login to a specific workspace profile
|
||||
yarn auth:login --workspace my-custom-workspace
|
||||
|
||||
# List all configured workspaces
|
||||
yarn auth:list
|
||||
|
||||
# Switch the default workspace (interactive)
|
||||
yarn auth:switch
|
||||
|
||||
# Switch to a specific workspace
|
||||
yarn auth:switch production
|
||||
|
||||
# Check current authentication status
|
||||
yarn auth:status
|
||||
```
|
||||
|
||||
## Use the SDK resources (types & config)
|
||||
한 번 `auth:switch`로 작업 공간을 전환하면, 이후의 모든 명령은 기본적으로 해당 작업 공간을 사용합니다. 여전히 `--workspace <name>`로 일시적으로 재정의할 수 있습니다.
|
||||
|
||||
The twenty-sdk provides typed building blocks you use inside your app. Below are the key pieces you'll touch most often.
|
||||
## SDK 리소스(타입 및 구성) 사용
|
||||
|
||||
### Defining objects
|
||||
twenty-sdk는 앱 내부에서 사용하는 타입드 빌딩 블록과 헬퍼 함수를 제공합니다. 가장 자주 사용하게 될 핵심 요소는 다음과 같습니다.
|
||||
|
||||
Custom objects are regular TypeScript classes annotated with decorators from `twenty-sdk`. They live under `src/objects/` in your app and describe both schema and behavior for records in your workspace.
|
||||
### 헬퍼 함수
|
||||
|
||||
Here is an example `postCard` object from the Hello World app:
|
||||
SDK는 앱 엔티티를 정의할 때 사용할 수 있는, 내장 검증이 포함된 네 가지 헬퍼 함수를 제공합니다:
|
||||
|
||||
| 함수 | 목적 |
|
||||
| ------------------ | ------------------- |
|
||||
| `defineApp()` | 애플리케이션 메타데이터 구성 |
|
||||
| `defineObject()` | 필드가 있는 사용자 정의 객체 정의 |
|
||||
| `defineFunction()` | 핸들러가 있는 서버리스 함수 정의 |
|
||||
| `defineRole()` | 역할 권한과 객체 접근 구성 |
|
||||
|
||||
이 함수들은 런타임에 구성을 검증하고, 더 나은 IDE 자동 완성과 타입 안정성을 제공합니다.
|
||||
|
||||
### 객체 정의하기
|
||||
|
||||
사용자 정의 객체는 워크스페이스의 레코드에 대한 스키마와 동작을 모두 정의합니다. `defineObject()`를 사용해 내장 검증과 함께 객체를 정의하세요:
|
||||
|
||||
```typescript
|
||||
import { type Note } from '../../generated';
|
||||
|
||||
import {
|
||||
type AddressField,
|
||||
Field,
|
||||
FieldType,
|
||||
type FullNameField,
|
||||
Object,
|
||||
OnDeleteAction,
|
||||
Relation,
|
||||
RelationType,
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-sdk';
|
||||
// src/app/postCard.object.ts
|
||||
import { defineObject, FieldType } from 'twenty-sdk';
|
||||
|
||||
enum PostCardStatus {
|
||||
DRAFT = 'DRAFT',
|
||||
@@ -166,176 +238,186 @@ enum PostCardStatus {
|
||||
RETURNED = 'RETURNED',
|
||||
}
|
||||
|
||||
@Object({
|
||||
export default defineObject({
|
||||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
nameSingular: 'postCard',
|
||||
namePlural: 'postCards',
|
||||
labelSingular: 'Post card',
|
||||
labelPlural: 'Post cards',
|
||||
description: ' A post card object',
|
||||
labelSingular: 'Post Card',
|
||||
labelPlural: 'Post Cards',
|
||||
description: 'A post card object',
|
||||
icon: 'IconMail',
|
||||
})
|
||||
export class PostCard {
|
||||
@Field({
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
type: FieldType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
icon: 'IconAbc',
|
||||
})
|
||||
content: string;
|
||||
|
||||
@Field({
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
type: FieldType.FULL_NAME,
|
||||
label: 'Recipient name',
|
||||
icon: 'IconUser',
|
||||
})
|
||||
recipientName: FullNameField;
|
||||
|
||||
@Field({
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
type: FieldType.ADDRESS,
|
||||
label: 'Recipient address',
|
||||
icon: 'IconHome',
|
||||
})
|
||||
recipientAddress: AddressField;
|
||||
|
||||
@Field({
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
type: FieldType.SELECT,
|
||||
label: 'Status',
|
||||
icon: 'IconSend',
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{ value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
|
||||
{ value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
|
||||
{ value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
|
||||
{ value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
|
||||
],
|
||||
})
|
||||
status: PostCardStatus;
|
||||
|
||||
@Relation({
|
||||
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
|
||||
type: RelationType.ONE_TO_MANY,
|
||||
label: 'Notes',
|
||||
icon: 'IconComment',
|
||||
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
|
||||
onDelete: OnDeleteAction.CASCADE,
|
||||
})
|
||||
notes: Note[];
|
||||
|
||||
@Field({
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
type: FieldType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
icon: 'IconCheck',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
})
|
||||
deliveredAt?: Date;
|
||||
}
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
name: 'content',
|
||||
type: FieldType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
icon: 'IconAbc',
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
name: 'recipientName',
|
||||
type: FieldType.FULL_NAME,
|
||||
label: 'Recipient name',
|
||||
icon: 'IconUser',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
name: 'recipientAddress',
|
||||
type: FieldType.ADDRESS,
|
||||
label: 'Recipient address',
|
||||
icon: 'IconHome',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
name: 'status',
|
||||
type: FieldType.SELECT,
|
||||
label: 'Status',
|
||||
icon: 'IconSend',
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{ value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
|
||||
{ value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
|
||||
{ value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
|
||||
{ value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
|
||||
],
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
name: 'deliveredAt',
|
||||
type: FieldType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
icon: 'IconCheck',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
핵심 요점:
|
||||
|
||||
* The `@Object` decorator defines the object identity and labels used across the workspace; its `universalIdentifier` must be unique and stable across deployments.
|
||||
* Each `@Field` decorator defines a field on the object with a type, label, and its own stable `universalIdentifier`.
|
||||
* `@Relation` wires this object to other objects (standard or custom) and controls cascade behavior with `onDelete`.
|
||||
* You can scaffold new objects using `yarn create-entity`, which guides you through naming, fields, and relationships, then generates object files similar to the `postCard` example.
|
||||
* 내장 검증과 더 나은 IDE 지원을 위해 `defineObject()`를 사용하세요.
|
||||
* `universalIdentifier`는 배포 전반에서 고유하고 안정적이어야 합니다.
|
||||
* 각 필드는 `name`, `type`, `label` 및 고유하고 안정적인 `universalIdentifier`가 필요합니다.
|
||||
* `fields` 배열은 선택 사항입니다. 사용자 정의 필드 없이도 객체를 정의할 수 있습니다.
|
||||
* `yarn app:create-entity`를 사용하여 새 객체를 스캐폴딩할 수 있으며, 이름, 필드, 관계 설정 과정을 안내합니다.
|
||||
|
||||
### Application config (application.config.ts)
|
||||
<Note>
|
||||
**기본 필드는 자동으로 생성됩니다.** 사용자 정의 객체를 정의하면 Twenty가 `name`, `createdAt`, `updatedAt`, `createdBy`, `position`, `deletedAt` 등의 표준 필드를 자동으로 추가합니다. 이 필드들은 `fields` 배열에 정의할 필요가 없습니다. 사용자 정의 필드만 추가하세요.
|
||||
</Note>
|
||||
|
||||
Every app has a single `application.config.ts` file that describes:
|
||||
<Accordion title="대안: 데코레이터 기반 문법">
|
||||
TypeScript 데코레이터를 사용하여 객체를 정의할 수도 있습니다. 이 접근 방식은 `@Object`, `@Field`, `@Relation` 데코레이터를 사용하는 클래스 기반 문법을 사용합니다:
|
||||
|
||||
* **Who the app is**: identifiers, display name, and description.
|
||||
* **How its functions run**: which role they use for permissions.
|
||||
* **(Optional) variables**: key–value pairs exposed to your functions as environment variables.
|
||||
```typescript
|
||||
import {
|
||||
type AddressField,
|
||||
Field,
|
||||
FieldType,
|
||||
type FullNameField,
|
||||
Object,
|
||||
OnDeleteAction,
|
||||
Relation,
|
||||
RelationType,
|
||||
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
||||
} from 'twenty-sdk';
|
||||
import { type Note } from '../../generated';
|
||||
|
||||
When you scaffold a new app, you start with a minimal config:
|
||||
@Object({
|
||||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
nameSingular: 'postCard',
|
||||
namePlural: 'postCards',
|
||||
labelSingular: 'Post card',
|
||||
labelPlural: 'Post cards',
|
||||
description: 'A post card object',
|
||||
icon: 'IconMail',
|
||||
})
|
||||
export class PostCard {
|
||||
@Field({
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
type: FieldType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
icon: 'IconAbc',
|
||||
})
|
||||
content: string;
|
||||
|
||||
@Relation({
|
||||
universalIdentifier: 'c9e2b4f4-b9ad-4427-9b42-9971b785edfe',
|
||||
type: RelationType.ONE_TO_MANY,
|
||||
label: 'Notes',
|
||||
icon: 'IconComment',
|
||||
inverseSideTargetUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.note,
|
||||
onDelete: OnDeleteAction.CASCADE,
|
||||
})
|
||||
notes: Note[];
|
||||
}
|
||||
```
|
||||
|
||||
참고: 데코레이터 접근 방식은 TypeScript 구성에서 `experimentalDecorators`가 필요합니다.
|
||||
</Accordion>
|
||||
|
||||
### 애플리케이션 구성(application.config.ts)
|
||||
|
||||
모든 앱에는 다음을 설명하는 단일 `application.config.ts` 파일이 있습니다:
|
||||
|
||||
* **앱에 대한 정보**: 식별자, 표시 이름, 설명.
|
||||
* **함수가 실행되는 방식**: 권한을 위해 사용하는 역할.
|
||||
* **(선택 사항) 변수**: 함수에 환경 변수로 노출되는 키–값 쌍.
|
||||
|
||||
`defineApp()`을 사용해 애플리케이션 구성을 정의하세요:
|
||||
|
||||
```typescript
|
||||
import { type ApplicationConfig } from 'twenty-sdk';
|
||||
// src/app/application.config.ts
|
||||
import { defineApp } from 'twenty-sdk';
|
||||
import { DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER } from './default-function.role';
|
||||
|
||||
const config: ApplicationConfig = {
|
||||
universalIdentifier: '<generated-app-uuid>',
|
||||
export default defineApp({
|
||||
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
|
||||
displayName: 'My Twenty App',
|
||||
description: 'My first Twenty app',
|
||||
functionRoleUniversalIdentifier: '<generated-role-uuid>',
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
You can gradually extend this file as your app grows. For example, you can add an icon and application-scoped variables:
|
||||
|
||||
```typescript
|
||||
import { type ApplicationConfig } from 'twenty-sdk';
|
||||
|
||||
const config: ApplicationConfig = {
|
||||
universalIdentifier: '<your-app-uuid>',
|
||||
displayName: 'My App',
|
||||
description: 'What your app does',
|
||||
icon: 'IconWorld', // Choose an icon by name
|
||||
icon: 'IconWorld',
|
||||
applicationVariables: {
|
||||
DEFAULT_RECIPIENT_NAME: {
|
||||
universalIdentifier: '<uuid>',
|
||||
description: 'Default recipient used by functions',
|
||||
universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
|
||||
description: 'Default recipient name for postcards',
|
||||
value: 'Jane Doe',
|
||||
isSecret: false,
|
||||
},
|
||||
},
|
||||
functionRoleUniversalIdentifier: '<your-role-uuid>',
|
||||
};
|
||||
|
||||
export default config;
|
||||
functionRoleUniversalIdentifier: DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
노트:
|
||||
|
||||
* `universalIdentifier` fields are deterministic IDs you own; generate them once and keep them stable across syncs.
|
||||
* `applicationVariables` become environment variables for your functions (for example, `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
|
||||
* `functionRoleUniversalIdentifier` must match the role you define in `role.config.ts` (see below).
|
||||
* `universalIdentifier` 필드는 고유하고 결정적인 ID입니다. 한 번 생성한 후 동기화 전반에 걸쳐 안정적으로 유지하세요.
|
||||
* `applicationVariables`는 함수의 환경 변수가 됩니다(예: `DEFAULT_RECIPIENT_NAME`는 `process.env.DEFAULT_RECIPIENT_NAME`로 사용 가능).
|
||||
* `functionRoleUniversalIdentifier`는 `*.role.ts` 파일에서 정의한 역할과 일치해야 합니다(아래 참조).
|
||||
|
||||
#### Roles and permissions
|
||||
#### 역할 및 권한
|
||||
|
||||
Applications can define roles that encapsulate permissions on your workspace’s objects and actions. The field `functionRoleUniversalIdentifier` in `application.config.ts` designates the default role used by your app’s serverless functions.
|
||||
애플리케이션은 워크스페이스의 객체와 작업에 대한 권한을 캡슐화하는 역할을 정의할 수 있습니다. `application.config.ts`의 `functionRoleUniversalIdentifier` 필드는 앱의 서버리스 함수가 사용하는 기본 역할을 지정합니다.
|
||||
|
||||
* The runtime API key injected as `TWENTY_API_KEY` is derived from this default function role.
|
||||
* The typed client will be restricted to the permissions granted to that role.
|
||||
* Follow least‑privilege: create a dedicated role with only the permissions your functions need, then reference its universal identifier.
|
||||
* `TWENTY_API_KEY`로 주입되는 런타임 API 키는 이 기본 함수 역할에서 파생됩니다.
|
||||
* 타입드 클라이언트는 해당 역할에 부여된 권한으로 제한됩니다.
|
||||
* 최소 권한 원칙을 따르세요. 함수에 필요한 권한만 가진 전용 역할을 만들고, 해당 역할의 universal identifier를 참조하세요.
|
||||
|
||||
##### Default function role (role.config.ts)
|
||||
##### 기본 함수 역할(\*.role.ts)
|
||||
|
||||
When you scaffold a new app, the CLI also creates `src/role.config.ts`. This file exports the default role your serverless functions will use at runtime:
|
||||
새 앱을 스캐폴딩하면, CLI가 기본 역할 파일도 생성합니다. `defineRole()`을 사용해 내장 검증과 함께 역할을 정의하세요:
|
||||
|
||||
```typescript
|
||||
import { PermissionFlag, type RoleConfig } from 'twenty-sdk';
|
||||
// src/app/default-function.role.ts
|
||||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||||
|
||||
export const functionRole: RoleConfig = {
|
||||
universalIdentifier: '<generated-role-uuid>',
|
||||
label: 'My Twenty App default function role',
|
||||
description: 'My Twenty App default function role',
|
||||
canReadAllObjectRecords: true,
|
||||
canUpdateAllObjectRecords: true,
|
||||
canSoftDeleteAllObjectRecords: true,
|
||||
canDestroyAllObjectRecords: false,
|
||||
};
|
||||
```
|
||||
export const DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER =
|
||||
'b648f87b-1d26-4961-b974-0908fd991061';
|
||||
|
||||
The `universalIdentifier` of this role is automatically wired into `application.config.ts` as `functionRoleUniversalIdentifier`. In other words:
|
||||
|
||||
* **role.config.ts** defines what the default function role can do.
|
||||
* **application.config.ts** points to that role so your functions inherit its permissions.
|
||||
|
||||
As you move beyond the initial scaffold, you should tighten this role and make it explicit about what it can access. A more production-ready role might look closer to:
|
||||
|
||||
```typescript
|
||||
import { PermissionFlag, type RoleConfig } from 'twenty-sdk';
|
||||
|
||||
export const functionRole: RoleConfig = {
|
||||
universalIdentifier: '<your-role-uuid>',
|
||||
export default defineRole({
|
||||
universalIdentifier: DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
label: 'Default function role',
|
||||
description: 'Default role for function Twenty client',
|
||||
canReadAllObjectRecords: false,
|
||||
@@ -363,41 +445,41 @@ export const functionRole: RoleConfig = {
|
||||
canUpdateFieldValue: false,
|
||||
},
|
||||
],
|
||||
permissionFlags: ['APPLICATIONS'],
|
||||
};
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
이 역할의 `universalIdentifier`는 `application.config.ts`에서 `functionRoleUniversalIdentifier`로 참조됩니다. 다시 말해:
|
||||
|
||||
* Start from the scaffolded role, then progressively restrict it following least‑privilege.
|
||||
* Replace the `objectPermissions` and `fieldPermissions` with the objects/fields your functions need.
|
||||
* `permissionFlags` control access to platform-level capabilities. Keep them minimal; add only what you need.
|
||||
* See a working example in the Hello World app: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
* **\*.role.ts**는 기본 함수 역할이 수행할 수 있는 작업을 정의합니다.
|
||||
* **application.config.ts**는 해당 역할을 가리키므로, 함수는 그 권한을 상속받습니다.
|
||||
|
||||
### Serverless function config and entrypoint
|
||||
노트:
|
||||
|
||||
Each function exports a main handler and a config describing its triggers. You can mix multiple trigger types.
|
||||
* 스캐폴딩된 역할에서 시작하여, 최소 권한 원칙에 따라 점진적으로 제한하세요.
|
||||
* `objectPermissions`와 `fieldPermissions`를 함수에 필요한 객체/필드로 교체하세요.
|
||||
* `permissionFlags`는 플랫폼 수준 기능에 대한 액세스를 제어합니다. 최소한으로 유지하고, 필요한 것만 추가하세요.
|
||||
* Hello World 앱의 동작 예제를 참조하세요: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||||
|
||||
### 서버리스 함수 구성과 엔트리포인트
|
||||
|
||||
각 함수 파일은 `defineFunction()`을 사용해 핸들러와 선택적 트리거가 포함된 구성을 내보냅니다. 자동 감지를 위해 `*.function.ts` 파일 접미사를 사용하세요.
|
||||
|
||||
```typescript
|
||||
// src/actions/create-new-post-card.ts
|
||||
import type {
|
||||
FunctionConfig,
|
||||
DatabaseEventPayload,
|
||||
ObjectRecordCreateEvent,
|
||||
CronPayload,
|
||||
} from 'twenty-sdk';
|
||||
import Twenty, { type Person } from '../generated';
|
||||
// src/app/createPostCard.function.ts
|
||||
import { defineFunction } from 'twenty-sdk';
|
||||
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
|
||||
import Twenty, { type Person } from '../../generated';
|
||||
|
||||
// main handler can accept parameters from route, cron, or database events
|
||||
export const main = async (
|
||||
const handler = async (
|
||||
params:
|
||||
| { name?: string }
|
||||
| RoutePayload
|
||||
| DatabaseEventPayload<ObjectRecordCreateEvent<Person>>
|
||||
| CronPayload,
|
||||
) => {
|
||||
const client = new Twenty(); // generated typed client
|
||||
const name = 'name' in params
|
||||
? params.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
|
||||
const name = 'name' in params.queryStringParameters
|
||||
? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
|
||||
: 'Hello world';
|
||||
|
||||
const result = await client.mutation({
|
||||
@@ -410,14 +492,15 @@ export const main = async (
|
||||
return result;
|
||||
};
|
||||
|
||||
export const config: FunctionConfig = {
|
||||
universalIdentifier: '<function-uuid>',
|
||||
export default defineFunction({
|
||||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||||
name: 'create-new-post-card',
|
||||
timeoutSeconds: 2,
|
||||
handler,
|
||||
triggers: [
|
||||
// Public HTTP route trigger '/s/post-card/create'
|
||||
{
|
||||
universalIdentifier: '<route-trigger-uuid>',
|
||||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||||
type: 'route',
|
||||
path: '/post-card/create',
|
||||
httpMethod: 'GET',
|
||||
@@ -425,39 +508,137 @@ export const config: FunctionConfig = {
|
||||
},
|
||||
// Cron trigger (CRON pattern)
|
||||
{
|
||||
universalIdentifier: '<cron-trigger-uuid>',
|
||||
universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
|
||||
type: 'cron',
|
||||
pattern: '0 0 1 1 *',
|
||||
},
|
||||
// Database event trigger
|
||||
{
|
||||
universalIdentifier: '<db-trigger-uuid>',
|
||||
universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
|
||||
type: 'databaseEvent',
|
||||
eventName: 'person.created',
|
||||
eventName: 'person.updated',
|
||||
updatedFields: ['name'],
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
일반적인 트리거 유형:
|
||||
|
||||
* **route**: **`/s/` 엔드포인트** 아래에서 HTTP 경로와 메서드로 함수를 노출합니다:
|
||||
|
||||
> 예: `path: '/post-card/create',` -> `<APP_URL>/s/post-card/create`에서 호출
|
||||
|
||||
* **cron**: CRON 식을 사용하여 예약된 일정으로 함수를 실행합니다.
|
||||
* **databaseEvent**: 워크스페이스 객체 라이프사이클 이벤트에서 실행됩니다. 이벤트 작업이 `updated`인 경우, 수신할 특정 필드를 `updatedFields` 배열에 지정할 수 있습니다. 정의하지 않거나 비워두면, 어떤 업데이트든 함수가 트리거됩니다.
|
||||
|
||||
> 예: `person.updated`
|
||||
|
||||
노트:
|
||||
|
||||
* `triggers` 배열은 선택 사항입니다. 트리거가 없는 함수는 다른 함수에서 호출되는 유틸리티 함수로 사용할 수 있습니다.
|
||||
* 하나의 함수에서 여러 트리거 유형을 혼합할 수 있습니다.
|
||||
|
||||
### 라우트 트리거 페이로드
|
||||
|
||||
<Warning>
|
||||
**호환성 파괴적 변경(v1.16, 2026년 1월):** 라우트 트리거 페이로드 형식이 변경되었습니다. v1.16 이전에는 쿼리 매개변수, 경로 매개변수, 그리고 본문이 페이로드로 직접 전송되었습니다. v1.16부터는 이들이 구조화된 `RoutePayload` 객체 내부에 중첩됩니다.
|
||||
|
||||
**v1.16 이전:**
|
||||
|
||||
```typescript
|
||||
const handler = async (params) => {
|
||||
const { param1, param2 } = params; // Direct access
|
||||
};
|
||||
```
|
||||
|
||||
**v1.16 이후:**
|
||||
|
||||
```typescript
|
||||
const handler = async (event: RoutePayload) => {
|
||||
const { param1, param2 } = event.body; // Access via .body
|
||||
const { queryParam } = event.queryStringParameters;
|
||||
const { id } = event.pathParameters;
|
||||
};
|
||||
```
|
||||
|
||||
**기존 함수 마이그레이션 방법:** 핸들러에서 params 객체에서 직접 구조 분해하는 대신 `event.body`, `event.queryStringParameters`, 또는 `event.pathParameters`에서 구조 분해하도록 업데이트하세요.
|
||||
</Warning>
|
||||
|
||||
라우트 트리거가 함수를 호출하면, AWS HTTP API v2 형식을 따르는 `RoutePayload` 객체를 받습니다. `twenty-sdk`에서 해당 타입을 임포트하세요:
|
||||
|
||||
```typescript
|
||||
import { defineFunction, type RoutePayload } from 'twenty-sdk';
|
||||
|
||||
const handler = async (event: RoutePayload) => {
|
||||
// Access request data
|
||||
const { headers, queryStringParameters, pathParameters, body } = event;
|
||||
|
||||
// HTTP method and path are available in requestContext
|
||||
const { method, path } = event.requestContext.http;
|
||||
|
||||
return { message: 'Success' };
|
||||
};
|
||||
```
|
||||
|
||||
Common trigger types:
|
||||
`RoutePayload` 타입은 다음과 같은 구조입니다:
|
||||
|
||||
* route: Exposes your function on an HTTP path and method **under the `/s/` endpoint**:
|
||||
| 속성 | 유형 | 설명 |
|
||||
| ---------------------------- | ------------------------------------- | ------------------------------------------------------- |
|
||||
| `headers` | `Record<string, string \| undefined>` | HTTP 헤더(`forwardedRequestHeaders`에 나열된 항목만) |
|
||||
| `queryStringParameters` | `Record<string, string \| undefined>` | 쿼리 문자열 매개변수(여러 값은 쉼표로 연결됨) |
|
||||
| `pathParameters` | `Record<string, string \| undefined>` | 라우트 패턴에서 추출된 경로 매개변수(예: `/users/:id` → `{ id: '123' }`) |
|
||||
| `본문` | `object \| null` | 파싱된 요청 본문(JSON) |
|
||||
| `isBase64Encoded` | `부울` | 본문이 base64로 인코딩되었는지 여부 |
|
||||
| `requestContext.http.method` | `string` | HTTP 메서드(GET, POST, PUT, PATCH, DELETE) |
|
||||
| `requestContext.http.path` | `string` | 원시 요청 경로 |
|
||||
|
||||
> e.g. `path: '/post-card/create',` -> call on `<APP_URL>/s/post-card/create`
|
||||
### HTTP 헤더 전달
|
||||
|
||||
* cron: Runs your function on a schedule using a CRON expression.
|
||||
* databaseEvent: Runs on workspace object lifecycle events
|
||||
기본적으로 보안상의 이유로 들어오는 요청의 HTTP 헤더는 서버리스 함수로 **전달되지 않습니다**. 특정 헤더에 접근하려면 `forwardedRequestHeaders` 배열에 명시적으로 나열하세요:
|
||||
|
||||
> e.g. `person.created`
|
||||
```typescript
|
||||
export default defineFunction({
|
||||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||||
name: 'webhook-handler',
|
||||
handler,
|
||||
triggers: [
|
||||
{
|
||||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||||
type: 'route',
|
||||
path: '/webhook',
|
||||
httpMethod: 'POST',
|
||||
isAuthRequired: false,
|
||||
forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
You can create new functions in two ways:
|
||||
핸들러에서 다음과 같이 해당 헤더에 접근할 수 있습니다:
|
||||
|
||||
* **Scaffolded**: Run `yarn create-entity --path <custom-path>` and choose the option to add a new function. This generates a starter file under `<custom-path>` with a `main` handler and a `config` block similar to the example above.
|
||||
* **Manual**: Create a new file and export `main` and `config` yourself, following the same pattern.
|
||||
```typescript
|
||||
const handler = async (event: RoutePayload) => {
|
||||
const signature = event.headers['x-webhook-signature'];
|
||||
const contentType = event.headers['content-type'];
|
||||
|
||||
### Generated typed client
|
||||
// Validate webhook signature...
|
||||
return { received: true };
|
||||
};
|
||||
```
|
||||
|
||||
Run yarn generate to create a local typed client in generated/ based on your workspace schema. Use it in your functions:
|
||||
<Note>
|
||||
헤더 이름은 소문자로 정규화됩니다. 소문자 키를 사용해 접근하세요(예: `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
새 함수를 만드는 방법은 두 가지입니다:
|
||||
|
||||
* **스캐폴딩**: `yarn app:create-entity`를 실행하고 새 함수를 추가하는 옵션을 선택하세요. 이렇게 하면 핸들러와 구성이 포함된 시작 파일이 생성됩니다.
|
||||
* **수동**: 새 `*.function.ts` 파일을 만들고 동일한 패턴에 따라 `defineFunction()`을 사용하세요.
|
||||
|
||||
### 생성된 타입드 클라이언트
|
||||
|
||||
워크스페이스 스키마를 기반으로 generated/에 로컬 타입드 클라이언트를 생성하려면 yarn app:generate를 실행하세요. 함수에서 사용하세요:
|
||||
|
||||
```typescript
|
||||
import Twenty from './generated';
|
||||
@@ -466,34 +647,34 @@ const client = new Twenty();
|
||||
const { me } = await client.query({ me: { id: true, displayName: true } });
|
||||
```
|
||||
|
||||
The client is re-generated by `yarn generate`. Re-run after changing your objects and `yarn sync` or when onboarding to a new workspace.
|
||||
클라이언트는 `yarn app:generate`로 다시 생성됩니다. 객체를 변경하고 `yarn app:sync`를 실행한 후 또는 새 워크스페이스에 온보딩할 때 다시 실행하세요.
|
||||
|
||||
#### Runtime credentials in serverless functions
|
||||
#### 서버리스 함수의 런타임 자격 증명
|
||||
|
||||
When your function runs on Twenty, the platform injects credentials as environment variables before your code executes:
|
||||
함수가 Twenty에서 실행될 때, 플랫폼은 코드가 실행되기 전에 자격 증명을 환경 변수로 주입합니다:
|
||||
|
||||
* `TWENTY_API_URL`: Base URL of the Twenty API your app targets.
|
||||
* `TWENTY_API_KEY`: Short‑lived key scoped to your application’s default function role.
|
||||
* `TWENTY_API_URL`: 앱이 대상으로 하는 Twenty API의 기본 URL.
|
||||
* `TWENTY_API_KEY`: 애플리케이션의 기본 함수 역할 범위로 제한된 단기 키.
|
||||
|
||||
Notes:
|
||||
노트:
|
||||
|
||||
* You do not need to pass URL or API key to the generated client. It reads `TWENTY_API_URL` and `TWENTY_API_KEY` from process.env at runtime.
|
||||
* The API key’s permissions are determined by the role referenced in your `application.config.ts` via `functionRoleUniversalIdentifier`. This is the default role used by serverless functions of your application.
|
||||
* Applications can define roles to follow least‑privilege. Grant only the permissions your functions need, then point `functionRoleUniversalIdentifier` to that role’s universal identifier.
|
||||
* 생성된 클라이언트에 URL이나 API 키를 전달할 필요가 없습니다. 런타임에 process.env에서 `TWENTY_API_URL`과 `TWENTY_API_KEY`를 읽습니다.
|
||||
* API 키의 권한은 `application.config.ts`에서 `functionRoleUniversalIdentifier`를 통해 참조된 역할에 의해 결정됩니다. 이는 애플리케이션의 서버리스 함수에서 사용하는 기본 역할입니다.
|
||||
* 애플리케이션은 최소 권한 원칙을 따르도록 역할을 정의할 수 있습니다. 함수에 필요한 권한만 부여하고, `functionRoleUniversalIdentifier`를 해당 역할의 universal identifier로 지정하세요.
|
||||
|
||||
### Hello World example
|
||||
### Hello World 예제
|
||||
|
||||
Explore a minimal, end-to-end example that demonstrates objects, functions, and multiple triggers [here](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world):
|
||||
객체, 함수, 여러 트리거를 보여주는 최소한의 엔드투엔드 예제를 [여기](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world)에서 살펴보세요:
|
||||
|
||||
## Manual setup (without the scaffolder)
|
||||
## 수동 설정(스캐폴더 없이)
|
||||
|
||||
While we recommend using `create-twenty-app` for the best getting-started experience, you can also set up a project manually. Do not install the CLI globally. Instead, add `twenty-sdk` as a local dependency and wire scripts in your package.json:
|
||||
최적의 시작 경험을 위해 `create-twenty-app` 사용을 권장하지만, 프로젝트를 수동으로 설정할 수도 있습니다. CLI를 전역으로 설치하지 마세요. 대신 `twenty-sdk`를 로컬 종속성으로 추가하고 package.json에 스크립트를 연결하세요:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn add -D twenty-sdk
|
||||
```
|
||||
|
||||
Then add scripts like these:
|
||||
그런 다음 다음과 같은 스크립트를 추가하세요:
|
||||
|
||||
```json filename="package.json"
|
||||
{
|
||||
@@ -510,13 +691,13 @@ Then add scripts like these:
|
||||
}
|
||||
```
|
||||
|
||||
Now you can run the same commands via Yarn, e.g. `yarn dev`, `yarn sync`, etc.
|
||||
이제 Yarn을 통해 동일한 명령을 실행할 수 있습니다. 예: `yarn app:dev`, `yarn app:sync` 등
|
||||
|
||||
## Troubleshooting
|
||||
## 문제 해결
|
||||
|
||||
* Authentication errors: run `yarn auth` and ensure your API key has the required permissions.
|
||||
* Cannot connect to server: verify the API URL and that the Twenty server is reachable.
|
||||
* Types or client missing/outdated: run `yarn generate` and then `yarn dev`.
|
||||
* Dev mode not syncing: ensure `yarn dev` is running and that changes are not ignored by your environment.
|
||||
* 인증 오류: `yarn auth:login`를 실행하고 API 키에 필요한 권한이 있는지 확인하세요.
|
||||
* 서버에 연결할 수 없음: API URL과 Twenty 서버에 접근 가능한지 확인하세요.
|
||||
* 타입 또는 클라이언트가 없거나 오래됨: `yarn app:generate`를 실행한 다음 `yarn app:dev`를 실행하세요.
|
||||
* 개발 모드가 동기화되지 않음: `yarn app:dev`가 실행 중인지, 환경에서 변경 사항을 무시하지 않는지 확인하세요.
|
||||
|
||||
Discord Help Channel: https://discord.com/channels/1130383047699738754/1130386664812982322
|
||||
Discord 도움말 채널: https://discord.com/channels/1130383047699738754/1130386664812982322
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
---
|
||||
title: Webhooks
|
||||
description: Receive real-time notifications when events occur in your CRM.
|
||||
description: CRM에서 이벤트가 발생하면 실시간 알림을 받으세요.
|
||||
---
|
||||
|
||||
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
|
||||
|
||||
Webhooks push data to your systems in real-time when events occur in Twenty — no polling required. Use them to keep external systems in sync, trigger automations, or send alerts.
|
||||
웹훅은 Twenty에서 이벤트가 발생하면 데이터를 실시간으로 귀하의 시스템으로 푸시합니다 — 폴링이 필요 없습니다. 이를 사용하여 외부 시스템을 동기화 상태로 유지하고, 자동화를 트리거하거나, 알림을 보낼 수 있습니다.
|
||||
|
||||
## Create a Webhook
|
||||
## Webhook 생성
|
||||
|
||||
1. Go to **Settings → APIs & Webhooks → Webhooks**
|
||||
2. Click **+ Create webhook**
|
||||
3. Enter your webhook URL (must be publicly accessible)
|
||||
4. Click **Save**
|
||||
1. **설정 → API 및 웹훅 → 웹훅**으로 이동
|
||||
2. **+ Webhook 생성** 클릭
|
||||
3. 웹훅 URL을 입력하세요(공개적으로 액세스 가능해야 함)
|
||||
4. **저장** 클릭
|
||||
|
||||
The webhook activates immediately and starts sending notifications.
|
||||
웹훅이 즉시 활성화되어 알림 전송을 시작합니다.
|
||||
|
||||
<VimeoEmbed videoId="928786708" title="Creating a webhook" />
|
||||
<VimeoEmbed videoId="928786708" title="웹훅 생성" />
|
||||
|
||||
### Manage Webhooks
|
||||
### 웹훅 관리
|
||||
|
||||
**Edit**: Click the webhook → Update URL → **Save**
|
||||
**편집**: 웹훅을 클릭 → URL 업데이트 → **저장**
|
||||
|
||||
**Delete**: Click the webhook → **Delete** → Confirm
|
||||
**삭제**: 웹훅을 클릭 → **삭제** → 확인
|
||||
|
||||
## Events
|
||||
## 이벤트
|
||||
|
||||
Twenty sends webhooks for these event types:
|
||||
Twenty는 다음 이벤트 유형에 대해 웹훅을 전송합니다:
|
||||
|
||||
| Event | Example |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| **Record Created** | `person.created`, `company.created`, `note.created` |
|
||||
| **Record Updated** | `person.updated`, `company.updated`, `opportunity.updated` |
|
||||
| **Record Deleted** | `person.deleted`, `company.deleted` |
|
||||
| 이벤트 | 예시 |
|
||||
| ------------- | ---------------------------------------------------------- |
|
||||
| **레코드 생성됨** | `person.created`, `company.created`, `note.created` |
|
||||
| **레코드 업데이트됨** | `person.updated`, `company.updated`, `opportunity.updated` |
|
||||
| **레코드 삭제됨** | `person.deleted`, `company.deleted` |
|
||||
|
||||
All event types are sent to your webhook URL. Event filtering may be added in future releases.
|
||||
모든 이벤트 유형은 귀하의 웹훅 URL로 전송됩니다. 이벤트 필터링은 향후 릴리스에서 추가될 수 있습니다.
|
||||
|
||||
## Payload Format
|
||||
## 페이로드 형식
|
||||
|
||||
Each webhook sends an HTTP POST with a JSON body:
|
||||
각 웹훅은 JSON 본문을 포함한 HTTP POST를 전송합니다:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -55,35 +55,35 @@ Each webhook sends an HTTP POST with a JSON body:
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
| ----------- | ------------------------------------------------ |
|
||||
| `event` | What happened (e.g., `person.created`) |
|
||||
| `data` | The full record that was created/updated/deleted |
|
||||
| `timestamp` | When the event occurred (UTC) |
|
||||
| 필드 | 설명 |
|
||||
| ------- | -------------------------------- |
|
||||
| `이벤트` | 무슨 일이 발생했는지(예: `person.created`) |
|
||||
| `데이터` | 생성/업데이트/삭제된 전체 레코드 |
|
||||
| `타임스탬프` | 이벤트가 발생한 시각(UTC) |
|
||||
|
||||
<Note>
|
||||
Respond with a **2xx HTTP status** (200-299) to acknowledge receipt. Non-2xx responses are logged as delivery failures.
|
||||
수신을 확인하기 위해 **2xx HTTP 상태**(200-299)로 응답하세요. 2xx가 아닌 응답은 전달 실패로 기록됩니다.
|
||||
</Note>
|
||||
|
||||
## Webhook Validation
|
||||
## 웹훅 검증
|
||||
|
||||
Twenty signs each webhook request for security. Validate signatures to ensure requests are authentic.
|
||||
Twenty는 보안을 위해 각 웹훅 요청에 서명합니다. 요청의 진위를 보장하기 위해 서명을 검증하세요.
|
||||
|
||||
### Headers
|
||||
### 헤더
|
||||
|
||||
| Header | Description |
|
||||
| ---------------------------- | --------------------- |
|
||||
| `X-Twenty-Webhook-Signature` | HMAC SHA256 signature |
|
||||
| `X-Twenty-Webhook-Timestamp` | Request timestamp |
|
||||
| 헤더 | 설명 |
|
||||
| ---------------------------- | -------------- |
|
||||
| `X-Twenty-Webhook-Signature` | HMAC SHA256 서명 |
|
||||
| `X-Twenty-Webhook-Timestamp` | 요청 타임스탬프 |
|
||||
|
||||
### Validation Steps
|
||||
### 검증 단계
|
||||
|
||||
1. Get the timestamp from `X-Twenty-Webhook-Timestamp`
|
||||
2. Create the string: `{timestamp}:{JSON payload}`
|
||||
3. Compute HMAC SHA256 using your webhook secret
|
||||
4. Compare with `X-Twenty-Webhook-Signature`
|
||||
1. `X-Twenty-Webhook-Timestamp`에서 타임스탬프를 가져옵니다
|
||||
2. 다음 문자열을 생성합니다: `{timestamp}:{JSON payload}`
|
||||
3. 웹훅 비밀을 사용하여 HMAC SHA256을 계산합니다
|
||||
4. `X-Twenty-Webhook-Signature`와 비교합니다
|
||||
|
||||
### Example (Node.js)
|
||||
### 예시(Node.js)
|
||||
|
||||
```javascript
|
||||
const crypto = require("crypto");
|
||||
@@ -101,12 +101,12 @@ const expectedSignature = crypto
|
||||
const isValid = expectedSignature === req.headers["x-twenty-webhook-signature"];
|
||||
```
|
||||
|
||||
## Webhooks vs Workflows
|
||||
## 웹훅 vs 워크플로
|
||||
|
||||
| Method | Direction | Use Case |
|
||||
| ---------------------------- | --------- | ---------------------------------------------------------- |
|
||||
| **Webhooks** | OUT | Automatically notify external systems of any record change |
|
||||
| **Workflow + HTTP Request** | OUT | Send data out with custom logic (filters, transformations) |
|
||||
| **Workflow Webhook Trigger** | IN | Receive data into Twenty from external systems |
|
||||
| 방법 | 방향 | 사용 사례 |
|
||||
| ------------------ | --- | ---------------------------------- |
|
||||
| **웹훅** | OUT | 레코드 변경 사항을 외부 시스템에 자동으로 알립니다 |
|
||||
| **워크플로 + HTTP 요청** | OUT | 사용자 지정 로직(필터, 변환)으로 데이터를 외부로 전송합니다 |
|
||||
| **워크플로 웹훅 트리거** | IN | 외부 시스템에서 Twenty로 데이터를 수신합니다 |
|
||||
|
||||
For receiving external data, see [Set Up a Webhook Trigger](/l/ko/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger).
|
||||
외부 데이터를 수신하려면 [웹훅 트리거 설정](/l/ko/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)을 참조하세요.
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
---
|
||||
title: Extend
|
||||
description: Extend Twenty's functionality with APIs, webhooks, and custom apps.
|
||||
title: 확장
|
||||
description: API, 웹훅 및 맞춤형 앱으로 Twenty의 기능을 확장하세요.
|
||||
---
|
||||
|
||||
<Frame>
|
||||
<img src="/images/user-guide/integrations/plug.png" alt="AI" />
|
||||
</Frame>
|
||||
|
||||
## Overview
|
||||
## 개요
|
||||
|
||||
Twenty is designed to be extensible. Use our APIs, webhooks, and app framework to integrate with your existing tools and build custom functionality.
|
||||
Twenty는 확장 가능하도록 설계되었습니다. 당사의 API, 웹훅 및 앱 프레임워크를 사용하여 기존 도구와 통합하고 맞춤형 기능을 구축하세요.
|
||||
|
||||
## What You Can Do
|
||||
## 가능한 작업
|
||||
|
||||
* **APIs**: Query and modify your CRM data programmatically using REST or GraphQL
|
||||
* **Webhooks**: Receive real-time notifications when events occur in Twenty
|
||||
* **Apps**: Build custom applications that extend Twenty's capabilities - Coming soon!
|
||||
* **API**: REST 또는 GraphQL을 사용해 프로그래밍 방식으로 CRM 데이터를 쿼리하고 수정하세요
|
||||
* **웹훅**: Twenty에서 이벤트가 발생하면 실시간 알림을 받으세요
|
||||
* **앱**: Twenty의 기능을 확장하는 맞춤형 앱을 구축하세요 - 곧 제공됩니다!
|
||||
|
||||
## Getting Started
|
||||
## 시작하기
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="APIs" icon="code" href="/l/ko/developers/extend/capabilities/apis">
|
||||
Connect to Twenty programmatically
|
||||
<Card title="API" icon="코드" href="/l/ko/developers/extend/capabilities/apis">
|
||||
프로그래밍 방식으로 Twenty에 연결하세요
|
||||
</Card>
|
||||
|
||||
<Card title="Webhooks" icon="bell" href="/l/ko/developers/extend/capabilities/webhooks">
|
||||
Get notified of events in real-time
|
||||
<Card title="웹훅" icon="bell" href="/l/ko/developers/extend/capabilities/webhooks">
|
||||
이벤트에 대한 실시간 알림을 받으세요
|
||||
</Card>
|
||||
|
||||
<Card title="Apps" icon="puzzle-piece" href="/l/ko/developers/extend/capabilities/apps">
|
||||
Build customizations as code (Alpha)
|
||||
<Card title="앱" icon="puzzle-piece" href="/l/ko/developers/extend/capabilities/apps">
|
||||
코드로 사용자 지정을 구축하세요(알파)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
---
|
||||
title: Getting Started
|
||||
description: Welcome to Twenty Developer Documentation, your resources for extending, self-hosting, and contributing to Twenty.
|
||||
title: 시작하기
|
||||
description: Twenty 개발자 문서에 오신 것을 환영합니다. 이 문서는 Twenty를 확장하고, 자체 호스팅하며, Twenty에 기여하는 데 필요한 자료를 제공합니다.
|
||||
---
|
||||
|
||||
import { CardTitle } from "/snippets/card-title.mdx"
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card href="/l/ko/developers/extend/extend" img="/images/user-guide/integrations/plug.png">
|
||||
<CardTitle>Extend</CardTitle>
|
||||
Build integrations with APIs, webhooks, and custom apps.
|
||||
<CardTitle>확장</CardTitle>
|
||||
API, 웹훅 및 맞춤형 앱과의 통합을 구축하세요.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/self-host/self-host" img="/images/user-guide/what-is-twenty/20.png">
|
||||
<CardTitle>Self-Host</CardTitle>
|
||||
Deploy and manage Twenty on your own infrastructure.
|
||||
<CardTitle>자체 호스팅</CardTitle>
|
||||
자체 인프라에 Twenty를 배포하고 관리하세요.
|
||||
</Card>
|
||||
|
||||
<Card href="/l/ko/developers/contribute/contribute" img="/images/user-guide/github/github-header.png">
|
||||
<CardTitle>Contribute</CardTitle>
|
||||
Join our open-source community and contribute to Twenty.
|
||||
<CardTitle>기여</CardTitle>
|
||||
오픈 소스 커뮤니티에 참여하고 Twenty에 기여하세요.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
---
|
||||
title: Other methods
|
||||
title: 기타 방법
|
||||
---
|
||||
|
||||
<Warning>
|
||||
This document is maintained by the community. It might contain issues.
|
||||
이 문서는 커뮤니티에서 관리됩니다. 문제점이 있을 수 있습니다.
|
||||
</Warning>
|
||||
|
||||
## Kubernetes via Terraform and Manifests
|
||||
## Terraform 및 매니페스트를 통한 Kubernetes
|
||||
|
||||
Community-led documentation for Kubernetes deployment is available [here](https://github.com/twentyhq/twenty/tree/main/packages/twenty-docker/k8s)
|
||||
Kubernetes 배포에 대한 커뮤니티 주도 문서는 [여기](https://github.com/twentyhq/twenty/tree/main/packages/twenty-docker/k8s)에서 확인할 수 있습니다.
|
||||
|
||||
### Coolify
|
||||
|
||||
Deploy Twenty on servers using Coolify. (official image on Coolify will be available soon)
|
||||
Coolify를 사용하여 서버에 Twenty를 배포하세요. (Coolify의 공식 이미지가 곧 제공될 예정입니다)
|
||||
|
||||
[Coolify documentation](https://coolify.io/docs/get-started/introduction)
|
||||
[Coolify 문서](https://coolify.io/docs/get-started/introduction)
|
||||
|
||||
### EasyPanel
|
||||
|
||||
Deploy Twenty on EasyPanel with the community maintained template below.
|
||||
아래의 커뮤니티가 유지 관리하는 템플릿으로 EasyPanel에 Twenty를 배포하세요.
|
||||
|
||||
[Deploy on EasyPanel](https://easypanel.io/docs/templates/twenty)
|
||||
[EasyPanel에 배포](https://easypanel.io/docs/templates/twenty)
|
||||
|
||||
### Elest.io
|
||||
|
||||
Deploy Twenty on servers with Elest.io using link below.
|
||||
아래 링크를 통해 Elest.io에서 서버에 Twenty를 배포하세요.
|
||||
|
||||
[Deploy on Elest.io](https://elest.io/open-source/twenty)
|
||||
[Elest.io에 배포](https://elest.io/open-source/twenty)
|
||||
|
||||
### Twenty on Railway
|
||||
### Railway에서의 Twenty
|
||||
|
||||
Deploy Twenty on Railway with the community maintained template below.
|
||||
아래의 커뮤니티가 유지 관리하는 템플릿으로 Railway에 Twenty를 배포하세요.
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty on Sealos
|
||||
### Sealos에서의 Twenty
|
||||
|
||||
Deploy Twenty on Sealos with the community maintained template below.
|
||||
아래의 커뮤니티가 유지 관리하는 템플릿으로 Sealos에 Twenty를 배포하세요.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Others
|
||||
## 기타
|
||||
|
||||
Please feel free to Open a PR to add more Cloud Provider options.
|
||||
더 많은 클라우드 제공자 옵션을 추가하기 위해 PR을 자유롭게 열어주세요.
|
||||
|
||||
@@ -1,253 +1,253 @@
|
||||
---
|
||||
title: 1-Click w/ Docker Compose
|
||||
title: Docker Compose로 1-클릭
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Docker containers are for production hosting or self-hosting, for the contribution please check the [Local Setup](/l/ko/developers/contribute/capabilities/local-setup).
|
||||
Docker 컨테이너는 프로덕션 호스팅 또는 셀프 호스팅을 위한 것입니다. 기여를 원하시면 [로컬 설정](/l/ko/developers/contribute/capabilities/local-setup)을 확인하세요.
|
||||
</Warning>
|
||||
|
||||
## Overview
|
||||
## 개요
|
||||
|
||||
This guide provides step-by-step instructions to install and configure the Twenty application using Docker Compose. The aim is to make the process straightforward and prevent common pitfalls that could break your setup.
|
||||
이 가이드는 Docker Compose를 사용하여 Twenty 애플리케이션을 설치 및 구성하기 위한 단계별 지침을 제공합니다. 프로세스를 간단하게 만들고 설정을 망칠 수 있는 일반적인 함정을 피하는 것이 목적입니다.
|
||||
|
||||
**Important:** Only modify settings explicitly mentioned in this guide. Altering other configurations may lead to issues.
|
||||
**중요:** 이 가이드에서 명시적으로 언급된 설정만 수정하세요. 다른 구성을 변경하면 문제가 발생할 수 있습니다.
|
||||
|
||||
See docs [Setup Environment Variables](/l/ko/developers/self-host/capabilities/setup) for advanced configuration. All environment variables must be declared in the docker-compose.yml file at the server and / or worker level depending on the variable.
|
||||
고급 설정을 위해 [환경 변수 설정](/l/ko/developers/self-host/capabilities/setup) 문서를 참조하세요. 모든 환경 변수는 서버 및/또는 작업자 수준에서 docker-compose.yml 파일에 선언되어야 합니다.
|
||||
|
||||
## System Requirements
|
||||
## 시스템 요구 사항
|
||||
|
||||
* RAM: Ensure your environment has at least 2GB of RAM. Insufficient memory can cause processes to crash.
|
||||
* Docker & Docker Compose: Make sure both are installed and up-to-date.
|
||||
* RAM: 환경에 최소 2GB의 RAM이 있는지 확인하십시오. 메모리가 충분하지 않으면 프로세스가 중단될 수 있습니다.
|
||||
* Docker 및 Docker Compose: 둘 다 설치되고 최신 상태인지 확인하세요.
|
||||
|
||||
## Option 1: One-line script
|
||||
## 옵션 1: 한 줄 스크립트
|
||||
|
||||
Install the latest stable version of Twenty with a single command:
|
||||
단일 명령으로 최신 안정 버전의 Twenty를 설치하십시오:
|
||||
|
||||
```bash
|
||||
bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
|
||||
```
|
||||
|
||||
To install a specific version or branch:
|
||||
특정 버전 또는 브랜치를 설치하려면:
|
||||
|
||||
```bash
|
||||
VERSION=vx.y.z BRANCH=branch-name bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
|
||||
```
|
||||
|
||||
* Replace x.y.z with the desired version number.
|
||||
* Replace branch-name with the name of the branch you want to install.
|
||||
* 원하는 버전 번호로 x.y.z를 대체하십시오.
|
||||
* 설치할 브랜치 이름으로 branch-name을 대체하십시오.
|
||||
|
||||
## Option 2: Manual steps
|
||||
## 옵션 2: 수동 단계
|
||||
|
||||
Follow these steps for a manual setup.
|
||||
수동 설정을 위해 다음 단계를 따릅니다.
|
||||
|
||||
### Step 1: Set Up the Environment File
|
||||
### 단계 1: 환경 파일 설정
|
||||
|
||||
1. **Create the .env File**
|
||||
1. **.env 파일 생성**
|
||||
|
||||
Copy the example environment file to a new .env file in your working directory:
|
||||
예제 환경 파일을 워킹 디렉토리의 새 .env 파일로 복사합니다.
|
||||
|
||||
```bash
|
||||
curl -o .env https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/.env.example
|
||||
```
|
||||
|
||||
2. **Generate Secret Tokens**
|
||||
2. **비밀 토큰 생성**
|
||||
|
||||
Run the following command to generate a unique random string:
|
||||
고유한 랜덤 문자열을 생성하기 위해 다음 명령을 실행하세요:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
**Important:** Keep this value secret / do not share it.
|
||||
**중요:** 이 값을 비공개로 유지/공유하지 마십시오.
|
||||
|
||||
3. **Update the `.env`**
|
||||
3. **`.env` 업데이트**
|
||||
|
||||
Replace the placeholder value in your .env file with the generated token:
|
||||
생성된 토큰으로 .env 파일의 플레이스홀더 값을 대체합니다.
|
||||
|
||||
```ini
|
||||
APP_SECRET=first_random_string
|
||||
```
|
||||
|
||||
4. **Set the Postgres Password**
|
||||
4. **Postgres 비밀번호 설정**
|
||||
|
||||
Update the `PG_DATABASE_PASSWORD` value in the .env file with a strong password without special characters.
|
||||
.env 파일에서 특수 문자가 없는 강력한 비밀번호로 `PG_DATABASE_PASSWORD` 값을 업데이트하십시오.
|
||||
|
||||
```ini
|
||||
PG_DATABASE_PASSWORD=my_strong_password
|
||||
```
|
||||
|
||||
### Step 2: Obtain the Docker Compose File
|
||||
### 단계 2: Docker Compose 파일 얻기
|
||||
|
||||
Download the `docker-compose.yml` file to your working directory:
|
||||
작업 디렉토리에 `docker-compose.yml` 파일을 다운로드합니다.
|
||||
|
||||
```bash
|
||||
curl -o docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/docker-compose.yml
|
||||
```
|
||||
|
||||
### Step 3: Launch the Application
|
||||
### 단계 3: 애플리케이션 시작
|
||||
|
||||
Start the Docker containers:
|
||||
Docker 컨테이너 시작:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Step 4: Access the Application
|
||||
### 단계 4: 애플리케이션에 액세스
|
||||
|
||||
If you host twentyCRM on your own computer, open your browser and navigate to [http://localhost:3000](http://localhost:3000).
|
||||
twentyCRM을 개인 컴퓨터에 호스팅하는 경우 브라우저를 열고 [http://localhost:3000](http://localhost:3000)으로 이동하세요.
|
||||
|
||||
If you host it on a server, check that the server is running and that everything is ok with
|
||||
서버에서 호스팅하는 경우 서버가 실행 중이며 모든 것이 문제없는지 확인하십시오.
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000
|
||||
```
|
||||
|
||||
## Configuration
|
||||
## 구성
|
||||
|
||||
### Expose Twenty to External Access
|
||||
### Twenty를 외부 액세스에 노출
|
||||
|
||||
By default, Twenty runs on `localhost` at port `3000`. To access it via an external domain or IP address, you need to configure the `SERVER_URL` in your `.env` file.
|
||||
기본적으로 Twenty는 `localhost`의 포트 `3000`에서 실행됩니다. 외부 도메인 또는 IP 주소로 액세스하려면 `.env` 파일의 `SERVER_URL`을 구성해야 합니다.
|
||||
|
||||
#### Understanding `SERVER_URL`
|
||||
#### `SERVER_URL` 이해하기
|
||||
|
||||
* **Protocol:** Use `http` or `https` depending on your setup.
|
||||
* Use `http` if you haven't set up SSL.
|
||||
* Use `https` if you have SSL configured.
|
||||
* **Domain/IP:** This is the domain name or IP address where your application is accessible.
|
||||
* **Port:** Include the port number if you're not using the default ports (`80` for `http`, `443` for `https`).
|
||||
* **프로토콜:** 구성에 따라 `http` 또는 `https`를 사용하십시오.
|
||||
* SSL을 설정하지 않은 경우 `http`를 사용합니다.
|
||||
* SSL이 구성되어 있으면 `https`를 사용하십시오.
|
||||
* **도메인/IP:** 애플리케이션을 액세스할 수 있는 도메인 이름 또는 IP 주소입니다.
|
||||
* **포트:** 기본 포트(`http`의 경우 `80`, `https`의 경우 `443`)를 사용하지 않는 경우 포트 번호를 포함하십시오.
|
||||
|
||||
### SSL Requirements
|
||||
### SSL 요구 사항
|
||||
|
||||
SSL (HTTPS) is required for certain browser features to work properly. While these features might work during local development (as browsers treat localhost differently), a proper SSL setup is needed when hosting Twenty on a regular domain.
|
||||
SSL(HTTPS)는 일부 브라우저 기능이 제대로 작동하기 위해 필수입니다. 이러한 기능은 로컬 개발 중에는 작동할 수 있지만 (브라우저는 localhost를 다르게 처리합니다), 일반 도메인에 Twenty를 호스팅할 때는 적절한 SSL 설정이 필요합니다.
|
||||
|
||||
For example, the clipboard API might require a secure context - some features like copy buttons throughout the application might not work without HTTPS enabled.
|
||||
예를 들어, 클립보드 API는 안전한 컨텍스트가 필요할 수 있습니다. 응용 프로그램 내 복사 버튼과 같은 일부 기능은 HTTPS가 활성화되지 않으면 작동하지 않을 수 있습니다.
|
||||
|
||||
We strongly recommend setting up Twenty behind a reverse proxy with SSL termination for optimal security and functionality.
|
||||
최적의 보안 및 기능을 위해 SSL 종료와 함께 Reverse Proxy 뒤에 Twenty를 설정하는 것을 강력히 권장합니다.
|
||||
|
||||
#### Configuring `SERVER_URL`
|
||||
#### `SERVER_URL` 설정
|
||||
|
||||
1. **Determine Your Access URL**
|
||||
* **Without Reverse Proxy (Direct Access):**
|
||||
1. **접속 URL 결정**
|
||||
* **리버스 프록시 없이(직접 접속):**
|
||||
|
||||
If you're accessing the application directly without a reverse proxy:
|
||||
리버스 프록시 없이 애플리케이션에 직접 액세스:
|
||||
|
||||
```ini
|
||||
SERVER_URL=http://your-domain-or-ip:3000
|
||||
```
|
||||
|
||||
* **With Reverse Proxy (Standard Ports):**
|
||||
* **리버스 프록시 사용 (표준 포트):**
|
||||
|
||||
If you're using a reverse proxy like Nginx or Traefik and have SSL configured:
|
||||
SSL이 구성된 Nginx 또는 Traefik과 같은 리버스 프록시를 사용하는 경우:
|
||||
|
||||
```ini
|
||||
SERVER_URL=https://your-domain-or-ip
|
||||
```
|
||||
|
||||
* **With Reverse Proxy (Custom Ports):**
|
||||
* **리버스 프록시 사용 (사용자 지정 포트):**
|
||||
|
||||
If you're using non-standard ports:
|
||||
비표준 포트를 사용하는 경우:
|
||||
|
||||
```ini
|
||||
SERVER_URL=https://your-domain-or-ip:custom-port
|
||||
```
|
||||
|
||||
2. **Update the `.env` File**
|
||||
2. **`.env` 파일 업데이트**
|
||||
|
||||
Open your `.env` file and update the `SERVER_URL`:
|
||||
`.env` 파일을 열고 `SERVER_URL`을 업데이트하십시오:
|
||||
|
||||
```ini
|
||||
SERVER_URL=http(s)://your-domain-or-ip:your-port
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
**예시:**
|
||||
|
||||
* Direct access without SSL:
|
||||
* SSL 없이 직접 접근:
|
||||
```ini
|
||||
SERVER_URL=http://123.45.67.89:3000
|
||||
```
|
||||
* Access via domain with SSL:
|
||||
* SSL을 사용한 도메인 접근:
|
||||
```ini
|
||||
SERVER_URL=https://mytwentyapp.com
|
||||
```
|
||||
|
||||
3. **Restart the Application**
|
||||
3. **애플리케이션 재시작**
|
||||
|
||||
For changes to take effect, restart the Docker containers:
|
||||
변경 사항을 적용하기 위해 Docker 컨테이너를 재시작하십시오.
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
#### Considerations
|
||||
#### 고려 사항
|
||||
|
||||
* **Reverse Proxy Configuration:**
|
||||
* **리버스 프록시 구성:**
|
||||
|
||||
Ensure your reverse proxy forwards requests to the correct internal port (`3000` by default). Configure SSL termination and any necessary headers.
|
||||
리버스 프록시가 올바른 내부 포트(`3000` 기본값)로 요청을 전달하도록 확인하십시오. SSL 종료와 필요한 헤더를 구성하십시오.
|
||||
|
||||
* **Firewall Settings:**
|
||||
* **방화벽 설정:**
|
||||
|
||||
Open necessary ports in your firewall to allow external access.
|
||||
외부 액세스를 허용하기 위해 방화벽에서 필요한 포트를 엽니다.
|
||||
|
||||
* **Consistency:**
|
||||
* **일관성:**
|
||||
|
||||
The `SERVER_URL` must match how users access your application in their browsers.
|
||||
`SERVER_URL`은 사용자가 브라우저에서 애플리케이션에 액세스하는 방식과 일치해야 합니다.
|
||||
|
||||
#### Persistence
|
||||
#### 영속성
|
||||
|
||||
* **Data Volumes:**
|
||||
* **데이터 볼륨:**
|
||||
|
||||
The Docker Compose configuration uses volumes to persist data for the database and server storage.
|
||||
Docker Compose 구성은 데이터베이스 및 서버 저장소의 데이터를 영구적으로 저장하기 위해 볼륨을 사용합니다.
|
||||
|
||||
* **Stateless Environments:**
|
||||
* **무상태 환경:**
|
||||
|
||||
If deploying to a stateless environment (e.g., certain cloud services), configure external storage to persist data.
|
||||
무상태 환경(예: 특정 클라우드 서비스)에 배포하는 경우 데이터 지속성을 위해 외부 저장소를 구성합니다.
|
||||
|
||||
## Backup and Restore
|
||||
## 백업 및 복원
|
||||
|
||||
Regular backups protect your CRM data from loss.
|
||||
정기 백업은 CRM 데이터를 손실로부터 보호합니다.
|
||||
|
||||
### Create a Database Backup
|
||||
### 데이터베이스 백업 생성
|
||||
|
||||
```bash
|
||||
docker exec twenty-postgres pg_dump -U postgres twenty > backup_$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
### Automate Daily Backups
|
||||
### 일일 백업 자동화
|
||||
|
||||
Add to your crontab (`crontab -e`):
|
||||
crontab에 추가하세요 (`crontab -e`):
|
||||
|
||||
```bash
|
||||
0 2 * * * docker exec twenty-postgres pg_dump -U postgres twenty > /backups/twenty_$(date +\%Y\%m\%d).sql
|
||||
```
|
||||
|
||||
### Restore from Backup
|
||||
### 백업에서 복원
|
||||
|
||||
1. Stop the application:
|
||||
1. 애플리케이션을 중지하세요:
|
||||
|
||||
```bash
|
||||
docker compose stop twenty-server twenty-front
|
||||
```
|
||||
|
||||
2. Restore the database:
|
||||
2. 데이터베이스를 복원하세요:
|
||||
|
||||
```bash
|
||||
docker exec -i twenty-postgres psql -U postgres twenty < backup_20240115.sql
|
||||
```
|
||||
|
||||
3. Restart services:
|
||||
3. 서비스 재시작:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Backup Best Practices
|
||||
### 백업 모범 사례
|
||||
|
||||
* **Test restores regularly** — verify backups actually work
|
||||
* **Store backups off-site** — use cloud storage (S3, GCS, etc.)
|
||||
* **Encrypt sensitive data** — protect backups with encryption
|
||||
* **Retain multiple copies** — keep daily, weekly, and monthly backups
|
||||
* **복원을 정기적으로 테스트하세요** — 백업이 실제로 작동하는지 확인하세요
|
||||
* **백업을 오프사이트에 보관하세요** — 클라우드 스토리지(S3, GCS 등)를 사용하세요
|
||||
* **민감한 데이터를 암호화하세요** — 암호화를 통해 백업을 보호하세요
|
||||
* **여러 사본을 유지하세요** — 일간, 주간, 월간 백업을 보관하세요
|
||||
|
||||
## Troubleshooting
|
||||
## 문제 해결
|
||||
|
||||
If you encounter any problem, check [Troubleshooting](/l/ko/developers/self-host/capabilities/troubleshooting) for solutions.
|
||||
문제가 발생하면 [문제 해결](/l/ko/developers/self-host/capabilities/troubleshooting)에서 해결책을 확인하십시오.
|
||||
|
||||
@@ -1,146 +1,146 @@
|
||||
---
|
||||
title: Setup
|
||||
title: 설정
|
||||
---
|
||||
|
||||
# Configuration Management
|
||||
# 구성 관리
|
||||
|
||||
<Warning>
|
||||
**First time installing?** Follow the [Docker Compose installation guide](/l/ko/developers/self-host/capabilities/docker-compose) to get Twenty running, then return here for configuration.
|
||||
**처음 설치하시나요?** [Docker Compose 설치 가이드](/l/ko/developers/self-host/capabilities/docker-compose)를 따라 Twenty를 실행하고, 이곳으로 돌아와 구성을 진행하세요.
|
||||
</Warning>
|
||||
|
||||
Twenty offers **two configuration modes** to suit different deployment needs:
|
||||
Twenty는 다른 배포 요구에 맞추기 위해 **두 가지 구성 모드**를 제공합니다:
|
||||
|
||||
**Admin panel access:** Only users with admin privileges (`canAccessFullAdminPanel: true`) can access the configuration interface.
|
||||
**관리자 패널 접근:** 관리자 권한이 있는 사용자만 (`canAccessFullAdminPanel: true`) 구성 인터페이스에 접근할 수 있습니다.
|
||||
|
||||
## 1. Admin Panel Configuration (Default)
|
||||
## 1. 관리자 패널 구성 (기본값)
|
||||
|
||||
```bash
|
||||
IS_CONFIG_VARIABLES_IN_DB_ENABLED=true # default
|
||||
```
|
||||
|
||||
**Most configuration happens through the UI** after installation:
|
||||
설치 후 **대부분의 구성은 UI를 통해 이루어집니다:**
|
||||
|
||||
1. Access your Twenty instance (usually `http://localhost:3000`)
|
||||
2. Go to **Settings / Admin Panel / Configuration Variables**
|
||||
3. Configure integrations, email, storage, and more
|
||||
4. Changes take effect immediately (within 15 seconds for multi-container deployments)
|
||||
1. Twenty 인스턴스에 접근하십시오 (보통 `http://localhost:3000`)
|
||||
2. **설정 / 관리자 패널 / 구성 변수**로 이동하세요
|
||||
3. 통합, 이메일, 저장소 등을 구성하세요
|
||||
4. 변경 사항은 즉시 적용됩니다 (멀티 컨테이너 배포의 경우 15초 이내)
|
||||
|
||||
<Warning>
|
||||
**Multi-Container Deployments:** When using database configuration (`IS_CONFIG_VARIABLES_IN_DB_ENABLED=true`), both server and worker containers read from the same database. Admin panel changes affect both automatically, eliminating the need to duplicate environment variables between containers (except for infrastructure variables).
|
||||
**멀티 컨테이너 배포:** 데이터베이스 구성을 사용할 때 (`IS_CONFIG_VARIABLES_IN_DB_ENABLED=true`), 서버와 작업자 컨테이너 모두 동일한 데이터베이스에서 읽습니다. 관리자 패널의 변경은 둘 다 자동으로 영향을 미쳐 환경 변수를 컨테이너 간에 복제할 필요가 없습니다 (인프라 변수 제외).
|
||||
</Warning>
|
||||
|
||||
**What you can configure through the admin panel:**
|
||||
**관리자 패널에서 구성할 수 있는 내용:**
|
||||
|
||||
* **Authentication** - Google/Microsoft OAuth, password settings
|
||||
* **Email** - SMTP settings, templates, verification
|
||||
* **Storage** - S3 configuration, local storage paths
|
||||
* **Integrations** - Gmail, Google Calendar, Microsoft services
|
||||
* **Workflow & Rate Limiting** - Execution limits, API throttling
|
||||
* **And much more...**
|
||||
* **인증** - Google/Microsoft OAuth, 비밀번호 설정
|
||||
* **이메일** - SMTP 설정, 템플릿, 확인
|
||||
* **저장소** - S3 구성, 로컬 저장 경로
|
||||
* **통합** - Gmail, Google 캘린더, Microsoft 서비스
|
||||
* **워크플로우 및 속도 제한** - 실행 제한, API 스로틀링
|
||||
* **그리고 훨씬 더...**
|
||||
|
||||

|
||||

|
||||
|
||||
<Warning>
|
||||
Each variable is documented with descriptions in your admin panel at **Settings → Admin Panel → Configuration Variables**.
|
||||
Some infrastructure settings like database connections (`PG_DATABASE_URL`), server URLs (`SERVER_URL`), and app secrets (`APP_SECRET`) can only be configured via `.env` file.
|
||||
각 변수는 **설정 → 관리자 패널 → 구성 변수**의 관리자 패널에 설명과 함께 문서화되어 있습니다.
|
||||
데이터베이스 연결 (`PG_DATABASE_URL`), 서버 URL (`SERVER_URL`), 앱 비밀 (`APP_SECRET`)과 같은 일부 인프라 설정은 `.env` 파일을 통해서만 구성할 수 있습니다.
|
||||
|
||||
[Complete technical reference →](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts)
|
||||
[완전한 기술적 참조 →](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts)
|
||||
</Warning>
|
||||
|
||||
## 2. Environment-Only Configuration
|
||||
## 2. 환경 전용 구성
|
||||
|
||||
```bash
|
||||
IS_CONFIG_VARIABLES_IN_DB_ENABLED=false
|
||||
```
|
||||
|
||||
**All configuration managed through `.env` files:**
|
||||
**모든 구성이 `.env` 파일을 통해 관리됩니다:**
|
||||
|
||||
1. Set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false` in your `.env` file
|
||||
2. Add all configuration variables to your `.env` file
|
||||
3. Restart containers for changes to take effect
|
||||
4. Admin panel will show current values but cannot modify them
|
||||
1. `.env` 파일에서 `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`로 설정하세요
|
||||
2. 모든 구성 변수를 `.env` 파일에 추가하세요
|
||||
3. 변경 사항이 적용되도록 컨테이너를 재시작하세요
|
||||
4. 관리자 패널에서는 현재 값을 표시하며 수정할 수 없습니다
|
||||
|
||||
## Multi-Workspace Mode
|
||||
## 멀티 워크스페이스 모드
|
||||
|
||||
By default, Twenty runs in **single-workspace mode** — ideal for most self-hosted deployments where you need one CRM instance for your organization.
|
||||
기본적으로 Twenty는 **단일 워크스페이스 모드**로 실행됩니다 — 조직에 하나의 CRM 인스턴스가 필요한 대부분의 자가 호스팅 배포에 적합합니다.
|
||||
|
||||
### Single-Workspace Mode (Default)
|
||||
### 단일 워크스페이스 모드(기본값)
|
||||
|
||||
```bash
|
||||
IS_MULTIWORKSPACE_ENABLED=false # default
|
||||
```
|
||||
|
||||
* One workspace per Twenty instance
|
||||
* First user automatically becomes admin with full privileges (`canImpersonate` and `canAccessFullAdminPanel`)
|
||||
* New signups are disabled after the first workspace is created
|
||||
* Simple URL structure: `https://your-domain.com`
|
||||
* Twenty 인스턴스당 하나의 워크스페이스
|
||||
* 첫 번째 사용자는 자동으로 전체 권한(`canImpersonate` 및 `canAccessFullAdminPanel`)을 가진 관리자가 됩니다
|
||||
* 첫 번째 워크스페이스가 생성된 후에는 신규 가입이 비활성화됩니다
|
||||
* 간단한 URL 구조: `https://your-domain.com`
|
||||
|
||||
### Enabling Multi-Workspace Mode
|
||||
### 멀티 워크스페이스 모드 활성화
|
||||
|
||||
```bash
|
||||
IS_MULTIWORKSPACE_ENABLED=true
|
||||
DEFAULT_SUBDOMAIN=app # default value
|
||||
```
|
||||
|
||||
Enable multi-workspace mode for SaaS-like deployments where multiple independent teams need their own workspaces on the same Twenty instance.
|
||||
여러 독립적인 팀이 동일한 Twenty 인스턴스에서 자체 워크스페이스가 필요한 SaaS형 배포에서 멀티 워크스페이스 모드를 활성화하세요.
|
||||
|
||||
**Key differences from single-workspace mode:**
|
||||
**단일 워크스페이스 모드와의 주요 차이점:**
|
||||
|
||||
* Multiple workspaces can be created on the same instance
|
||||
* Each workspace gets its own subdomain (e.g., `sales.your-domain.com`, `marketing.your-domain.com`)
|
||||
* Users sign up and log in at `{DEFAULT_SUBDOMAIN}.your-domain.com` (e.g., `app.your-domain.com`)
|
||||
* No automatic admin privileges — first user in each workspace is a regular user
|
||||
* Workspace-specific settings like subdomain and custom domain become available in workspace settings
|
||||
* 동일한 인스턴스에서 여러 워크스페이스를 생성할 수 있습니다
|
||||
* 각 워크스페이스는 자체 서브도메인을 갖습니다 (예: `sales.your-domain.com`, `marketing.your-domain.com`)
|
||||
* 사용자는 `{DEFAULT_SUBDOMAIN}.your-domain.com`에서 가입하고 로그인합니다 (예: `app.your-domain.com`)
|
||||
* 관리자 권한이 자동으로 부여되지 않습니다 — 각 워크스페이스의 첫 번째 사용자는 일반 사용자입니다
|
||||
* 서브도메인 및 사용자 지정 도메인과 같은 워크스페이스 전용 설정이 워크스페이스 설정에서 제공됩니다
|
||||
|
||||
<Warning>
|
||||
**Environment-only setting:** `IS_MULTIWORKSPACE_ENABLED` can only be configured via `.env` file and requires a restart. It cannot be changed through the admin panel.
|
||||
**환경 전용 설정:** `IS_MULTIWORKSPACE_ENABLED`는 `.env` 파일을 통해서만 구성할 수 있으며 재시작이 필요합니다. 관리자 패널을 통해 변경할 수 없습니다.
|
||||
</Warning>
|
||||
|
||||
### DNS Configuration for Multi-Workspace
|
||||
### 멀티 워크스페이스를 위한 DNS 구성
|
||||
|
||||
When using multi-workspace mode, configure your DNS with a wildcard record to allow dynamic subdomain creation:
|
||||
멀티 워크스페이스 모드를 사용할 때, 동적 서브도메인 생성을 허용하도록 와일드카드 레코드로 DNS를 구성하세요:
|
||||
|
||||
```
|
||||
*.your-domain.com -> your-server-ip
|
||||
```
|
||||
|
||||
This enables automatic subdomain routing for new workspaces without manual DNS configuration.
|
||||
이렇게 하면 수동 DNS 구성 없이 새 워크스페이스에 대한 서브도메인 라우팅이 자동으로 활성화됩니다.
|
||||
|
||||
### Restricting Workspace Creation
|
||||
### 워크스페이스 생성 제한
|
||||
|
||||
In multi-workspace mode, you may want to limit who can create new workspaces:
|
||||
멀티 워크스페이스 모드에서, 누가 새 워크스페이스를 생성할 수 있는지 제한하고 싶을 수 있습니다:
|
||||
|
||||
```bash
|
||||
IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS=true
|
||||
```
|
||||
|
||||
When enabled, only users with `canAccessFullAdminPanel` can create additional workspaces. Users can still create their first workspace during initial signup.
|
||||
활성화되면 `canAccessFullAdminPanel` 권한이 있는 사용자만 추가 워크스페이스를 생성할 수 있습니다. 사용자는 초기 가입 과정에서 첫 번째 워크스페이스를 여전히 생성할 수 있습니다.
|
||||
|
||||
## Gmail & Google Calendar Integration
|
||||
## Gmail & Google 캘린더 통합
|
||||
|
||||
### Create Google Cloud Project
|
||||
### Google 클라우드 프로젝트 생성
|
||||
|
||||
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
||||
2. Create a new project or select existing one
|
||||
3. Enable these APIs:
|
||||
1. [Google Cloud Console](https://console.cloud.google.com/)로 이동하세요
|
||||
2. 새 프로젝트를 생성하거나 기존 프로젝트를 선택하세요
|
||||
3. 이 API들을 활성화하세요:
|
||||
|
||||
* [Gmail API](https://console.cloud.google.com/apis/library/gmail.googleapis.com)
|
||||
* [Google Calendar API](https://console.cloud.google.com/apis/library/calendar-json.googleapis.com)
|
||||
* [Google 캘린더 API](https://console.cloud.google.com/apis/library/calendar-json.googleapis.com)
|
||||
* [People API](https://console.cloud.google.com/apis/library/people.googleapis.com)
|
||||
|
||||
### Configure OAuth
|
||||
### OAuth 구성
|
||||
|
||||
1. Go to [Credentials](https://console.cloud.google.com/apis/credentials)
|
||||
2. Create OAuth 2.0 Client ID
|
||||
3. Add these redirect URIs:
|
||||
* `https://{your-domain}/auth/google/redirect` (for SSO)
|
||||
* `https://{your-domain}/auth/google-apis/get-access-token` (for integrations)
|
||||
1. [자격 증명](https://console.cloud.google.com/apis/credentials)으로 이동하세요
|
||||
2. OAuth 2.0 클라이언트 ID를 생성하세요
|
||||
3. 이러한 리디렉션 URI를 추가하세요:
|
||||
* `https://{your-domain}/auth/google/redirect` (SSO용)
|
||||
* `https://{your-domain}/auth/google-apis/get-access-token` (통합용)
|
||||
|
||||
### Configure in Twenty
|
||||
### Twenty에서 구성하기
|
||||
|
||||
1. Go to **Settings → Admin Panel → Configuration Variables**
|
||||
2. Find the **Google Auth** section
|
||||
3. Set these variables:
|
||||
1. **설정 → 관리자 패널 → 구성 변수**로 이동하세요
|
||||
2. **Google 인증** 섹션을 찾으세요
|
||||
3. 다음 변수를 설정하세요:
|
||||
* `MESSAGING_PROVIDER_GMAIL_ENABLED=true`
|
||||
* `CALENDAR_PROVIDER_GOOGLE_ENABLED=true`
|
||||
* `AUTH_GOOGLE_CLIENT_ID={client-id}`
|
||||
@@ -149,35 +149,35 @@ When enabled, only users with `canAccessFullAdminPanel` can create additional wo
|
||||
* `AUTH_GOOGLE_APIS_CALLBACK_URL=https://{your-domain}/auth/google-apis/get-access-token`
|
||||
|
||||
<Warning>
|
||||
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
|
||||
**환경 전용 모드:** `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`로 설정한 경우, `.env` 파일에 이러한 변수를 추가하세요.
|
||||
</Warning>
|
||||
|
||||
**Required scopes** (automatically configured):
|
||||
[See relevant source code](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes.ts#L4-L10)
|
||||
**필요한 범위** (자동 구성됨):
|
||||
[관련 소스 코드 보기](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes.ts#L4-L10)
|
||||
|
||||
* `https://www.googleapis.com/auth/calendar.events`
|
||||
* `https://www.googleapis.com/auth/gmail.readonly`
|
||||
* `https://www.googleapis.com/auth/profile.emails.read`
|
||||
|
||||
### If your app is in test mode
|
||||
### 앱이 테스트 모드인 경우
|
||||
|
||||
If your app is in test mode, you will need to add test users to your project.
|
||||
앱이 테스트 모드인 경우, 프로젝트에 테스트 사용자를 추가해야 합니다.
|
||||
|
||||
Under [OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent), add your test users to the "Test users" section.
|
||||
[OAuth 승인 화면](https://console.cloud.google.com/apis/credentials/consent)에서 "테스트 사용자" 섹션에 테스트 사용자를 추가하세요.
|
||||
|
||||
## Microsoft 365 Integration
|
||||
## Microsoft 365 통합
|
||||
|
||||
<Warning>
|
||||
Users must have a [Microsoft 365 Licence](https://admin.microsoft.com/Adminportal/Home) to be able to use the Calendar and Messaging API. They will not be able to sync their account on Twenty without one.
|
||||
사용자는 캘린더 및 메시징 API를 사용하려면 [Microsoft 365 라이선스](https://admin.microsoft.com/Adminportal/Home)를 보유해야 합니다. 없이는 Twenty에서 계정을 동기화할 수 없습니다.
|
||||
</Warning>
|
||||
|
||||
### Create a project in Microsoft Azure
|
||||
### Microsoft Azure에 프로젝트 생성
|
||||
|
||||
You will need to create a project in [Microsoft Azure](https://portal.azure.com/#view/Microsoft_AAD_IAM/AppGalleryBladeV2) and get the credentials.
|
||||
[Microsoft Azure](https://portal.azure.com/#view/Microsoft_AAD_IAM/AppGalleryBladeV2)에서 프로젝트를 생성하고 자격 증명을 확보해야 합니다.
|
||||
|
||||
### Enable APIs
|
||||
### API 활성화
|
||||
|
||||
On Microsoft Azure Console enable the following APIs in "Permissions":
|
||||
Microsoft Azure 콘솔에서 "권한"에서 다음 API를 활성화하세요:
|
||||
|
||||
* Microsoft Graph: Mail.ReadWrite
|
||||
* Microsoft Graph: Mail.Send
|
||||
@@ -188,20 +188,20 @@ On Microsoft Azure Console enable the following APIs in "Permissions":
|
||||
* Microsoft Graph: profile
|
||||
* Microsoft Graph: offline_access
|
||||
|
||||
Note: "Mail.ReadWrite" and "Mail.Send" are only mandatory if you want to send emails using our workflow actions. You can use "Mail.Read" instead if you only want to receive emails.
|
||||
참고: "Mail.ReadWrite"와 "Mail.Send"는 워크플로우 작업을 통해 이메일을 보내려면 필수입니다. 수신 이메일만 원하시면 "Mail.Read"를 사용하실 수 있습니다.
|
||||
|
||||
### Authorized redirect URIs
|
||||
### 인가된 리디렉션 URI
|
||||
|
||||
You need to add the following redirect URIs to your project:
|
||||
프로젝트에 다음 리디렉션 URI를 추가해야 합니다:
|
||||
|
||||
* `https://{your-domain}/auth/microsoft/redirect` if you want to use Microsoft SSO
|
||||
* Microsoft SSO를 사용하려면 `https://{your-domain}/auth/microsoft/redirect`
|
||||
* `https://{your-domain}/auth/microsoft-apis/get-access-token`
|
||||
|
||||
### Configure in Twenty
|
||||
### Twenty에서 구성하기
|
||||
|
||||
1. Go to **Settings → Admin Panel → Configuration Variables**
|
||||
2. Find the **Microsoft Auth** section
|
||||
3. Set these variables:
|
||||
1. **설정 → 관리자 패널 → 구성 변수**로 이동하세요
|
||||
2. **Microsoft 인증** 섹션을 찾으세요
|
||||
3. 다음 변수를 설정하세요:
|
||||
* `MESSAGING_PROVIDER_MICROSOFT_ENABLED=true`
|
||||
* `CALENDAR_PROVIDER_MICROSOFT_ENABLED=true`
|
||||
* `AUTH_MICROSOFT_ENABLED=true`
|
||||
@@ -211,32 +211,32 @@ You need to add the following redirect URIs to your project:
|
||||
* `AUTH_MICROSOFT_APIS_CALLBACK_URL=https://{your-domain}/auth/microsoft-apis/get-access-token`
|
||||
|
||||
<Warning>
|
||||
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
|
||||
**환경 전용 모드:** `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`로 설정한 경우, `.env` 파일에 이러한 변수를 추가하세요.
|
||||
</Warning>
|
||||
|
||||
### Configure scopes
|
||||
### 범위 구성
|
||||
|
||||
[See relevant source code](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes.ts#L2-L9)
|
||||
[관련 소스 코드 보기](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes.ts#L2-L9)
|
||||
|
||||
* 'openid'
|
||||
* 'email'
|
||||
* 'profile'
|
||||
* '이메일'
|
||||
* '프로필'
|
||||
* 'offline_access'
|
||||
* 'Mail.ReadWrite'
|
||||
* 'Mail.Send'
|
||||
* 'Calendars.Read'
|
||||
|
||||
### If your app is in test mode
|
||||
### 앱이 테스트 모드인 경우
|
||||
|
||||
If your app is in test mode, you will need to add test users to your project.
|
||||
앱이 테스트 모드인 경우, 프로젝트에 테스트 사용자를 추가해야 합니다.
|
||||
|
||||
Add your test users to the "Users and groups" section.
|
||||
"사용자 및 그룹" 섹션에 테스트 사용자를 추가하세요.
|
||||
|
||||
## Background Jobs for Calendar & Messaging
|
||||
## 캘린더 및 메시징을 위한 배경 작업
|
||||
|
||||
After configuring Gmail, Google Calendar, or Microsoft 365 integrations, you need to start the background jobs that sync data.
|
||||
Gmail, Google 캘린더 또는 Microsoft 365 통합을 구성한 후, 데이터를 동기화하는 배경 작업을 시작해야 합니다.
|
||||
|
||||
Register the following recurring jobs in your worker container:
|
||||
작업자 컨테이너에 다음 주기 작업을 등록하세요:
|
||||
|
||||
```bash
|
||||
# from your worker container
|
||||
@@ -249,15 +249,15 @@ yarn command:prod cron:calendar:ongoing-stale
|
||||
yarn command:prod cron:workflow:automated-cron-trigger
|
||||
```
|
||||
|
||||
## Email Configuration
|
||||
## 이메일 구성
|
||||
|
||||
1. Go to **Settings → Admin Panel → Configuration Variables**
|
||||
2. Find the **Email** section
|
||||
3. Configure your SMTP settings:
|
||||
1. **설정 → 관리자 패널 → 구성 변수**로 이동하세요
|
||||
2. **이메일** 섹션을 찾으세요
|
||||
3. SMTP 설정을 구성하세요:
|
||||
|
||||
<ArticleTabs label1="Gmail" label2="Office365" label3="Smtp4dev">
|
||||
<ArticleTabs label1="Gmail" label2="오피스365" label3="Smtp4dev">
|
||||
<ArticleTab>
|
||||
You will need to provision an [App Password](https://support.google.com/accounts/answer/185833).
|
||||
[App Password](https://support.google.com/accounts/answer/185833)를 프로비저닝해야 합니다.
|
||||
|
||||
* EMAIL_DRIVER=smtp
|
||||
* EMAIL_SMTP_HOST=smtp.gmail.com
|
||||
@@ -267,7 +267,7 @@ yarn command:prod cron:workflow:automated-cron-trigger
|
||||
</ArticleTab>
|
||||
|
||||
<ArticleTab>
|
||||
Keep in mind that if you have 2FA enabled, you will need to provision an [App Password](https://support.microsoft.com/en-us/account-billing/manage-app-passwords-for-two-step-verification-d6dc8c6d-4bf7-4851-ad95-6d07799387e9).
|
||||
2단계 인증을 사용 중인 경우, [앱 비밀번호](https://support.microsoft.com/en-us/account-billing/manage-app-passwords-for-two-step-verification-d6dc8c6d-4bf7-4851-ad95-6d07799387e9)를 발급받아야 합니다.
|
||||
|
||||
* EMAIL_DRIVER=smtp
|
||||
* EMAIL_SMTP_HOST=smtp.office365.com
|
||||
@@ -277,11 +277,11 @@ yarn command:prod cron:workflow:automated-cron-trigger
|
||||
</ArticleTab>
|
||||
|
||||
<ArticleTab>
|
||||
**smtp4dev** is a fake SMTP email server for development and testing.
|
||||
**smtp4dev**는 개발 및 테스트를 위한 가상의 SMTP 이메일 서버입니다.
|
||||
|
||||
* Run the smtp4dev image: `docker run --rm -it -p 8090:80 -p 2525:25 rnwood/smtp4dev`
|
||||
* Access the smtp4dev ui here: [http://localhost:8090](http://localhost:8090)
|
||||
* Set the following variables:
|
||||
* smtp4dev 이미지를 실행하세요: `docker run --rm -it -p 8090:80 -p 2525:25 rnwood/smtp4dev`
|
||||
* smtp4dev UI에 여기에 접근하세요: [http://localhost:8090](http://localhost:8090)
|
||||
* 다음 변수를 설정하세요:
|
||||
* EMAIL_DRIVER=smtp
|
||||
* EMAIL_SMTP_HOST=localhost
|
||||
* EMAIL_SMTP_PORT=2525
|
||||
@@ -289,5 +289,49 @@ yarn command:prod cron:workflow:automated-cron-trigger
|
||||
</ArticleTabs>
|
||||
|
||||
<Warning>
|
||||
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
|
||||
**환경 전용 모드:** `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`로 설정한 경우, `.env` 파일에 이러한 변수를 추가하세요.
|
||||
</Warning>
|
||||
|
||||
## 서버리스 함수
|
||||
|
||||
Twenty는 워크플로 및 사용자 지정 로직을 위해 서버리스 함수를 지원합니다. `SERVERLESS_TYPE` 환경 변수를 통해 실행 환경을 구성합니다.
|
||||
|
||||
<Warning>
|
||||
**보안 공지:** 로컬 서버리스 드라이버 (`SERVERLESS_TYPE=LOCAL`)는 샌드박싱 없이 호스트의 Node.js 프로세스에서 코드를 직접 실행합니다. 개발 환경에서 신뢰할 수 있는 코드에만 사용해야 합니다. 신뢰할 수 없는 코드를 처리하는 프로덕션 배포의 경우 `SERVERLESS_TYPE=LAMBDA` 또는 `SERVERLESS_TYPE=DISABLED` 사용을 강력히 권장합니다.
|
||||
</Warning>
|
||||
|
||||
### 사용 가능한 드라이버
|
||||
|
||||
| 드라이버 | 환경 변수 | 사용 사례 | 보안 수준 |
|
||||
| ------ | -------------------------- | ------------------------- | --------------- |
|
||||
| 비활성화 | `SERVERLESS_TYPE=DISABLED` | 서버리스 함수를 완전히 비활성화 | 해당 없음 |
|
||||
| 로컬 | `SERVERLESS_TYPE=LOCAL` | 개발 및 신뢰할 수 있는 환경 | 낮음 (샌드박싱 없음) |
|
||||
| Lambda | `SERVERLESS_TYPE=LAMBDA` | 신뢰할 수 없는 코드를 처리하는 프로덕션 환경 | 높음 (하드웨어 수준 격리) |
|
||||
|
||||
### 권장 구성
|
||||
|
||||
**개발:**
|
||||
|
||||
```bash
|
||||
SERVERLESS_TYPE=LOCAL # default
|
||||
```
|
||||
|
||||
**프로덕션(AWS):**
|
||||
|
||||
```bash
|
||||
SERVERLESS_TYPE=LAMBDA
|
||||
SERVERLESS_LAMBDA_REGION=us-east-1
|
||||
SERVERLESS_LAMBDA_ROLE=arn:aws:iam::123456789:role/your-lambda-role
|
||||
SERVERLESS_LAMBDA_ACCESS_KEY_ID=your-access-key
|
||||
SERVERLESS_LAMBDA_SECRET_ACCESS_KEY=your-secret-key
|
||||
```
|
||||
|
||||
**서버리스 함수를 비활성화하려면:**
|
||||
|
||||
```bash
|
||||
SERVERLESS_TYPE=DISABLED
|
||||
```
|
||||
|
||||
<Note>
|
||||
`SERVERLESS_TYPE=DISABLED`를 사용하는 경우 서버리스 함수를 실행하려는 모든 시도는 오류를 반환합니다. 서버리스 함수 기능 없이 Twenty를 실행하려는 경우 유용합니다.
|
||||
</Note>
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
---
|
||||
title: Troubleshooting
|
||||
title: 문제 해결
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
## 문제 해결
|
||||
|
||||
If you encounter any problem while setting up environment for development, upgrading your instance or self-hosting,
|
||||
here are some solutions for common problems.
|
||||
개발 환경을 설정하거나 인스턴스를 업그레이드하거나 자체 호스팅하는 도중 문제가 발생하는 경우, 여기에는 일반적인 문제들에 대한 몇 가지 해결책이 있습니다.
|
||||
|
||||
### Self-hosting
|
||||
### 셀프 호스팅
|
||||
|
||||
#### First install results in `password authentication failed for user "postgres"`
|
||||
#### 첫 설치 시 `사용자 "postgres"에 대한 비밀번호 인증 실패`라는 메시지가 표시됨
|
||||
|
||||
🚨 **IMPORTANT: This solution is ONLY for fresh installations** 🚨
|
||||
If you have an existing Twenty instance with production data, **DO NOT** follow these steps as they will permanently delete your database!
|
||||
⚠️ 경고: 다음 단계는 데이터베이스 데이터를 **영구적으로 삭제합니다!** ⚠️
|
||||
중요한 데이터가 없는 새 설치인 경우에만 진행하십시오.
|
||||
|
||||
While installing Twenty for the first time, you might want to change the default database password.
|
||||
The password you set during the first installation becomes permanently stored in the database volume. If you later try to change this password in your configuration without removing the old volume, you'll get authentication errors because the database is still using the original password.
|
||||
Twenty를 처음 설치할 때, 기본 데이터베이스 비밀번호를 변경하고 싶을 수 있습니다.
|
||||
첫 설치 시 설정한 비밀번호는 데이터베이스 볼륨에 영구 저장됩니다. 나중에 기존의 볼륨을 제거하지 않고 설정에서 비밀번호를 변경하려고 하면, 데이터베이스에서 원래 비밀번호를 사용하고 있기 때문에 인증 오류가 발생할 수 있습니다.
|
||||
|
||||
⚠️ WARNING: Following steps will PERMANENTLY DELETE all database data! ⚠️
|
||||
Only proceed if this is a fresh installation with no important data.
|
||||
⚠️ 경고: 다음 단계는 데이터베이스 데이터를 **영구적으로 삭제합니다!** ⚠️ 경고: 다음 단계는 데이터베이스 데이터를 **영구적으로 삭제합니다!** ⚠️
|
||||
중요한 데이터가 없는 새 설치인 경우에만 진행하십시오.
|
||||
|
||||
In order to update the `PG_DATABASE_PASSWORD` you need to:
|
||||
`PG_DATABASE_PASSWORD`를 업데이트하려면 다음을 수행하십시오:
|
||||
|
||||
```sh
|
||||
# Update the PG_DATABASE_PASSWORD in .env
|
||||
@@ -28,33 +27,33 @@ docker compose down --volumes
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
#### CR line breaks found [Windows]
|
||||
#### CR 줄바꿈이 발견되었습니다 [Windows]
|
||||
|
||||
This is due to the line break characters of Windows and the git configuration. Try running:
|
||||
이는 Windows 줄바꿈 문자와 git 설정 때문입니다. 다음 명령을 실행해 보세요:
|
||||
|
||||
```
|
||||
git config --global core.autocrlf false
|
||||
```
|
||||
|
||||
Then delete the repository and clone it again.
|
||||
그런 다음 저장소를 삭제하고 다시 클론하세요.
|
||||
|
||||
#### Missing metadata schema
|
||||
#### 메타데이터 스키마 누락
|
||||
|
||||
During Twenty installation, you need to provision your postgres database with the right schemas, extensions, and users.
|
||||
If you're successful in running this provisioning, you should have `default` and `metadata` schemas in your database.
|
||||
If you don't, make sure you don't have more than one postgres instance running on your computer.
|
||||
Twenty 설치 중에 적절한 스키마, 확장, 사용자를 사용하여 postgres 데이터베이스를 프로비저닝해야 합니다.
|
||||
프로비저닝이 성공적으로 이루어지면 데이터베이스에 `기본` 및 `메타데이터` 스키마가 있어야 합니다.
|
||||
그렇지 않을 경우, 컴퓨터에서 여러 개의 postgres 인스턴스가 실행되지 않도록 하십시오.
|
||||
|
||||
#### Cannot find module 'twenty-emails' or its corresponding type declarations.
|
||||
#### 모듈 'twenty-emails' 또는 해당 형식 선언을 찾을 수 없습니다.
|
||||
|
||||
You have to build the package `twenty-emails` before running the initialization of the database with `npx nx run twenty-emails:build`
|
||||
데이터베이스 초기화하기 전에 `twenty-emails` 패키지를 빌드해야 합니다: `npx nx run twenty-emails:build`
|
||||
|
||||
#### Missing twenty-x package
|
||||
#### twenty-x 패키지가 누락됨
|
||||
|
||||
Make sure to run yarn in the root directory and then run `npx nx server:dev twenty-server`. If this still doesn't work try building the missing package manually.
|
||||
루트 디렉토리에서 yarn을 실행한 다음 `npx nx server:dev twenty-server` 를 실행하십시오. 여전히 작동하지 않으면 누락된 패키지를 수동으로 빌드해보세요.
|
||||
|
||||
#### Lint on Save not working
|
||||
#### 저장 시 린트가 작동하지 않음
|
||||
|
||||
This should work out of the box with the eslint extension installed. If this doesn't work try adding this to your vscode setting (on the dev container scope):
|
||||
eslint 확장 프로그램이 설치된 상태에서는 기본 설정으로 작동해야 합니다. 작동하지 않으면 vscode 설정(개발 컨테이너 범위)에 다음을 추가해 보세요:
|
||||
|
||||
```
|
||||
"editor.codeActionsOnSave": {
|
||||
@@ -64,85 +63,85 @@ This should work out of the box with the eslint extension installed. If this doe
|
||||
}
|
||||
```
|
||||
|
||||
#### While running `npx nx start` or `npx nx start twenty-front`, Out of memory error is thrown
|
||||
#### `npx nx start` 또는 `npx nx start twenty-front` 실행 시 메모리 부족 오류 발생
|
||||
|
||||
In `packages/twenty-front/.env` uncomment `VITE_DISABLE_TYPESCRIPT_CHECKER=true` to disable background checks thus reducing amount of needed RAM.
|
||||
`packages/twenty-front/.env`에서 `VITE_DISABLE_TYPESCRIPT_CHECKER=true`와 `VITE_DISABLE_ESLINT_CHECKER=true`를 주석 해제하여 백그라운드 검사 기능을 비활성화하여 필요한 RAM의 양을 줄입니다.
|
||||
|
||||
**If it does not work:**
|
||||
Run only the services you need, instead of `npx nx start`. For instance, if you work on the server, run only `npx nx worker twenty-server`
|
||||
**작동하지 않는 경우:**
|
||||
`npx nx start` 대신 필요한 서비스만 실행하십시오. 예를 들어, 서버에서 작업하는 경우, `npx nx worker twenty-server`만 실행하십시오.
|
||||
|
||||
**If it does not work:**
|
||||
If you tried to run only `npx nx run twenty-server:start` on WSL and it's failing with the below memory error:
|
||||
**작동하지 않는 경우:**
|
||||
WSL에서 `npx nx run twenty-server:start`만 실행하려고 했으나 아래의 메모리 오류로 실패할 경우:
|
||||
|
||||
`FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory`
|
||||
`치명적인 오류: 효과적인 마크-컴팩트 임계값 인근 할당 실패 - JavaScript 힙 메모리 부족`
|
||||
|
||||
Workaround is to execute below command in terminal or add it in .bashrc profile to get setup automatically:
|
||||
해결 방법은 아래 명령을 터미널에서 실행하거나 .bashrc 프로파일에 추가하여 자동 설정을 하는 것입니다:
|
||||
|
||||
`export NODE_OPTIONS="--max-old-space-size=8192"`
|
||||
|
||||
The --max-old-space-size=8192 flag sets an upper limit of 8GB for the Node.js heap; usage scales with application demand.
|
||||
Reference: https://stackoverflow.com/questions/56982005/where-do-i-set-node-options-max-old-space-size-2048
|
||||
\--max-old-space-size=8192 플래그는 Node.js 힙의 상한선을 8GB로 설정합니다. 사용량은 애플리케이션 수요에 따라 조정됩니다.
|
||||
참고: https://stackoverflow.com/questions/56982005/where-do-i-set-node-options-max-old-space-size-2048
|
||||
|
||||
**If it does not work:**
|
||||
Investigate which processes are taking you most of your machine RAM. At Twenty, we noticed that some VScode extensions were taking a lot of RAM so we temporarily disable them.
|
||||
**작동하지 않는 경우:**
|
||||
어떤 프로세스가 대부분의 머신 RAM을 소모하고 있는지 조사하십시오. Twenty에서는 일부 VScode 확장이 많은 RAM을 소모하고 있음을 발견하여 임시로 비활성화했습니다.
|
||||
|
||||
**If it does not work:**
|
||||
Restart your machine helps to clean up ghost processes.
|
||||
**작동하지 않는 경우:**
|
||||
머신을 다시 시작하면 유령 프로세스를 정리하는 데 도움이 됩니다.
|
||||
|
||||
#### While running `npx nx start` there are weird [0] and [1] in logs
|
||||
#### `npx nx start`를 실행할 때 로그에 이상한 [0]과 [1]이 표시됨
|
||||
|
||||
That's expected as command `npx nx start` is running more commands under the hood
|
||||
이는 `npx nx start` 명령이 내부적으로 더 많은 명령을 실행하기 때문에 예상된 것입니다.
|
||||
|
||||
#### No emails are sent
|
||||
#### 이메일이 전송되지 않음
|
||||
|
||||
Most of the time, it's because the `worker` is not running in the background. Try to run
|
||||
대부분의 경우, 이는 `worker`가 백그라운드에서 실행되지 않기 때문입니다. 실행해 보세요
|
||||
|
||||
```
|
||||
npx nx worker twenty-server
|
||||
```
|
||||
|
||||
#### Cannot connect my Microsoft 365 account
|
||||
#### Microsoft 365 계정에 연결할 수 없음
|
||||
|
||||
Most of the time, it's because your admin has not enabled the Microsoft 365 Licence for your account. Check [https://admin.microsoft.com/](https://admin.microsoft.com/Adminportal/Home).
|
||||
대부분의 경우, 관리자님께서 계정에 대한 Microsoft 365 라이센스를 활성화하지 않았기 때문입니다. [https://admin.microsoft.com/](https://admin.microsoft.com/Adminportal/Home)에서 확인하십시오.
|
||||
|
||||
If you have an error code `AADSTS50020`, it probably means that you are using a personal Microsoft account. This is not supported yet. More info [here](https://learn.microsoft.com/fr-fr/troubleshoot/entra/entra-id/app-integration/error-code-aadsts50020-user-account-identity-provider-does-not-exist)
|
||||
`AADSTS50020` 오류 코드가 표시되는 경우, 개인 Microsoft 계정을 사용하고 있을 가능성이 높습니다. 이는 아직 지원되지 않습니다. 추가 정보는 [여기](https://learn.microsoft.com/fr-fr/troubleshoot/entra/entra-id/app-integration/error-code-aadsts50020-user-account-identity-provider-does-not-exist)에서 확인하십시오
|
||||
|
||||
#### While running `yarn` warnings appear in console
|
||||
#### `yarn`을 실행하는 동안 콘솔에 경고가 나타남
|
||||
|
||||
Warnings are informing about pulling additional dependencies which aren't explicitly stated in `package.json`, so as long as no breaking error appears, everything should work as expected.
|
||||
경고는 `package.json`에 명시적으로 나타나지 않는 추가 종속성을 끌어오는 것에 대한 정보입니다. 중대한 오류가 나타나지 않는 한 모든 것이 예상대로 작동해야 합니다.
|
||||
|
||||
#### When user accesses login page, error about unauthorized user trying to access workspace appears in logs
|
||||
#### 사용자가 로그인 페이지에 접근할 때 로그에 작업 공간에 접근하려는 승인되지 않은 사용자 오류 발생
|
||||
|
||||
That's expected as user is unauthorized when logged out since its identity is not verified.
|
||||
이는 로그아웃된 상태에서 사용자 신분이 확인되지 않기 때문에 예상된 것입니다.
|
||||
|
||||
#### How to check if your worker is running?
|
||||
#### 작업자가 작동 중인지 확인하는 방법은?
|
||||
|
||||
* Go to [webhook-test.com](https://webhook-test.com/) and copy **Your Unique Webhook URL**.
|
||||
* [webhook-test.com](https://webhook-test.com/)으로 이동하여 **고유한 웹훅 URL**을 복사하십시오.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/self-hosting/webhook-test.jpg" alt="Webhook test" />
|
||||
<img src="/images/docs/developers/self-hosting/webhook-test.jpg" alt="웹훅 테스트" />
|
||||
</div>
|
||||
|
||||
* Open your Twenty app, navigate to `/settings`, and enable the **Advanced** toggle at the bottom left of the screen.
|
||||
* Create a new webhook.
|
||||
* Paste **Your Unique Webhook URL** in the **Endpoint Url** field in Twenty. Set the **Filters** to `Companies` and `Created`.
|
||||
* Twenty 앱을 열고 `/settings`로 이동하여 화면 왼쪽 하단에 있는 **고급** 토글을 활성화하십시오.
|
||||
* 새 웹훅 생성.
|
||||
* **고유한 웹훅 URL**을 Twenty의 **엔드포인트 URL** 필드에 붙여넣습니다. **필터**를 `회사`와 `생성됨`으로 설정하십시오.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/self-hosting/webhook-settings.jpg" alt="Webhook settings" />
|
||||
<img src="/images/docs/developers/self-hosting/webhook-settings.jpg" alt="웹훅 설정" />
|
||||
</div>
|
||||
|
||||
* Go to `/objects/companies` and create a new company record.
|
||||
* Return to [webhook-test.com](https://webhook-test.com/) and check if a new **POST request** has been received.
|
||||
* `/objects/companies`로 이동하여 새 회사 레코드를 만드십시오.
|
||||
* [webhook-test.com](https://webhook-test.com/)으로 돌아가 새 **POST 요청**이 수신되었는지 확인하십시오.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/self-hosting/webhook-test-result.jpg" alt="Webhook test result" />
|
||||
<img src="/images/docs/developers/self-hosting/webhook-test-result.jpg" alt="웹훅 테스트 결과" />
|
||||
</div>
|
||||
|
||||
* If a **POST request** is received, your worker is running successfully. Otherwise, you need to troubleshoot your worker.
|
||||
* **POST 요청**이 수신된 경우, 작업자가 성공적으로 실행 중입니다. 그렇지 않으면, 작업자에 대한 문제 해결이 필요합니다.
|
||||
|
||||
#### Front-end fails to start and returns error TS5042: Option 'project' cannot be mixed with source files on a command line
|
||||
#### 프런트엔드 시작 실패 및 TS5042 오류: 명령줄에서 소스 파일과 함께 옵션 '프로젝트'를 사용할 수 없음
|
||||
|
||||
Comment out checker plugin in `packages/twenty-ui/vite-config.ts` like in example below
|
||||
`packages/twenty-ui/vite-config.ts`의 체크 플러그인을 아래 예와 같이 주석 처리하십시오
|
||||
|
||||
```
|
||||
plugins: [
|
||||
@@ -166,62 +165,62 @@ plugins: [
|
||||
],
|
||||
```
|
||||
|
||||
#### Admin panel not accessible
|
||||
#### 관리자 패널에 액세스할 수 없음
|
||||
|
||||
Run `UPDATE core."user" SET "canAccessFullAdminPanel" = TRUE WHERE email = 'you@yourdomain.com';` in database container to get access to admin panel.
|
||||
데이터베이스 컨테이너에서 관리자 패널에 액세스하기 위해 `UPDATE core."user" SET "canAccessFullAdminPanel" = TRUE WHERE email = 'you@yourdomain.com';`을 실행하십시오.
|
||||
|
||||
### 1-click Docker compose
|
||||
### 1-클릭 Docker 구성
|
||||
|
||||
#### Unable to Log In
|
||||
#### 로그인할 수 없음
|
||||
|
||||
If you can't log in after setup:
|
||||
설정 후 로그인할 수 없는 경우:
|
||||
|
||||
1. Run the following commands:
|
||||
1. 다음 명령어를 실행하십시오:
|
||||
```bash
|
||||
docker exec -it twenty-server-1 yarn
|
||||
docker exec -it twenty-server-1 npx nx database:reset --configuration=no-seed
|
||||
```
|
||||
2. Restart the Docker containers:
|
||||
2. Docker 컨테이너를 다시 시작하십시오:
|
||||
```bash
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Note the database:reset command will completely erase your database and recreate it from scratch.
|
||||
database:reset 명령은 데이터베이스를 완전히 지우고 처음부터 다시 만듭니다.
|
||||
|
||||
#### Connection Issues Behind a Reverse Proxy
|
||||
#### 리버스 프록시 뒤에서 연결 문제
|
||||
|
||||
If you're running Twenty behind a reverse proxy and experiencing connection issues:
|
||||
Twenty를 리버스 프록시 뒤에서 실행 중이며 연결 문제가 있는 경우:
|
||||
|
||||
1. **Verify SERVER_URL:**
|
||||
1. **SERVER_URL 확인:**
|
||||
|
||||
Ensure `SERVER_URL` in your `.env` file matches your external access URL, including `https` if SSL is enabled.
|
||||
`.env` 파일의 `SERVER_URL`이 SSL이 활성화된 경우 외부 액세스 URL과 `https`까지 일치하는지 확인하십시오.
|
||||
|
||||
2. **Check Reverse Proxy Settings:**
|
||||
2. **리버스 프록시 설정 확인:**
|
||||
|
||||
* Confirm that your reverse proxy is correctly forwarding requests to the Twenty server.
|
||||
* Ensure headers like `X-Forwarded-For` and `X-Forwarded-Proto` are properly set.
|
||||
* 리버스 프록시가 Twenty 서버로 요청을 정확히 전달하는지 확인하십시오.
|
||||
* `X-Forwarded-For`, `X-Forwarded-Proto`와 같은 헤더가 적절히 설정되어 있는지 확인하십시오.
|
||||
|
||||
3. **Restart Services:**
|
||||
3. **서비스 재시작:**
|
||||
|
||||
After making changes, restart both the reverse proxy and Twenty containers.
|
||||
변경 후, 리버스 프록시와 Twenty 컨테이너를 모두 다시 시작하십시오.
|
||||
|
||||
#### Error when uploading an image - permission denied
|
||||
#### 이미지 업로드 시 권한 거부 오류 발생
|
||||
|
||||
Switching the data folder ownership on the host from root to another user and group resolves this problem.
|
||||
호스트의 데이터 폴더 소유권을 루트에서 다른 사용자 및 그룹으로 전환하면 이 문제가 해결됩니다.
|
||||
|
||||
## Getting Help
|
||||
## 도움 받기
|
||||
|
||||
If you encounter issues not covered in this guide:
|
||||
이 가이드에 다루지 않은 문제를 겪는 경우:
|
||||
|
||||
* Check Logs:
|
||||
* 로그 확인:
|
||||
|
||||
View container logs for error messages:
|
||||
컨테이너 로그에서 오류 메시지 확인:
|
||||
|
||||
```bash
|
||||
docker compose logs
|
||||
```
|
||||
|
||||
* Community Support:
|
||||
* 커뮤니티 지원:
|
||||
|
||||
Reach out to the [Twenty community](https://github.com/twentyhq/twenty/issues) or [support channels](https://discord.gg/cx5n4Jzs57) for assistance.
|
||||
[Twenty 커뮤니티](https://github.com/twentyhq/twenty/issues)나 [지원 채널](https://discord.gg/cx5n4Jzs57)에 문의하십시오.
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
---
|
||||
title: Upgrade guide
|
||||
title: 업그레이드 가이드
|
||||
---
|
||||
|
||||
## General guidelines
|
||||
## 일반 가이드라인
|
||||
|
||||
**Always make sure to back up your database before starting the upgrade process** by running `docker exec -it {db_container_name_or_id} pg_dumpall -U {postgres_user} > databases_backup.sql`.
|
||||
**업그레이드 프로세스를 시작하기 전에 다음 명령을 실행하여 데이터베이스를 반드시 백업하십시오**: `docker exec -it {db_container_name_or_id} pg_dumpall -U {postgres_user} > databases_backup.sql`.
|
||||
|
||||
To restore backup, run `cat databases_backup.sql | docker exec -i {db_container_name_or_id} psql -U {postgres_user}`.
|
||||
백업을 복원하려면 `cat databases_backup.sql | docker exec -i {db_container_name_or_id} psql -U {postgres_user}`를 실행하십시오.
|
||||
|
||||
If you used Docker Compose, follow these steps:
|
||||
Docker Compose를 사용한 경우, 다음 단계를 따르십시오:
|
||||
|
||||
1. In a terminal, on the host where Twenty is running, turn off Twenty: `docker compose down`
|
||||
1. Twenty가 실행되고 있는 호스트의 터미널에서 Twenty를 종료하십시오: `docker compose down`
|
||||
|
||||
2. Upgrade the version by changing the `TAG` value in the .env file near your docker-compose. ( We recommend consuming `major.minor` version such as `v0.53` )
|
||||
2. `TAG` 값을 docker-compose와 가까운 .env 파일에 변경하여 버전을 업그레이드하십시오. ( `v0.53`과 같은 `major.minor` 버전 사용을 권장합니다 )
|
||||
|
||||
3. Bring Twenty back online with `docker compose up -d`
|
||||
3. `docker compose up -d`로 Twenty를 다시 온라인 상태로 전환하십시오.
|
||||
|
||||
If you want to upgrade your instance by few versions, e.g. from v0.33.0 to v0.35.0, you have to upgrade your instance sequentially, in this example from v0.33.0 to v0.34.0, then from v0.34.0 to v0.35.0.
|
||||
여러 버전으로 인스턴스를 업그레이드하려는 경우, 예를 들어 v0.33.0에서 v0.35.0으로 업그레이드하려면 v0.33.0에서 v0.34.0으로, 그런 다음 v0.34.0에서 v0.35.0으로 업그레이드하십시오.
|
||||
|
||||
**Make sure that after each upgraded version you have non-corrupted backup.**
|
||||
**각 버전 업그레이드 후마다 백업이 손상되지 않았는지 확인하십시오.**
|
||||
|
||||
## Version-specific upgrade steps
|
||||
## 버전별 업그레이드 단계
|
||||
|
||||
## v1.0
|
||||
|
||||
Hello Twenty v1.0! 🎉
|
||||
안녕하세요 Twenty v1.0! 🎉
|
||||
|
||||
## v0.60
|
||||
|
||||
### Performance Enhancements
|
||||
### 성능 개선
|
||||
|
||||
All interactions with the metadata API have been optimized for better performance, particularly for object metadata manipulation and workspace creation operations.
|
||||
메타데이터 API와의 모든 상호작용이 최적화되어, 특히 객체 메타데이터 조작 및 워크스페이스 생성 작업에서 성능이 향상되었습니다.
|
||||
|
||||
We've refactored our caching strategy to prioritize cache hits over database queries when possible, significantly improving the performance of metadata API operations.
|
||||
데이터베이스 쿼리보다는 캐시 히트를 우선시하도록 캐싱 전략을 재구성하여 메타데이터 API 작업의 성능을 대폭 향상시켰습니다.
|
||||
|
||||
If you encounter any runtime issues after upgrading, you may need to flush your cache to ensure it's synchronized with the latest changes. Run this command in your twenty-server container:
|
||||
업그레이드 후 실행 중 문제가 발생하면 캐시를 플러시하여 최신 변경 사항과 동기화해야 할 수도 있습니다. twenty-server 컨테이너에서 이 명령을 실행하십시오:
|
||||
|
||||
```bash
|
||||
yarn command:prod cache:flush
|
||||
@@ -42,64 +42,64 @@ yarn command:prod cache:flush
|
||||
|
||||
### v0.55
|
||||
|
||||
Upgrade your Twenty instance to use v0.55 image
|
||||
Twenty 인스턴스를 v0.55 이미지로 업그레이드하십시오.
|
||||
|
||||
You don't need to run any command anymore, the new image will automatically care about running all required migrations.
|
||||
이제 명령어를 실행할 필요가 없으며, 새로운 이미지는 모든 필요한 마이그레이션을 자동으로 처리할 것입니다.
|
||||
|
||||
### `User does not have permission` error
|
||||
### `사용자에게 권한이 없습니다` 오류
|
||||
|
||||
If you encounter authorization errors on most requests after upgrading, you may need to flush your cache to recompute the latest permissions.
|
||||
업그레이드 후 대부분의 요청에서 권한 오류가 발생하면 캐시를 플러시하여 최신 권한을 다시 계산해야 할 수도 있습니다.
|
||||
|
||||
In your `twenty-server` container, run:
|
||||
`twenty-server` 컨테이너에서 실행하십시오:
|
||||
|
||||
```bash
|
||||
yarn command:prod cache:flush
|
||||
```
|
||||
|
||||
This issue is specific to this Twenty version and should not be required for future upgrades.
|
||||
이 문제는 이 Twenty 버전에만 해당하며, 향후 업그레이드에서는 필요하지 않을 것입니다.
|
||||
|
||||
### v0.54
|
||||
|
||||
Since version `0.53`, no manual actions needed.
|
||||
버전 `0.53` 이후로 수동 작업이 필요하지 않습니다.
|
||||
|
||||
#### Metadata schema deprecation
|
||||
#### 메타데이터 스키마 사용 중단
|
||||
|
||||
We've merged the `metadata` schema into the `core` one to simplify data retrieval from `TypeORM`.
|
||||
We have merged the `migrate` command step within the `upgrade` command. We do not recommend running `migrate` manually within any of your server/worker containers.
|
||||
`metadata` 스키마를 `core` 스키마로 병합하여 `TypeORM`에서 데이터 검색을 간소화했습니다.
|
||||
`migrate` 명령 단계를 `upgrade` 명령과 통합했습니다. 서버/작업자 컨테이너 내에서 `migrate`를 수동으로 실행하지 않는 것을 권장합니다.
|
||||
|
||||
### Since v0.53
|
||||
|
||||
Starting from `0.53`, upgrade is programmatically done within the `DockerFile`, this means from now on, you shouldn't have to run any command manually anymore.
|
||||
`0.53`부터 업그레이드는 `DockerFile` 내에서 프로그래밍 방식으로 수행되므로 앞으로는 수동으로 명령을 실행할 필요가 없습니다.
|
||||
|
||||
Make sure to keep upgrading your instance sequentially, without skipping any major version (e.g. `0.43.3` to `0.44.0` is allowed, but `0.43.1` to `0.45.0` isn't), else could lead to workspace version desynchronization that could result in runtime error and missing functionality.
|
||||
인스턴스를 순차적으로 업그레이드하고 주요 버전을 건너뛰지 마십시오(e.g. `0.43.3`에서 `0.44.0`으로의 업그레이드는 가능하지만 `0.43.1`에서 `0.45.0`으로의 업그레이드는 불가능), 그렇지 않으면 워크스페이스 버전 비동기화가 발생하여 런타임 오류 및 기능 누락이 발생할 수 있습니다.
|
||||
|
||||
To check if a workspace has been correctly migrated you can review its version in database in `core.workspace` table.
|
||||
워크스페이스가 올바르게 마이그레이션되었는지 확인하려면 `core.workspace` 테이블에서 데이터베이스의 버전을 검토할 수 있습니다.
|
||||
|
||||
It should always be in the range of your current Twenty's instance `major.minor` version, you can view your instance version in the admin panel (at `/settings/admin-panel`, accessible if your user has `canAccessFullAdminPanel` property set to true in the database) or by running `echo $APP_VERSION` in your `twenty-server` container.
|
||||
항상 현재 Twenty 인스턴스의 `주.소` 버전 범위 내에 있어야 하며, 인스턴스 버전은 admin 패널에서 볼 수 있습니다(`/설정/admin-panel`, 사용자가 데이터베이스에서 `canAccessFullAdminPanel` 속성이 true로 설정된 경우 접근 가능) 또는 `twenty-server` 컨테이너에서 `echo $APP_VERSION`을 실행하여 확인할 수 있습니다.
|
||||
|
||||
To fix a desynchronized workspace version, you will have to upgrade from the corresponding twenty's version following related upgrade guide sequentially and so on until it reaches desired version.
|
||||
비동기화된 워크스페이스 버전을 수정하려면 해당 Twenty 버전의 관련 업그레이드 가이드를 따르고 원하는 버전에 도달할 때까지 순차적으로 업그레이드해야 합니다.
|
||||
|
||||
#### `auditLog` removal
|
||||
#### `auditLog` 제거
|
||||
|
||||
We've removed the auditLog standard object, which means your backup size might be significantly reduced after this migration.
|
||||
auditLog 표준 객체를 제거했으며, 이로 인해 이 마이그레이션 이후 백업 크기가 상당히 줄어들 수 있습니다.
|
||||
|
||||
### v0.51 to v0.52
|
||||
|
||||
Upgrade your Twenty instance to use v0.52 image
|
||||
Twenty 인스턴스를 v0.52 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade
|
||||
```
|
||||
|
||||
#### I have a workspace blocked in version between `0.52.0` and `0.52.6`
|
||||
#### 버전이 `0.52.0`과 `0.52.6` 사이에 차단된 워크스페이스가 있습니다.
|
||||
|
||||
Unfortunately `0.52.0` and `0.52.6` have been completely removed from dockerHub.
|
||||
You will have to manually update your workspace version to `0.51.0` in database and upgrade using twenty version `0.52.11` following its just above upgrade guide.
|
||||
불행히도 `0.52.0` 및 `0.52.6`은 dockerHub에서 완전히 삭제되었습니다.
|
||||
데이터베이스의 워크스페이스 버전을 `0.51.0`으로 수동 업데이트하고 바로 위 업그레이드 가이드를 따라 Twenty 버전 `0.52.11`로 업그레이드해야 합니다.
|
||||
|
||||
### v0.50 to v0.51
|
||||
|
||||
Upgrade your Twenty instance to use v0.51 image
|
||||
Twenty 인스턴스를 v0.51 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
@@ -108,21 +108,21 @@ yarn command:prod upgrade
|
||||
|
||||
### v0.44.0 to v0.50.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.50.0 image
|
||||
Twenty 인스턴스를 v0.50.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade
|
||||
```
|
||||
|
||||
#### Docker-compose.yml mutation
|
||||
#### Docker-compose.yml 변경
|
||||
|
||||
This version includes a `docker-compose.yml` mutation to give `worker` service access to the `server-local-data` volume.
|
||||
Please update your local `docker-compose.yml` with [v0.50.0 docker-compose.yml](https://github.com/twentyhq/twenty/blob/v0.50.0/packages/twenty-docker/docker-compose.yml)
|
||||
이 버전은 `worker` 서비스가 `server-local-data` 볼륨에 접근할 수 있도록 `docker-compose.yml` 변경을 포함합니다.
|
||||
로컬 `docker-compose.yml`을 [v0.50.0 docker-compose.yml](https://github.com/twentyhq/twenty/blob/v0.50.0/packages/twenty-docker/docker-compose.yml)로 업데이트하십시오.
|
||||
|
||||
### v0.43.0 to v0.44.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.44.0 image
|
||||
Twenty 인스턴스를 v0.44.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
@@ -131,24 +131,24 @@ yarn command:prod upgrade
|
||||
|
||||
### v0.42.0 to v0.43.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.43.0 image
|
||||
Twenty 인스턴스를 v0.43.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade
|
||||
```
|
||||
|
||||
In this version, we have also switched to postgres:16 image in docker-compose.yml.
|
||||
이 버전에서는 docker-compose.yml 이미지가 postgres:16으로 전환되었습니다.
|
||||
|
||||
#### (Option 1) Database migration
|
||||
#### (옵션 1) 데이터베이스 마이그레이션
|
||||
|
||||
Keeping the existing postgres-spilo image is fine, but you will have to freeze the version in your docker-compose.yml to be 0.43.0.
|
||||
기존 postgres-spilo 이미지를 유지해도 되지만, docker-compose.yml에서 버전을 0.43.0으로 고정해야 합니다.
|
||||
|
||||
#### (Option 2) Database migration
|
||||
#### (옵션 2) 데이터베이스 마이그레이션
|
||||
|
||||
If you want to migrate your database to the new postgres:16 image, please follow these steps:
|
||||
데이터베이스를 새로운 postgres:16 이미지로 마이그레이션하려면, 다음 단계를 따르십시오:
|
||||
|
||||
1. Dump your database from the old postgres-spilo container
|
||||
1. 이전 postgres-spilo 컨테이너에서 데이터베이스를 덤프하십시오.
|
||||
|
||||
```
|
||||
docker exec -it twenty-db-1 sh
|
||||
@@ -157,11 +157,11 @@ exit
|
||||
docker cp twenty-db-1:/home/postgres/databases_backup.sql .
|
||||
```
|
||||
|
||||
Make sure your dump file is not empty.
|
||||
덤프 파일이 비어 있지 않은지 확인하십시오.
|
||||
|
||||
2. Upgrade your docker-compose.yml to use postgres:16 image as in the [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) file.
|
||||
2. docker-compose.yml을 postgres:16 이미지를 사용하도록 [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) 파일에 따라 업그레이드하십시오.
|
||||
|
||||
3. Restore the database to the new postgres:16 container
|
||||
3. 새로운 postgres:16 컨테이너에 데이터베이스를 복원하십시오.
|
||||
|
||||
```
|
||||
docker cp databases_backup.sql twenty-db-1:/databases_backup.sql
|
||||
@@ -172,84 +172,82 @@ exit
|
||||
|
||||
### v0.41.0 to v0.42.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.42.0 image
|
||||
Twenty 인스턴스를 v0.42.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.42
|
||||
```
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
* Removed: `FRONT_PORT`, `FRONT_PROTOCOL`, `FRONT_DOMAIN`, `PORT`
|
||||
* Added: `FRONTEND_URL`, `NODE_PORT`, `MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION`, `MESSAGING_PROVIDER_MICROSOFT_ENABLED`, `CALENDAR_PROVIDER_MICROSOFT_ENABLED`, `IS_MICROSOFT_SYNC_ENABLED`
|
||||
* 삭제됨: `FRONT_PORT`, `FRONT_PROTOCOL`, `FRONT_DOMAIN`, `PORT`
|
||||
* 추가됨: `FRONTEND_URL`, `NODE_PORT`, `MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION`, `MESSAGING_PROVIDER_MICROSOFT_ENABLED`, `CALENDAR_PROVIDER_MICROSOFT_ENABLED`, `IS_MICROSOFT_SYNC_ENABLED`
|
||||
|
||||
### v0.40.0 to v0.41.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.41.0 image
|
||||
Twenty 인스턴스를 v0.41.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.41
|
||||
```
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
* Removed: `AUTH_MICROSOFT_TENANT_ID`
|
||||
* 삭제됨: `AUTH_MICROSOFT_TENANT_ID`
|
||||
|
||||
### v0.35.0 to v0.40.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.40.0 image
|
||||
Twenty 인스턴스를 v0.40.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.40
|
||||
```
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
* Added: `IS_EMAIL_VERIFICATION_REQUIRED`, `EMAIL_VERIFICATION_TOKEN_EXPIRES_IN`, `WORKFLOW_EXEC_THROTTLE_LIMIT`, `WORKFLOW_EXEC_THROTTLE_TTL`
|
||||
* 추가됨: `IS_EMAIL_VERIFICATION_REQUIRED`, `EMAIL_VERIFICATION_TOKEN_EXPIRES_IN`, `WORKFLOW_EXEC_THROTTLE_LIMIT`, `WORKFLOW_EXEC_THROTTLE_TTL`
|
||||
|
||||
### v0.34.0 to v0.35.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.35.0 image
|
||||
Twenty 인스턴스를 v0.35.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.35
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.35` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.35`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
* We replaced `ENABLE_DB_MIGRATIONS` with `DISABLE_DB_MIGRATIONS` (default value is now `false`, you probably don't have to set anything)
|
||||
* `ENABLE_DB_MIGRATIONS`를 `DISABLE_DB_MIGRATIONS`로 교체했습니다(기본값은 이제 `false`이며, 별도의 설정이 필요하지 않을 것입니다.)
|
||||
|
||||
### v0.33.0 to v0.34.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.34.0 image
|
||||
Twenty 인스턴스를 v0.34.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.34
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.34` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.34`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
* Removed: `FRONT_BASE_URL`
|
||||
* Added: `FRONT_DOMAIN`, `FRONT_PROTOCOL`, `FRONT_PORT`
|
||||
* 삭제됨: `FRONT_BASE_URL`
|
||||
* 추가됨: `FRONT_DOMAIN`, `FRONT_PROTOCOL`, `FRONT_PORT`
|
||||
|
||||
We have updated the way we handle the frontend URL.
|
||||
You can now set the frontend URL using the `FRONT_DOMAIN`, `FRONT_PROTOCOL` and `FRONT_PORT` variables.
|
||||
If FRONT_DOMAIN is not set, the frontend URL will fall back to `SERVER_URL`.
|
||||
프런트엔드 URL을 처리하는 방식을 업데이트했습니다.
|
||||
이제 `FRONT_DOMAIN`, `FRONT_PROTOCOL` 및 `FRONT_PORT` 변수를 사용하여 프런트엔드 URL을 설정할 수 있습니다.
|
||||
`FRONT_DOMAIN`이 설정되지 않은 경우 프런트엔드 URL은 `SERVER_URL`로 대체됩니다.
|
||||
|
||||
### v0.32.0 to v0.33.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.33.0 image
|
||||
Twenty 인스턴스를 v0.33.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn command:prod cache:flush
|
||||
@@ -257,68 +255,65 @@ yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.33
|
||||
```
|
||||
|
||||
The `yarn command:prod cache:flush` command will flush the Redis cache.
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.33` takes care of the data migration of all workspaces.
|
||||
`yarn command:prod cache:flush` 명령은 Redis 캐시를 플러시합니다.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.33`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
Starting from this version, twenty-postgres image for DB became deprecated and twenty-postgres-spilo is used instead.
|
||||
If you want to keep using twenty-postgres image, simply replace `twentycrm/twenty-postgres:${TAG}` with `twentycrm/twenty-postgres` in docker-compose.yml.
|
||||
이 버전부터 DB용으로 twenty-postgres 이미지가 폐기되어 twenty-postgres-spilo가 대신 사용되었습니다.
|
||||
twenty-postgres 이미지를 계속 사용하려면, docker-compose.yml에서 `twentycrm/twenty-postgres:${TAG}`를 `twentycrm/twenty-postgres`로 교체하십시오.
|
||||
|
||||
### v0.31.0 to v0.32.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.32.0 image
|
||||
Twenty 인스턴스를 v0.32.0 이미지로 업그레이드하십시오.
|
||||
|
||||
**Schema and data migration**
|
||||
**스키마 및 데이터 마이그레이션**
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.32
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.32` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.32`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
**Environment Variables**
|
||||
**환경 변수**
|
||||
|
||||
We have updated the way we handle the Redis connection.
|
||||
Redis 연결을 처리하는 방식을 업데이트했습니다.
|
||||
|
||||
* Removed: `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`
|
||||
* Added: `REDIS_URL`
|
||||
* 삭제됨: `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`
|
||||
* 추가됨: `REDIS_URL`
|
||||
|
||||
Update your `.env` file to use the new `REDIS_URL` variable instead of the individual Redis connection parameters.
|
||||
`.env` 파일을 업데이트하여 개별 Redis 연결 매개변수 대신 새 `REDIS_URL` 변수를 사용하십시오.
|
||||
|
||||
We have also simplified the way we handle the JWT tokens.
|
||||
JWT 토큰을 처리하는 방식도 간소화했습니다.
|
||||
|
||||
* Removed: `ACCESS_TOKEN_SECRET`, `LOGIN_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `FILE_TOKEN_SECRET`
|
||||
* Added: `APP_SECRET`
|
||||
* 삭제됨: `ACCESS_TOKEN_SECRET`, `LOGIN_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `FILE_TOKEN_SECRET`
|
||||
* 추가됨: `APP_SECRET`
|
||||
|
||||
Update your `.env` file to use the new `APP_SECRET` variable instead of the individual tokens secrets (you can use the same secret as before or generate a new random string)
|
||||
.env 파일을 업데이트하여 개별 토큰 비밀 대신 새로운 `APP_SECRET` 변수를 사용하십시오 (이전 비밀을 그대로 사용하거나 새 임의 문자열을 생성할 수 있습니다.)
|
||||
|
||||
**Connected Account**
|
||||
**연결된 계정**
|
||||
|
||||
If you are using connected account to synchronize your Google emails and calendars, you will need to activate the [People API](https://developers.google.com/people) on your Google Admin console.
|
||||
Google 이메일 및 캘린더 동기화를 위해 연결된 계정을 사용하는 경우, Google 관리 콘솔에서 [People API](https://developers.google.com/people)를 활성화해야 합니다.
|
||||
|
||||
### v0.30.0 to v0.31.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.31.0 image
|
||||
Twenty 인스턴스를 v0.31.0 이미지로 업그레이드하십시오.
|
||||
|
||||
**Schema and data migration**:
|
||||
**스키마 및 데이터 마이그레이션**:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.31
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.31` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.31`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
### v0.24.0 to v0.30.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.30.0 image
|
||||
Twenty 인스턴스를 v0.30.0 이미지로 업그레이드하십시오.
|
||||
|
||||
**Breaking change**:
|
||||
To enhance performances, Twenty now requires redis cache to be configured. We have updated our [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) to reflect this.
|
||||
Make sure to update your configuration and to update your environment variables accordingly:
|
||||
**중대한 변경 사항**:
|
||||
성능을 개선하기 위해, 이제 Twenty는 redis 캐시 구성이 필요합니다. [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml)을 업데이트하여 이를 반영했습니다.
|
||||
구성을 업데이트하고 환경 변수를 적절히 업데이트하십시오:
|
||||
|
||||
```
|
||||
REDIS_HOST={your-redis-host}
|
||||
@@ -326,49 +321,47 @@ REDIS_PORT={your-redis-port}
|
||||
CACHE_STORAGE_TYPE=redis
|
||||
```
|
||||
|
||||
**Schema and data migration**:
|
||||
**스키마 및 데이터 마이그레이션**:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.30
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.30` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.30`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
### v0.23.0 to v0.24.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.24.0 image
|
||||
Twenty 인스턴스를 v0.24.0 이미지로 업그레이드하십시오.
|
||||
|
||||
Run the following commands:
|
||||
다음 명령어를 실행하십시오:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.24
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
|
||||
The `yarn command:prod upgrade-0.24` takes care of the data migration of all workspaces.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스 구조(핵심 및 메타데이터 스키마)에 마이그레이션을 적용합니다. `yarn command:prod upgrade-0.24`는 모든 워크스페이스의 데이터 마이그레이션을 처리합니다.
|
||||
|
||||
### v0.22.0 to v0.23.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.23.0 image
|
||||
Twenty 인스턴스를 v0.23.0 이미지로 업그레이드하십시오.
|
||||
|
||||
Run the following commands:
|
||||
다음 명령어를 실행하십시오:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod upgrade-0.23
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the Database.
|
||||
The `yarn command:prod upgrade-0.23` takes care of the data migration, including transferring activities to tasks/notes.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스에 마이그레이션을 적용합니다.
|
||||
`yarn command:prod upgrade-0.23`는 데이터 마이그레이션을 처리하며, 활동을 작업/노트로 전송하는 것도 포함합니다.
|
||||
|
||||
### v0.21.0 to v0.22.0
|
||||
|
||||
Upgrade your Twenty instance to use v0.22.0 image
|
||||
Twenty 인스턴스를 v0.22.0 이미지로 업그레이드하십시오.
|
||||
|
||||
Run the following commands:
|
||||
다음 명령어를 실행하십시오:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
@@ -376,6 +369,6 @@ yarn command:prod workspace:sync-metadata -f
|
||||
yarn command:prod upgrade-0.22
|
||||
```
|
||||
|
||||
The `yarn database:migrate:prod` command will apply the migrations to the Database.
|
||||
The `yarn command:prod workspace:sync-metadata -f` command will sync the definition of standard objects to the metadata tables and apply to required migrations to existing workspaces.
|
||||
The `yarn command:prod upgrade-0.22` command will apply specific data transformations to adapt to the new object defaultRequestInstrumentationOptions.
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스에 마이그레이션을 적용합니다.
|
||||
`yarn command:prod workspace:sync-metadata -f` 명령은 표준 객체의 정의를 메타데이터 테이블에 동기화하고 기존 워크스페이스에 필요한 마이그레이션을 적용합니다.
|
||||
`yarn command:prod upgrade-0.22` 명령은 새 객체 defaultRequestInstrumentationOptions에 적응하기 위한 특정 데이터 변환을 적용합니다.
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
---
|
||||
title: Self-Host
|
||||
description: Deploy and manage Twenty on your own infrastructure.
|
||||
title: 셀프 호스팅
|
||||
description: 자체 인프라에 Twenty를 배포하고 관리하세요.
|
||||
---
|
||||
|
||||
<Frame>
|
||||
<img src="/images/user-guide/what-is-twenty/20.png" alt="AI" />
|
||||
</Frame>
|
||||
|
||||
## Overview
|
||||
## 개요
|
||||
|
||||
Twenty can be self-hosted on your own infrastructure, giving you full control over your data and deployment.
|
||||
Twenty는 자체 인프라에서 셀프 호스팅할 수 있어 데이터와 배포에 대해 완전한 제어권을 가질 수 있습니다.
|
||||
|
||||
## Why Self-Host?
|
||||
## 왜 셀프 호스팅인가요?
|
||||
|
||||
* **Data ownership**: Keep all CRM data on your own servers
|
||||
* **Compliance**: Meet regulatory requirements for data residency
|
||||
* **Customization**: Full access to modify and extend the platform
|
||||
* **데이터 소유권**: 모든 CRM 데이터를 자체 서버에 보관하세요
|
||||
* **컴플라이언스**: 데이터 상주에 대한 규제 요구사항을 준수하세요
|
||||
* **커스터마이징**: 플랫폼을 수정하고 확장할 수 있는 완전한 접근 권한
|
||||
|
||||
## Getting Started
|
||||
## 시작하기
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Docker Compose" icon="docker" href="/l/ko/developers/self-host/capabilities/docker-compose">
|
||||
Quick setup with Docker
|
||||
Docker로 빠르게 설정
|
||||
</Card>
|
||||
|
||||
<Card title="Cloud Providers" icon="cloud" href="/l/ko/developers/self-host/capabilities/cloud-providers">
|
||||
Deploy on AWS, GCP, or Azure
|
||||
<Card title="클라우드 제공자" icon="cloud" href="/l/ko/developers/self-host/capabilities/cloud-providers">
|
||||
AWS, GCP 또는 Azure에 배포
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
Reference in New Issue
Block a user