๐Ÿ” Spring Boot + React๋กœ ๋งŒ๋“œ๋Š” API ๋ชจ๋‹ˆํ„ฐ๋ง & ์•Œ๋ฆผ ์‹œ์Šคํ…œ (MVP)

Nolrimboยท2025๋…„ 9์›” 4์ผ

ํฌํŠธํด๋ฆฌ์˜ค

๋ชฉ๋ก ๋ณด๊ธฐ
11/21

HTTP/HTTPS ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ฒดํฌํ•ด์„œ ๊ฐ€์šฉ์„ฑ/์†๋„๋ฅผ ๊ธฐ๋กํ•˜๊ณ , ์—ฐ์† ์‹คํŒจ ์‹œ Slack์œผ๋กœ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋Š” ๊ฒฝ๋Ÿ‰ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
Spring Boot + MariaDB + React ๊ธฐ๋ฐ˜์ด๋ฉฐ, ๋Œ€์‹œ๋ณด๋“œ๋กœ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.


TL;DR

  • ๋ชจ๋‹ˆํ„ฐ ๋“ฑ๋ก โ†’ ์ฃผ๊ธฐ์  ์ฒดํฌ โ†’ ๊ฒฐ๊ณผ ๊ธฐ๋ก โ†’ ์—ฐ์† ์‹คํŒจ ์‹œ Incident ์˜คํ”ˆ & Slack ์•Œ๋ฆผ โ†’ ์„ฑ๊ณต 1ํšŒ ์‹œ ์ž๋™ ์ข…๋ฃŒ
  • ๋ฐฑ์—”๋“œ: Spring Boot(WebFlux WebClient), JPA, Swagger
  • ํ”„๋ก ํŠธ: React + Vite + TS, Recharts
  • DB: MariaDB

๐Ÿงญ ์™œ ๋งŒ๋“ค์—ˆ๋‚˜

  • ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ/๊ฐœ์ธ ์„œ๋ฒ„/์†Œ๊ทœ๋ชจ ์„œ๋น„์Šค์—์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ API ํ—ฌ์Šค ์ฒดํฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์šฉ ์†”๋ฃจ์…˜์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๊ฐ€๋ณ๊ฒŒ ์‹œ์ž‘ํ•  MVP๊ฐ€ ํ•„์š”ํ–ˆ์–ด์š”.
  • ๊ทธ๋ž˜์„œ ๋“ฑ๋กโ†’์ฒดํฌโ†’์•Œ๋ฆผ ํ•ต์‹ฌ ์‚ฌ์ดํด๋งŒ ์™ ๋ฝ‘์•„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

โœจ ๊ธฐ๋Šฅ ์š”์•ฝ (MVP)

  • ๋ชจ๋‹ˆํ„ฐ: URL, Method, ์ฃผ๊ธฐ, ํƒ€์ž„์•„์›ƒ, ๊ธฐ๋Œ€ ์ƒํƒœ์ฝ”๋“œ ๋ฒ”์œ„, ์—ฐ์† ์‹คํŒจ ์ž„๊ณ„์น˜
  • ์ฒดํฌ: ์‘๋‹ต ์ฝ”๋“œ, ์ง€์—ฐ(ms), ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๊ธฐ๋ก
  • Incident: ์—ฐ์† ์‹คํŒจ ์‹œ Open, ์„ฑ๊ณต ์‹œ Close
  • ์•Œ๋ฆผ: Slack Webhook
  • ๋Œ€์‹œ๋ณด๋“œ: ์ตœ๊ทผ ์ƒํƒœ, ์ŠคํŒŒํฌ๋ผ์ธ(latency), Open Incidents

๐Ÿ› ์•„ํ‚คํ…์ฒ˜

[React Dashboard] --Axios--> [Spring Boot API]
โ”‚
[Scheduler 60s / WebClient]
โ”‚
[MariaDB ์ €์žฅ]
โ”‚
[Slack ์•Œ๋ฆผ]

โš™๏ธ ๋กœ์ปฌ ์‹คํ–‰ (์š”์•ฝ)

Backend

# MariaDB ์ƒ์„ฑ/๊ถŒํ•œ โ†’ application.properties ์„ค์ •
./gradlew bootRun
# Swagger: http://localhost:8080/swagger-ui/index.html

Frontend

cd frontend
npm i
npm run dev
# http://localhost:5173

Slack Webhook ๋“ฑ๋ก

POST /api/integrations
{
  "type": "SLACK_WEBHOOK",
  "name": "Main Slack",
  "webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}

๋ชจ๋‹ˆํ„ฐ ๋งŒ๋“ค๊ธฐ(๋น ๋ฅธ ํ…Œ์ŠคํŠธ)

POST /api/monitors
{
  "name": "httpstat.us 503",
  "url": "https://httpstat.us/503",
  "method": "GET",
  "intervalSeconds": 30,
  "timeoutMs": 2000,
  "expectedStatusFrom": 200,
  "expectedStatusTo": 399,
  "latencyThresholdMs": 1500,
  "alertConsecutiveFailures": 1
}

1~2๋ถ„ ๋‚ด /results์— ๊ธฐ๋ก์ด ์Œ“์ด๊ณ , ์ž„๊ณ„์น˜์— ๋„๋‹ฌํ•˜๋ฉด Slack์œผ๋กœ Incident ์•Œ๋ฆผ์ด ์˜ต๋‹ˆ๋‹ค.


๐Ÿงฉ ๊ตฌํ˜„ ํฌ์ธํŠธ

1) ๋™์  ์Šค์ผ€์ค„๋ง

  • DB์˜ next_check_at ์„ ๊ธฐ์ค€์œผ๋กœ Due ๋Œ€์ƒ๋งŒ ์‹คํ–‰
  • ์ฒดํฌ ํ›„ next_check_at = now + intervalSeconds

2) ์ฒดํฌ & ํŒ์ •

  • WebClient + Reactor Netty๋กœ ์—ฐ๊ฒฐ/์ฝ๊ธฐ/์“ฐ๊ธฐ ํƒ€์ž„์•„์›ƒ
  • status in [expected_from..expected_to] โ‡’ ์„ฑ๊ณต
  • ์˜ˆ์™ธ/ํƒ€์ž„์•„์›ƒ/DNS/SSL ์˜ค๋ฅ˜๋Š” ์‹คํŒจ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ €์žฅ

3) Incident & ์•Œ๋ฆผ

  • ์—ฐ์† ์‹คํŒจ ํšŸ์ˆ˜๊ฐ€ ์ž„๊ณ„์น˜ ๋„๋‹ฌ ์‹œ Incident ์˜คํ”ˆ
  • Slack Webhook์œผ๋กœ ์•Œ๋ฆผ(์ตœ์ดˆ 1ํšŒ)
  • ๋‹ค์Œ ์„ฑ๊ณต 1ํšŒ ์‹œ Incident Close

4) ๋Œ€์‹œ๋ณด๋“œ

  • ๋ชจ๋‹ˆํ„ฐ ์นด๋“œ: ์ตœ๊ทผ ์ƒํƒœ/์ŠคํŒŒํฌ๋ผ์ธ
  • Open Incidents ํ…Œ์ด๋ธ”
  • Integrations: Slack Webhook ๋“ฑ๋ก

๐Ÿงช ์Šคํฌ๋ฆฐ์ƒท/๋ฐ๋ชจ


๐Ÿงญ ๋‹ค์Œ์— ํ•  ์ผ(์•„์ด๋””์–ด)

  • ๋ณธ๋ฌธ ํ‚ค์›Œ๋“œ/JSONPath ์–ด์„ค์…˜
  • ์žฌ์•Œ๋ฆผ ์ฟจ๋‹ค์šด, ํ”Œ๋ž˜ํ•‘ ์–ต์ œ
  • 24h/7d ๊ฐ€์šฉ์„ฑ% / p95 ์ง€์—ฐ ๋กค์—…
  • Kakao Biz/Email ์•Œ๋ฆผ ์–ด๋Œ‘ํ„ฐ
  • JWT / ๋ฉ€ํ‹ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค

โœ… ์ฐธ๊ณ 

profile
Java ๊ฐœ๋ฐœ์ž | ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ ๋งˆ๋‹ˆ์•„ | GPT ๊ธฐ๋ฐ˜ ์ž๋™ํ™” ํˆด ์—ฐ๊ตฌ ์ค‘ ๊ธฐ์ˆ  ๋ฆฌ๋ทฐ, ๊ฐœ๋ฐœ์ผ์ง€

0๊ฐœ์˜ ๋Œ“๊ธ€