Skip to content

Commit ac7c00e

Browse files
authored
Update README.md
1 parent 3caf77e commit ac7c00e

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737

3838
### Server Sent Event를 통한 서버 리소스 절약
3939

40+
<div style="display: flex; gap: 0;">
41+
<img src="https://github.com/user-attachments/assets/148dc6c0-b2e7-4d1b-a1d6-8a341d2e80ee" style="width: 70%;"/>
42+
<img src="https://github.com/user-attachments/assets/3207f889-d086-4648-b80c-6bc5bccb4c84" style="width: 70%;"/>
43+
</div>
44+
4045
- 기존에 선택한 WebSocket을 통한 실시간 통신은 서버가 클라이언트의 요청을 계속해서 수신해야 하기에 서버의 리소스 부담으로 이어진다.
4146
- 서버가 클라이언트에게 일방적으로 데이터를 푸시하는 Server Sent Event로 실시간 통신 방식을 변경한다.
4247
- 서버가 더 이상 클라이언트 요청 수신에 대한 리소스를 낭비하지 않게 된다.
@@ -46,6 +51,11 @@
4651
---
4752
### 데이터 발행 비용 절약을 위한 SSE 브로드캐스팅
4853

54+
<div style="display: flex; gap: 0;">
55+
<img src="https://github.com/user-attachments/assets/ac9b0141-d688-422c-a6f2-3d80bac313c1" style="width: 70%;"/>
56+
<img src="https://github.com/user-attachments/assets/b347e44a-1fe5-48de-9098-7906b16940ec" style="width: 70%;"/>
57+
</div>
58+
4959
- 기존 방식은 클라이언트마다 각각 데이터가 발행돼, 구독자가 늘어남에 따라 오버헤드가 커지는 문제가 있었다.
5060
- 동일한 데이터 소스를 여러 클라이언트가 참조하는 형태의 브로드캐스팅을 구현했다.
5161
- 구독자의 수에 상관 없이 데이터 발행에 드는 비용을 고정적으로 줄일 수 있었다.
@@ -64,6 +74,11 @@
6474
---
6575
### 상태 관리와 추적을 통한 대기열 누수 방지
6676

77+
<div style="display: flex; gap: 0;">
78+
<img src="https://github.com/user-attachments/assets/5a0bff85-cf15-49fe-bcc8-eeb0a352b50b" style="width: 70%;"/>
79+
<img src="https://github.com/user-attachments/assets/08176f3f-808b-450d-9517-ceaa32d087e2" style="width: 70%;"/>
80+
</div>
81+
6782
- 대기열 화면과 좌석 선택 화면 사이에서 클라이언트의 갖은 예외적 움직임이 발생했고, 대기열 운영에 오류를 일으켰다.
6883
- 변수를 통제하는 방향으로 유저의 상태를 세분하게 정의, 추적, 관리했다.
6984
- 예외적 상황에도 누수 없이 정확한 인원 추적으로 서비스의 무결성을 유지할 수 있게 되었다.
@@ -73,6 +88,11 @@
7388
---
7489
### 매크로 방지 문자를 통해 부하 분산
7590

91+
<div style="display: flex; gap: 0;">
92+
<img src="https://github.com/user-attachments/assets/7146aa41-9eed-46ed-b59e-12f875fc2363" style="width: 70%;"/>
93+
<img src="https://github.com/user-attachments/assets/fd02af81-48e3-4ce6-a04a-b38a138de3e8" style="width: 70%;"/>
94+
</div>
95+
7696
- 예매 오픈 시 다수의 클라이언트가 동시에 좌석 점유 페이지로 이동해 서버에 과도한 부하가 발생한다.
7797
- 매크로 방지 기능을 사용해 사용자 입력을 요구하여 의도적으로 지연을 발생시킨다.
7898
- 동시에 들어오는 요청을 분산시켜 서버의 안정성을 확보한다.
@@ -82,6 +102,11 @@
82102
---
83103
### 좌표 기반 데이터로 통신 비용 절약
84104

105+
<div style="display: flex; gap: 0;">
106+
<img src="https://github.com/user-attachments/assets/c3885644-2982-455b-b74f-0498af65acdd" style="width: 70%;"/>
107+
<img src="https://github.com/user-attachments/assets/8a26192e-b92a-4e88-9731-e335722f8e90" style="width: 70%;"/>
108+
</div>
109+
85110
- 클라이언트에게 SVG 데이터 전송하는 것은 용량이 커져서 효율적이지 못했다.
86111
- viewbox 데이터와 모서리 좌표 데이터를 전송하는 방식 도입했다.
87112
- 데이터의 볼륨을 줄이고 네트워크 비용을 감소시켰다.
@@ -91,6 +116,12 @@
91116
---
92117
### 반정규화를 통한 DB 효율성 확보
93118

119+
<div style="display: flex; gap: 0;">
120+
<img src="https://github.com/user-attachments/assets/14dc5243-45d5-43f5-ba12-3f1839a37181" style="width: 70%;"/>
121+
<img src="https://github.com/user-attachments/assets/0479f029-6c01-4be3-8de0-5a36d480474b" style="width: 70%;"/>
122+
<img src="https://github.com/user-attachments/assets/8a4374de-b667-424c-8a68-ab580ee824c5" style="width: 70%;"/>
123+
</div>
124+
94125
- 좌석 배치 데이터 저장을 위해 좌석 하나당 하나의 행을 차지했다. 또한 좌석 조회시 JOIN을 통해 데이터를 조회해야 했다.
95126
- 좌석 배치 데이터의 정적인 특성을 활용해, 저장 형태를 압축하는 반정규화를 했다.
96127
- 좌석 배치 데이터의 관리, 조회에 드는 오버헤드를 해소하였다.
@@ -100,6 +131,11 @@
100131
---
101132
### Redis 동시성 이슈 예방, 조회/수정 쿼리 성능 개선
102133

134+
<div style="display: flex; gap: 0;">
135+
<img src="https://github.com/user-attachments/assets/4cfe7fea-405f-4a18-9107-2977c79b1bec" style="width: 70%;"/>
136+
<img src="https://github.com/user-attachments/assets/e5b36e55-635a-4775-9066-d754896ecd49" style="width: 70%;"/>
137+
</div>
138+
103139
- 좌석 현황의 저장 형태가 길어 수정/조회에 큰 오버헤드가 있었다. 또한 좌석 현황에 대한 동시적 수정/조회 때문에 동시성 이슈가 발생했다.
104140
- 좌석 현황의 저장 타입을 변환하여 부분 수정을 가능케 하고, 조회/수정 명령에는 원자성을 부여했다.
105141
- 가장 요청이 많고 핵심 병목 구간인 좌석 현황에서, 동시성을 제어하고 쿼리 성능을 개선해 병목을 완화했다.
@@ -109,6 +145,11 @@
109145
---
110146
### TanstackQuery의 queryKey, staleTime, invalidQueries를 이용한 API 호출 최소화
111147

148+
<div style="display: flex; gap: 0;">
149+
<img src="https://github.com/user-attachments/assets/1c79c967-596e-49e4-a676-903d4ba66f26" style="width: 70%;"/>
150+
<img src="https://github.com/user-attachments/assets/d0142c11-dd70-4064-9d78-b959c1810bfe" style="width: 70%;"/>
151+
</div>
152+
112153
- 여러 페이지에서 동일한 데이터에 대한 API 반복해서 호출하고 있었다.
113154
- query키와 staleTIme설정을 통해서 캐시 데이터를 사용했다.
114155
- API 호출 감소로 서버 부하를 감소시켰다.
@@ -118,6 +159,11 @@
118159
---
119160
### UI/UX 설계를 통한 동시 선택 문제 해결
120161

162+
<div style="display: flex; gap: 0;">
163+
<img src="https://github.com/user-attachments/assets/22f0e213-aac3-4e44-a292-25c3b1098320" style="width: 70%;"/>
164+
<img src="https://github.com/user-attachments/assets/3c005bea-c50b-416f-9ddb-3e947fae030a" style="width: 70%;"/>
165+
</div>
166+
121167
- 여러 사용자의 좌석 동시 선택으로 인한 충돌 문제가 있었다.
122168
- 클라이언트에서는 pending 상태를 표시, 서버에서 실패 응답시에는 사용자 행동을 방해하지 않으면서 실패 사실을 알렸다.
123169
- 사용자는 동시 선택 충돌이 일어나더라도 다음 행동을 방해받지 않으며, 즉시 인지하여 다른 좌석을 취할 수 있다.
@@ -127,6 +173,11 @@
127173
---
128174
### 쿼리문 감소를 위한 TypeORM 최적화
129175

176+
<div style="display: flex; gap: 0;">
177+
<img src="https://github.com/user-attachments/assets/c1e64524-2cd9-4c50-aa62-710936213188" style="width: 70%;"/>
178+
<img src="https://github.com/user-attachments/assets/cbb79390-993c-41b4-97a0-3417d12b5d01" style="width: 70%;"/>
179+
</div>
180+
130181
- 개발 편의성을 위해 도입한 TypeORM이 불필요한 쿼리 요청을 만들어내고 있었다.
131182
- 옵션을 통한 선택적 EAGER 로딩 정책으로 필요한 데이터만 불러오도록 한다.
132183
- 최소한의 쿼리로 필요한 데이터만 불러오도록 해 효율적으로 TypeORM을 사용한다.

0 commit comments

Comments
 (0)