Skip to content

Commit 0455de2

Browse files
docs(blog): sir.kr 2025년 포스트 6건 마이그레이션 (3개 언어)
- API 엔드포인트 보안 (2025-02-10) - Ollama 로컬 LLM 사용후기 (2025-02-15) - Cursor 에이전트 1달 후기 (2025-03-20) - AI에게 개발 잘 시키는법 (2025-03-25) - 개발인생 20년 회고 (2025-04-10) - 라즈베리파이 키오스크 (2025-07-20)
1 parent ceffc8a commit 0455de2

18 files changed

Lines changed: 1080 additions & 0 deletions
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
layout: post
3+
title: "API Endpoint Security Without Authentication - How Far Should You Go?"
4+
date: 2025-02-10 09:00:00 +0900
5+
categories: [Development, Security]
6+
tags: [API, Security, CORS, Rate Limiting, Token]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Protecting API endpoints on public sites with no login system. CORS alone isn't enough, but you can't force authentication either. Here's the practical approach."
10+
---
11+
12+
# API Endpoint Security Without Authentication
13+
14+
## The Problem
15+
16+
I needed to secure API endpoints on a public website with no login functionality.
17+
18+
Example: a company info page with a contact form that submits data via API. The API is exposed to the public. No login means no JWT or session-based authentication.
19+
20+
Leave it unprotected? Someone discovers the API URL and scripts thousands of form submissions.
21+
22+
## CORS Alone Isn't Enough
23+
24+
The first thing that comes to mind is CORS configuration.
25+
26+
```
27+
Access-Control-Allow-Origin: https://mysite.com
28+
```
29+
30+
This blocks browser requests from other domains. But CORS is a **browser policy**. Requests from curl, Postman, or server-side scripts bypass CORS entirely.
31+
32+
CORS is a convenience mechanism, not a security mechanism. Necessary but insufficient.
33+
34+
## Practical Defense Strategy
35+
36+
You need to combine multiple approaches.
37+
38+
**1. API Key + HMAC Signature**
39+
40+
The frontend generates an HMAC signature with a timestamp for each request. The server validates it using the same method. The key is exposed in source code, but combined with obfuscation, it deters casual attacks.
41+
42+
**2. Rate Limiting**
43+
44+
Block requests from the same IP beyond a certain threshold. Configurable at the API Gateway or Nginx level.
45+
46+
```
47+
# Nginx rate limiting
48+
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/m;
49+
50+
location /api/contact {
51+
limit_req zone=api burst=2 nodelay;
52+
}
53+
```
54+
55+
No legitimate use case needs more than 5 contact submissions per minute. This stops scripted attacks.
56+
57+
**3. CAPTCHA**
58+
59+
Add reCAPTCHA or hCaptcha to the form. The most reliable way to block automated submissions. Downside: degrades user experience.
60+
61+
**4. Honeypot Fields**
62+
63+
Add a hidden input field via CSS. Humans can't see it and won't fill it. Bots try to fill every field. If the field has a value, reject the submission.
64+
65+
```html
66+
<input type="text" name="website" style="display:none" tabindex="-1">
67+
```
68+
69+
Simple but surprisingly effective.
70+
71+
**5. One-Time Tokens**
72+
73+
Issue a disposable token on page load. Include it with the API request. Discard after single use. Similar principle to CSRF protection.
74+
75+
## My Chosen Combination
76+
77+
Here's what I implemented:
78+
79+
1. **Rate Limiting** (baseline defense)
80+
2. **Honeypot field** (bot defense)
81+
3. **One-time token** (replay prevention)
82+
4. **CORS** (standard configuration)
83+
84+
Skipped CAPTCHA due to UX impact. Not perfect, but achieves a realistic security level for a no-auth environment.
85+
86+
There's no 100% perfect security. The core strategy is raising the attack cost until it's not worth the effort.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
layout: post
3+
title: "ログインなしのAPIエンドポイントセキュリティ - どこまで守るべきか"
4+
date: 2025-02-10 09:00:00 +0900
5+
categories: [Development, Security]
6+
tags: [API, セキュリティ, CORS, Rate Limiting, トークン]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "ログイン機能のない公開サイトでAPIエンドポイントを安全に保護する方法。CORSだけでは不十分で、かといって認証を強制もできない状況での現実的な対策。"
10+
---
11+
12+
# ログインなしのAPIエンドポイントセキュリティ
13+
14+
## 問題の状況
15+
16+
ログイン機能のない公開ウェブサイトでAPIエンドポイントを保護する必要が出てきました。
17+
18+
例えば、会社紹介ページでお問い合わせフォームを送信するとAPIにデータが送られますが、このAPIが外部にそのまま公開されています。ログインがないのでJWTやセッションベースの認証が使えません。
19+
20+
放置すると?誰かがAPIのURLを見つけて、スクリプトでフォームを何千件も送信できてしまいます。
21+
22+
## CORSだけでは不十分
23+
24+
最初に思いつくのはCORS設定です。
25+
26+
```
27+
Access-Control-Allow-Origin: https://mysite.com
28+
```
29+
30+
これで他のドメインからブラウザでリクエストするのは防げます。でもCORSは**ブラウザのポリシー**です。curlやPostman、サーバーサイドスクリプトからのリクエストはCORS制限を受けません。
31+
32+
結局CORSはセキュリティ手段ではなく便宜的な仕組みです。必要ですが、これだけでは足りません。
33+
34+
## 現実的な防御戦略
35+
36+
複数の方法を組み合わせて使う必要があります。
37+
38+
**1. APIキー + HMAC署名**
39+
40+
フロントエンドからリクエストする際にタイムスタンプと共にHMAC署名を生成して送ります。サーバーで同じ方法で署名を検証します。キーがソースコードに露出する問題がありますが、難読化と組み合わせればカジュアルな攻撃は防げます。
41+
42+
**2. Rate Limiting**
43+
44+
同じIPから一定回数以上のリクエストが来たらブロックします。API GatewayやNginxレベルで設定できます。
45+
46+
```
47+
# Nginx rate limiting
48+
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/m;
49+
50+
location /api/contact {
51+
limit_req zone=api burst=2 nodelay;
52+
}
53+
```
54+
55+
お問い合わせフォームが毎分5件以上必要なケースはないので、これでスクリプト攻撃は防げます。
56+
57+
**3. CAPTCHA**
58+
59+
reCAPTCHAやhCaptchaをフォームに追加します。ボットによる自動送信を防ぐ最も確実な方法です。ただしユーザー体験が悪くなるデメリットがあります。
60+
61+
**4. ハニーポットフィールド**
62+
63+
CSSで非表示にした入力フィールドをフォームに追加します。人間はこのフィールドが見えないので入力しませんが、ボットはすべてのフィールドを埋めようとします。このフィールドに値があればボットと判断して拒否します。
64+
65+
```html
66+
<input type="text" name="website" style="display:none" tabindex="-1">
67+
```
68+
69+
シンプルですが意外と効果的です。
70+
71+
**5. ワンタイムトークン**
72+
73+
ページロード時にサーバーからワンタイムトークンを発行し、APIリクエスト時にこのトークンを一緒に送ります。一度使われたトークンは破棄します。CSRF防御と似た原理です。
74+
75+
## 私が選んだ組み合わせ
76+
77+
最終的に適用したのはこの組み合わせです。
78+
79+
1. **Rate Limiting**(基本防御)
80+
2. **ハニーポットフィールド**(ボット防御)
81+
3. **ワンタイムトークン**(再利用防止)
82+
4. **CORS**(基本設定)
83+
84+
CAPTCHAはUXへの影響が大きいので外しました。完璧ではありませんが、ログインなしの環境で現実的に可能なレベルのセキュリティは確保できます。
85+
86+
100%完璧なセキュリティはありません。結局「攻撃コストを上げて面倒にする」のが核心です。
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
layout: post
3+
title: "로그인 없는 API 엔드포인트 보안 - 어디까지 막아야 하나"
4+
date: 2025-02-10 09:00:00 +0900
5+
categories: [Development, Security]
6+
tags: [API, 보안, CORS, Rate Limiting, 토큰]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "로그인 없이 접근 가능한 API를 안전하게 보호하는 방법. CORS만으로는 부족하고, 그렇다고 인증을 강제할 수도 없는 상황에서의 현실적인 대책."
10+
---
11+
12+
# 로그인 없는 API 엔드포인트 보안
13+
14+
## 문제 상황
15+
16+
로그인 기능이 없는 공개 웹사이트에서 API 엔드포인트를 보호해야 하는 상황이 생겼다.
17+
18+
예를 들어 회사 소개 페이지에서 문의 폼을 제출하면 API로 데이터가 전송되는데, 이 API가 외부에 그대로 노출되어 있다. 로그인이 없으니 JWT나 세션 기반 인증을 쓸 수가 없다.
19+
20+
그냥 놔두면? 누군가 API 주소를 알아내서 스크립트로 문의 폼을 수천 건씩 제출할 수 있다.
21+
22+
## CORS만으로는 부족하다
23+
24+
가장 먼저 떠오르는 건 CORS 설정이다.
25+
26+
```
27+
Access-Control-Allow-Origin: https://mysite.com
28+
```
29+
30+
이렇게 하면 다른 도메인에서 브라우저로 요청하는 건 막을 수 있다. 근데 CORS는 **브라우저 정책**이다. curl이나 Postman, 서버 사이드 스크립트에서 보내는 요청은 CORS 제한을 안 받는다.
31+
32+
결국 CORS는 보안 수단이 아니라 편의 수단이다. 있어야 하지만 이것만으로는 안 된다.
33+
34+
## 현실적인 방어 전략
35+
36+
여러 방법을 조합해서 써야 한다.
37+
38+
**1. API Key + HMAC 서명**
39+
40+
프론트엔드에서 요청할 때 타임스탬프와 함께 HMAC 서명을 생성해서 보낸다. 서버에서 같은 방식으로 서명을 검증한다. 키가 소스 코드에 노출되는 문제가 있지만, 난독화와 조합하면 캐주얼한 공격은 막을 수 있다.
41+
42+
**2. Rate Limiting**
43+
44+
같은 IP에서 일정 횟수 이상 요청이 오면 차단한다. API Gateway나 Nginx 레벨에서 설정할 수 있다.
45+
46+
```
47+
# Nginx rate limiting
48+
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/m;
49+
50+
location /api/contact {
51+
limit_req zone=api burst=2 nodelay;
52+
}
53+
```
54+
55+
문의 폼이 분당 5건 이상 필요한 경우는 없으니까 이 정도면 스크립트 공격은 막을 수 있다.
56+
57+
**3. CAPTCHA**
58+
59+
reCAPTCHA나 hCaptcha를 폼에 붙인다. 봇이 자동으로 제출하는 걸 막는 가장 확실한 방법이다. 근데 사용자 경험이 나빠지는 단점이 있다.
60+
61+
**4. Honeypot 필드**
62+
63+
폼에 CSS로 숨긴 입력 필드를 추가한다. 사람은 이 필드를 안 보니까 안 채우지만, 봇은 모든 필드를 채우려고 한다. 이 필드에 값이 있으면 봇으로 판단해서 거부한다.
64+
65+
```html
66+
<input type="text" name="website" style="display:none" tabindex="-1">
67+
```
68+
69+
단순하지만 의외로 효과적이다.
70+
71+
**5. 일회용 토큰**
72+
73+
페이지 로드 시 서버에서 일회용 토큰을 발급하고, API 요청 시 이 토큰을 함께 보낸다. 한 번 사용된 토큰은 폐기된다. CSRF 방어와 비슷한 원리다.
74+
75+
## 내가 선택한 조합
76+
77+
결론적으로 내가 적용한 건 이 조합이다.
78+
79+
1. **Rate Limiting** (기본 방어)
80+
2. **Honeypot 필드** (봇 방어)
81+
3. **일회용 토큰** (재사용 방지)
82+
4. **CORS** (기본 설정)
83+
84+
CAPTCHA는 UX 영향이 커서 뺐다. 이 정도면 완벽하진 않지만, 로그인 없는 환경에서 현실적으로 가능한 수준의 보안은 확보된다.
85+
86+
100% 완벽한 보안은 없다. 결국 "공격 비용을 올려서 귀찮게 만드는" 게 핵심이다.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
layout: post
3+
title: "Running LLMs Locally With Ollama - It Depends on the Use Case"
4+
date: 2025-02-15 09:00:00 +0900
5+
categories: [Development, AI]
6+
tags: [Ollama, LLM, Local AI, Llama, Offline]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "I wanted to run LLMs locally so I set up Ollama. Surprisingly easy to get running, but the gap with cloud APIs is clear when you need real capability."
10+
---
11+
12+
# Running LLMs Locally With Ollama
13+
14+
## Why Run AI Locally?
15+
16+
Using cloud services like ChatGPT and Claude, there's always one nagging concern: sending my code to external servers.
17+
18+
Personal projects, fine. But working with client code or company-confidential material? That's uncomfortable. "We don't use your data for training," they say. But still.
19+
20+
So I decided to try running LLMs locally. Ollama seemed like the simplest option for installation and model management.
21+
22+
## Setup Is Dead Simple
23+
24+
```bash
25+
# macOS
26+
brew install ollama
27+
28+
# Start the service
29+
ollama serve
30+
31+
# Download and run a model
32+
ollama run llama3.1
33+
```
34+
35+
That's it. Three lines and you have a local LLM running. No Docker configuration, no GPU driver hassle.
36+
37+
The model library is solid too. Llama 3.1, CodeLlama, Mistral, Gemma — open-source models downloadable with a single `ollama pull`.
38+
39+
## Real-World Usage
40+
41+
**Code assistance** — Tried CodeLlama. Simple function generation and code explanation work fine. But complex refactoring or architecture-level suggestions fall well short of GPT-4 or Claude.
42+
43+
**Document summarization** — Used Llama 3.1 for summarization. English documents came out decent. Non-English languages are noticeably weaker compared to cloud models.
44+
45+
**Speed** — Ran it on an M4 Mac Mini. 7B models have acceptable speed. But 70B-class models generate tokens too slowly to be practical. GPU memory is the bottleneck.
46+
47+
## My Conclusion
48+
49+
After trying various configurations, here's where I landed:
50+
51+
**Local LLM works well for:**
52+
- Security-sensitive environments (proprietary code, confidential documents)
53+
- Offline usage requirements
54+
- Simple repetitive tasks (format conversion, basic classification)
55+
- Reducing API costs
56+
57+
**Cloud LLM wins for:**
58+
- Complex reasoning tasks
59+
- Non-English language processing
60+
- Access to current knowledge
61+
- Long context handling
62+
63+
The conclusion is the predictable "it depends on the use case," but actually using both clarified exactly where that boundary sits. Local LLMs don't replace cloud LLMs — they complement them.
64+
65+
For daily work, Claude and GPT remain the primary tools, with Ollama reserved for security-sensitive tasks. Open-source models are improving rapidly, so this could change — but that's where things stand today.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
layout: post
3+
title: "OllamaでローカルLLMを動かしてみた感想 - 結論は用途次第"
4+
date: 2025-02-15 09:00:00 +0900
5+
categories: [Development, AI]
6+
tags: [Ollama, LLM, ローカルAI, Llama, オフライン]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "ローカルでLLMを動かしたくてOllamaを導入しました。思ったより簡単に動きますが、クラウドAPIと比べると限界は明確です。"
10+
---
11+
12+
# OllamaでローカルLLMを動かしてみた
13+
14+
## ローカルでAIを動かしたかった
15+
16+
ChatGPTやClaudeのようなクラウドサービスを使っていると、一つ気になることがあります。自分のコードを外部サーバーに送らなければならないことです。
17+
18+
個人プロジェクトなら構いませんが、クライアントのコードや会社の機密が含まれる作業をする時はちょっと不安です。「データを学習に使用しません」と言われても、やはり。
19+
20+
そこでローカルでLLMを動かしてみることにしました。Ollamaがインストールも簡単でモデル管理も楽だと聞いて選びました。
21+
22+
## セットアップは本当に簡単
23+
24+
```bash
25+
# macOS
26+
brew install ollama
27+
28+
# サービス開始
29+
ollama serve
30+
31+
# モデルダウンロードと実行
32+
ollama run llama3.1
33+
```
34+
35+
これだけです。本当に3行でローカルLLMが動きます。Dockerの設定もGPUドライバも何も必要ありません。
36+
37+
モデルも豊富です。Llama 3.1、CodeLlama、Mistral、Gemmaなどのオープンソースモデルを`ollama pull`一行でダウンロードできます。
38+
39+
## 実際の使用感
40+
41+
**コード作成補助** — CodeLlamaを試しました。簡単な関数作成やコード説明は大丈夫ですが、複雑なリファクタリングやアーキテクチャレベルの提案はGPT-4やClaudeに比べるとかなり劣ります。
42+
43+
**ドキュメント要約** — Llama 3.1でドキュメント要約をさせてみました。英語のドキュメントはまあまあですが、日本語はまだ弱いです。日本語の理解力がクラウドモデルに比べて明らかに劣ります。
44+
45+
**速度** — M4 Mac Miniで動かしましたが、7Bモデルは体感速度が悪くありません。でも70B級モデルはトークン生成速度が遅すぎて実用的ではありません。GPUメモリが鍵です。
46+
47+
## 自分なりの結論
48+
49+
いろいろ試してみて出した結論はこうです。
50+
51+
**ローカルLLMが適しているケース:**
52+
- セキュリティが重要な環境(コード、機密文書)
53+
- オフライン環境で使う必要がある時
54+
- 単純な繰り返し作業(フォーマット変換、簡単な分類など)
55+
- APIコストを節約したい時
56+
57+
**クラウドLLMの方が良いケース:**
58+
- 複雑な推論が必要な時
59+
- 日本語処理
60+
- 最新の知識が必要な時
61+
- 長いコンテキストを扱う時
62+
63+
結局「用途次第」というありきたりな結論ですが、実際に使ってみるとこの「用途」の境界が明確になりました。ローカルLLMはクラウドを代替するのではなく、補完する関係なのです。
64+
65+
業務用にはまだClaudeやGPTをメインで使いつつ、セキュリティが必要な作業でのみOllamaを使うのが現実的だと思います。オープンソースモデルが急速に発展しているので、今後は変わるかもしれませんが。

0 commit comments

Comments
 (0)