Files
twenty/packages/twenty-docs/l/ko/developers/frontend-development/style-guide.mdx
T
8cadd00d34 i18n - translations (#15799)
Created by Github action

---------

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: github-actions <github-actions@twenty.com>
2025-11-13 16:34:00 +01:00

296 lines
9.2 KiB
Plaintext

---
title: 스타일 가이드
image: /images/user-guide/notes/notes_header.png
---
<Frame>
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>
이 문서에는 코드 작성 시 따라야 할 규칙이 포함되어 있습니다.
여기서 목표는 읽기 쉽고 유지 관리가 쉬운 일관된 코드베이스를 갖는 것입니다.
이를 위해서는 너무 간결하기보다는 약간 더 장황한 것이 낫습니다.
항상 사람들이 코드를 작성하는 것보다 더 자주 읽는다는 점을 염두에 두십시오. 특히 누구나 기여할 수 있는 오픈 소스 프로젝트에서 그렇습니다.
여기에 정의되지 않은 많은 규칙이 있지만 린터에 의해 자동으로 확인됩니다.
## 리액트
### 함수형 컴포넌트 사용
항상 TSX 함수형 컴포넌트를 사용하십시오.
기본 `import`를 `const`와 함께 사용하지 마십시오. 읽기 어렵고 코드 자동 완성으로 import하기 어렵습니다.
```tsx
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Hello World</div>;
};
export default MyComponent;
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Hello World</div>;
};
```
### 프로퍼티
props의 유형을 만들고 내보낼 필요가 없으면 `(ComponentName)Props`라고 명명하십시오.
props 구조 분해를 사용하십시오.
```tsx
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```
#### prop 유형을 정의하기 위해 `React.FC` 또는 `React.FunctionComponent`를 사용하지 마십시오.
```tsx
/* ❌ - Bad, defines the component type annotations with `FC`
* - With `React.FC`, the component implicitly accepts a `children` prop
* even if it's not defined in the prop type. This might not always be
* desirable, especially if the component doesn't intend to render
* children.
*/
const EmailField: React.FC<{
value: string;
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
```
```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.
*/
type EmailFieldProps = {
value: string;
};
const EmailField = ({ value }: EmailFieldProps) => (
<TextInput value={value} disabled fullWidth />
);
```
#### JSX 요소에서 단일 변수 prop 확산 방지
JSX 요소에서 `{...props}`와 같은 단일 변수 prop 확산을 피하십시오. 이 관행은 구성 요소가 수신되는 props를 명확하게 하지 않아 가독성과 유지 관리가 어려운 코드를 생성하는 경우가 많습니다.
```tsx
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
}
```
```tsx
/* ✅ - Good, Explicitly lists all props
* - Enhances readability and maintainability
*/
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
};
```
이유:
- 한눈에 코드가 전달하는 props를 명확하게 하여 이해하고 유지하기 쉽습니다.
- 이것은 구성 요소가 각자의 props로 긴밀하게 결합되는 것을 방지하는 데 도움이 됩니다.
- props를 명시적으로 나열하면 Linting 도구에서 잘못된 철자나 사용되지 않는 props를 쉽게 식별할 수 있습니다.
## 자바스크립트
### nullish 병합 연산자 `??` 사용
```tsx
// ❌ Bad, can return 'default' even if value is 0 or ''
const value = process.env.MY_VALUE || 'default';
// ✅ Good, will return 'default' only if value is null or undefined
const value = process.env.MY_VALUE ?? 'default';
```
### 옵셔널 체이닝 `?.` 사용
```tsx
// ❌ Bad
onClick && onClick();
// ✅ Good
onClick?.();
```
## 타입스크립트
### `interface` 대신 `type` 사용
항상 `interface` 대신 `type`을 사용하십시오. 두 개의 기능은 거의 항상 중첩되며, `type`이 더 유연합니다.
```tsx
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Good
type MyType = {
name: string;
};
```
### 열거형 대신 문자열 리터럴 사용
[String literals](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types)는 TypeScript에서 열거형과 같은 값을 처리하는 주요 방법입니다. 그들은 Pick와 Omit으로 확장하기 쉬우며, 특히 코드 완성 기능을 사용할 때 더 나은 사용자 경험을 제공합니다.
타입스크립트가 열거형 사용을 피하도록 권장하는 이유는 [여기](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums)에서 확인할 수 있습니다.
```tsx
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
let color = Color.Red;
```
```tsx
// ✅ Good, utilizes a string literal
let color: "red" | "green" | "blue" = "red";
```
#### GraphQL 및 내부 라이브러리
GraphQL 코드 생성기가 생성한 열거형을 사용해야 합니다.
내부 라이브러리를 사용할 때도 열거형을 사용하는 것이 좋으며, 내부 API와 관련이 없는 문자열 리터럴 유형을 노출할 필요가 없습니다.
예시:
```TSX
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
setHotkeyScopeAndMemorizePreviousScope(
RelationPickerHotkeyScope.RelationPicker,
);
```
## 스타일링
### StyledComponents 사용
[styled-components](https://emotion.sh/docs/styled)로 구성 요소를 스타일링하십시오.
```tsx
// ❌ Bad
<div className="my-class">Hello World</div>
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
스타일드 컴포넌트 앞에 "Styled"를 붙여 실제 컴포넌트와 구분하십시오.
```tsx
// ❌ Bad
const Title = styled.div`
color: red;
`;
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
### 테마
대부분의 구성 요소 스타일링에는 테마를 활용하는 것이 선호되는 접근 방식입니다.
#### 측정 단위
스타일드 컴포넌트 내에서 `px` 또는 `rem` 값을 직접 사용하는 것을 피하십시오. 필요한 값은 일반적으로 테마에 이미 정의되어 있으므로 이러한 목적으로 테마를 활용하는 것이 좋습니다.
#### 색상
새로운 색상을 도입하지 말고 테마에서 기존 팔레트를 사용하십시오. 팔레트가 맞지 않는 경우가 있다면 팀이 수정할 수 있도록 댓글을 남겨야 합니다.
```tsx
// ❌ Bad, directly specifies style values without utilizing the theme
const StyledButton = styled.button`
color: #333333;
font-size: 1rem;
font-weight: 400;
margin-left: 4px;
border-radius: 50px;
`;
```
```tsx
// ✅ Good, utilizes the theme
const StyledButton = styled.button`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
margin-left: ${({ theme }) => theme.spacing(1)};
border-radius: ${({ theme }) => theme.border.rounded};
`;
```
## No-Type Import 강제 실행
타입 import를 피하십시오. 이 표준을 강화하기 위해 ESLint 규칙이 모든 타입 import를 확인하고 보고합니다. 이는 TypeScript 코드의 일관성과 가독성을 유지하는 데 도움이 됩니다.
```tsx
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';
// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```
### No-Type Import의 이유
- **일관성**: 타입 import를 피하고, 타입과 값 import 모두의 단일 접근 방식을 사용하여 모듈 import 스타일의 일관성을 유지합니다.
- **가독성**: No-Type Import는 값을 가져오거나 타입을 가져오는 것을 명확히 하여 코드 가독성을 향상시킵니다. 이는 모호성을 줄이고 가져온 기호의 목적을 이해하기 쉽게 만듭니다.
- **유지관리성**: 이는 코드베이스 유지관리를 향상시킵니다. 개발자가 코드를 검토하거나 수정할 때 타입 전용 import를 식별하고 찾을 수 있습니다.
### ESLint 규칙
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. 이 규칙은 모든 타입 import 위반에 대해 오류나 경고를 생성합니다.
이 규칙은 의도치 않은 타입 import가 발생하는 드문 경계 사례를 구체적으로 다룹니다. 타입스크립트 자체는 [TypeScript 3.8 릴리스 노트](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html)에서 이 관행을 권장하지 않습니다. 대부분의 상황에서 타입 전용 import를 사용할 필요가 없습니다.
이 규칙을 준수하는 코드를 보장하기 위해 ESLint를 개발 워크플로의 일부로 실행하십시오.