๋ฐฐํฌ ํ ์๋ฆผ ์๋น์ค๊ฐ ์ ๋๋ก ๋์ํ์ง ์๋๋ค๋ ์ ๋ณด๋ฅผ ๋ฐ์๋ค. ๋ก์ปฌ ํ๊ฒฝ์์๋ ๋ฉ์ฉกํ๋๋ฐ, ๋ฐฐํฌ ํ๊ฒฝ์์๋ ์๋ฆผ์ด ์ค์ง ์์๋ค. ๋ก์ปฌ์์๋ Spring Boot WAS๊ฐ SSE ์์ฒญ์ ๋ฐ๋ก ์ฒ๋ฆฌํ์ง๋ง, ๋ฐฐํฌ ํ๊ฒฝ์์๋ Nginx๊ฐ ์ค๊ฐ์ ๋ผ์ด ์์๋ค.
'์ด๊ฑฐ Nginx๊ฐ ๋ฌธ์ ์ผ ์๋ ์๊ฒ ๋ค...' ์ถ์ด์ ์ค์ ํ์ผ์ ์ ์ ์ด ๋ค์ฌ๋ค๋ณด๊ธฐ๋ก ํ๋ค.
# Default server configuration
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# HTTP ์์ฒญ์ HTTPS๋ก ๋ฆฌ๋๋ ์
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl ipv6only=on;
server_name sharespace.store;
root /var/www/html;
ssl_certificate /etc/letsencrypt/live/sharespace.store/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sharespace.store/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass <http://127.0.0.1:8080>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP ์์ฒญ์ HTTPS๋ก ๋ฆฌ๋๋ ์
(ํน์ ๋๋ฉ์ธ)
server {
if ($host = sharespace.store) {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
server_name sharespace.store;
return 404;
}
๋ญ๊ฐ ํ๋ฒํด ๋ณด์ด๋ ์ค์ ์ธ๋ฐ, ์ฌ๊ธฐ์ SSE์ ํน์ฑ์ ๊ณ ๋ คํ์ง ์์ ์ ์ด ๋ฌธ์ ์๋ค. SSE๋ ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ ์กํด์ผ ํ๋ค. ํ์ง๋ง Nginx๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฒํผ๋งํ๋ค. ์ด๋ฌ๋ฉด ์ค์๊ฐ ์ ์ก์ด ๋งํ๋ฒ๋ฆฐ๋ค.
SSE๋ ๋ฒํผ๋ง์ด ํ์ ์๋ค. ์คํ๋ ค ๋ฐ์ดํฐ๊ฐ ๋ฒํผ์ ์์ฌ ์ค์๊ฐ ์๋ฆผ์ด ์ง์ฐ๋ ๋ฟ์ด๋ค. Nginx ์ค์ ์์ /notification/sse ๊ฒฝ๋ก์ ๋ํด proxy_buffering off๋ฅผ ์ถ๊ฐํ๋ค.
<aside>
โ proxy_buffering์ด๋?
proxy_buffering์ NGINX๊ฐ ๋ฐฑ์๋ ์๋ฒ๋ก๋ถํฐ ๋ฐ์ ์๋ต ๋ฐ์ดํฐ๋ฅผ ๋ฒํผ์ ์ ์ฅํ ํ, ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๋ ๊ธฐ๋ฅ์ด๋ค. ์ด ๊ณผ์ ์์ ๋ชจ๋ ์๋ต์ ํ ๋ฒ์ ๋ฐ์ ํ ํด๋ผ์ด์ธํธ๋ก ์ ์กํ๋ฏ๋ก, ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก์ด ํ์ํ ๊ฒฝ์ฐ์๋ ์ ํฉํ์ง ์๋ค.
๐ฅ SSE์ proxy_buffering์ ์ถฉ๋
SSE๋ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ํด๋ผ์ด์ธํธ์ ์ ์กํ๋ค. ํ์ง๋ง NGINX์ ๋ฒํผ๋ง์ด ํ์ฑํ๋์ด ์์ผ๋ฉด ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ด์ธํธ๋ก ์ฆ์ ๋ณด๋ด์ง ์๊ณ ๋ฒํผ์ ์์๋ค๊ฐ ์ ์กํ๋ฏ๋ก, ์ค์๊ฐ์ฑ์ด ์ฌ๋ผ์ง๋ค.
</aside>
Nginx๋ ๊ธฐ๋ณธ์ ์ผ๋ก HTTP/1.1์ ์ฒญํฌ ์ ์ก์ ํ์ฑํํ๋ค. ํ์ง๋ง SSE๋ ์์ฒด์ ์ผ๋ก ์คํธ๋ฆฌ๋ฐ์ ์ฒ๋ฆฌํ๋ฏ๋ก ์ฒญํฌ ์ ์ก์ ๋๋ ๊ฒ์ด ๋ ์์ ์ ์ด๋ค.
<aside>
โ chunked_transfer_encoding์ด๋?
HTTP/1.1์ ์ฒญํฌ ์ ์ก ๋ฐฉ์์ผ๋ก, ์๋ต ๋ฐ์ดํฐ๋ฅผ ์์ ์ฒญํฌ(chunk) ๋จ์๋ก ๋๋์ด ํด๋ผ์ด์ธํธ๋ก ์ ์กํ๋ ๋ฐฉ์์ด๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋ ๊ฐ ์ฒญํฌ์ ํฌ๊ธฐ๋ฅผ ๋ช ์ํ๋ฉฐ, ๋ฐ์ดํฐ๊ฐ ๋๋ ๋๊น์ง ์ฒญํฌ๋ฅผ ๊ณ์ ๋ณด๋ด๋ ๊ตฌ์กฐ์ด๋ค.
๐ฅ SSE์ chunked_transfer_encoding์ ๋ฌธ์
SSE๋ ์์ฒด์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆฌ๋ฐํ๊ธฐ ๋๋ฌธ์ ์ฒญํฌ ์ ์ก ๋ฐฉ์์ ์ฌ์ฉํ ํ์๊ฐ ์๋ค. NGINX๊ฐ ์ด ๋ฐฉ์์ ๊ฐ์ ๋ก ์ ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ๋๋ก ์ฒ๋ฆฌํ์ง ๋ชปํ๊ฑฐ๋ ์ฐ๊ฒฐ์ด ๋๊ธฐ๋ ๋ฑ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
</aside>
SSE๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ์ฅ์๊ฐ ์ฐ๊ฒฐ์ ์ ์งํด์ผ ํ๋ค. ์ด๋ฅผ ์ํด Connection ํค๋๋ฅผ ๋น์์(๋น ๋ฌธ์์ด) ๋ช
์์ ์ผ๋ก ์ค์ ํ๋ค.
๊ธฐ๋ณธ ํ์์์์ ๋๋ฌด ์งง์์ SSE ์ฐ๊ฒฐ์ด ์๊พธ ๋๊ธธ ๊ฐ๋ฅ์ฑ์ด ์์๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด proxy_read_timeout๊ณผ keepalive_timeout์ 300์ด๋ก ๋๋ ธ๋ค.
์ค์๊ฐ ์๋ฆผ ๋ฐ์ดํฐ๋ ์บ์ฑ๋๋ฉด ์ ๋๋ค. ๊ทธ๋์ Cache-Control ํค๋๋ฅผ ํตํด ์บ์ฑ์ ๋ฐฉ์งํ๋ค.