Skip to content

Commit cff5af2

Browse files
docs(blog): 검색 유입용 기술 팁 포스트 2차 배치 (5개, 3개 언어)
- PM2 cluster mode로 Next.js 성능 올리기 - JavaScript Intl.NumberFormat 숫자 포맷팅 - fetch API Bearer Token 인증 헬퍼 - Docker Compose Redis healthcheck 설정 - Next.js HttpOnly Cookie JWT 인증
1 parent 589cb20 commit cff5af2

15 files changed

Lines changed: 798 additions & 0 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
layout: post
3+
title: "PM2 Cluster Mode for Next.js Production Performance"
4+
date: 2025-05-15 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [PM2, Node.js, Next.js, cluster, production]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Use PM2 cluster mode to leverage multi-core CPUs and boost Next.js throughput in production."
10+
---
11+
12+
## Problem
13+
14+
Node.js is single-threaded. Even with 4 CPU cores, only one gets used. When traffic spikes, a single process handles everything.
15+
16+
## Solution
17+
18+
```javascript
19+
// ecosystem.config.js
20+
module.exports = {
21+
apps: [{
22+
name: 'my-app',
23+
script: 'node_modules/next/dist/bin/next',
24+
args: 'start --port 3000',
25+
instances: 2, // number of CPU cores (or 'max')
26+
exec_mode: 'cluster', // enable cluster mode
27+
max_memory_restart: '800M',
28+
env: {
29+
NODE_ENV: 'production',
30+
},
31+
// restart policy
32+
exp_backoff_restart_delay: 100,
33+
max_restarts: 10,
34+
min_uptime: '10s',
35+
// logging
36+
log_date_format: 'YYYY-MM-DD HH:mm:ss',
37+
merge_logs: true,
38+
}]
39+
};
40+
```
41+
42+
```bash
43+
pm2 start ecosystem.config.js
44+
pm2 monit # real-time monitoring
45+
pm2 reload my-app # zero-downtime restart
46+
```
47+
48+
## Key Points
49+
50+
- `instances: 'max'` uses all cores, but on small servers like Raspberry Pi, limit to 2. The OS and other services (Redis, etc.) need cores too.
51+
- `exp_backoff_restart_delay: 100` starts at 100ms and increases the restart interval progressively, preventing infinite restart loops.
52+
- `pm2 reload` differs from `restart` — it replaces processes one at a time for zero downtime.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
layout: post
3+
title: "PM2 clusterモードでNext.jsプロダクション性能を向上させる"
4+
date: 2025-05-15 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [PM2, Node.js, Next.js, cluster, production]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "PM2のclusterモード設定でマルチコアを活用し、Next.jsアプリのスループットを向上させる方法をご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
Node.jsはシングルスレッドのため、CPUコアが4つあっても1つしか使いません。トラフィックが集中すると、1つのプロセスがすべてを処理しなければなりません。
15+
16+
## 解決方法
17+
18+
```javascript
19+
// ecosystem.config.js
20+
module.exports = {
21+
apps: [{
22+
name: 'my-app',
23+
script: 'node_modules/next/dist/bin/next',
24+
args: 'start --port 3000',
25+
instances: 2, // CPUコア数分(または'max')
26+
exec_mode: 'cluster', // clusterモード有効化
27+
max_memory_restart: '800M',
28+
env: {
29+
NODE_ENV: 'production',
30+
},
31+
// 再起動ポリシー
32+
exp_backoff_restart_delay: 100,
33+
max_restarts: 10,
34+
min_uptime: '10s',
35+
// ログ
36+
log_date_format: 'YYYY-MM-DD HH:mm:ss',
37+
merge_logs: true,
38+
}]
39+
};
40+
```
41+
42+
```bash
43+
pm2 start ecosystem.config.js
44+
pm2 monit # リアルタイム監視
45+
pm2 reload my-app # ゼロダウンタイム再起動
46+
```
47+
48+
## ポイント
49+
50+
- `instances: 'max'`にすると全コアを使いますが、Raspberry Piのような小型サーバーでは2つ程度に制限するのが安定的です。OSやRedisなど他のサービスにもコアが必要です。
51+
- `exp_backoff_restart_delay: 100`はアプリがクラッシュした際、100msから始めて段階的に間隔を広げて再起動します。無限再起動ループを防ぎます。
52+
- `pm2 reload``restart`と異なり、プロセスを1つずつ順番に入れ替えるため、ダウンタイムがありません。
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
layout: post
3+
title: "PM2 cluster mode로 Next.js 프로덕션 성능 올리기"
4+
date: 2025-05-15 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [PM2, Node.js, Next.js, cluster, production]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "PM2 cluster mode 설정으로 멀티코어를 활용해 Next.js 앱의 처리량을 높이는 방법."
10+
---
11+
12+
## 문제
13+
14+
Node.js는 싱글 스레드라서 CPU 코어가 4개여도 1개만 쓴다. 트래픽이 몰리면 하나의 프로세스가 다 감당해야 한다.
15+
16+
## 해결
17+
18+
```javascript
19+
// ecosystem.config.js
20+
module.exports = {
21+
apps: [{
22+
name: 'my-app',
23+
script: 'node_modules/next/dist/bin/next',
24+
args: 'start --port 3000',
25+
instances: 2, // CPU 코어 수만큼 (또는 'max')
26+
exec_mode: 'cluster', // cluster 모드 활성화
27+
max_memory_restart: '800M',
28+
env: {
29+
NODE_ENV: 'production',
30+
},
31+
// 재시작 정책
32+
exp_backoff_restart_delay: 100,
33+
max_restarts: 10,
34+
min_uptime: '10s',
35+
// 로그
36+
log_date_format: 'YYYY-MM-DD HH:mm:ss',
37+
merge_logs: true,
38+
}]
39+
};
40+
```
41+
42+
```bash
43+
pm2 start ecosystem.config.js
44+
pm2 monit # 실시간 모니터링
45+
pm2 reload my-app # 무중단 재시작
46+
```
47+
48+
## 핵심 포인트
49+
50+
- `instances: 'max'`로 하면 전체 코어를 다 쓰는데, 라즈베리파이 같은 소형 서버에서는 2개 정도로 제한하는 게 안정적이다. OS랑 Redis 같은 다른 서비스에도 코어가 필요하니까.
51+
- `exp_backoff_restart_delay: 100`은 앱이 죽었을 때 100ms부터 시작해서 점점 간격을 늘리며 재시작한다. 무한 재시작 루프를 방지한다.
52+
- `pm2 reload``restart`와 다르게 프로세스를 하나씩 순차적으로 교체해서 다운타임이 없다.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
layout: post
3+
title: "JavaScript Intl.NumberFormat - Format Numbers Without Libraries"
4+
date: 2025-06-25 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, Intl, NumberFormat, formatting, i18n]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Use the built-in Intl.NumberFormat API for currency, thousands separators, and percentage formatting without external libraries."
10+
---
11+
12+
## Problem
13+
14+
Installing numeral.js or accounting.js just to display "1,000" or "$1,234.56". There's a built-in browser API that handles this already.
15+
16+
## Solution
17+
18+
```javascript
19+
// Korean Won
20+
new Intl.NumberFormat('ko-KR', {
21+
style: 'currency',
22+
currency: 'KRW',
23+
minimumFractionDigits: 0,
24+
}).format(15000);
25+
// → "₩15,000"
26+
27+
// Thousands separator
28+
new Intl.NumberFormat('ko-KR').format(1234567);
29+
// → "1,234,567"
30+
31+
// US Dollar
32+
new Intl.NumberFormat('en-US', {
33+
style: 'currency',
34+
currency: 'USD',
35+
}).format(1234.5);
36+
// → "$1,234.50"
37+
38+
// Percentage
39+
new Intl.NumberFormat('ko-KR', {
40+
style: 'percent',
41+
minimumFractionDigits: 1,
42+
}).format(0.1234);
43+
// → "12.3%"
44+
```
45+
46+
## Key Points
47+
48+
- `Intl.NumberFormat` is supported in all modern browsers and Node.js. Even IE11 handles the basics.
49+
- `currency: 'KRW'` displays without decimals, while `'USD'` automatically adds 2 decimal places. Each currency follows its own conventions.
50+
- For repeated use, store the formatter instance in a variable. Creating `new` instances every time is wasteful.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
layout: post
3+
title: "JavaScript Intl.NumberFormat - ライブラリなしで数値フォーマット"
4+
date: 2025-06-25 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, Intl, NumberFormat, formatting, i18n]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "JavaScript内蔵のIntl.NumberFormatで通貨、桁区切り、パーセントフォーマットをライブラリなしで処理する方法をご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
数値を「1,000円」や「$1,234.56」のように表示するためにnumeral.jsやaccounting.jsをインストールしていました。しかし、ブラウザにはすでに内蔵機能がありました。
15+
16+
## 解決方法
17+
18+
```javascript
19+
// 韓国ウォン
20+
new Intl.NumberFormat('ko-KR', {
21+
style: 'currency',
22+
currency: 'KRW',
23+
minimumFractionDigits: 0,
24+
}).format(15000);
25+
// → "₩15,000"
26+
27+
// 桁区切り
28+
new Intl.NumberFormat('ko-KR').format(1234567);
29+
// → "1,234,567"
30+
31+
// 米ドル
32+
new Intl.NumberFormat('en-US', {
33+
style: 'currency',
34+
currency: 'USD',
35+
}).format(1234.5);
36+
// → "$1,234.50"
37+
38+
// パーセント
39+
new Intl.NumberFormat('ko-KR', {
40+
style: 'percent',
41+
minimumFractionDigits: 1,
42+
}).format(0.1234);
43+
// → "12.3%"
44+
```
45+
46+
## ポイント
47+
48+
- `Intl.NumberFormat`はすべてのモダンブラウザとNode.jsでサポートされています。IE11でも基本機能は動作します。
49+
- `currency: 'KRW'`にすると小数点なしで表示され、`'USD'`にすると自動的に小数点2桁が付きます。各通貨の慣例に自動的に従います。
50+
- 同じフォーマットを繰り返し使う場合は、インスタンスを変数に保存しておくとパフォーマンスが向上します。毎回`new`するのは無駄です。
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
layout: post
3+
title: "JavaScript Intl.NumberFormat - 숫자 포맷팅 라이브러리 없이 해결"
4+
date: 2025-06-25 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, Intl, NumberFormat, formatting, i18n]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "JavaScript 내장 Intl.NumberFormat으로 통화, 천단위 구분, 퍼센트 포맷팅을 라이브러리 없이 처리하는 방법."
10+
---
11+
12+
## 문제
13+
14+
숫자를 "1,000원"이나 "$1,234.56" 같은 형식으로 표시하려고 numeral.js나 accounting.js를 설치하고 있었다. 근데 브라우저에 이미 내장된 기능이 있었다.
15+
16+
## 해결
17+
18+
```javascript
19+
// 한국 원화
20+
new Intl.NumberFormat('ko-KR', {
21+
style: 'currency',
22+
currency: 'KRW',
23+
minimumFractionDigits: 0,
24+
}).format(15000);
25+
// → "₩15,000"
26+
27+
// 천단위 구분
28+
new Intl.NumberFormat('ko-KR').format(1234567);
29+
// → "1,234,567"
30+
31+
// 미국 달러
32+
new Intl.NumberFormat('en-US', {
33+
style: 'currency',
34+
currency: 'USD',
35+
}).format(1234.5);
36+
// → "$1,234.50"
37+
38+
// 퍼센트
39+
new Intl.NumberFormat('ko-KR', {
40+
style: 'percent',
41+
minimumFractionDigits: 1,
42+
}).format(0.1234);
43+
// → "12.3%"
44+
```
45+
46+
## 핵심 포인트
47+
48+
- `Intl.NumberFormat`은 모든 모던 브라우저와 Node.js에서 지원된다. IE11도 기본 기능은 된다.
49+
- `currency: 'KRW'`로 하면 소수점 없이 표시되고, `'USD'`면 자동으로 소수점 2자리가 붙는다. 각 통화의 관례를 알아서 따른다.
50+
- 같은 포맷을 반복 사용하면 인스턴스를 변수에 저장해두는 게 성능상 좋다. 매번 `new` 하는 건 낭비다.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
layout: post
3+
title: "Auto-Inject Bearer Token with a fetch API Auth Helper"
4+
date: 2025-07-10 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, fetch, Bearer Token, authentication, API]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Stop repeating Authorization headers — build a fetch wrapper that auto-injects Bearer tokens."
10+
---
11+
12+
## Problem
13+
14+
Manually adding `headers: { 'Authorization': 'Bearer ...' }` to every API call. Token refresh and error handling duplicated across each function.
15+
16+
## Solution
17+
18+
```typescript
19+
let authToken: string | null = null;
20+
21+
export function setAuthToken(token: string | null) {
22+
authToken = token;
23+
if (token) localStorage.setItem('auth_token', token);
24+
else localStorage.removeItem('auth_token');
25+
}
26+
27+
function getAuthToken(): string | null {
28+
if (!authToken) authToken = localStorage.getItem('auth_token');
29+
return authToken;
30+
}
31+
32+
async function fetchWithAuth<T>(
33+
endpoint: string,
34+
options: RequestInit = {}
35+
): Promise<T> {
36+
const token = getAuthToken();
37+
const headers: Record<string, string> = {
38+
'Content-Type': 'application/json',
39+
...(options.headers as Record<string, string>),
40+
};
41+
if (token) headers['Authorization'] = `Bearer ${token}`;
42+
43+
const res = await fetch(`${API_URL}${endpoint}`, { ...options, headers });
44+
45+
if (!res.ok) {
46+
const err = await res.json().catch(() => ({ message: 'Unknown error' }));
47+
throw new Error(err.message || `HTTP ${res.status}`);
48+
}
49+
50+
return res.json();
51+
}
52+
```
53+
54+
## Key Points
55+
56+
- Dual-layer token storage: in-memory variable first, `localStorage` as fallback. Faster than calling `localStorage.getItem` every time.
57+
- All API functions reduce to `fetchWithAuth<ResponseType>('/endpoint')`. Token management logic lives in one place — easy to add refresh logic later.
58+
- `res.json().catch()` gracefully handles non-JSON responses (like HTML error pages from the server).

0 commit comments

Comments
 (0)