
내가 지금 처음 타입스크립트 라는 것을 공부하다보니, 자바스크립트나 리액트와는 다르게, 타입을 정말 하나하나 전부 다 지정을 해두더라고,
그리고 타입을 또 만들어서 이 타입은 이런 이런 타입만 있고, 이런 걸 만들어주던데, 그거에 대해서 어떻게 작성하는지 정말 많이 만들었던 버튼 컴포넌트를 가지고 설명해볼게.
theme.ts (설계도) Button.tsx (실제 사용)
↓ ↓
"버튼은 3가지 크기" → size="large" 선택
"각 크기마다 폰트, 패딩" → 자동으로 스타일 적용
"모든 디자인 규칙을 한 곳에 모아둔 설계도"
export type ButtonSize = "large" | "medium" | "small";
export type ButtonScheme = "primary" | "normal";
의미:
button: {
large: {
fontSize: "1.5rem",
padding: "1rem 2rem",
},
medium: {
fontSize: "1rem",
padding: "0.5px 1px",
},
// ...
}
의미:
"theme의 규칙을 따라서 실제 버튼 만드는 곳"
interface Props {
children: React.ReactNode; // 버튼 안 텍스트
size: ButtonSize; // theme에서 정의한 타입!
scheme: ButtonScheme; // theme에서 정의한 타입!
disabled?: boolean; // 비활성화 여부
isLoading?: boolean; // 로딩 중 여부
}
의미:
const ButtonStyle = styled.button<Omit<Props, "children">>`
font-size: ${({ theme, size }) => theme.button[size].fontSize};
padding: ${({ theme, size }) => theme.button[size].padding};
해석:
size="large" 전달하면theme.button["large"].fontSize 가져옴theme.button["large"].padding 가져옴// 나쁜 예 (각자 맘대로)
<button style={{ fontSize: "16px" }}>버튼1</button>
<button style={{ fontSize: "1rem" }}>버튼2</button>
<button style={{ fontSize: "18px" }}>버튼3</button>
// 좋은 예 (규칙 따름)
<Button size="medium">버튼1</Button>
<Button size="medium">버튼2</Button>
<Button size="medium">버튼3</Button>
// 전부 똑같은 크기로 나옴!
// theme.ts에서 한 줄만 바꾸면
button: {
large: {
fontSize: "2rem", // 1.5rem → 2rem으로 변경
}
}
// 모든 large 버튼이 자동으로 바뀜!
// 100개 파일 수정 안 해도 됨
// ❌ 에러남 (오타)
<Button size="big">버튼</Button>
// ✅ 자동완성됨
<Button size="large">버튼</Button>
// ^ 여기서 large/medium/small 자동완성
1. theme.ts에서 규칙 정의
↓
2. ThemeProvider로 전체 앱에 전달
↓
3. Button.tsx에서 theme 받아옴
↓
4. size prop에 따라 적절한 스타일 선택
↓
5. 화면에 버튼 렌더링
// App.tsx
<ThemeProvider theme={light}> // ← light 테마 전달
<Button size="large">클릭</Button> // ← large 요청
</ThemeProvider>
// Button.tsx 내부에서
theme.button["large"].fontSize // ← "1.5rem" 가져옴
const ButtonStyle = styled.button<Omit<Props, "children">>`
의미:
Props에서 children 빼고 나머지만 사용children은 HTML 속성이 아니라서 제외함// Props 전체
{ children, size, scheme, disabled, isLoading }
// Omit<Props, "children">
{ size, scheme, disabled, isLoading } // children 제외됨
// 사용하는 쪽
function HomePage() {
return (
<>
<Button size="large" scheme="primary">
구매하기
</Button>
<Button size="medium" scheme="normal" disabled>
품절
</Button>
</>
);
}
결과:
"디자인 시스템을 코드로 만든 것"임!