Skip to content

Commit 7ad8ed6

Browse files
docs(blog): 6차 배치 팁 포스트 5개 추가 (3개 언어)
- LLM 토큰 수 추정 (한국어/영어 차이) - Next.js rewrites 마이크로서비스 프록시 - pnpm workspace 모노레포 구성 - Cookie 인증 + localStorage 폴백 - Nginx Docker 정적 사이트 서빙
1 parent 1c0e570 commit 7ad8ed6

15 files changed

Lines changed: 713 additions & 0 deletions
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
layout: post
3+
title: "Estimate LLM Token Count - Korean vs English Differences"
4+
date: 2026-02-28 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [LLM, token, estimation, Korean, NLP]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "A simple token estimation algorithm without a full tokenizer. Korean text consumes more tokens than English."
10+
---
11+
12+
## Problem
13+
14+
Need to estimate token count before calling an LLM API. Installing tiktoken is overkill — just need a rough estimate.
15+
16+
## Solution
17+
18+
```typescript
19+
function estimateTokenCount(text: string): number {
20+
const words = text.trim().split(/\s+/).filter(w => w.length > 0);
21+
let tokens = 0;
22+
23+
for (const word of words) {
24+
const hasKorean = /[가-힣]/.test(word);
25+
if (hasKorean) {
26+
tokens += Math.ceil(word.length * 1.5); // Korean: ~1.5 tokens/char
27+
} else {
28+
tokens += Math.ceil(word.length * 0.75); // English: ~0.75 tokens/char
29+
}
30+
}
31+
32+
const mdElements = text.match(/```[\s\S]*?```|`[^`]+`|#{1,6}\s/g);
33+
if (mdElements) tokens += mdElements.length * 2;
34+
35+
return Math.max(1, Math.round(tokens));
36+
}
37+
38+
function formatTokens(count: number): string {
39+
return count < 1000 ? `${count} tokens` : `${(count / 1000).toFixed(1)}K tokens`;
40+
}
41+
```
42+
43+
## Key Points
44+
45+
- Korean characters take 3 bytes in UTF-8 and consume more tokens in BPE tokenizers than English. The same content in Korean uses 1.5-2x more tokens.
46+
- This estimate isn't exact, but it's sufficient for pre-call cost estimation and input length checks.
47+
- For precise counts, use OpenAI's tiktoken or Anthropic's tokenizer. But this approximation works for most use cases.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
layout: post
3+
title: "LLMトークン数の推定 - 韓国語と英語の違い"
4+
date: 2026-02-28 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [LLM, token, estimation, Korean, NLP]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "正確なトークナイザーなしでLLM APIコストを推定するシンプルなトークン数推定アルゴリズムをご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
LLM APIを呼び出す前に大まかなトークン数を知りたい。tiktokenのようなライブラリをインストールするのは過剰で、簡単な推定だけあれば十分です。
15+
16+
## 解決方法
17+
18+
```typescript
19+
function estimateTokenCount(text: string): number {
20+
const words = text.trim().split(/\s+/).filter(w => w.length > 0);
21+
let tokens = 0;
22+
23+
for (const word of words) {
24+
const hasKorean = /[가-힣]/.test(word);
25+
if (hasKorean) {
26+
tokens += Math.ceil(word.length * 1.5); // 韓国語:文字あたり約1.5トークン
27+
} else {
28+
tokens += Math.ceil(word.length * 0.75); // 英語:文字あたり約0.75トークン
29+
}
30+
}
31+
32+
const mdElements = text.match(/```[\s\S]*?```|`[^`]+`|#{1,6}\s/g);
33+
if (mdElements) tokens += mdElements.length * 2;
34+
35+
return Math.max(1, Math.round(tokens));
36+
}
37+
38+
function formatTokens(count: number): string {
39+
return count < 1000 ? `${count} tokens` : `${(count / 1000).toFixed(1)}K tokens`;
40+
}
41+
```
42+
43+
## ポイント
44+
45+
- 韓国語はUTF-8エンコーディングで1文字3バイトを占め、BPEトークナイザーでも英語よりトークンを多く消費します。同じ意味のテキストでも韓国語は英語の1.5〜2倍のトークンを使います。
46+
- この推定は正確ではありませんが、API呼び出し前のコスト見積もりや入力長チェックには十分です。
47+
- 正確なトークン数が必要な場合は、OpenAIのtiktokenやAnthropicのトークナイザーを使用してください。ただし、ほとんどの場合はこの程度の推定で十分です。
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
layout: post
3+
title: "LLM 토큰 수 추정하기 - 한국어와 영어 차이"
4+
date: 2026-02-28 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [LLM, token, estimation, Korean, NLP]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "정확한 토크나이저 없이 LLM API 비용을 추정하는 간단한 토큰 수 추정 알고리즘. 한국어는 영어보다 토큰을 더 많이 소비한다."
10+
---
11+
12+
## 문제
13+
14+
LLM API를 호출하기 전에 대략적인 토큰 수를 알고 싶다. tiktoken 같은 라이브러리를 설치하기엔 과하고, 간단한 추정만 필요하다.
15+
16+
## 해결
17+
18+
```typescript
19+
function estimateTokenCount(text: string): number {
20+
const words = text.trim().split(/\s+/).filter(w => w.length > 0);
21+
let tokens = 0;
22+
23+
for (const word of words) {
24+
const hasKorean = /[가-힣]/.test(word);
25+
if (hasKorean) {
26+
tokens += Math.ceil(word.length * 1.5); // 한국어: 글자당 ~1.5 토큰
27+
} else {
28+
tokens += Math.ceil(word.length * 0.75); // 영어: 글자당 ~0.75 토큰
29+
}
30+
}
31+
32+
// 마크다운 구문 추가 토큰
33+
const mdElements = text.match(/```[\s\S]*?```|`[^`]+`|#{1,6}\s/g);
34+
if (mdElements) tokens += mdElements.length * 2;
35+
36+
return Math.max(1, Math.round(tokens));
37+
}
38+
39+
// 포맷팅 헬퍼
40+
function formatTokens(count: number): string {
41+
return count < 1000 ? `${count} tokens` : `${(count / 1000).toFixed(1)}K tokens`;
42+
}
43+
```
44+
45+
## 핵심 포인트
46+
47+
- 한국어는 UTF-8 인코딩에서 글자당 3바이트를 차지하고, BPE 토크나이저에서도 영어보다 토큰을 많이 소비한다. 같은 의미의 텍스트라도 한국어가 영어보다 1.5~2배 더 많은 토큰을 쓴다.
48+
- 이 추정은 정확하지 않지만, API 호출 전 비용 가늠이나 입력 길이 제한 체크에는 충분하다.
49+
- 정확한 토큰 수가 필요하면 OpenAI의 tiktoken이나 Anthropic의 토크나이저를 사용해야 한다. 하지만 대부분의 경우 이 정도 추정이면 된다.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
layout: post
3+
title: "Next.js API Proxy with rewrites for Microservices"
4+
date: 2026-03-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Next.js, rewrites, proxy, microservice, API]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Use Next.js rewrites to proxy multiple backend microservices behind a single domain — no CORS headaches."
10+
---
11+
12+
## Problem
13+
14+
One Next.js frontend, multiple backend microservices on different ports. Calling them directly from the client means dealing with CORS configuration for every service.
15+
16+
## Solution
17+
18+
```javascript
19+
// next.config.js
20+
const nextConfig = {
21+
async rewrites() {
22+
return [
23+
{
24+
source: '/api/proxy/token/:path*',
25+
destination: 'http://127.0.0.1:3001/:path*',
26+
},
27+
{
28+
source: '/api/proxy/file/:path*',
29+
destination: 'http://127.0.0.1:3002/:path*',
30+
},
31+
];
32+
},
33+
};
34+
35+
module.exports = nextConfig;
36+
```
37+
38+
The client calls `/api/proxy/token/verify` and Next.js proxies it server-side to `http://127.0.0.1:3001/verify`.
39+
40+
## Key Points
41+
42+
- `rewrites` changes the destination without changing the URL visible to the client. Unlike `redirects`, the proxy is transparent.
43+
- `:path*` is a wildcard that forwards all sub-paths. `/api/proxy/token/a/b/c` maps to `http://127.0.0.1:3001/a/b/c`.
44+
- Since requests originate from the same domain, no CORS configuration is needed. Especially convenient during development.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
layout: post
3+
title: "Next.js rewritesでマイクロサービスAPIプロキシを設定する"
4+
date: 2026-03-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Next.js, rewrites, proxy, microservice, API]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "Next.jsのrewrites機能で複数のバックエンドサービスを1つのドメインに集約するAPIプロキシの設定方法をご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
フロントエンドはNext.js1つなのに、バックエンドのマイクロサービスがそれぞれ異なるポートで動いています。クライアントから直接呼び出すとCORSの問題が発生します。
15+
16+
## 解決方法
17+
18+
```javascript
19+
// next.config.js
20+
const nextConfig = {
21+
async rewrites() {
22+
return [
23+
{
24+
source: '/api/proxy/token/:path*',
25+
destination: 'http://127.0.0.1:3001/:path*',
26+
},
27+
{
28+
source: '/api/proxy/file/:path*',
29+
destination: 'http://127.0.0.1:3002/:path*',
30+
},
31+
];
32+
},
33+
};
34+
35+
module.exports = nextConfig;
36+
```
37+
38+
クライアントからは`/api/proxy/token/verify`のように呼び出すだけです。Next.jsがサーバーサイドで`http://127.0.0.1:3001/verify`にプロキシしてくれます。
39+
40+
## ポイント
41+
42+
- `rewrites`はURLを変えずに転送先だけを変更します。`redirects`と違い、クライアントからはプロキシの存在が見えません。
43+
- `:path*`はワイルドカードで、すべてのサブパスを転送します。`/api/proxy/token/a/b/c``http://127.0.0.1:3001/a/b/c`にマッピングされます。
44+
- 同一ドメインからリクエストが送信されるため、CORS設定が不要です。開発環境で特に便利です。
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
layout: post
3+
title: "Next.js rewrites로 마이크로서비스 API 프록시 설정"
4+
date: 2026-03-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Next.js, rewrites, proxy, microservice, API]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "Next.js rewrites 기능으로 여러 백엔드 서비스를 하나의 도메인 뒤에 숨기는 API 프록시 설정법."
10+
---
11+
12+
## 문제
13+
14+
프론트엔드는 Next.js 하나인데, 뒤에 마이크로서비스가 여러 개다. 각각 다른 포트에서 돌아가는 서비스들을 클라이언트에서 직접 호출하면 CORS 지옥이 펼쳐진다.
15+
16+
## 해결
17+
18+
```javascript
19+
// next.config.js
20+
const nextConfig = {
21+
async rewrites() {
22+
return [
23+
{
24+
source: '/api/proxy/token/:path*',
25+
destination: 'http://127.0.0.1:3001/:path*',
26+
},
27+
{
28+
source: '/api/proxy/file/:path*',
29+
destination: 'http://127.0.0.1:3002/:path*',
30+
},
31+
];
32+
},
33+
};
34+
35+
module.exports = nextConfig;
36+
```
37+
38+
클라이언트에서는 그냥 `/api/proxy/token/verify` 이런 식으로 호출하면 된다. Next.js가 서버사이드에서 `http://127.0.0.1:3001/verify`로 프록시해준다.
39+
40+
## 핵심 포인트
41+
42+
- `rewrites`는 URL은 바뀌지 않고 목적지만 바뀐다. 클라이언트는 프록시 존재를 모른다. `redirects`와 다른 점이 이거다.
43+
- `:path*`는 와일드카드로, 하위 경로를 모두 포워딩한다. `/api/proxy/token/a/b/c``http://127.0.0.1:3001/a/b/c`로 매핑된다.
44+
- 같은 도메인에서 요청이 나가니까 CORS 설정이 필요 없다. 개발 환경에서 특히 편하다.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
layout: post
3+
title: "Set Up a Monorepo with pnpm Workspace"
4+
date: 2026-03-03 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [pnpm, monorepo, workspace, Node.js]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Configure a monorepo with pnpm workspace to manage frontend, infra, and mobile projects in a single repository."
10+
---
11+
12+
## Problem
13+
14+
Frontend, landing page, mobile apps, and infrastructure code scattered across separate repos makes dependency management painful and sharing common code difficult.
15+
16+
## Solution
17+
18+
```yaml
19+
# pnpm-workspace.yaml
20+
packages:
21+
- frontend
22+
- landing
23+
- android
24+
- ios
25+
- infra
26+
```
27+
28+
```json
29+
// Root package.json
30+
{
31+
"name": "my-project",
32+
"private": true,
33+
"scripts": {
34+
"dev": "pnpm -F @my-project/frontend dev",
35+
"build": "pnpm -F @my-project/frontend build"
36+
}
37+
}
38+
```
39+
40+
A single `pnpm install` at the root installs dependencies for all packages. Use the `-F` (filter) flag to target specific packages.
41+
42+
## Key Points
43+
44+
- A single `pnpm-workspace.yaml` file is all you need. Unlike yarn workspaces, there's no need to configure anything in `package.json`.
45+
- pnpm uses symlinks and content-addressable storage, saving disk space while enforcing strict dependency isolation. It's structurally better suited for monorepos than npm or yarn.
46+
- Always set `"private": true` in the root `package.json` to prevent accidental publishing to npm.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
layout: post
3+
title: "pnpm workspaceでモノレポを構成する"
4+
date: 2026-03-03 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [pnpm, monorepo, workspace, Node.js]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "pnpm workspaceでフロントエンド、インフラ、モバイルプロジェクトを1つのリポジトリで管理するモノレポ構成法をご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
フロントエンド、ランディングページ、モバイルアプリ、インフラコードがそれぞれ別のリポジトリに分散していると、依存関係の管理が面倒で共通コードの共有も困難です。
15+
16+
## 解決方法
17+
18+
```yaml
19+
# pnpm-workspace.yaml
20+
packages:
21+
- frontend
22+
- landing
23+
- android
24+
- ios
25+
- infra
26+
```
27+
28+
```json
29+
// ルート package.json
30+
{
31+
"name": "my-project",
32+
"private": true,
33+
"scripts": {
34+
"dev": "pnpm -F @my-project/frontend dev",
35+
"build": "pnpm -F @my-project/frontend build"
36+
}
37+
}
38+
```
39+
40+
ルートで`pnpm install`を1回実行するだけで、すべてのパッケージの依存関係がインストールされます。特定のパッケージだけを実行するには`-F`(filter)フラグを使います。
41+
42+
## ポイント
43+
44+
- `pnpm-workspace.yaml`ファイル1つでモノレポの設定が完了します。yarn workspaceのように`package.json`に設定を書く必要がないためシンプルです。
45+
- pnpmはシンボリックリンクベースでディスク容量を節約し、パッケージ間の依存関係分離も厳格です。npmやyarnよりモノレポに適した構造です。
46+
- ルートの`package.json`には`"private": true`を必ず設定してください。誤ってnpmにパブリッシュされるのを防ぎます。

0 commit comments

Comments
 (0)