데이터 베이스 설계, 세부 UI 컴포넌트 설계

⭐ 아엔 Aen·2026년 1월 15일

데브코스

목록 보기
122/131

데이터베이스 설계, 한 번에 이해하기

DB를 그냥 막 만들면 나중에 데이터가 중복되고, 쿼리가 느려지고, 고치려면 테이블을 다 갈아엎어야 하는 상황이 온다. 처음부터 잘 설계해두면 이런 일이 없다. 핵심부터 한 줄로 정리하면 이렇다.

데이터베이스 설계 = 데이터를 어떤 테이블에, 어떤 구조로, 어떻게 연결해서 저장할지 미리 계획하는 것


쉽게 비유하면

서류 캐비닛 설계라고 생각하면 됨! 회사 서류를 캐비닛에 정리할 때, 서랍을 어떻게 나누고 어떤 라벨을 붙일지 먼저 계획하는 거다. 계획 없이 막 넣으면 나중에 "그 서류 어디 있지?" 할 때 캐비닛 전체를 다 뒤져야 한다.

  • 서랍 = 테이블
  • 서류 = 데이터(행, row)
  • 라벨·항목 = 컬럼
  • 서랍끼리 참조 = 관계(Foreign Key)

잘 설계된 캐비닛은 원하는 서류를 바로 찾을 수 있고, 새 서류 추가도 쉬운 것 같음!


자세히

설계 3단계

1단계 — 개념적 설계 (Conceptual Design)

"뭘 저장할 거냐"를 추상적으로 정리하는 단계. ERD(Entity-Relationship Diagram) 를 그린다.

  • Entity(개체): 저장할 대상 (유저, 게시글, 댓글 등)
  • Attribute(속성): 각 개체의 특징 (유저의 이름, 이메일 등)
  • Relationship(관계): 개체들 사이의 연결 (유저가 게시글을 씀)

2단계 — 논리적 설계 (Logical Design)

ERD를 실제 테이블 구조로 변환. 테이블명, 컬럼명, 데이터 타입, 키를 정한다.

3단계 — 물리적 설계 (Physical Design)

어떤 DB에서 어떻게 저장할지. 인덱스, 파티셔닝, 스토리지 엔진 같은 것들을 결정한다.

관계의 종류

테이블끼리 연결 방식이 세 가지다.

1:1 (일대일)

  • 유저 1명 ↔ 유저 프로필 1개
  • 흔하진 않음. 테이블을 굳이 나눌 이유가 있을 때 씀

1:N (일대다)

  • 유저 1명 ↔ 게시글 여러 개
  • 제일 흔한 관계. 게시글 테이블에 user_id 컬럼(외래키)을 넣어서 연결

N:M (다대다)

  • 유저 여러 명 ↔ 태그 여러 개 (유저가 여러 태그를 달고, 태그는 여러 유저에게 달림)
  • 중간 테이블(Junction Table)을 만들어서 연결
    유저 테이블  ←→  유저_태그 테이블  ←→  태그 테이블

정규화 (Normalization)

중복을 없애고 구조를 깔끔하게 만드는 과정. 단계가 있다.

  • 1NF — 컬럼에 값이 하나씩만 들어가야 함 (배열이나 콤마로 여러 값 넣으면 안 됨)
  • 2NF — 기본키가 아닌 컬럼이 기본키 전체에 의존해야 함
  • 3NF — 컬럼이 기본키에만 의존하고, 다른 일반 컬럼에 의존하면 안 됨

쉽게 말하면 "중복 데이터 없애기" 가 정규화의 핵심이다. 같은 정보가 여러 테이블에 흩어져 있으면, 하나 바꿀 때 다 찾아서 바꿔야 해서 실수가 난다.

비정규화 (Denormalization)

정규화를 일부러 풀기도 한다. 정규화된 구조는 깔끔하지만, 조회할 때 JOIN이 많아져서 느려질 수 있기 때문이다. 읽기 성능이 정말 중요한 경우에 중복을 허용하고 JOIN을 줄이는 전략이다. 설계할 때는 정규화로 시작하고, 성능 문제가 생기면 그때 비정규화를 고려하는 게 순서 같음!

인덱스 설계

DB 설계에서 인덱스도 미리 계획해야 한다.

  • 자주 검색되는 컬럼 (예: email, user_id)
  • WHERE 조건에 자주 오는 컬럼
  • JOIN 할 때 쓰이는 외래키 컬럼

인덱스가 없으면 풀 스캔(처음부터 끝까지 다 훑기)이 일어나서 데이터 많아질수록 느려짐. 단, 인덱스가 많아지면 쓰기 성능이 떨어지니까 남발하면 안 됨 같음!


실사용 예

간단한 투표 서비스 DB 설계를 예로 들면 이렇다.

[users]
- id (PK)
- email
- nickname
- created_at

[polls]
- id (PK)
- user_id (FK → users.id)   ← 누가 만들었나
- title
- description
- created_at

[options]
- id (PK)
- poll_id (FK → polls.id)   ← 어느 투표 항목인가
- content

[votes]
- id (PK)
- user_id (FK → users.id)   ← 누가 투표했나
- option_id (FK → options.id) ← 어느 항목에 투표했나
- created_at

여기서 votes 테이블이 usersoptions의 N:M 관계를 해결하는 중간 테이블이다. "유저는 여러 투표를 할 수 있고, 항목은 여러 유저에게 선택될 수 있으니까" 딱 N:M 관계인 거다.

자주 하는 실수는 options 컬럼을 콤마로 한 셀에 넣는 거다("선택1,선택2,선택3"). 이러면 나중에 각 옵션 별 투표 수 집계하려면 파싱부터 해야 해서 굉장히 불편해짐. 처음부터 테이블 나눠두는 게 맞다 같음!


한 방 정리

구분내용
한 줄 정의데이터를 어떤 구조로 저장할지 미리 계획하는 것
비유서류 캐비닛 서랍 설계
설계 3단계개념적 → 논리적 → 물리적
관계 종류1:1 / 1:N / N:M (중간 테이블)
정규화중복 없애기. 성능 필요하면 비정규화 고려
인덱스자주 검색·조건·JOIN 컬럼에 걸기

쉽게 외우면 "테이블을 어떻게 나누고 연결할지 미리 그림 그리는 것" — ERD 한 장 그려두면 개발하다 방향 잃을 일이 없어지는 것 같음!


세부 UI 컴포넌트 설계, 한 번에 이해하기

버튼 하나, 인풋 하나도 그냥 만들면 나중에 유지보수가 힘들어진다. 컴포넌트를 어떻게 나누고, 어떤 props를 줄지, 어떻게 재사용할지를 미리 고민하는 게 UI 컴포넌트 설계다. 핵심부터 한 줄로 정리하면 이렇다.

UI 컴포넌트 설계 = 화면을 구성하는 UI 조각들을 재사용 가능하고, 일관성 있고, 유지보수하기 쉽게 구조화하는 것


쉽게 비유하면

레고 블록 설계라고 생각하면 됨! 집(화면)을 만들 때마다 벽돌을 처음부터 새로 만들면 비효율적이다. 규격화된 레고 블록(컴포넌트)을 미리 잘 만들어두면, 다른 집 만들 때도 그 블록을 꺼내서 조립하면 된다.

  • 레고 블록 = 버튼, 인풋, 카드, 모달 같은 UI 컴포넌트
  • 블록 규격 통일 = props 인터페이스 설계
  • 블록 재사용 = 여러 페이지에서 같은 컴포넌트 사용
  • 블록 조합 = 작은 컴포넌트를 합쳐서 큰 컴포넌트 만들기

잘 설계된 블록은 어디서든 끼워 맞출 수 있고, 한 블록 고쳐도 다른 블록에 영향이 없는 것 같음!


자세히

컴포넌트를 나누는 기준

모든 걸 컴포넌트로 만들 필요도 없고, 너무 안 나눠도 안 된다. 이럴 때 나누면 됨:

  • 2번 이상 반복 — 같은 UI가 두 곳 이상에 쓰이면 컴포넌트로 분리
  • 역할이 명확히 다를 때 — 한 컴포넌트가 너무 많은 일을 하면 쪼개기
  • 독립적으로 테스트할 수 있을 때 — 분리하면 테스트·스토리북 작성이 쉬워짐

아토믹 디자인 (Atomic Design)

컴포넌트를 5단계 계층으로 나누는 방법론이다.

Atoms (원자)
  → Molecules (분자)
    → Organisms (유기체)
      → Templates (템플릿)
        → Pages (페이지)
  • Atoms — 더 이상 쪼갤 수 없는 최소 단위. Button, Input, Label, Icon
  • Molecules — Atoms 조합. SearchBar(Input + Button), FormField(Label + Input)
  • Organisms — Molecules 조합. Header(Logo + Nav + SearchBar), Card(Image + Title + Button)
  • Templates — 레이아웃 골격. 실제 데이터 없이 구조만 잡은 것
  • Pages — 실제 데이터가 들어간 완성된 화면

비유: Atoms는 밀가루·달걀, Molecules는 반죽, Organisms는 케이크 한 조각, Templates는 케이크 틀, Pages는 완성된 케이크 같음!

Props 설계

컴포넌트의 "입력 인터페이스"다. 잘 설계된 props는 이런 특징이 있다.

명확한 타입 정의 (TypeScript)

interface ButtonProps {
  label: string
  variant?: "primary" | "secondary" | "danger"
  size?: "sm" | "md" | "lg"
  disabled?: boolean
  onClick?: () => void
}
  • 필수값과 옵션값을 구분 (? 유무)
  • string 대신 유니온 타입으로 허용값을 제한 ("primary" | "secondary")
  • 쓰는 사람이 타입 보고 바로 어떻게 쓰는지 알 수 있어야 함

Props 설계 원칙

  • 단순하게 — props가 너무 많으면(10개 이상) 컴포넌트가 너무 많은 일을 하는 신호
  • 일관성 있게 — 클릭 핸들러는 항상 onClick, 변경 핸들러는 onChange처럼 네이밍 통일
  • 조합 가능하게children을 잘 활용하면 유연한 컴포넌트를 만들 수 있음

상태 관리와 컴포넌트 설계

컴포넌트를 나눌 때 "이 상태가 어디에 있어야 하나" 도 같이 고민해야 한다.

  • 로컬 상태 — 해당 컴포넌트 안에서만 쓰이면 useState로 해결
  • 공유 상태 — 여러 컴포넌트가 같이 쓰면 상위로 올리거나(Lifting State Up) 전역 상태 관리 도구 사용
  • 서버 상태 — API에서 받아오는 데이터면 React Query 같은 도구 활용

컴포넌트 설계 패턴

Presentational vs Container 패턴

Container 컴포넌트     → 데이터 가져오고, 로직 처리
        ↓ props
Presentational 컴포넌트 → 받은 데이터 그냥 보여주기만 함

Presentational 컴포넌트는 순수하게 UI만 담당해서 재사용이 쉽고 테스트도 쉬워진다.

Compound Component 패턴

관련된 컴포넌트를 그룹으로 묶는 패턴. 라이브러리에서 자주 보임.

<Select>
  <Select.Trigger />
  <Select.Options>
    <Select.Option value="a">옵션 A</Select.Option>
  </Select.Options>
</Select>

실사용 예

버튼 컴포넌트 하나 제대로 설계하는 것만 봐도 차이가 확 보인다.

나쁜 예 — 상황마다 따로 만들기

<BlueButton />
<RedButton />
<SmallBlueButton />
<LargeRedButton />

→ 버튼 색이나 크기 바꿀 때 파일 여러 개 고쳐야 함

좋은 예 — props로 유연하게

<Button variant="primary" size="lg" onClick={handleSubmit}>
  제출
</Button>
<Button variant="danger" size="sm" disabled>
  삭제
</Button>

→ Button 컴포넌트 하나만 관리하면 됨. 스타일 바꾸면 전체 적용

폴더 구조도 설계의 일부다.

components/
├── ui/              ← Atoms (Button, Input, Badge...)
├── common/          ← Molecules (SearchBar, FormField...)
├── features/        ← 기능별 Organisms (PollCard, VoteForm...)
└── layouts/         ← 레이아웃 관련

이렇게 잡아두면 팀원이 "버튼 어디 있어요?" 할 때 components/ui/ 보면 되고, "투표 카드 어디 있어요?" 할 때 components/features/ 보면 된다 같음!


한 방 정리

구분내용
한 줄 정의UI 조각을 재사용 가능하고 일관성 있게 구조화하는 것
비유레고 블록 규격 설계
나누는 기준2번 이상 반복 / 역할이 명확히 다를 때
대표 방법론아토믹 디자인 (Atoms → Pages)
Props 핵심명확한 타입 + 유니온으로 허용값 제한
상태는?쓰이는 범위에 따라 로컬 / 공유 / 서버 상태 구분

쉽게 외우면 "나중에 고치기 쉽고, 어디서든 꺼내 쓸 수 있게 컴포넌트를 설계하는 것" — 처음엔 귀찮지만 페이지가 10개 넘어가는 순간 설계해둔 게 빛나는 것 같음!

profile
Dive Head First | Work Super Hard | Attract Great People

0개의 댓글