image

이해가 돼야 기억도 하지!!

DB초보자 PostgreSQL 실습노트 01_요구사항 분석부터 ERD까지

이 시리즈는 요구사항 분석 → ERD → CRUD → 대시보드 SQL까지 따라간다.
이번 글에서는 첫 번째 카페 주문 및 메뉴 관리 예시로, 요구사항 분석부터 ERD의 뼈대까지 만든다!

덴지, 레제, 포치타가 카페 주문 정보를 요구사항에서 ERD로 정리하는 학습 표지 이미지

* 이번 글의 목표

실습은 모두 5개다. 이번 글은 1번, 카페 주문 및 메뉴 관리다.

  1. 카페 주문 및 메뉴 관리
    고객, 메뉴, 주문, 주문상세 관리
  2. 도서 대여 관리
    회원, 도서, 대여, 반납 관리
  3. 반려동물 병원 예약 관리
    보호자, 반려동물, 수의사, 예약 관리
  4. 헬스장 회원·수업 예약 관리
    회원, 강사, 수업, 예약 관리
  5. 스터디 모임 및 참여자 관리
    회원, 스터디 그룹, 모임, 참여 신청 관리

이 글은 이렇게 흘러간다.

카페 주문 관리 실습이 요구사항 분석에서 ERD 설계까지 이어지는 학습 흐름도

이 글은 PostgreSQL 문법을 바로 쓰기 전, 요구 사항에 대한 DB를 어떻게 설계할지 먼저 생각해보는 글이다. 지금은 훑어보고 넘어가자.

한국어영어 표기간단 설명
테이블Table같은 종류의 데이터를 저장하는 표
행Row / Record테이블에 저장된 실제 데이터 한 건
컬럼Column / Field각 데이터가 가지는 항목
기본키Primary Key / PK한 행을 구분하는 고유한 값
외래키Foreign Key / FK다른 테이블의 행과 연결하는 값



1. 요구사항 분석으로 시작

요구사항 분석? 무슨 요구사항을 분석한다는 말이야?

내가 만들고 싶거나, 의뢰받은 서비스가 어떤 정보와 흐름을 가지는지 먼저 정리하는 단계다.

카페로 예를 들면 “카페 주문 관리 프로그램을 만든다면 어떤 정보를 저장해야 할까?”를 생각해보는 것이다.

카페에는 고객과 메뉴가 있고, 고객은 메뉴를 주문한다. 주문에는 여러 메뉴가 들어갈 수 있다.

그러면 먼저 찾아야 할 것은 고객 / 메뉴 / 주문 / 주문 안의 메뉴 정보다.

이 외에도 가격, 수량, 테이블 번호, 할인, 테이크아웃 등이 떠오를 수 있다.
처음에는 다 적어보고, 그다음에 분류해보자.

SQL을 작성하기 전에 이렇게 먼저 생각해보는 게 시작이다.

2. 왜 이렇게 먼저 생각해봐야 할까?

카페 업무는 현실에서는 하나의 흐름이다.

고객이 와서 메뉴를 고르고, 수량을 말하고, 포장 여부와 결제를 정한 뒤 주문을 완료한다.

그런데 컴퓨터는 이 흐름을 그대로 “상황”으로 기억하지 못한다.
그래서 정보를 잘게 나눠, 정리된 형태로 저장해야 한다.

3. 그래, 그럼 어떻게 분류하면 되는데?

단순하게 혼자 관리할 대상인가? 아니면 다른 대상을 설명하는 값인가?

고객은 혼자 관리할 수 있다. 이름, 연락처, 이메일이 있기 때문이다.

메뉴 – 메뉴명, 종류, 기본 가격
주문 – 누가 언제 주문했는지를 기록해야 하기 때문이다.

수량? 수량만 따로 저장하면 의미가 없다.
왜? 주문 “2개”라고만 있으면 무엇이 2개인지 알 수 없기 때문이다.

그래서 수량은 주문 안의 메뉴를 설명하는 값이다.
가격도 같은 이유다.

4. 분류해보자

나올 수 있는 정보: 고객, 메뉴, 주문, 가격, 수량, 주문 시간, 판매 여부, 할인, 포장 여부

이제 이것을 두 가지로 나눈다.
같은 종류의 것을 모아두는 목록표인지, 그 목록표 안에 들어가야 할 요소인지.

예를 들면:

과자 상자(목록표) → 과자, 젤리, 초콜릿

장난감 상자(목록표) → 자동차, 블록, 공

옷 상자(목록표) → 티셔츠, 바지, 양말

돌아와서 카페로 바꾸면,

고객 상자 → 고객의 정보가 들어간다. (이름, 나이, 성별, 생일) 회원제라면.

메뉴 상자 → 아아, 아라, 스무디, 차 등

주문 상자 → 고객이 주문한 주문 한 건씩 추가된다.

주문상세 상자 → 주문 안의 메뉴 줄이 들어간다.

즉, 테이블 = 같은 종류의 것을 모아두는 목록표
행 = 그 목록 안에 들어가는 하나
컬럼 = 그 하나를 설명하는 항목


지금까지는 머릿속에 떠오르는 정보를 전부 꺼내는 단계였다.

다음은 분류표를 작성하는 단계다.

  • 후보 목록 예시 –
    고객, 메뉴, 주문, 가격, 수량, 주문 시간, 판매 여부, 할인, 포장 여부, 이메일, 연락처,메뉴 종류, 주문 상태

작성 형식:

분류명1
분류항목1
분류항목2
분류항목3
분류항목4
분류명2
분류항목1
분류항목2
분류항목3
분류항목4
분류명3
분류항목1
분류항목2
분류항목3
분류항목4
분류명4
분류항목1
분류항목2
분류항목3
분류항목4

이렇게 표로 만들어보면서 분류하면 더 직관적으로 확인할 수 있다.
항목을 꽉 채우지 않아도 된다! 할 수 있는 만큼만 채워보자.

이렇게 분류하면

분류표명(같은 종류의 정보를 모아둔 표) = 테이블명

분류 항목(표 안에서 저장할 항목) = 컬럼

추가되는 실제 데이터 한 줄 = 행(Row)

이 된다.

즉, 고객이라는 분류표를 만들었다면

  • 분류표 명(테이블): 고객
  • 분류 항목(컬럼): 이름, 연락처, 이메일, 가입일
  • 추가되는 데이터(행): 포치타 / 010-1234-5678 / abc@email.com / 2026-09-09

즉, 지금 이 과정은
단순히 표를 그리는 게 아니라,

현실의 정보를
데이터베이스의 구조로 바꾸어 보는 과정이다.

여기까지 테이블, 컬럼, 행이 무엇인지 정도는 이해됐길 바란다.

완성한 형태는 아래와 같다.

테이블을 연결할 때 중요한 컬럼은 고객 번호, 메뉴 번호, 주문 번호 같은 번호들이다.

이어서 설명하겠지만, 이 번호들은 누가 어떤 주문을 했는지 헷갈리지 않게 하는 기준이다.

손님이 입장해서 주문하고 그것이 처리되는 흐름을 따라가며 보면 이해하기 쉽다.

첫 번째 손님을 “포치타”라고 하자. 포치타는 고객 번호 1번이다.

고객 번호 1번인 포치타가 주문표에서 주문하면 주문번호 1번이 생긴다.

주문상세표에는 주문번호 1번에 대한 상세 행이 3개 들어갈 수 있다.
이때 주문상세표의 메뉴 번호를 보고 메뉴표에서 메뉴 이름과 가격을 확인한다.


첫 번째 손님이 들어와 주문했을 때, 각 항목에 어떤 정보가 들어가는지 먼저 생각해본다.

포치타 고객이 메뉴를 주문하고 주문상세에 기록되는 카페 주문 흐름 예시

이렇게 처리하려면 테이블 간의 관계를 만들 기준이 필요하다.

그래서 고유번호, 즉 PK(기본키)를 둔다.

각 테이블에 추가되는 정보를 구분하기 위한 고유번호 정도로 이해하자.

이 고유번호는 중복되거나 비어 있으면 안 된다.

그리고 이 고유번호가 다른 테이블에 들어가 연결 역할을 하면 FK(외래키)라고 한다.

간단히 정리하면

PK = 각 테이블에서 원하는 한 줄(데이터)을 정확히 찾기 위한 고유번호

FK = 다른 테이블의 한 줄을 가리키는 연결 번호

고객, 메뉴, 주문, 주문상세 테이블의 PK와 FK 연결을 설명한 다이어그램

이 카페 예시에서 테이블 관계는 대부분 1:N으로 생각해볼 수 있다.
응? 이건 또 왜?

그런데 주문상세표를 보면 의아한 점이 있었을 수도 있다.

수량은 메뉴표에 들어가도 될 것 같고, 주문표에 들어갈 수도 있을 것 같다.

주문 당시 가격도 메뉴표나 주문표에 들어가도 될 것처럼 애매하다.

한눈에 확인해보자.

고객, 주문, 메뉴, 주문상세 테이블의 1:N과 N:M 관계를 보여주는 다이어그램

그래서 주문상세 테이블을 만들어 중간 연결 테이블로 사용한다.

그래서 그게 뭐냐고?

카페 주문을 생각해보자. 포치타라는 고객이 있다.

포치타는 오늘도 주문할 수 있고, 내일도 다시 주문할 수 있다.

즉, 고객 한 명은 여러 번 주문할 수 있다.

그래서 고객과 주문은 1:N 관계라고 표현한다.

쉽게 말하면 고객 1명 → 주문 여러 건, 이런 구조다.


이번에는 주문 하나를 보자.

포치타가 주문 1번에서 아메리카노, 치즈케이크, 카페라떼를 같이 주문했다고 하자.

그러면 주문 1번 안에는 메뉴가 여러 개 들어간다.

즉, 주문 1건 → 주문상세 여러 줄. 이것도 1:N 관계다.

주문상세는 영수증 안에 적힌 메뉴 줄이라고 보면 된다.


그런데 주문과 메뉴를 보면 관계가 조금 더 복잡하다.

한 주문에는 여러 메뉴가 들어갈 수 있다.

반대로 아메리카노 같은 메뉴도 여러 주문에 들어갈 수 있다.

즉, 주문과 메뉴는 서로 여러 개씩 연결된다. 이걸 N:M 관계라고 한다.


문제는 N:M 관계를 그대로 표에 넣기 어렵다는 것이다.

주문표에 메뉴를 전부 넣으면 메뉴 1, 메뉴 2, 메뉴 3처럼 컬럼이 계속 늘어난다.
메뉴가 많아질수록 표가 금방 복잡해진다.

그래서 중간에 주문상세표를 둔다.


주문상세표는 주문과 메뉴 사이를 연결한다.

예를 들어 주문 1번에 아메리카노 2잔, 치즈케이크 1개가 있다면 주문상세표에는 이렇게 들어간다.

주문 1번 / 아메리카노 / 2잔
주문 1번 / 치즈케이크 / 1개

즉, 주문상세는 한 주문 안의 메뉴들을 줄 단위로 정리하는 표다.

중간 테이블이 있고 없고의 차이를 확인해보자.

주문 테이블과 메뉴 테이블 사이에 주문상세 중간 테이블을 두는 예시

한 주문 안에 여러 메뉴가 들어갈 수 있기 때문이다.

예를 들어 포치타가 와서 아메리카노 2잔, 치즈케이크 1개,
카페라떼 1잔을 주문했다고 하자.

이걸 주문 표에 전부 넣으려고 하면

메뉴 1, 수량 1, 메뉴 2, 수량 2, 메뉴 3, 수량 3처럼
표가 점점 지저분해진다.

처음에는 괜찮아 보여도, 메뉴가 5개, 10개가 되면 컬럼을 계속 늘려야 한다.

그래서 주문 표에는 주문 한 건의 정보만 남긴다.

예를 들면 누가 주문했는지, 언제 주문했는지, 주문 상태가 무엇인지 정도다.

그리고 실제 주문한 메뉴들은 주문 상세 표에 따로 적는다.

즉, 영수증으로 비유하면 이렇다. 주문 표는 영수증 한 장이다.
주문 상세 표는 영수증 안의 메뉴 줄이다.

영수증 한 장 안에 아메리카노 2잔, 치즈케이크 1개가 적히는 것처럼,

주문 상세 표에는 주문한 메뉴가 한 줄씩 들어간다.

이렇게 하면 좋은 점은 명확하다.

메뉴가 몇 개든 깔끔하게 저장할 수 있다.

메뉴별 수량도 정확히 관리할 수 있다.

나중에 어떤 메뉴가 많이 팔렸는지도 쉽게 계산할 수 있다.

한 줄로 정리하면:

중간 테이블은 복잡한 주문 내용을 메뉴별 한 줄로 풀어서 정리하는 표다.

그럼 중간 테이블인지 아닌지는 이렇게 판단하자.

두 대상이 서로 여러 개씩 엮이면
중간 테이블을 의심한다.

예를 들어 카페에서는:

한 주문에 메뉴가 여러 개 들어갈 수 있나?
→ 그렇다.

한 메뉴도 여러 주문에 들어갈 수 있나?
→ 그렇다.

그러면 주문과 메뉴는 N:M 관계가 된다.

이때는 보통 중간 테이블이 필요하다.

더 간단하게!

A도 B를 여러 개 가질 수 있고,
B도 A에 여러 번 등장할 수 있으면
중간 테이블을 둔다.

카페 주문 관리 데이터베이스의 고객, 메뉴, 주문, 주문상세 ERD
카페 주문 관리 데이터베이스의 ERD 학습 완료 이미지

To be continued..

Next.

CRUD를 이해하고 Datebase와 Schema 까지 만들어본다

ERD초안을 가지고 CRUD를 이해하고
Datebase와 Schema 까지 만들어본다.

PostgreSQL 초보자 실습 03: 테이블 생성과 INSERT 데이터 입력