Mini
[์ฑ๋ฅ๊ฐ์ ] ์ค์๊ฐ ๊ฒ์ ์๋ฒ ์ฑ๋ฅ ์ต์ ํ - ๋ฉํฐํ๋ก์ธ์ ๋ฐ ๋ฐฐ์น์ฒ๋ฆฌ๋ฅผ ํตํด 90% ์ด์์ ์ฑ๋ฅ ํฅ์ ๋ณธ๋ฌธ
[์ฑ๋ฅ๊ฐ์ ] ์ค์๊ฐ ๊ฒ์ ์๋ฒ ์ฑ๋ฅ ์ต์ ํ - ๋ฉํฐํ๋ก์ธ์ ๋ฐ ๋ฐฐ์น์ฒ๋ฆฌ๋ฅผ ํตํด 90% ์ด์์ ์ฑ๋ฅ ํฅ์
Mini_96 2025. 1. 14. 00:03๐ ์๋น์ค ํ๋์ ๋ณด๊ธฐ
์ค์๊ฐ์ผ๋ก ํด์ฆ ๋ง์ถ๊ธฐ!
์ค์๊ฐ ํด์ฆ ๊ฒ์ ํ๋ซํผ ํ๋ก์ ํธ์์
์ฑ๋ฅ ์ต์ ํํ ๊ฒฝํ์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค!
๋ถํํ ์คํธ๋ฅผ ํตํด ๋ฉํธ๋ฆญ์ ์์งํ๊ณ ,
๋ณ๋ชฉ์ ์์ธ์ ๋ถ์ํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ต์ ํํ ๋ฐฉ๋ฒ๊น์ง
์์ธํ๊ฒ ๋จ๊ฒจ๋ณด๊ณ ์ ํฉ๋๋ค!
๐ ํ ๊ฒ์๋ฐฉ์ 200๋ช ์ ์ง์ํ๊ณ ์ ํ ์ด์
ํ ๊ฒ์๋ฐฉ์ 200๋ช ์ ์ง์ํ๊ณ ์ ํ ์ด์ ๋..! ํ์ ๋ชฉํ์๊ธฐ ๋๋ฌธ์ ๋๋ค!
ํ ๊ฒ์๋ฐฉ ๋ด 200๋ช ์ ํ๋ ์ด์ด๊ฐ ์ํํ ํ๋ ์ดํ ์ ์๊ฒ ๊ตฌํ
๊ทธ๋ฐ๋ฐ ์ 200๋ช ์ผ๊น์? ์ ํฌ์ ์๋น์ค๊ฐ ์ฌ์ฉ๋๊ธธ ๊ธฐ๋ํ๋ ์ํฉ์ ์์ ๊ฐ์์ต๋๋ค.
๋๊ท๋ชจ์ ์ธ์์ด ํ ์ฅ์์์ ์ฆ๊ฒ๊ฒ ์์ด์ค๋ธ๋ ์ดํน, ๋ ํฌ๋ฆฌ์์ด์ ๋ฑ์ ์ฉ๋๋ก ์ฌ์ฉ๋๊ธธ ์ํ์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ์ง๋ฃจํ ์๋ ์๋ ๊ฐ์ฐ์ด๋ ํ์์ฅ์์๋ ์ฆ๊ฑฐ์์ ๋ํด์ค ์ ์์ผ๋๊น์! ๊ทธ๋ฆฌ๊ณ ๋ค์ด๋ฒ ๋ถ์คํธ์บ ํ ์ธ์ ์ ์ฒด๋ฅผ ์์ฉํ์๋ ์๋ฏธ์์ 200๋ช ์ด๋ผ๋ ๊ตฌ์ฒด์ ์ธ ์์น๋ฅผ ์ก์์ต๋๋ค.
๋ถํํ ์คํธ๋ฅผ ํตํด ํ ๊ฒ์๋ฐฉ ๋ด 200๋ช ์ ํธ๋ํฝ์ ์ฃผ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ํ๋ ์ฑ๋ฅ์ด ๋์ค๋์ง ์ฒดํฌํ๊ณ , ๋ณ๋ชฉ์ ๋ถ์ํ์ฌ ๊ฐ์ ํ ๊ฒฝํ์ ์ด์ผ๊ธฐํด๋ณด๋ ค ํฉ๋๋ค.
๐ ๋ถํํ ์คํธ ์คํ
๋จผ์ ๋ถํํ ์คํธ๋ฅผ ํตํด ํ ๊ฒ์๋ฐฉ ๋ด 200๋ช ์ ํธ๋ํฝ์ ๋ฐ์๋ณด๊ณ ์ ํ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ํํ ๊ฒ์์ด ๋๋์ง ํ์ธํ๊ณ ์ ํ๊ณ , ์ ์ ๋๋ค๋ฉด ๋ณ๋ชฉ ์ง์ ์ ๋ถ์ํ์ฌ ์ต์ ํํ๊ณ ์ ํ์ต๋๋ค.
์๋๋ฆฌ์ค
๋ถํํ ์คํธ์ ์๋๋ฆฌ์ค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ค์ ์ ๋น์ทํ๊ฒ ๋ถํ๋ฅผ ์ฃผ๋ ค๊ณ ๋ ธ๋ ฅํ์ต๋๋ค.
- ํ ๊ฒ์๋ฐฉ์ 200๋ช ์ vuser๊ฐ ์ ์
- ๊ฐ๊ฐ์ vuesr๋ 1์ด์ 2๋ฒ ๊ผด๋ก ์ด๋ฒคํธ(์์น ๋ณ๊ฒฝ ํน์ ์ฑํ
๋ฉ์์ง ์์ฒญ)๋ฅผ ์ ์ก
- ์ด๋ฒคํธ์๋ ์์น ๋ณ๊ฒฝ ํน์ ์ฑํ ๋ฉ์์ง๊ฐ ์์
- ์์น ๋ณ๊ฒฝ(9):์ฑํ ๋ฉ์์ง(1)์ ๋น์ค์ผ๋ก ์์ฒญ
- ์ด 60์ด ๋์ ์ง์
์ฒซ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
๋ถํํ ์คํธ๋ฅผ ์คํํ ๊ฒฐ๊ณผ ์ฃผ์ ์ด๋ฒคํธ์์ ์๋์ ๊ฐ์ ์๋ต์๊ฐ์ด ์ธก์ ๋์์ต๋๋ค.
์ฌ๊ธฐ์์ ์๋ต์๊ฐ์ ๋คํธ์ํฌ๋ฅผ ์ ์ธํ ์๋ฒ ์์ฒด์ ์ฒ๋ฆฌ ์๊ฐ์ ์ธก์ ํ ๊ฐ์ ๋ํ๋ ๋๋ค.
์ฒซ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
ํ๋์์ด '์บ๋ฆญํฐ ์์น ๋ณ๊ฒฝ', ์ฃผํฉ์์ด '์ฑํ ๋ฉ์์ง ์ ๋ฌ' ์๋ต์๊ฐ์ ๋๋ค! ์งํ๋ฅผ ๋ณด๋ฉด 5์ด, 8์ด๊ฐ ๋์ค๋ค์.
์ฑ๋ฅ ์ธก์ ๊ฒฐ๊ณผ, ์ฐธ๋ดํ ๊ฒฐ๊ณผ๊ฐ ๋์์ต๋๋ค ใ ใ .. ์ด๋ฐ ๊ฒ์์ ํ๊ณ ์ถ์ ์ฌ์ฉ์๋ ์๋ง ์์ ๊ฒ๋๋ค. ๊ฐ์ ์ด ์๊ธํ์ต๋๋ค!
์ฐธ๊ณ ๋ก p95๋ ๋ฐฑ๋ถ์์๋ก 95%์ ์์ฒญ์ ํด๋น ์๊ฐ ๋ด์ ์ฒ๋ฆฌ๋์๋ค๋ ๊ฑธ ์๋ฏธํฉ๋๋ค. ์ฝ๊ฒ ๋งํ๋ฉด 100๋ช ์ ์ฑ์ ์์ผ๋ก ์ค์ ์ธ์ ์ ๋ 95๋ฑ์ ์ฑ์ ์ ๋ปํฉ๋๋ค.
๐ ์์ผ ์๋ฒ๋ฅผ ๋ฉํฐ ํ๋ก์ธ์ค๋ก!
Why Multi Process?
์ ์ธก์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์๋ฉด ์๊ฒ ์ง๋ง, ๊ฒ์ ์งํ ์์ฒด๊ฐ ํ๋ ์์ค์ ๋๋ค. ๊ฒ์์์ ์บ๋ฆญํฐ๋ฅผ ์ด๋์์ผฐ๋๋ฐ 5์ด ๋ค์ ์ด๋ํ๋ค๋ฉด ๋๊ฐ ๊ทธ ๊ฒ์์ ํ ๊น์? ๊ทธ๋์ ๋๋ฌด ๊ธด ์๋ต ์๊ฐ์ ๋ฌธ์ ์์์ ์ผ๊ณ ๊ฐ์ ํ๊ณ ์ ํ์ต๋๋ค.
์ฐ์ ์ฝ๋ ๋ ๋ฒจ์์ ๋นํจ์จ์ ์ธ ๋ถ๋ถ์ด ์๋์ง ์ฒดํฌํ์ต๋๋ค. ์บ๋ฆญํฐ ์์น ๋ณ๊ฒฝ, ์ฑํ ์ ๋ฐ์ดํธ๋ฅผ ๋ด๋นํ๋ ๋ชจ๋, ํจ์๋ฅผ ์ญ ์ดํด๋ดค์ต๋๋ค. ํ์ง๋ง, ๋์ ๋๊ฒ ๋นํจ์จ์ ์ผ๋ก ์ง์ธ ์ฝ๋๋ฅผ ๋ณด์ง ๋ชปํ๊ณ ์ ๋ง ํ์ํ ๋ก์ง๋ค๋ง์ด ๋ด๊ฒผ์์ต๋๋ค.
ํ๋ก์ ํธ ๊ธฐ๊ฐ์ด ์ผ๋ง ๋จ์ง ์์ ์ํฉ์ด๋ผ ์ฐ์ ํด๋ณผ ์ ์๋ ๊ฒ๋ถํฐ ๋น ๋ฅด๊ฒ ์๋ํ๊ณ ์ ํ์ต๋๋ค.
๊ทธ๋์ ๋ธ ์๋ฃจ์ ์์!
๊ธฐ์กด์๋ ๋จ์ผ ํ๋ก์ธ์ค๋ก ์๋ฒ๊ฐ ๋์๊ฐ๋๋ฐ์.
๋ฐฐํฌ๋ ์๋ฒ์ CPU๊ฐ 2๊ฐ์ธ ์ ์ ์ด์ฉํ์ฌ ๋จ์ผ ํ๋ก์ธ์ค์์ ๋ฉํฐ ํ๋ก์ธ์ค๋ก ์ ํํ๊ณ ์ ํ์ต๋๋ค. ๋์์ ๋ง์ ์์ฒญ์ด ๋ค์ด์๋ ๋ก๋๋ฐธ๋ฐ์ฑ์ ํตํด ๋ ๊ฐ์ ํ๋ก์ธ์ค๊ฐ ๋๋ ์ ์ผํ๋๋ก ํ๋ ๊ฑธ ์ ๋ํ์ด์.
๋ฉํฐ ํ๋ก์ธ์ค๋ก ๋ฐ๊พผ ํ ๋ค์ ๋ถํํ ์คํธํ์ฌ ์ถ๊ฐ๋ก ๋ณ๋ชฉ์ ์ฐพ์๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
๋ฉํฐ ํ๋ก์ธ์ค๋ก ๋ฐ๊พธ๋ ์ฃผ์ ๊ณผ์ 3๊ฐ์ง
1) ๊ฒ์ ์๋ฒ๋ฅผ ๋ฉํฐ ํ๋ก์ธ์ค๋ก ์คํ
- pm2๋ฅผ ํตํด 3000๋ฒ, 3001๋ฒ ํฌํธ๋ก ํ๋ก์ธ์ค 2๊ฐ ์คํ
- ํด๋ผ์ฐ๋ ์๋ฒ vCPU 2๊ฐ์ ๋ง์ถฐ ํ๋ก์ธ์ค 2๊ฐ๋ก ๊ฒฐ์
2) NginX๋ก ๋ก๋ ๋ฐธ๋ฐ์ฑ
upstream backend-socket {
ip_hash;
server localhost:3000;
server localhost:3001;
}
- NginX์์ 3333๋ฒ ํฌํธ๋ก ์ค๋ ๊ฑด ์์ผ ์ฐ๊ฒฐ๋ก 3000๋ฒ, 3001๋ฒ์ผ๋ก ๋ก๋๋ฐธ๋ฐ์ฑ
- ip_hash๋ก ํ์ฌ ์์ผ ์ฐ๊ฒฐ์ด ์ง์์ ์ผ๋ก ์ด๋ฃจ์ด์ง ์ ์๊ฒ ํจ
- ๋ค์ด๋ฒ ํด๋ผ์ฐ๋ ์ฝ์์์ ACG Inbound์ 3333๋ฒ ํฌํธ ์ด๊ธฐ
์ดํ ์ํคํ ์ฒ
์ดํ์๋ ์๋์ ๊ฐ์ด ๋ฉํฐ ํ๋ก์ธ์ค๋ก ์ด์ํ ์ ์๋ ๊ตฌ์กฐ๋ก ๋ฐ๋์์ต๋๋ค.
NginX๊ฐ 3333๋ฒ์ ํตํด ์์ผ ์์ฒญ์ ๋ฐ์์ฃผ๊ณ ,
์ด๋ฅผ ๋ ๊ฐ์ ํ๋ก์ธ์ค 3000, 3001๋ฒ์ผ๋ก ๋ก๋ ๋ฐธ๋ฐ์ฑํด์ฃผ๋ ๊ตฌ์กฐ์ ๋๋ค!
๐ ๋ฉํฐํ๋ก์ธ์ค๋ก ๋ฐ๊พผ ์ดํ, ๋ถํํ ์คํธ ์คํ
์ดํ ๊ฐ์ ํ๊ฒฝ์์ ๋ค์ ๋ถํํ ์คํธ๋ฅผ ์คํํ์ด์! ๊ฒฐ๊ณผ๋ฅผ ๋ณด์์ฃ !
์บ๋ฆญํฐ ์์น ๋ณ๊ฒฝ ์๋ต์๊ฐ - ์ด์ ๊ณผ ์ดํ ๊ฒฐ๊ณผ ๋น๊ต
๋ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
์ฑํ ์ ์๋ต์๊ฐ - ์ด์ ๊ณผ ์ดํ ๊ฒฐ๊ณผ ๋น๊ต
๋ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
ํด์
์์น ๋ณ๊ฒฝ์ ๋ํ ์๋ต ์๊ฐ์ด ํ๊ท , p95, max ์งํ์์ ๋๋ถ๋ถ ์ ๋ฐ ์ด์ ์ค์ด๋ค์์ต๋๋ค! ์ฑํ ์ ๋ํ ์๋ฒ ์ฒ๋ฆฌ ์๊ฐ์ 4 ~ 6๋ฐฐ ์ ๋ ์ค์ด๋ค์์ต๋๋ค.
ํ์ง๋ง, ์ฌ์ ํ ์ค์๊ฐ์ผ๋ก ๊ฒ์์ ํ๋ ์ดํ๊ธฐ ํ๋ ์์น์ ๋๋ค..!! ๊ทธ๋์ ์ถ๊ฐ๋ก ๋ณ๋ชฉ ์์ธ์ ์ฐพ์๋ณด๊ณ ์ ํ์ต๋๋ค.
๐ง ๋๋์ฒด ๋ฌด์์ด ๋ณ๋ชฉ์ผ๊น?
๋๋์ฒด ๋ฌด์์ด ๋ณ๋ชฉ์ผ์ง ๊ณ ๋ฏผํ์ต๋๋ค!
์ต๋ํ ๊ฐ๋ฅ์ฑ์ ์ด์ด๋๊ณ ํ์ํ ๋ค, ๊ฐ์ฅ ์์ฌ์ด ๋๋ ๋ถ๋ถ์ ๊ณจ๋์ด์!
1) Redis์ ๋ํ ๋ง์ ์กฐํ
์ฒซ ๋ฒ์งธ ํ๋ณด๋ Redis์ ๋๋ค! Redis์ ๋ง์ ์กฐํ๊ฐ ๋ฐ์ํด์ ๋๋ ค์ง๋ ๊ฑฐ๋ผ ์ถ์ธกํด๋ณผ ์ ์์ต๋๋ค.
์๋ฒ ๋ด ์ฝ๋์์๋ ์ฑํ ์ ๋ธ๋ก๋์บ์คํ ํ๊ธฐ ์ ์ ํ๋ฝํ ์ฌ๋์ด ๋ณด๋ธ ์ฑํ ์ธ์ง๋ฅผ ์กฐํํฉ๋๋ค. ๊ฒ์์์ ํ๋ฝํ ํ๋ ์ด์ด๋ผ๋ฉด ์์กดํ ํ๋ ์ด์ด์๊ฒ ์ฑํ ์ด ๊ฐ์ง ์๋๋ก ํ์ฌ ๊ฒ์ ํ๋ ์ด์ ๋ฐฉํด๊ฐ ๋์ง ์๋๋ก ํ๊ธฐ ์ํจ์ ๋๋ค.
ํ๋ฝํ ์ฌ๋์ด ๋ณด๋ธ ์ฑํ ์ธ์ง ํ์ธํ๊ธฐ ์ํด redis์์ ํด๋น ํ๋ ์ด์ด์ isAlive๋ฅผ ์กฐํํฉ๋๋ค. ์บ๋ฆญํฐ์ ๋ณ๊ฒฝ๋ ์์น๋ฅผ ์ ์กํ๋ ๊ฒ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ๋ถํํ ์คํธ ์คํฌ๋ฆฝํธ์ 1์ด์ ์บ๋ฆญํฐ ์์น ๋ณ๊ฒฝ, ์ฑํ ์ ์ก ์ดํฉ 400๊ฐ์ ์์ฒญ์ด ์ค๊ธฐ์ 1์ด์ 400๋ฒ Redis์์ ํน์ ํ๋ ์ด์ด์ isAlive๋ฅผ ์กฐํํด์ผ ํ์ด์. ๋ํ, Redis๋ Private Subnet์ ๋ณ๋์ ์๋ฒ์์ ์คํ๋๊ณ ์์๊ธฐ์ ์ถ๊ฐ์ ์ธ ๋คํธ์ํฌ ๋น์ฉ์ด ๋ฐ์ํ์ ๊ฑฐ๋ผ ์ถ์ธกํ์ต๋๋ค.
๊ทธ๋ฌ๋ Redis๊ฐ 1์ด์ 400๋ฒ ์กฐํ๋ก ๋ถํ๊ฐ ์ค๊ธฐ๋ ํ๋ค ๊ฒ ๊ฐ๋ค๊ณ ํ๋จํ์ต๋๋ค. ์ผ๋จ ๋๋์ ์ผ๋ก Redis๊ฐ 1์ด์ 400๋ฒ ์ ๋๋ฅผ ๋ชป ๋ฒํด๋ค๋ฉด ์ด๋ ๊ฒ ์ธ๊ธฐ ์๋ ๋น ๋ฅธ ์ธ๋ฉ๋ชจ๋ฆฌ DB๊ฐ ๋ ์๋ ์์๊ฒ ์ฃ . ๊ทธ๋ฆฌ๊ณ ์๋ ค์ง๊ธฐ๋ฅผ Redis์์๋ ๋๊ฒ ์ด๋น 100,000 QPS๋ ๋๋ค๊ณ ํด์.
๊ฒฐ๋ก ์ Redis ์ฑ๋ฅ ์ 1์ด์ 400๋ฒ ์กฐํ๋ ๋ฌด๋ฆฌ๊ฐ ์์ ๊ฑฐ๋ผ ํ๋จํ์ฌ ๋ค์ ์์ธ์ ๋ถ์ํด๋ณด๊ฒ ์ต๋๋ค.
+) ํด๋น isAlive๋ฅผ ์กฐํํ๋ ๋ก์ง์ ๊ฐ์ ์์ฒด๊ฐ ํ์ํ ๊ฑด ๋ง์ต๋๋ค. isAlive๋ ์์ฃผ ๋ฐ๋๋ ๊ฒ ์๋๊ธฐ์ WAS ๋ด์์ ๊ฐ๋จํ ์ธ์ ์ผ๋ก ๊ด๋ฆฌํด๋ ๋๋ ๋ฐ์ดํฐ์ ๋๋ค.
2) NginX ๊ณผ๋ถํ
๊ทธ๋ค์์ NginX์ธ๋ฐ์!
NginX์์๋ 1์ด์ 400๋ฒ ์์ฒญ์ ๋ฐ์์ผ ํ๊ณ , 1์ด์ 80000๋ฒ ์๋ต์ ํด์ค์ผ ํ์ต๋๋ค. 80000๋ฒ ์๋ต์ ํด์ค์ผ ํ๋ ์ด์ ๋ ํ ๊ฒ์๋ฐฉ์ 200๋ช ์ ํ๋ ์ด์ด๊ฐ ์๊ณ 1์ด๋น 400๊ฐ์ ์์ฒญ์ด ์ค๋ฉด, ์ด๋ฅผ ๋ธ๋ก๋์บ์คํ ํ๊ธฐ ์ํด์ 200๋ช ์๊ฒ 400๊ฐ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด์ผ ํ๊ธฐ์ 200 * 400 = 80000๊ฐ์ ์๋ต์ด ํ์ํฉ๋๋ค.
400๊ฐ์ ์์ฒญ์ ๊ด์ฐฎ์ง๋ง, 80000๊ฐ์ ์๋ต์ ์ด์ง ๋ถ๋ด์ด ๋ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ณ๋ชฉ์ ์์ธ์ผ ํ๋ฅ ์ด Redis๋ณด๋ค๋ ๋์๋ณด์ ๋๋ค.
๊ทธ๋ฌ๋ NginX์์ ์๋ต์ ์ฃผ๋ ๊ณผ์ ์์ ์ ํํ ๋ฌด์ ๋๋ฌธ์ ๋ถํ๊ฐ ์๊ธธ์ง ๊ฐ๋ ์ด ์ ๋์ต๋๋ค. ์ผ๋จ ๋ณด๋ฅํ๊ณ 80000๊ฐ์ ๋คํธ์ํฌ ์๋ต์ ์ง์คํด๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
3) ์ ํ๋ ๋คํธ์ํฌ ๋์ญํญ
๋คํธ์ํฌ ๋์ญํญ์ด 1์ด์ 80000๊ฐ ์๋ต์ ๊ฒฌ๋์ง ๋ชปํ์ ๊ฒ์ด๋ผ ์ถ์ธกํด๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ์๋์์ต๋๋ค.
๊ทธ ์ด์ ๋ ์๋ฒ๋ฅผ Ncloud๋ก ์ด์ํ๊ณ ์์๊ณ , Ncloud ์๋ฒ์ ๊ธฐ๋ณธ ๋คํธ์ํฌ ๋์ญํญ์ 1Gbps์ ๋๋ค. 1์ด์ 80000๊ฐ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ธฐ ์ํด ํ์ํ ๋์ญํญ์ 122.24Mbps ์ ๋์ ๋๋ค. 1๊ฐ์ ๋ฉ์์ง๋ฅผ ๋๋ต 191bytes ์ ๋๋ก ์ก๊ณ ๊ณ์ฐํ์ต๋๋ค.
`1Gbps = 1000Mbps > 122.24Mbps`์ด๊ธฐ์ ๋์ญํญ ์์ฒด์ ๋ฌธ์ ๋ ์๋ ๊ฒ์ผ๋ก ํ๋จํ์ต๋๋ค.
4) Node.js event loop ๊ณผ๋ถํ - Network I/O๋ก ์ธํ
๋๋์ด ๋ง์ง๋ง์ ๋๋ค! ๋ง์ง๋ง์ ๋ ์ด์ ๊ฐ ์๊ฒ ์ฃ ? ใ ใ
Node.js event loop๊ฐ ์ฒ๋ฆฌํด์ผ ๋ ๊ฒ ๋ง์ ๊ณผ๋ถํ๋์ด ๋ค๋ฅธ ์์ฒญ์ด ์๋ ๊ณ์ํด์ ๋๊ธฐํ๊ณ ์ง์ฐ๋๋ค๊ณ ์ถ์ ํ์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด Node.js event loop๋ ์ด๋ค ๊ฒ ๋๋ฌธ์ ๊ณผ๋ถํ๋์์๊น์? ์ด์ ๊ด๋ จํด ๊ณ ๋ฏผํ๋ ์ค ์ธํ๋ฐ์์ ์๊ฐํ๋ ํ์ผ์ ์ถ๋ ฅ ๊ด๋ จ ํ์ต๋ด์ฉ์ด ๋ ์ฌ๋์ต๋๋ค.
ํ์ผ ์ ์ถ๋ ฅ์์ ๋ฌธ์ ์ํฉ์ ๋ค์๊ณผ ๊ฐ์์ต๋๋ค.
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream(FILE_NAME);
long startTime = System.currentTimeMillis();
for (int i = 0; i < FILE_SIZE; i++) {
fos.write(1);
}
fos.close();
long endTime = System.currentTimeMillis();
System.out.println("File created: " + FILE_NAME);
System.out.println("File size: " + FILE_SIZE / 1024 / 1024 + "MB");
System.out.println("Time taken: " + (endTime - startTime) + "ms");
}
ํ์ผ์ ์ฐ๊ธฐ๋ฅผ ํ๋ ์ํฉ์ธ๋ฐ, 1byte์ฉ ๋์คํฌ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ์ํฉ์ ๋๋ค.
- ์ฑ๋ฅ ์ ํ ํ์: 10MB ํ์ผ ์ฐ๊ธฐ์ 14์ด ์์
- ๊ทผ๋ณธ ์์ธ: 1byte์ฉ ๋์คํฌ์ ๋ฐ์ดํฐ ์ ๋ฌ
- ๋ฐ๋ณต ํ์: ๋ฌด๋ ค 1,000๋ง ๋ฒ์ ๋ฐ๋ณต ์์
์์คํ ์ฝ ์ค๋ฒํค๋ ๋ฐ์
- ๋งค write(), read() ํธ์ถ ์ OS ์์คํ ์ฝ ๋ฐ์
- ์์คํ ์ฝ์ ์๋์ ์ผ๋ก ๋ฌด๊ฑฐ์ด ์์
- ์ปจํ ์คํธ ์ ํ ๋น์ฉ ๋ฐ์
๋ง์น ํ๋ฌผ์ฐจ์ ํ ๋ฒ์ ํ๋์ ๋ฌผ๊ฑด๋ง ์ค์ด ๋๋ฅด๋ ๊ฒ์ฒ๋ผ, 1byte์ฉ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์ ๊ทน๋๋ก ๋นํจ์จ์ ์ ๋๋ค. 1,000๋ง ๋ฒ์ ์๋ณต ์์ ์ ์์คํ ์์์ ๋ถํ์ํ๊ฒ ์๋ชจํ์ต๋๋ค.
์ด๋ฌํ ํ์ผ I/O ํ์ต ๊ฒฝํ์ ์ด๋ ค Network I/O ์ํฉ์ ์ ์ถํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ํ์ต๋๋ค.
์ ํฌ ํ๋ก์ ํธ์์ ๊ธฐ์กด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์์ต๋๋ค.
private async handlePlayerPosition(playerId: string, playerData: any, server: Namespace) {
const { gameId, positionX, positionY } = playerData;
const playerPosition = [parseFloat(positionX), parseFloat(positionY)];
const updateData = { playerId, playerPosition };
const isAlivePlayer = await this.redis.hget(REDIS_KEY.PLAYER(playerId), 'isAlive');
if (isAlivePlayer === SurvivalStatus.ALIVE) {
server.to(gameId).emit(SocketEvents.UPDATE_POSITION, updateData);
}
player๊ฐ ์ด๋ํ ๋, ๋ค๋ฅธ ํ๋ ์ด์ด๋ค์๊ฒ ์ ์์น๋ฅผ ์ ๋ฌํ๋ ๋ก์ง์ ๋๋ค.
์ด๋, 1๋ช ์ด ์ด๋ํ๋ฉด 200๋ฒ(๋ฐฉ์ ํ๋ ์ด์ด ์)์ emit์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
๋ง์น 1byte ์ฉ ํ์ผ์ ์ฐ๊ณ ์๋ ์ํฉ๊ณผ ๋งค์ฐ ์ ์ฌํ์ต๋๋ค!!
๋นํจ์จ์ ์ธ I/O๊ฐ ์ผ์ด๋๋ ์ํฉ์ด ์ ํฌ ํ๋ก์ ํธ์์๋ ๋ฐ์ํ๊ฒ ์ ๋๋ค.ํ์ผ I/O ์์ฒด๊ฐ ๋น์ฉ์ด ๋น์ผ ์์ ์ด๋ฉฐ Network I/O ์ญ์ ๋ง์ฐฌ๊ฐ์ง ์ผ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค. 1์ด์ 80000๋ฒ Network Ouput์ ํ๋ ๊ฒ์ด๋ ์ฌ๊ธฐ์ ๋ณ๋ชฉ์ด ๋ฐ์ํ์ ๊ฑธ๋ก ์ถ์ ํ์ต๋๋ค.
ํ์ผ I/O์ ๋ง์ฐฌ๊ฐ์ง๋ก Network Output์ ์ํด์๋ OS์์ ์์คํ ์ฝ์ ํตํด ์ ์ ๋ชจ๋์ ์ปค๋๋ชจ๋ ์ฌ์ด๋ฅผ ์ ํํ๋ฉด์ ์๊ธด ์ค๋ฒํค๋๊ฐ ์์ ๊ฑธ๋ก ์ถ์ ํ์ต๋๋ค. ๋, Network Output์ ์ฒ๋ฆฌํ๋ฉด์๋ ์๋ก์ด ์์ฒญ๋ ์ฒ๋ฆฌํด์ผ ํ๊ธฐ์ ์ปจํ ์คํธ ์ค์์นญ์ด ๋ค์ ์ผ์ด๋ฌ์ ๊ฒ์ ๋๋ค.
์๋ง์ Network I/O๊ฐ ์ ๋ ฅํ ์์ธ์ผ ๊ฒ์ผ๋ก ํ์ ํ์ต๋๋ค. ๊ทธ๋์ Network I/O๋ก ์ธํ ๋ถํ๊ฐ Node.js event loop์๋ ์ํฅ์ ์ฃผ์์ ๊ฒ์ ๋๋ค.
๊ณผ๊ฐํ ๊ฐ์ ํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค!
๐ฏ ์๋ง์ Network Output์ ์ด๋ป๊ฒ ๊ฐ์ ํ ์ ์์๊น?
1) ๋ฐ์ดํฐ ๋ฐฐ์น ์ฒ๋ฆฌ
- ๋ฐฐ์น ์ฒ๋ฆฌ(Batch Processing): ๋ฐ์ดํฐ์ ๋ํ ๋ฐ๋ณต์ ์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋์ , ๋ฐ์ดํฐ๋ฅผ ๋ชจ์์ ์ผ์ ์ฃผ๊ธฐ๋ก ํ ๋ฒ์ ์ฒ๋ฆฌ
- ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ก ๋ธ๋ก๋์บ์คํ
ํ์ง ์๊ณ ํ์ ์์๋๊ธฐ
- (์๋ฐ์ ํ์ผ ์ ์ถ๋ ฅ Buffered ์คํธ๋ฆผ์ฒ๋ผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ๋ ์์์ง๋ง, ์ด๊ฒ ํ์คํ ์์ธ์ธ์ง ๋ชจ๋ฅด๋ ์ํฉ์ด์๊ณ ํ์ดํ๋ก๊ทธ๋๋ฐ ํ๊ฒฝ์์ ๋ค๊ฐ์ด ์ดํดํ ์ ์๋ ์๋ฃ๊ตฌ์กฐ์ธ ํ๋ก ๊ตฌํํ๊ณ ์ ํ์ต๋๋ค.)
- ์ ํด์ง ์ฃผ๊ธฐ๋ก ํ์ ์๋ ๊ฑธ ํ ๋ฒ์ ์ ์กํจ์ผ๋ก์จ Network Output ๋ถ๋ด ์ค์ด๊ธฐ
- ๊ธฐ์กด์๋ 1์ด์ 80000๋ฒ Network Output์ ํด์ผ ํ์ง๋ง,
0.1์ด์ 1๋ฒ์ฉ ์์ธ ๋ฐฐ์น๋ฅผ ์ฒ๋ฆฌํ๋ค๋ฉด ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ํตํด 1์ด์ 10๋ฒ Network Outputํ๊ฒ ๋จ
2) ๋ฐ์ดํฐ ์์ถ
- ๋ฐ์ดํฐ ํฌ๊ธฐ๋ฅผ ์ค์ฌ ๋คํธ์ํฌ ๋ถ๋ด์ ์ค์ด๊ธฐ
- Network I/O ํ์ ์์ฒด๋ ๋ณ๋์ด ์๊ธฐ์ ์ง๊ธ ๋ฌธ์ ์ ์ ์ ํ ํด๊ฒฐ ๋ฐฉ์์ ์๋
3) ์ํ์ ํ์ฅ ๋๋ ์์ง์ ํ์ฅ
- ์๋ฒ๋ฅผ ๋ ๋๋ฆฌ๊ฑฐ๋ ์ฌ์์ ๋์ด๋ ๊ฑด ๋ณธ์ง์ ์ธ ํด๊ฒฐ ๋ฐฉ์์ด ์๋ (์ฐ์ pass)
๋ฐฐ์น ์ฒ๋ฆฌ๋ก ์ ํ
์ง๊ธ ๋น์ฅ ์๋ํด๋ณผ ๋ฒํ ๊ฑด ๋ฐฐ์น ์ฒ๋ฆฌ๋ผ๊ณ ํ๋จํ์ต๋๋ค. Network Output ํ์ ์์ฒด๋ฅผ ์ค์ด๋ ๊ฒ ๋ณ๋ชฉ์ ์์ธ์ ์ ๊ฑฐํ๋ ๋ฐ ํต์ฌ์ด๊ธฐ ๋๋ฌธ์ด์ฃ . ๊ทธ๋ฆฌ๊ณ ๋ฐฐ์น์ฒ๋ฆฌ๋ ํ์๋ฅผ ์ค์ฌ์ค ์ ์๋ ์์ฃผ ์ข์ ์๋ฃจ์ ์ ๋๋ค.
โ๏ธ ๋ฐ์ดํฐ ๋ฐฐ์น ์ฒ๋ฆฌ ๋์ ํ๊ธฐ
๊ตฌํ ๊ณํ
- ๋ฉ๋ชจ๋ฆฌ ๋ณ์์ ํ๋ฅผ ๋๊ธฐ
- ์ฑํ , ์์น ๋ณ๊ฒฝ ์์ฒญ์ด ๋ค์ด์ค๋ฉด ๋ฐ๋ก ๋ธ๋ก๋์บ์คํ ํ์ง ์๊ณ , ํ์ ๋ฐ์ดํฐ๋ฅผ ์ผ๋จ ์์๋๊ธฐ
- 0.1์ด์ ํ ๋ฒ์ฉ ํ ๋ฐฐ์น ์ฒ๋ฆฌํ๊ธฐ
๊ตฌํ ์ฝ๋
์์น ๋ณ๊ฒฝ๊ณผ ์ฑํ ์ ๋ํด์ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์์ต๋๋ค. ์๋๋ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ์ง์ ๊ตฌํํ ์ฝ๋์ ๋๋ค! ๋ฐฐ์น ํ๋ก์ธ์์ ์์น ๋ณ๊ฒฝ ํจ์์ ๋ํด ์ดํด๋ณด์์ฃ !
์ฐธ๊ณ ๋ก ์์น ๋ณ๊ฒฝ์ ๋ฐฐ์น์ฒ๋ฆฌ ์ฃผ๊ธฐ๋ 0.1์ด๋ก ์ค์ ํ์ต๋๋ค. ์ฑํ ์ ๋ ๋น ๋ฅธ ์ค์๊ฐ ๋๊ธฐํ๋ฅผ ์ํด 0.05์ด๋ก ์ค์ ํ์ต๋๋ค.
1) batch.processor.ts (๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ์ง์ํ๋ ๋ชจ๋)
// ๋ฐฐ์น์ฒ๋ฆฌ ๋ชจ๋
export class BatchProcessor implements OnApplicationShutdown, OnModuleDestroy {
private batchMap: Map<BatchProcessorType, Map<string, any[]>> = new Map();
private isProcessing = false;
private intervalId: NodeJS.Timeout;
private server: Namespace;
private eventName: string;
constructor(
@InjectRedis() private readonly redis: Redis
) {}
// ์ด๋ค ์๋ฒ, ์ด๋ฒคํธ์์ ์ฌ์ฉํ๋ ๋ฐฐ์น์ฒ๋ฆฌ์ธ์ง ์ด๊ธฐํ
initialize(server: Namespace, eventName: string) {
this.server = server;
this.eventName = eventName;
for (const type of Object.values(BatchProcessorType)) {
this.batchMap.set(type, new Map());
}
}
// ํน์ ๊ฒ์๋ฐฉ์ ๋ณด๋ด์ผ ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐฐ์น ํ์ ์ฝ์
pushData(type: BatchProcessorType, gameId: string, data: any): void {
const batchMap = this.batchMap.get(type);
if (!batchMap.has(gameId)) {
batchMap.set(gameId, []);
}
batchMap.get(gameId).push(data);
}
// ์ฃผ๊ธฐ์ ์ธ ๋ฐฐ์น ์ฒ๋ฆฌ ์์คํ
์์
startProcessing(interval: number = 100): void {
this.intervalId = setInterval(() => this.processBatch(), interval);
}
// ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐฐ์น ์ฒ๋ฆฌํ๋ฉฐ ๊ฐ ๊ฒ์๋ฐฉ์ ๋ธ๋ก๋์บ์คํ
private async processBatch(): Promise<void> {
// isProcessing์ ํตํด lock์ ๊ฑธ์ด ํ ๋ฐ์ดํฐ์ ๋ํ ์ฌ๋ฌ ๋ฒ์ ๋ฐฐ์น ์ฒ๋ฆฌ ๋ฐฉ์ง
if (this.isProcessing) {
return;
}
this.isProcessing = true;
// BatchProcessorType์ ๋ฐ๋ผ ์ฒ๋ฆฌ (ex. ์ฑํ
์ ๋ชจ๋์๊ฒ ๋ณด๋ผ์ง, ํน์ ์ธ์๊ฒ ๋ณด๋ผ์ง)
for (const type of Object.values(BatchProcessorType)) {
const batchMap = this.batchMap.get(type);
const processingTasks = Array.from(batchMap.entries()).map(async ([gameId, queue]) => {
if (queue.length > 0) {
const batch = queue.splice(0, queue.length);
const handler = this.batchProcessHandlers[type];
await handler(gameId, batch);
}
});
// isProcessing ๋ณ์ ๊ด๋ฆฌ๋ฅผ ์ํด await
// ์์คํ
์์ผ๋ก ๋ธ๋ก์ด ๋๋ ๊ฒ์ ์๋๋ฉฐ ๋ฐฐ์น ์ฒ๋ฆฌ ์ดํ ์คํํด์ผ ํ ์ฃผ์ ํจ์๋ ์๊ธฐ์ ์ฑ๋ฅ ์ํฅx
await Promise.all([...processingTasks]);
}
this.isProcessing = false;
}
// ๋ฐฐ์น ์ฒ๋ฆฌ ํธ๋ค๋ฌ
private batchProcessHandlers: Record<
BatchProcessorType,
(gameId: string, batch: any[]) => Promise<void>
> = {
[BatchProcessorType.DEFAULT]: // (์๋ต) ๋ํดํธ ๋ธ๋ก๋์บ์คํ
ํด์ฃผ๋ ํจ์,
[BatchProcessorType.ONLY_DEAD]: // (์๋ต) ๊ฒ์์์ ์ฃฝ์ ์ฌ๋๋ผ๋ฆฌ ๋ธ๋ก๋์บ์คํ
ํ๋ ํจ์
};
}
2) player.subscriber.ts (์บ๋ฆญํฐ์ ๋ณ๊ฒฝ๋ ์์น๋ฅผ ๋ธ๋ก๋์บ์คํ ํ๋ ๋ชจ๋)
@Injectable()
export class PlayerSubscriber extends RedisSubscriber {
constructor(
@InjectRedis() redis: Redis,
private positionProcessor: BatchProcessor
) {
super(redis);
}
// ๋ฐฐ์น์ฒ๋ฆฌ ๊ฐ์ฒด ์ด๊ธฐํ ๋ฐ ์์
async subscribe(server: Namespace): Promise<void> {
this.positionProcessor.initialize(server, SocketEvents.UPDATE_POSITION);
this.positionProcessor.startProcessing(POSITION_BATCH_TIME);
...
}
// ๋ฐฐ์น ์ฒ๋ฆฌ ํ์ ๋ฐ์ดํฐ ์์๋๊ธฐ
private async handlePlayerPosition(playerId: string, playerData: any) {
const { gameId, positionX, positionY } = playerData;
const playerPosition = [parseFloat(positionX), parseFloat(positionY)];
const updateData = { playerId, playerPosition };
const isAlivePlayer = await this.redis.hget(REDIS_KEY.PLAYER(playerId), 'isAlive');
const processorType = isAlivePlayer === SurvivalStatus.ALIVE
? BatchProcessorType.DEFAULT
: BatchProcessorType.ONLY_DEAD;
this.positionProcessor.pushData(processorType, gameId, updateData);
}
๋ณด์๋ค์ํผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ณ๋๋ก ์ฌ์ฉํ์ง ์๊ณ ์ง์ ๊ตฌํํ๋๋ฐ์! ๊ทธ ์ด์ ๋ ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ์ง์ ๊ตฌํํ์ฌ ํ์ตํ๊ธฐ ์ํจ์ด์์ต๋๋ค. ํ์ ๋ชจ๋ ๋ฐฐ์น ์ฒ๋ฆฌ ๊ด๋ จ ๊ฒฝํ์ด ์ฒ์์ด์๊ณ , ์ด๋ฅผ ์ง์ ๊ตฌํํ๋ฉด์ ๋ฐฐ์น ์ฒ๋ฆฌ์ ๋ํด ์์๊ฐ๋ณด๊ณ ์ ํ์ต๋๋ค. ๊ทธ๋์ผ ํฅํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋์ ํ๋๋ผ๋ ๋ ์ ์ธ ์ ์๊ณ , ์ฅ์ ์๋ ๋ ๋น ๋ฅด๊ฒ ๋์ํ ์ ์์ ๊ฑฐ๋ผ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๐ ๋ถํํ ์คํธ ์คํํ์ฌ ํ์ธํด๋ณด์!
๊ฐ์
- ์ด์ ๋ถํํ ์คํธ ํ๊ฒฝ๊ณผ ๋์ผ
์์น ๋ณ๊ฒฝ์ ์๋ต์๊ฐ - ์ด์ ๊ณผ ์ดํ ๊ฒฐ๊ณผ ๋น๊ต
์ธ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
์ฑํ ์ ์๋ต์๊ฐ - ์ด์ ๊ณผ ์ดํ ๊ฒฐ๊ณผ ๋น๊ต
์ธ ๋ฒ์งธ ๋ถํํ ์คํธ ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ ํด์
์ฑํ , ์์น ๋ณ๊ฒฝ์ ์๋ต์๊ฐ์ด ๋น์ฝ์ ์ผ๋ก ๋จ์ถ๋์์ต๋๋ค!! E2E ์ธก์ ์๊ฐ์ ๋ณด๋๋ผ๋ ์ต๋ 0.12์ด ์์ ๋ณ๊ฒฝ๋ ์์น ์๋ต์ ๋ฐ๋ ๋ชจ์ต์ ๋ณด์์ต๋๋ค. ์ฆ, ๋ฐฐ์น ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ด๋ฃจ์ด์ก๋ค๋ ๊ฑธ ์ ์ ์์ด์!
๊ธฐ์กด์๋ Network Output์ด 1์ด์ 80000๋ฒ์ด์๊ณ , ์ด์ ๋ 1์ด์ 30๋ฒ ์ดํ์ ๋๋ค. ์ญ์ ์๋ง์ Network I/O๋ก ์ธํ ์ค๋ฒํค๋๊ฐ ๋ณ๋ชฉ์ ์์ธ์ด์์ ๊ฑธ๋ก ์ถ์ ๋๋ค์.
๐ ์ถ๊ฐ ๋ถ์
'๋ฉํฐ ํ๋ก์ธ์ค + ๋ฐฐ์น ์ฒ๋ฆฌ' ๋ชจ๋ํฐ๋ง ๊ฒฐ๊ณผ
Ncloud์ cloud insight ํ์ฉ
- Memory: ์ฝ 500MB ์์น
- Network Output: 100Mbps
- CPU: 50% ์์น (์ฉ๋์ด ํฐ ๋ฐ์ดํฐ์ ์ง๋ ฌํ, ํจํท ๋ฑ ๋คํธ์ํฌ ์คํ์์ ๋ถํ๊ฐ ์๊ฒผ์ ๊ฑธ๋ก ๋ณด์)
ํฅํ ๊ฐ์ ์ฌํญ
- ํ ๊ฒ์๋ฐฉ 200๋ช ์ด ์์ ๋ ๋ช ๊ฐ์ ๊ฒ์๋ฐฉ๊น์ง ๋ฒํธ ์ ์๋์ง ์ฒดํฌ ํ, ๋ณ๋ชฉ ์ฌ๋ถ์
- ๋ฐฐ์น ์ฒ๋ฆฌ ์์ด ๋ง์์ง ๋๋ฅผ ๊ฐ์ํ์ฌ ๋ฉ์์ง ์์ถ ๊ณ ๋ ค
- ๊ธ๊ฒฉํ ํธ๋ํฝ ๋ง์์ง๋ ๊ฑธ ๋๋นํด ์คํ ์ค์ผ์ผ๋ง ์กฐ๊ฑด์ ์ธ์ฐ๊ณ ํด๋ผ์ฐ๋์์ ์ค์
- ๋ชจ๋ํฐ๋ง ๋๊ตฌ๋ฅผ ๋์ ํ์ฌ ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ๋ณ๋ชฉ ๋ถ์
- ์ปค์คํ ๋ฉํธ๋ฆญ ์ธก์ ์ฝ๋๊ฐ ๋ฐฐ์น ์ฒ๋ฆฌ ๋ก์ง๊ณผ ์์ฌ์๋ ๊ฒ ๋ถ๋ฆฌ
โญ๏ธ ๊ฒฐ๋ก
์์ฝ
- ํ ๊ฒ์๋ฐฉ 200๋ช ์ํํ ํ๋ ์ด ์ง์ํ๊ณ ์ ๋ถํํ ์คํธ ์งํ
- '๋ฉํฐ ํ๋ก์ธ์ค + ๋ฐฐ์น์ฒ๋ฆฌ'๋ฅผ ๋์ ํด (ํ๊ท 5.8์ด -> 3.3์ด -> 0.06์ด๋ก) ๋๋ถ๋ถ 0.1์ด ์์ ์๋ต์ ๋ฐ์ ์ ์๊ฒ ๋๋ฉฐ ๋น์ฝ์ ์ธ ์ฑ๋ฅ ํฅ์
- ํ ๊ฒ์๋ฐฉ 200๋ช ๋ชฉํ๋ฅผ ๋ฌ์ฑํ์ผ๋ฉฐ, ๋ ๋ง์ ํธ๋ํฝ์ ๊ฐ๋นํ๊ธฐ ์ํด์๋ ์ถ๊ฐ ๊ฐ์ ์ด ํ์
๋ ํผ๋ฐ์ค
- https://aws.amazon.com/what-is/batch-processing/
- https://kakaoentertainment-tech.tistory.com/109
- https://kakaoentertainment-tech.tistory.com/110
- https://dev.to/nodedoctors/an-animated-guide-to-nodejs-event-loop-3g62
- https://socket.io/how-to/check-the-latency-of-the-connection
- https://github.com/socketio/socket.io
- https://manvscloud.com/?p=1400