Skip to content

Commit 3b32b4b

Browse files
docs(blog): 10차 배치 팁 포스트 5개 추가 (3개 언어)
1 parent 4e0e10b commit 3b32b4b

15 files changed

Lines changed: 1122 additions & 0 deletions
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
layout: post
3+
title: "Handling Fetch Timeouts with Node.js AbortController"
4+
date: 2026-02-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Node.js, AbortController, fetch, timeout]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "A clean pattern for adding timeouts to fetch requests using AbortController in Node.js."
10+
---
11+
12+
## Problem
13+
14+
When calling external APIs, requests can hang indefinitely if the server doesn't respond. A slow or failing third-party API takes your service down with it. The `setTimeout` + `Promise.race` workaround results in messy code.
15+
16+
## Solution
17+
18+
`AbortController` provides a clean way to add timeouts to fetch requests.
19+
20+
```javascript
21+
async function fetchWithTimeout(url, timeoutMs = 5000) {
22+
const controller = new AbortController();
23+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
24+
25+
try {
26+
const response = await fetch(url, { signal: controller.signal });
27+
return await response.json();
28+
} catch (error) {
29+
if (error.name === 'AbortError') {
30+
throw new Error(`Request timed out after ${timeoutMs}ms`);
31+
}
32+
throw error;
33+
} finally {
34+
clearTimeout(timeoutId);
35+
}
36+
}
37+
38+
// Usage
39+
const data = await fetchWithTimeout('https://api.example.com/users', 3000);
40+
```
41+
42+
Node.js 20+ offers an even simpler approach with `AbortSignal.timeout()`:
43+
44+
```javascript
45+
// One line is all you need
46+
const response = await fetch('https://api.example.com/users', {
47+
signal: AbortSignal.timeout(3000),
48+
});
49+
```
50+
51+
Cancelling multiple requests at once is also straightforward:
52+
53+
```javascript
54+
async function fetchMultiple(urls) {
55+
const controller = new AbortController();
56+
const timeout = setTimeout(() => controller.abort(), 5000);
57+
58+
try {
59+
const results = await Promise.all(
60+
urls.map((url) =>
61+
fetch(url, { signal: controller.signal }).then((r) => r.json())
62+
)
63+
);
64+
return results;
65+
} catch (error) {
66+
controller.abort(); // Cancel all remaining requests if one fails
67+
throw error;
68+
} finally {
69+
clearTimeout(timeout);
70+
}
71+
}
72+
```
73+
74+
## Key Points
75+
76+
- `AbortController` works with more than fetch — it's supported by `addEventListener`, `ReadableStream`, and more
77+
- `AbortSignal.timeout()` (Node.js 20+) requires no manual cleanup, eliminating memory leak concerns
78+
- A single controller can cancel multiple requests simultaneously, making it ideal for parallel request management
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
layout: post
3+
title: "Node.js AbortControllerでfetchのタイムアウトを処理する方法"
4+
date: 2026-02-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Node.js, AbortController, fetch, timeout]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "Node.jsでAbortControllerを活用して、fetchリクエストにタイムアウトを設定するクリーンなパターンをご紹介します。"
10+
---
11+
12+
## 問題
13+
14+
外部APIを呼び出す際、レスポンスが返ってこないとリクエストが永遠に待機してしまう問題がありました。サードパーティAPIが遅くなったり障害が発生すると、自分たちのサービスまで一緒に止まってしまいます。`setTimeout` + `Promise.race`の組み合わせで解決しようとすると、コードが煩雑になります。
15+
16+
## 解決方法
17+
18+
`AbortController`を使えば、fetchリクエストにタイムアウトをクリーンに設定できます。
19+
20+
```javascript
21+
async function fetchWithTimeout(url, timeoutMs = 5000) {
22+
const controller = new AbortController();
23+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
24+
25+
try {
26+
const response = await fetch(url, { signal: controller.signal });
27+
return await response.json();
28+
} catch (error) {
29+
if (error.name === 'AbortError') {
30+
throw new Error(`Request timed out after ${timeoutMs}ms`);
31+
}
32+
throw error;
33+
} finally {
34+
clearTimeout(timeoutId);
35+
}
36+
}
37+
38+
// 使用例
39+
const data = await fetchWithTimeout('https://api.example.com/users', 3000);
40+
```
41+
42+
Node.js 20+では`AbortSignal.timeout()`でさらに簡単に書けます:
43+
44+
```javascript
45+
// 一行で完結
46+
const response = await fetch('https://api.example.com/users', {
47+
signal: AbortSignal.timeout(3000),
48+
});
49+
```
50+
51+
複数のリクエストを一括でキャンセルするパターンも便利です:
52+
53+
```javascript
54+
async function fetchMultiple(urls) {
55+
const controller = new AbortController();
56+
const timeout = setTimeout(() => controller.abort(), 5000);
57+
58+
try {
59+
const results = await Promise.all(
60+
urls.map((url) =>
61+
fetch(url, { signal: controller.signal }).then((r) => r.json())
62+
)
63+
);
64+
return results;
65+
} catch (error) {
66+
controller.abort(); // 一つでも失敗したら残りを全てキャンセル
67+
throw error;
68+
} finally {
69+
clearTimeout(timeout);
70+
}
71+
}
72+
```
73+
74+
## ポイント
75+
76+
- `AbortController`はfetchだけでなく、`addEventListener``ReadableStream`などでも使用できます
77+
- `AbortSignal.timeout()`はNode.js 20+でサポートされており、手動のクリーンアップが不要なのでメモリリークの心配がありません
78+
- 一つのcontrollerで複数のリクエストを同時にキャンセルできるので、並行リクエストの管理に最適です
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
layout: post
3+
title: "Node.js AbortController로 fetch 타임아웃 처리하기"
4+
date: 2026-02-02 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [Node.js, AbortController, fetch, timeout]
7+
author: "Kevin Park"
8+
lang: ko
9+
excerpt: "Node.js에서 AbortController를 활용해 fetch 요청에 타임아웃을 거는 깔끔한 패턴을 정리했다."
10+
---
11+
12+
## 문제
13+
14+
외부 API를 호출할 때 응답이 안 오면 요청이 영원히 대기하는 문제가 있었다. 서드파티 API가 느려지거나 장애가 나면 우리 서비스까지 같이 멈추는 거다. `setTimeout` + Promise.race 조합으로 해결하려니 코드가 지저분해졌다.
15+
16+
## 해결
17+
18+
`AbortController`를 쓰면 fetch 요청에 타임아웃을 깔끔하게 걸 수 있다.
19+
20+
```javascript
21+
async function fetchWithTimeout(url, timeoutMs = 5000) {
22+
const controller = new AbortController();
23+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
24+
25+
try {
26+
const response = await fetch(url, { signal: controller.signal });
27+
return await response.json();
28+
} catch (error) {
29+
if (error.name === 'AbortError') {
30+
throw new Error(`Request timed out after ${timeoutMs}ms`);
31+
}
32+
throw error;
33+
} finally {
34+
clearTimeout(timeoutId);
35+
}
36+
}
37+
38+
// 사용
39+
const data = await fetchWithTimeout('https://api.example.com/users', 3000);
40+
```
41+
42+
Node.js 20+에서는 `AbortSignal.timeout()`으로 더 간단하게 쓸 수 있다:
43+
44+
```javascript
45+
// 한 줄이면 끝
46+
const response = await fetch('https://api.example.com/users', {
47+
signal: AbortSignal.timeout(3000),
48+
});
49+
```
50+
51+
여러 요청을 한번에 취소하는 패턴도 유용하다:
52+
53+
```javascript
54+
async function fetchMultiple(urls) {
55+
const controller = new AbortController();
56+
const timeout = setTimeout(() => controller.abort(), 5000);
57+
58+
try {
59+
const results = await Promise.all(
60+
urls.map((url) =>
61+
fetch(url, { signal: controller.signal }).then((r) => r.json())
62+
)
63+
);
64+
return results;
65+
} catch (error) {
66+
controller.abort(); // 하나라도 실패하면 나머지 전부 취소
67+
throw error;
68+
} finally {
69+
clearTimeout(timeout);
70+
}
71+
}
72+
```
73+
74+
## 핵심 포인트
75+
76+
- `AbortController`는 fetch뿐 아니라 `addEventListener`, `ReadableStream` 등에서도 쓸 수 있다
77+
- `AbortSignal.timeout()`은 Node.js 20+에서 지원하고, 별도 cleanup이 필요 없어서 메모리 누수 걱정이 없다
78+
- 하나의 controller로 여러 요청을 동시에 취소할 수 있어서 병렬 요청 관리에 딱이다
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
layout: post
3+
title: "Array Grouping in One Line with Object.groupBy"
4+
date: 2026-02-03 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, Object.groupBy, array, ES2024]
7+
author: "Kevin Park"
8+
lang: en
9+
excerpt: "Stop writing reduce boilerplate for grouping arrays. Object.groupBy does it in one line."
10+
---
11+
12+
## Problem
13+
14+
Every time you needed to group an array by some criteria, you had to write a `reduce` with initial value setup, key existence checks, and array pushes. A simple grouping operation shouldn't require 5+ lines of code.
15+
16+
```javascript
17+
// The old way
18+
const grouped = items.reduce((acc, item) => {
19+
const key = item.category;
20+
if (!acc[key]) acc[key] = [];
21+
acc[key].push(item);
22+
return acc;
23+
}, {});
24+
```
25+
26+
## Solution
27+
28+
ES2024's `Object.groupBy` does it in one line.
29+
30+
```javascript
31+
const items = [
32+
{ name: 'Apple', category: 'fruit' },
33+
{ name: 'Carrot', category: 'vegetable' },
34+
{ name: 'Banana', category: 'fruit' },
35+
{ name: 'Spinach', category: 'vegetable' },
36+
];
37+
38+
const grouped = Object.groupBy(items, (item) => item.category);
39+
// {
40+
// fruit: [{ name: 'Apple', ... }, { name: 'Banana', ... }],
41+
// vegetable: [{ name: 'Carrot', ... }, { name: 'Spinach', ... }]
42+
// }
43+
```
44+
45+
Common real-world patterns:
46+
47+
```javascript
48+
// Group orders by status
49+
const orders = [
50+
{ id: 1, status: 'pending' },
51+
{ id: 2, status: 'shipped' },
52+
{ id: 3, status: 'pending' },
53+
];
54+
const byStatus = Object.groupBy(orders, (o) => o.status);
55+
56+
// Group logs by date
57+
const logs = [
58+
{ msg: 'error', date: '2026-03-14' },
59+
{ msg: 'info', date: '2026-03-14' },
60+
{ msg: 'warn', date: '2026-03-13' },
61+
];
62+
const byDate = Object.groupBy(logs, (log) => log.date);
63+
64+
// Conditional grouping
65+
const users = [
66+
{ name: 'Kim', age: 25 },
67+
{ name: 'Lee', age: 17 },
68+
];
69+
const byAge = Object.groupBy(users, (u) => u.age >= 18 ? 'adult' : 'minor');
70+
```
71+
72+
## Key Points
73+
74+
- `Object.groupBy` returns a null-prototype object — no need for `hasOwnProperty` checks
75+
- Use `Map.groupBy` if you need symbol keys or non-string keys
76+
- Supported in Node.js 21+, Chrome 117+, Safari 17.4+. Use core-js polyfill for older browsers
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
layout: post
3+
title: "Object.groupByで配列グルーピングを一行で完結する"
4+
date: 2026-02-03 09:00:00 +0900
5+
categories: [Development, Tips]
6+
tags: [JavaScript, Object.groupBy, array, ES2024]
7+
author: "Kevin Park"
8+
lang: ja
9+
excerpt: "reduceで複雑にグルーピングする時代は終わりました。Object.groupBy一つで完結します。"
10+
---
11+
12+
## 問題
13+
14+
配列を特定の基準でグルーピングするたびに`reduce`を書く必要がありました。毎回初期値を設定し、キーの存在チェックをして、配列にpushして... 単純なグルーピングなのにコードが5行以上になるのは少し煩わしいものです。
15+
16+
```javascript
17+
// 毎回これを書いていました
18+
const grouped = items.reduce((acc, item) => {
19+
const key = item.category;
20+
if (!acc[key]) acc[key] = [];
21+
acc[key].push(item);
22+
return acc;
23+
}, {});
24+
```
25+
26+
## 解決方法
27+
28+
ES2024で追加された`Object.groupBy`を使えば一行で済みます。
29+
30+
```javascript
31+
const items = [
32+
{ name: 'りんご', category: '果物' },
33+
{ name: 'にんじん', category: '野菜' },
34+
{ name: 'バナナ', category: '果物' },
35+
{ name: 'ほうれん草', category: '野菜' },
36+
];
37+
38+
const grouped = Object.groupBy(items, (item) => item.category);
39+
// {
40+
// '果物': [{ name: 'りんご', ... }, { name: 'バナナ', ... }],
41+
// '野菜': [{ name: 'にんじん', ... }, { name: 'ほうれん草', ... }]
42+
// }
43+
```
44+
45+
実務でよく使うパターンです:
46+
47+
```javascript
48+
// ステータス別に注文を分類
49+
const orders = [
50+
{ id: 1, status: 'pending' },
51+
{ id: 2, status: 'shipped' },
52+
{ id: 3, status: 'pending' },
53+
];
54+
const byStatus = Object.groupBy(orders, (o) => o.status);
55+
56+
// 日付別にログをグルーピング
57+
const logs = [
58+
{ msg: 'error', date: '2026-03-14' },
59+
{ msg: 'info', date: '2026-03-14' },
60+
{ msg: 'warn', date: '2026-03-13' },
61+
];
62+
const byDate = Object.groupBy(logs, (log) => log.date);
63+
64+
// 条件付きグルーピング(成人/未成年)
65+
const users = [
66+
{ name: 'Kim', age: 25 },
67+
{ name: 'Lee', age: 17 },
68+
];
69+
const byAge = Object.groupBy(users, (u) => u.age >= 18 ? 'adult' : 'minor');
70+
```
71+
72+
## ポイント
73+
74+
- `Object.groupBy`はnullプロトタイプオブジェクトを返します。`hasOwnProperty`チェックは不要です
75+
- キーにシンボルを使いたい場合は`Map.groupBy`を使います
76+
- Node.js 21+、Chrome 117+、Safari 17.4+でサポートされています。古いブラウザにはcore-jsポリフィルで対応できます

0 commit comments

Comments
 (0)