17일 차 TIL
팀에서 설계한 ERD, 테이블 명세서, API 명세서, 인프라 설계도를 피드백받았다.
인프라 설계는 그 설계가 무엇을 보여주기 위한 설계인 지 명확히 해야 한다고 했다.
- CI/CD와 인프라 아키텍처, 서비스 아키텍처를 나누기
또한 ERD를 설계할 때,
트레이드-오프를 고려하는 것의 중요성을 느꼈다.
트레이드-오프 문제들
1. 행 생성 vs 컬럼 수정
- 결제의 상태를 변경하면
- 새로 행을 생성해서 추가 vs update 쿼리로 해당 컬럼을 수정 ( 이 경우 before/after값을 위한 컬럼도 추가해야 함 )
=> 복잡해질 것 같아서 새로 행을 추가하기로 결정
2. 외래키를 가질 것이냐 컬럼만 둘 것이냐
2-1. 가게의 리뷰를 관리할 때,
가게에 리뷰 테이블을 외래키로 둬야 하는가?
- 리뷰를 달고 가게의 컬럼을 업데이트 vs 가게를 조회할 때 리뷰 객체를 조회
= 조회의 성능을 높임 vs 수정의 성능을 높임
=> 리뷰를 조회하는 경우가 훨씬 많아서 조회의 성능을 높이기로 결정 ( n+1 문제 해결 )
추가로 가게의 리뷰를 수정할 때, 누군가 조회한다면
즉 커밋 전에 조회한다면 언 커밋티드 리드가 나가야 하지 않나?
=> 업데이트 쿼리를 이벤트로 발행 생각해 보기
=> 트랜잭션 격리 수준 생각하기
2-2. AI로 상품 설명을 생성할 때( AI의 질문과 응답을 테이블로 저장할 때 )
이때 AI 응답 테이블에 상품을 외래키로 둬야 하는가?
- 상품명 컬럼을 추가/관리 vs 외래키로 상품 테이블을 가져옴
=> 모든 AI응답을 사장님이 사용할 수도 안 할 수도 있어서
상품명만 컬럼으로 추가해서 관리하기로 결정
3. 가게주소 정규화 vs 컬럼에 저장
- 가게의 주소를 시도 + 시/군/구 + 읍/면/동테이블로 나눠서 관리 vs 컬럼으로 나눌지
주소는 거의 불변이라서, 주소는 거의 불변이라서, 시/군/구로 나눠서 테이블 구조
결제 흐름 ( 장바구니 )
쿠팡이츠 기준 사용자 주문 흐름
1. 사용자는 가게를 고른다.
2. 음식과 옵션을 정해서 배달 카트에 담는다.
3. 카트 보기를 누른다.
4. 결제하기 버튼을 누른다.
5. 가게로 주문이 보내진다.
6. 가게에서 주문을 확인하고 수락/거절을 한다.
7. 배달이 진행 및 완료된다.
따라서, 장바구니를 결제하고 주문이 생성된다.
하지만 주문은 장바구니 정보가 필요가 없다.
주문에는 누가 주문했는지, 그리고 그 사람이 무엇을 주문했는 지를 알면 된다.
주문에서 외래키로 회원테이블을 가져오고
주문에서 상품정보를 가져오면 된다. (주문-상품은 다대다로 정의)
그리고 주문과 결제를 매핑
이때, 결제는 결제상태에 따라서
하나의 주문에 여러 개의 결제데이터가 생길 수 있기에 다대일의 관계이다.
이때, 결제 상태를 변경하면 새로운 데이터를 생성해서 저장하는 식이다.
1. 가게 - 상품은 일대다 관계
2. 장바구니-가게는 다대일 관계
( 하나의 가게는 여러 개의 장바구니를 가질 수 있다. )
3. 장바구니-회원은 일대일 관계
( 하나의 회원은 하나의 장바구니를 가진다. )
4. 장바구니-상품은 다대다 관계
( 하나의 장바구니는 여러 개의 상품을 가질 수 있다 / 하나의 상품은 여러 개의 장바구니를 가질 수 있다. )
5. 주문-상품은 다대다 관계
6. 주문-결제는 다대일 관계
반정규화
반정규화는 데이터의 중복이 있어도 이점이 있을 경우에 컬럼 중복을 허용하는 개념이다.
이때 이점의 예시는 성능 향상이나 데이터 일관성 유지 등이 있다.
주문과 상품의 관계에서, 상품테이블에는 해당 상품의 가격컬럼이 있다.
근데 중간테이블인 주문품목 테이블에서도 가격을 저장해야 하는가?
일단 주문에서는 외래키로 상품을 가지고 있기 때문에,
주문에서 상품을 조회하고, 해당 상품의 가격정보를 가져올 수 있다.
하지만 이때 매번 주문을 조회할 때 가격정보를 가져오려면 Join기능이 필요하다.
근데 상품가격이 바뀌었다면?
이전가격이 아닌 바뀐 가격이 조회되기 때문에
이전 가격을 조회하기 위해 이 데이터가 등록되는 시점의 가격을 기록해 둘 필요가 있다.
따라서 중간테이블에서도 당시의 가격을 기록하기 위해 가격 컬럼을 뒀다.
REST의 의미
REST = 표현(Representation), 상태(State), 전달(Transfer)
URI로 자원을 표현하고, HTTP 메서드로 행위를 구분한다.
서버는 이전 요청의 상태를 포함하지 않는다. ( Stateless )
따라서 매 요청마다 필요한 정보를 모두 포함해야 한다.
REST 원칙을 잘 지킨 API가 RESTFul API이다.
추가로 API는 계층형임을 인지하자
ex) /api/me/review vs /api/review/me
둘의 의미가 다르다.
Redis
Redis는 데이터를 디스크가 아니라 RAM에 저장하기에
매우 빠른 속도로 읽고 쓸 수 있는 인메모리 데이터 저장소이다.
- Key-Value 구조의 NoSQL 데이터 저장소이다.
회원 리프레시 토큰이나 장바구니에 쓰인다.
- 회원 리프레시 토큰에서 사용하는 이유
1. 로그인 트래픽이 많으면 DB의 부하가 증가한다.
2. 보통 만료 기한이 설정되어 있는데, 이를 Redis에서 쉽게 설정 가능하다.
3. 로그아웃 시 Redis에서 삭제
4. Redis Only 저장, DB엔 저장 x
SET refresh:1234 abcdef EX 1209600
- 장바구니에서 사용하는 이유
1. 조회/수정이 매우 잦다.
2. 실시간 응답이 중요
3. 일시적 데이터기에 휘발성 면에서 Redis와 궁합이 좋다.
보통 Redis에만 저장하고 DB에는 저장을 안 하거나
DB에는 주기적으로 백업하는 식으로 한다.
장바구니 말고 주문 기록부터 DB에 저장하는 식으로
AWS개념 정리
VPC (Virtual Private Cloud)이란?
개인용 가상 네트워크
서브넷이란?
VPC 안을 다시 나눈 작은 네트워크 공간
- 보안
- 서버 역할을 나눔
퍼블릭 서브넷이란?
- 인터넷에서 직접 접근 가능
- 외부 IP 있음
ex) 로드밸런서, Bastion 서버
프라이빗 서브넷이란?
- 인터넷에서 직접 접근 불가
- 외부에서 바로 못 들어옴
ex) EC2 애플리케이션 서버, DB(RDS)
+) 보안 구조를 보여주기 위해 인프라 설계도에
같이 퍼블릭/프라이빗을 표시해야 한다.
ex)
[Internet]
↓
[ALB - Public Subnet]
↓
[EC2 - Private Subnet]
↓
[RDS - Private Subnet]
EC2와 ECR란?
EC2는 서버 컴퓨터, ECR은 도커 이미지 저장소
UUID 사용 이유
가용성을 높이기 위해 데이터를 기준(예: 사용자 ID, 지역 등)에 따라
여러 데이터베이스에 나누어 저장하는 방식을 샤딩(Sharding)이라고 한다.
이때 각 DB가 독립적으로 숫자 기반 AUTO_INCREMENT 방식으로 ID를 생성하면,
서로 다른 DB에서 동일한 ID 값이 생성될 수 있다.
예를 들어)
- DB1 → ID 1
- DB2 → ID 1
이 경우, 데이터 통합, 글로벌 참조, 또는 DB 병합 시
ID 충돌 문제가 발생할 수 있다.
이를 해결하기 위해 UUID를 사용한다.
UUID는 중앙 ID 발급 서버 없이도
각 노드가 독립적으로 전역적으로 유일한 식별자를 생성할 수 있다.
따라서 ID 충돌을 방지할 수 있고
중앙 서버 의존성을 제거할 수 있으며
분산 환경에서 확장성과 가용성을 확보할 수 있다.
도메인의 의미
주문 ENUM
오더는 오더 상태값만 가져야 함. 현재 오더가 결제, 배달 상태값도 가지고 있음.
자신의 도메인의 상태 변경에 필요한 것만 써야 함.
내일 할 일(27일에 할 거)
팀 단위)
인프라 설계 ( CI / CD 분리 )
API 명세 작성
테이블 명세서 수정
역할 분담
개인 단위)
리뷰 수정 시, 개발 고려사항으로 업데이트 쿼리를 이벤트로 발행 어떤 뜻인지 질문하기.
- 트랜잭션 격리 수준이랑 연관 지었던 걸로 기억
'내배캠' 카테고리의 다른 글
| [내일배움캠프] 19일 차 TIL 도메인 중심 아키텍처 (0) | 2026.03.01 |
|---|---|
| [내일배움캠프] 18일 차 TIL 동시성문제 해결방법들 (0) | 2026.02.27 |
| [내일배움캠프 본캠프] 16일 차 TIL 도커 (0) | 2026.02.25 |
| 스파르타 12조 질문 정리 (0) | 2026.02.25 |
| [내일배움캠프 본캠프] 15일 차 TIL 1차 팀 프로젝트 시작 (0) | 2026.02.24 |
