
PHP ์จ๋ผ์ธ ๊ฐ์
>PHP - ๊ณ ๊ธ
๐ PHP ๊ณ ๊ธ - 5์ฃผ์ฐจ: RESTful API ๋ณด์ ๋ฐ ์ธ์ฆ - 03 API ์์ฒญ ์ ํ (Rate Limiting)
![]() |
ํ์ | 10.0 | ๋ผ์ด์ผ์ค | free |
---|---|---|---|---|
์ฌ์ฉ์ํ์ | 10.0 | ์ด์์ฒด์ | ||
๋ค์ด๋ก๋ | 1 | ํ์ผํฌ๊ธฐ | 0 | |
์ ์์ฌ | LUZENSOFT | ๋ฑ๋ก์ผ | 2025-09-14 16:09:03 | |
์กฐํ์ | 1 |
API ์์ฒญ ์ ํ (Rate Limiting)์ด๋?
#API์์ฒญ์ ํ (#RateLimiting)์ ํน์ ๊ธฐ๊ฐ ๋์ ์ฌ์ฉ์๊ฐ API์ ๋ณด๋ผ ์ ์๋ ์์ฒญ์ ์๋ฅผ ์ ํํ๋ ๊ธฐ์ ์ด๋ค. ์ด๋ API ์๋ฒ๋ฅผ ๊ณผ๋ํ ๋ถํ๋ก๋ถํฐ ๋ณดํธํ๊ณ , ์๋น์ค์ ์์ ์ฑ์ ์ ์งํ๋ฉฐ, ์ ์์ ์ธ ๊ณต๊ฒฉ(์: #DDoS๊ณต๊ฒฉ)์ ๋ฐฉ์ดํ๋ ๋ฐ ํ์์ ์ธ ๋ณด์ ์กฐ์น์ด๋ค.
API ์์ฒญ ์ ํ์ด ํ์ํ ์ด์
์๋ฒ ๋ณดํธ: ๋ฌด๋ถ๋ณํ ์์ฒญ์ผ๋ก ์ธํด ์๋ฒ์ ๊ณผ๋ถํ๊ฐ ๊ฑธ๋ ค ์๋น์ค๊ฐ ๋ง๋น๋๋ ๊ฒ์ ๋ง๋๋ค.
๋น์ฉ ์ ๊ฐ: API ์ฌ์ฉ๋์ ๋ฐ๋ผ ๊ณผ๊ธ๋๋ ๊ฒฝ์ฐ, ์๋์น ์์ ๋น์ฉ ํญํ์ ๋ง์์ค๋ค.
๊ณต์ ์ฑ ๋ณด์ฅ: ๋ชจ๋ ์ฌ์ฉ์๊ฐ API๋ฅผ ๊ณต์ ํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋ณด์ฅํ๋ค.
๋ณด์ ๊ฐํ: ๋ฌด์ฐจ๋ณ ๋์ ๊ณต๊ฒฉ(Brute-force attack)์ด๋ DDoS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ์์คํ ์ ๋ณดํธํ๋ค.
API ์์ฒญ ์ ํ์ ๊ตฌํ ๋ฐฉ๋ฒ
API ์์ฒญ ์ ํ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์๋ค. ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก๋ ํ ํฐ ๋ฒํท ์๊ณ ๋ฆฌ์ฆ, ๊ณ ์ ์๋์ฐ ์๊ณ ๋ฆฌ์ฆ, ์ฌ๋ผ์ด๋ฉ ์๋์ฐ ์๊ณ ๋ฆฌ์ฆ ๋ฑ์ด ์๋ค. ์ฌ๊ธฐ์๋ PHP์์ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ์ดํด๋ณธ๋ค.
1. ์นด์ดํฐ ๊ธฐ๋ฐ ์์ฒญ ์ ํ (Counter-based Rate Limiting)
๊ฐ์ฅ ๋จ์ํ ๋ฐฉ๋ฒ์ผ๋ก, ํน์ ๊ธฐ๊ฐ(์: 1๋ถ) ๋์ ์ฌ์ฉ์(IP ์ฃผ์ ๋๋ API ํค)์ ์์ฒญ ํ์๋ฅผ ์นด์ดํธํ๊ณ , ๋ฏธ๋ฆฌ ์ค์ ๋ ํ๋๋ฅผ ์ด๊ณผํ๋ฉด ์์ฒญ์ ๊ฑฐ๋ถํ๋ ๋ฐฉ์์ด๋ค.
PHP์์ ๊ตฌํ ์์
์ด ์์ ์์๋ ์ฌ์ฉ์์ #IP์ฃผ์ ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฒญ ํ์๋ฅผ ์ ํํ๋ค. Redis
๋ #ํ์ผ ์์คํ
์ ์ฌ์ฉํ์ฌ ์์ฒญ ์นด์ดํฐ๋ฅผ ์ ์ฅํ ์ ์๋ค. ์ฌ๊ธฐ์๋ ๊ฐ๋จํ๊ฒ ํ์ผ ์์คํ
์ ์ฌ์ฉํ ์์ ๋ฅผ ์ ์ํ๋ค.
PHP
<?php
// ์์ฒญ ์ ํ ์ค์
$limit = 10; // ๋ถ๋น 10ํ ์์ฒญ ์ ํ
$time_window = 60; // 60์ด (1๋ถ)
// ์ฌ์ฉ์ ์๋ณ (์ฌ๊ธฐ์๋ IP ์ฃผ์ ์ฌ์ฉ)
$user_identifier = $_SERVER['REMOTE_ADDR'];
// ์์ฒญ ์ ๋ณด ์ ์ฅ ๊ฒฝ๋ก
$log_file = 'rate_limit_' . md5($user_identifier) . '.log';
// ํ์ฌ ์๊ฐ
$current_time = time();
// ๊ธฐ์กด ์์ฒญ ์ ๋ณด ๋ถ๋ฌ์ค๊ธฐ
$requests = [];
if (file_exists($log_file)) {
$requests = json_decode(file_get_contents($log_file), true);
}
// ์๋์ฐ ๋ฐ์ ์ค๋๋ ์์ฒญ ์ ๊ฑฐ
$requests_in_window = array_filter($requests, function($timestamp) use ($current_time, $time_window) {
return ($current_time - $timestamp) < $time_window;
});
// ํ์ฌ ์์ฒญ ์ถ๊ฐ
$requests_in_window[] = $current_time;
// ์์ฒญ ํ์ ํ์ธ
if (count($requests_in_window) > $limit) {
// ์์ฒญ ํ์ ์ด๊ณผ
header('HTTP/1.1 429 Too Many Requests');
header('Content-Type: application/json');
echo json_encode(['error' => 'Rate limit exceeded. Please try again later.']);
exit();
}
// ์
๋ฐ์ดํธ๋ ์์ฒญ ์ ๋ณด ์ ์ฅ
file_put_contents($log_file, json_encode($requests_in_window));
// API ๋ก์ง ์คํ
// ...
// ์์ ์๋ต
header('Content-Type: application/json');
echo json_encode(['message' => 'API call successful.']);
?>
2. HTTP ์๋ต ํค๋
API ์์ฒญ ์ ํ์ ๊ตฌํํ ๋, ํด๋ผ์ด์ธํธ์๊ฒ ํ์ฌ ์ํ๋ฅผ ์๋ ค์ฃผ๋ ๊ฒ์ด ์ค์ํ๋ค. ์ด๋ฅผ ์ํด ๋ค์๊ณผ ๊ฐ์ HTTP ํค๋๋ฅผ ์ฌ์ฉํ๋ค.
X-RateLimit-Limit
: ํ์ฉ๋ ์์ฒญ์ ์ต๋ ํ์.X-RateLimit-Remaining
: ๋จ์ ์์ฒญ ํ์.X-RateLimit-Reset
: ์ ํ์ด ์ด๊ธฐํ๋๋ ์๊ฐ (UNIX ํ์์คํฌํ).
์ด ํค๋๋ค์ ์๋ต์ ํฌํจ์์ผ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ์กฐ์ ํ ์ ์๋๋ก ์ ๋ํด์ผ ํ๋ค.
์์ฝ
#API์์ฒญ์ ํ ์ ์๋ฒ์ ์์ ์ฑ๊ณผ ๋ณด์์ ์ํด ํ์์ ์ธ ๊ธฐ์ ์ด๋ค. #PHP ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ #์์ฒญ์ ํ ๋ก์ง์ ๊ตฌํํ ์ ์์ผ๋ฉฐ, ํด๋ผ์ด์ธํธ ์นํ์ ์ธ API๋ฅผ ๋ง๋ค๊ธฐ ์ํด #HTTPํค๋ ๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํด์ผ ํ๋ค. ๋ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ #Redis ์ ๊ฐ์ ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ค.
API์์ฒญ์ ํ RateLimiting DDoS๊ณต๊ฒฉ IP์ฃผ์ ํ์ผ ์์คํ HTTPํค๋ PHP ์์ฒญ์ ํ Redis
์ ํ๋ธ/์ธ์คํ๊ทธ๋จ ์กฐํ ์ ํจ KT์์ดํผ, ์ผํ ํฌ๋กค๋ง, ์ง์ญ๋ณ ๋ค๋์ญ IP๋ณด์
https://xn--299ao67b9qbmsf04c.net/