diff --git a/README.md b/README.md
index 3d131475..6d4c631e 100644
--- a/README.md
+++ b/README.md
@@ -12,12 +12,12 @@
---
-## ๐ฏ Real Match๊ฐ ์ ๊ณตํ๋ ํต์ฌ ๊ธฐ๋ฅ
+## Real Match๊ฐ ์ ๊ณตํ๋ ํต์ฌ ๊ธฐ๋ฅ
-- ๐ **๋งค์นญ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ ์ถ์ฒ**
-- ๐ **๋งค์นญ ์ง๋จ ๋์๋ณด๋**
-- ๐
**ํ์
์ํ ์ถ์ ๋ฐ ์ผ์ ๊ด๋ฆฌ ๋ก์ง**
-- ๐ฌ **์ค์๊ฐ ์ปค๋ฎค๋์ผ์ด์
๋ฐ ์๋ฆผ ์์คํ
**
+- **๋งค์นญ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ ์ถ์ฒ**
+- **๋งค์นญ ์ง๋จ ๋์๋ณด๋**
+- **ํ์
์ํ ์ถ์ ๋ฐ ์ผ์ ๊ด๋ฆฌ ๋ก์ง**
+- **์ค์๊ฐ ์ปค๋ฎค๋์ผ์ด์
๋ฐ ์๋ฆผ ์์คํ
**
---
@@ -26,15 +26,15 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
๋จ์ ๋งค์นญ์ ๋์ด,
-> ๐ **๋ฐ์ดํฐ ๊ธฐ๋ฐ ๋ถ์ + ํ์
ํ๋ก์ธ์ค ํตํฉ ๊ด๋ฆฌ**
+> **ํ๊ทธ ๊ธฐ๋ฐ ๋งค์นญ + ์ฑํ
๊ธฐ๋ฐ ํ์ฝ ์งํ**
๋ฅผ ํตํด ๋ณด๋ค ์ ๊ตํ๊ณ ํจ์จ์ ์ธ ๋ธ๋๋ ๋ง์ผํ
ํ๊ฒฝ์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
-## ๐งฉ ์ฃผ์ ๊ธฐ๋ฅ
+## ์ฃผ์ ๊ธฐ๋ฅ
| ๊ธฐ๋ฅ | ์ค๋ช
|
|------------------|-----------------------------|
-| ๐ **๋งค์นญ ๊ฒ์ฌ** | ๋งค์นญ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ ๋ธ๋๋ ์ถ์ฒ |
+| ๐ **๋งค์นญ ๊ฒ์ฌ** | ๋งค์นญ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ ๋ธ๋๋ ๋ฐ ์บ ํ์ธ ์ถ์ฒ |
| ๐ **๋งค์นญ ์ง๋จ ๋์๋ณด๋** | ๋ธ๋๋ ยท ์ธํ๋ฃจ์ธ์๊ฐ์ ๋งค์นญ ํํฉ ๊ด๋ฆฌ |
| ๐ **ํ์
์ผ์ ๊ด๋ฆฌ** | ์ผ์ ๋ฐ ํ์
๊ด๋ฆฌ ์บ๋ฆฐ๋ |
| ๐ **์ค์๊ฐ ์ฑํ
๊ธฐ๋ฅ** | ๋ธ๋๋ยท์ธํ๋ฃจ์ธ์ ๊ฐ ์ค์๊ฐ ๋ฉ์์ง ๋ฐ ํ์ผ ๊ณต์ |
@@ -43,16 +43,16 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
| ๐ค **ํ์ ๊ด๋ฆฌ** | JWT ๊ธฐ๋ฐ ํ์๊ฐ์
/ ์์
๋ก๊ทธ์ธ |
| ๐ผ๏ธ **ํ๋กํ ๊ด๋ฆฌ** | ๋ง์ดํ์ด์ง์์ ํ๋กํ ๋ฐ ๊ด์ฌ์ฌ ์์ |
----
-## ๐ ์ํคํ
์ณ ๊ตฌ์กฐ
+
+## ์ํคํ
์ณ ๊ตฌ์กฐ

---
-## ๐ฉโ๐ป RealMatch Spring Developers
+## RealMatch Spring Developers
@@ -65,15 +65,7 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
-## ๐ฅ Detailed Responsibilities
-
-๐ฑ๏ธ ์ข์ฐ๋ก ์คํฌ๋กคํด์ ๋ด์ฉ์ ํ์ธํด์ฃผ์ธ์.
-
-
-
-
-
-
+## Detailed Responsibilities
### ๐จโ๐ป ๊ณ ๊ฒฝ์
**Backend Developer**
@@ -83,10 +75,6 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
- ์ฌ์ฉ์ ์ ๋ณด ๊ด๋ฆฌ ๋ฐ ๋ง์ดํ์ด์ง API ๊ตฌํ
- Role ๊ธฐ๋ฐ ์ ๊ทผ ์ ์ด ์ฒ๋ฆฌ
-
-
-
-
### ๐ฉโ๐ป ๋ฐ์ง์
**Backend Developer / API Lead**
@@ -96,10 +84,6 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
- ๋ธ๋๋-์บ ํ์ธ ์กฐํ ๋ฐ ์ข์์ ๊ธฐ๋ฅ ๊ตฌํ
- Docker ๊ธฐ๋ฐ CD ๊ตฌ์ถ ๋ฐ ์๋ฒ ๋ฐฐํฌ ์๋ํ
-
-
-
-
### ๐ฉโ๐ป ์ฌ์ฑํ
**Backend Developer**
@@ -108,10 +92,6 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
- RabbitMQ ๊ธฐ๋ฐ ๋น๋๊ธฐ ์๋ฆผ ์ด๋ฒคํธ ์ฒ๋ฆฌ
- Firebase ยท Email ์ฐ๋ ์๋ฆผ ์์คํ
๊ตฌํ
-
-
-
-
### ๐ฉโ๐จ ์ด์๋ฆผ
**Backend Developer**
@@ -119,10 +99,6 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
- ๋ธ๋๋ ๋ชฉ๋ก ยท ์์ธ ยท ์์ฝ ์กฐํ API ๊ฐ๋ฐ
- ๋ธ๋๋ ์ข์์ ํ ๊ธ ๋ฐ ํ์ฐฌ ์ ํ ์กฐํ ๊ธฐ๋ฅ ๊ตฌํ
-
-
-
-
### ๐จโ๐ป ์ ์ค์ฒ
**Backend Developer / Algorithm Lead**
@@ -130,38 +106,9 @@ Real Match๋ ์ ๊ธฐ๋ฅ์ ํตํฉ ์ ๊ณตํ์ฌ ๋ธ๋๋์ ์ธํ๋ฃจ์ธ์ ๊ฐ
- ๋งค์นญ ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ ์ถ์ฒ API ์ค๊ณ ๋ฐ ๊ตฌํ
- Redis ์บ์ฑ์ ํ์ฉํ ์กฐํ ์ฑ๋ฅ ๊ฐ์
- Docker ๊ธฐ๋ฐ ์๋ฒ ํ๊ฒฝ ๊ตฌ์ฑ ๋ฐ CI ์๋ํ ๊ตฌ์ถ
+- ์ฝ๋ ์ปจ๋ฒค์
๊ด๋ฆฌ
+- HAProxy๋ฅผ ์ด์ฉํ ์๋ฒ ๋ณด์ ๊ด๋ฆฌ
-
-
-
-
----
-
-## ๐ Project Structure
-
-```yml
-BE
-โโโ global (๊ณตํต ์ค์ , ์์ธ ์ฒ๋ฆฌ, ์ ํธ ๋ฑ)
-โโโ user
- โโโ presentation (์ธ๋ถ์์ ์ ์ )
- โ โโโ UserController.java
- โ โโโ dto (ํด๋น ๋๋ฉ์ธ ์ ์ฉ ๋ฐ์ดํฐ ์ ์ก ๊ฐ์ฒด)
- โ โโโ request
- โ โ โโโ UserRequest.java
- โ โโโ response
- โ โโโ UserResponse.java
- โโโ application (๋น์ฆ๋์ค ๋ก์ง์ ํ๋ฆ ์ ์ด)
- โ โโโ service
- โ โโโ UserService.java (Interface)
- โ โโโ UserServiceImpl.java
- โโโ domain (ํต์ฌ ๋น์ฆ๋์ค ๊ท์น ๋ฐ ์ํฐํฐ)
- โโโ entity
- โ โโโ UserEntity.java
- โโโ repository
- โโโ UserRepository.java
-
-```
----
## ๐ Tech Stack
@@ -178,16 +125,15 @@ BE
### Infra
- Docker / Docker Compose
-- AWS EC2
-- AWS RDS
+- Gabia Cloud
- AWS S3 / CloudFront
+- HAProxy
### Communication
- WebSocket (์ฑํ
)
- Firebase / Email (์๋ฆผ)
- RabbitMQ
----
## ๐ ์ฝ๋ ์ปจ๋ฒค์
diff --git a/haproxy/fail2ban-haproxy.conf b/haproxy/fail2ban-haproxy.conf
new file mode 100644
index 00000000..89d09b1f
--- /dev/null
+++ b/haproxy/fail2ban-haproxy.conf
@@ -0,0 +1,14 @@
+[Definition]
+
+# ๋ก๊ทธ ํ์: 2026-02-15T17:06:02.613Z IP:PORT [haproxy_date] frontend backend/server timers status ...
+# docker logs --timestamps ๊ฐ ISO8601 ํ์์คํฌํ๋ฅผ ์ค ์์์ ์ถ๊ฐ
+# fail2ban์ด ํ์์คํฌํ ์ ๊ฑฐ ํ ๊ณต๋ฐฑ์ด ๋จ์ผ๋ฏ๋ก ^\s* ์ฌ์ฉ
+
+# 403 ๊ฑฐ๋ถ (๋ธ๋๋ฆฌ์คํธ, ACL ๊ฑฐ๋ถ)
+# 429 Rate Limit ์ด๊ณผ
+# ์ทจ์ฝ์ ์ค์บ ํจํด (.php, cgi-bin, .env, wp-admin, .git, shell, passwd ๋ฑ)
+failregex = ^\s*:\d+\s+\[.*\]\s+\S+\s+\S+\s+\S+\s+403\s
+ ^\s*:\d+\s+\[.*\]\s+\S+\s+\S+\s+\S+\s+429\s
+ ^\s*:\d+\s+\[.*\]\s+\S+\s+\S+\s+\S+\s+\d+\s.*"(GET|POST|PUT|DELETE|HEAD|OPTIONS)\s+.*(\.php|cgi-bin|\.env|wp-admin|wp-login|\.git|shell|passwd|\.asp)
+
+ignoreregex =
diff --git a/haproxy/haproxy-log.service b/haproxy/haproxy-log.service
new file mode 100644
index 00000000..ea8969a9
--- /dev/null
+++ b/haproxy/haproxy-log.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Stream HAProxy Docker logs to file
+After=docker.service
+
+[Service]
+Type=simple
+ExecStart=/bin/bash -c '/usr/bin/docker logs -f --timestamps --tail=0 haproxy 2>&1 | sed -u "s/\([0-9]\{3\}\)[0-9]*Z/\1Z/" >> /var/log/haproxy/access.log'
+Restart=always
+RestartSec=10
+
+[Install]
+WantedBy=multi-user.target
diff --git a/haproxy/haproxy.cfg b/haproxy/haproxy.cfg
index 293fc8cc..bb49d376 100644
--- a/haproxy/haproxy.cfg
+++ b/haproxy/haproxy.cfg
@@ -3,26 +3,79 @@ global
maxconn 4096
daemon
+ # ์๋ฒ ์ ๋ณด ์จ๊ธฐ๊ธฐ
+ tune.h2.max-concurrent-streams 128
+
defaults
log global
mode http
option httplog
option dontlognull
+ option forwardfor
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
timeout http-request 10s
timeout http-keep-alive 2s
+ # ๊ธฐ๋ณธ ์๋ฌ ํ์ด์ง์์ HAProxy ๋ฒ์ ์จ๊ธฐ๊ธฐ
+ errorfile 403 /usr/local/etc/haproxy/errors/403.http
+
frontend http_in
bind *:80
- # HTTP๋ฅผ HTTPS๋ก ๋ฆฌ๋ค์ด๋ ํธ
+
+ acl blacklisted src -f /usr/local/etc/haproxy/blacklist.lst
+ http-request deny if blacklisted
+
+ stick-table type ip size 100k expire 30s store http_req_rate(10s)
+ http-request track-sc0 src
+ http-request deny deny_status 429 if { sc_http_req_rate(0) gt 50 }
+
http-request redirect scheme https unless { ssl_fc }
frontend https_in
- bind *:443 ssl crt /etc/ssl/certs/realmatch.pem
+ bind *:443 ssl crt /etc/ssl/certs/realmatch.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
+
+ acl blacklisted src -f /usr/local/etc/haproxy/blacklist.lst
+ http-request deny if blacklisted
+
+ stick-table type ip size 100k expire 30s store http_req_rate(10s)
+ http-request track-sc0 src
+ http-request deny deny_status 429 if { sc_http_req_rate(0) gt 50 }
+
+ acl valid_host hdr(host) -i api.realmatch.co.kr
+ http-request deny deny_status 403 unless valid_host
+
+ http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
+ http-response set-header X-Frame-Options "SAMEORIGIN"
+ http-response set-header X-Content-Type-Options "nosniff"
+ http-response set-header X-XSS-Protection "1; mode=block"
+ http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
+ http-response set-header Permissions-Policy "camera=(), microphone=(), geolocation=()"
+
+ http-response del-header Server
+ http-response del-header X-Powered-By
+
+ http-request deny if { req.hdr_cnt(content-length) gt 1 }
+
default_backend spring_servers
+listen stats
+ bind *:8404
+ stats enable
+ stats uri /stats
+ stats refresh 5s
+ stats show-legends
+ stats show-node
+ stats auth admin:realmatch2026!
+ stats admin if TRUE
+
+frontend prometheus
+ bind *:8405
+ mode http
+ http-request use-service prometheus-exporter if { path /metrics }
+ no log
+
backend spring_servers
balance roundrobin
option httpchk GET /actuator/health
diff --git a/haproxy/iptables-docker.conf b/haproxy/iptables-docker.conf
new file mode 100644
index 00000000..6e5a24da
--- /dev/null
+++ b/haproxy/iptables-docker.conf
@@ -0,0 +1,16 @@
+# Fail2ban action for Docker (uses DOCKER-USER chain)
+[Definition]
+
+actionstart = iptables -N f2b- 2>/dev/null
+ iptables -A f2b- -j RETURN
+ iptables -I DOCKER-USER -j f2b-
+
+actionstop = iptables -D DOCKER-USER -j f2b-
+ iptables -F f2b-
+ iptables -X f2b-
+
+actioncheck = iptables -n -L DOCKER-USER | grep -q 'f2b-'
+
+actionban = iptables -I f2b- 1 -s -j DROP
+
+actionunban = iptables -D f2b- -s -j DROP
diff --git a/haproxy/jail-haproxy.conf b/haproxy/jail-haproxy.conf
new file mode 100644
index 00000000..ca8ac148
--- /dev/null
+++ b/haproxy/jail-haproxy.conf
@@ -0,0 +1,8 @@
+[haproxy-attack]
+enabled = true
+filter = haproxy-attack
+logpath = /var/log/haproxy/access.log
+action = iptables-docker[name=haproxy]
+maxretry = 3
+findtime = 300
+bantime = 3600
diff --git a/haproxy/logrotate-haproxy b/haproxy/logrotate-haproxy
new file mode 100644
index 00000000..450752be
--- /dev/null
+++ b/haproxy/logrotate-haproxy
@@ -0,0 +1,9 @@
+/var/log/haproxy/access.log {
+ daily
+ rotate 14
+ compress
+ delaycompress
+ missingok
+ notifempty
+ copytruncate
+}