๐ก ์๋ณธ๊ธ
Five API Performance Optimization Tricks that Every Java Developer Must Know
์ ๋น์ ์ API ์๋ต์ด ๋๋ฆฐ๊ฐ์? ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ ํ์๊ฐ ์์์ ์์ต๋๋ค.
๋ฐฑ์๋ ๊ฐ๋ฐ์๋ก์, ํ๋ก ํธ์๋ ์น์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํ HTTP REST API์ด๋ , ๋ด๋ถ์์ ์ฌ์ฉ์ ์ํ RPC API์ด๋ ์ฐ๋ฆฌ๋ ํญ์ ๋ค์ํ API๋ค์ ์์ฑํ๊ณ ์์ต๋๋ค.
์ด API๋ค์ ์๋น์ค ์ด๊ธฐ ๋จ๊ณ์๋ ์ ์๋ํ ์ ์์ง๋ง, ์ฌ์ฉ์ ์๊ฐ ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์ฒ์์๋ ๋น ๋ฅด๊ฒ ์๋ตํ๋ API๋ค์ด ์ ์ ๋๋ ค์ง๊ธฐ ์์ํ๋ฉด์ ์ฌ์ฉ์๋ค์ด “๋น์ ์ ์์คํ ์ ๋ฌธ์ ๊ฐ ์์ด์. ๊ทธ์ ์น ํ์ด์ง๋ฅผ ๋ณด๊ธฐ๋ง ํ๋๋ฐ ์ ์ด๋ ๊ฒ ๋๋ฆฐ๊ฑฐ์ฃ ?” ์ด๋ฌํ ๋ถ๋ง์ ํ์ถํ๊ธฐ ์์ํ ์ ์์ต๋๋ค. ์ด๋, ์ฌ๋ฌ๋ถ์ API ์ฑ๋ฅ์ ์ต์ ํ ํ๋ ๋ฐฉ๋ฒ์ ๊ณ ๋ คํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค.
API ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด์๋ ๋จผ์ ์ธํฐํ์ด์ค์ ๋๋ฆฐ ์๋ต์ ์ด๋ํ ์ ์๋ ๋ฌธ์ ์ ์ ํ์ ํด์ผ ํฉ๋๋ค. API ์ค๊ณ๋ ๋ง์ ์ธก๋ฉด์ ๊ณ ๋ ค์ ์ผ ํฉ๋๋ค.
๊ฐ๋ฐ ์ธ์ด ์์ค์ ์ผ๋ถ๋ถ์ ๋ถ๊ณผํฉ๋๋ค. ์ค๊ณ๊ฐ ์๋ชป๋ ๋ถ๋ถ์ด ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ด๋ํ ๊ฒ์ ๋๋ค. API ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์๋ ๋ง์ ์์๋ค์ด ์์ ์ ์์ผ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ด ์์ฝํ ์ ์์ต๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๋ฆฐ ์ฟผ๋ฆฌ
- ๋ณต์กํ ๋น์ง๋์ค ๋ก์ง
- ๋ฎ์ ์ฑ๋ฅ์ ์ฝ๋
- ๋ถ์กฑํ ๋ฆฌ์์ค
๋ค๋ฒ์งธ ํฌ์ธํธ์ธ ๋ถ์กฑํ ๋ฆฌ์์ค๋ ์๋์ ์ผ๋ก ํด๊ฒฐํ๊ธฐ ์ฝ์ต๋๋ค. ์์คํ ์ ์ผ์ ํ ํ์ฅ์ฑ์ด ์๋ค๋ฉด ์๋ฒ๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ํด๊ฒฐ ํ ์ ์์ต๋๋ค. ์ต์ ํ๊ฐ ํ์ํ ๋ค๋ฅธ ํฌ์ธํธ์ ๋ํด์๋ ์๋๋ฆฌ์ค์ ๋ฐ๋ผ ํด๊ฒฐ์ฑ ์ ์ ์ํด์ผ ํฉ๋๋ค. ๋ฎ์ ์ฑ๋ฅ ์ฝ๋์ ๋ํด์๋ ์ฌ์ค ์ ๋ ์ด์ ์ Java ์ฝ๋์ ์ฑ๋ฅ ์ต์ ํ์ ๋ํ ๊ธ์ ์์ฑํ ์ ์ด ์์ผ๋ฉฐ, ๊ด์ฌ์๋ ๋ ์๋ค์ ์ฝ์ด๋ณด์ธ์.
์ด ๊ธ์์๋ ์ ๋ ๋ช ๊ฐ์ง ํจ๊ณผ์ ์ธ API ์ฑ๋ฅ ์ต์ ํ ๊ธฐ์ ์ ์์ฝํ์์ต๋๋ค. ํ์ํ ๋ ์๋ค์๊ฒ ๋์์ด ๋๊ธธ ๋ฐ๋๋๋ค.
๋ณ๋ ฌ ํธ์ถ
์ด์ ์ฃผ๋ฌธ์ ํ ์ ์๋ ์ ์ ์๊ฑฐ๋ ์์คํ ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. ์ด ๊ธฐ๋ฅ์ ์ฌ๊ณ ์์คํ ์ ํธ์ถํ์ฌ ์ฌ๊ณ ๊ฒ์ฌ์ ์ฐจ๊ฐ์ ์ํํด์ผ ํ๋ฉฐ, ์ฌ์ฉ์ ์ฃผ์ ์ ๋ณด๋ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ํ ๊ด๋ฆฌ ์์คํ ์ ํธ์ถํด ์ด ๊ฑฐ๋๊ฐ ์ํํ์ง ์๋ค๋ ๊ฒ์ ํ์ธํด์ผ ํฉ๋๋ค. ์ด ์ธํฐํ์ด์ค์ ๋๋ถ๋ถ์ ์ค๊ณ๋ ์์ฐจ ์คํ ์ธํฐํ์ด์ค๋ก ์ค๊ณ๋ ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ, ๋ค์ ๋จ๊ณ๋ก ์งํํ๊ธฐ ์ ์ ์ฌ์ฉ์ ์ฃผ์ ์ ๋ณด๋ฅผ ์ป๊ณ ์ฌ๊ณ ์ฐจ๊ฐ์ ์๋ฃํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์์ฌ(Pseudo) ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ๋ ์ ์์ต๋๋ค.
๋ง์ฝ ์ด ๊ธฐ๋ฅ์ ๋ถ์ํ๋ฉด, ์ฌ๋ฌ ๋ฉ์๋ ํธ์ถ๊ฐ์ ๊ฐํ ์์กด์ฑ์ด ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ํ ์ด ์ธ ์๋น์ค์ ํธ์ถ์ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆฝ๋๋ค. ์ด ์๋น์ค๋ค์ ์๊ฐ ์๋ชจ์ ์ธ ํธ์ถ์ ๋ค์๊ณผ ๊ฐ์ด ๋ถํฌ๋๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
- stockService.check() 150ms.
- addressService.getByUser() 200ms.
- riskControlSerivce.check() 300ms.
์ด API๊ฐ ์์ฐจ์ ์ผ๋ก ํธ์ถ๋๋ค๋ฉด, ์ ์ฒด API์ ์คํ ์๊ฐ์ 650ms(150ms + 200ms + 300ms)์ ๋๋ค. ์ด๋ฅผ ๋ณ๋ ฌ ํธ์ถ๋ก ์ ํํ ์ ์๋ค๋ฉด, ์๊ฐ์ 300ms๊ฐ ๋๋ฉฐ, ์ฑ๋ฅ์ 50% ํฅ์๋ฉ๋๋ค. ์์ฌ(Pseudo) ์ฝ๋๋ ์๋์ ๊ฐ์ด ์์ฑ๋ ์ ์์ต๋๋ค.
๋๊ท๋ชจ ํธ๋์ญ์ ์ ํผํด๋ผ.
์์ ๋งํ๋ ๋๊ท๋ชจ ํธ๋์ญ์ ์ด๋ ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ํธ๋์ญ์ ์ ๋งํฉ๋๋ค. ์คํ๋ง์ @Trasaction ์ ์ฌ์ฉํ์ฌ ํธ๋์ญ์ ์ ๊ด๋ฆฌํ ๊ฒฝ์ฐ, ์ค์๋ก ๋๊ท๋ชจ ํธ๋์ญ์ ์ ์์ํ์ง ์์๋์ง ์ฃผ์ํด์ผ ํฉ๋๋ค. ์คํ๋ง์ ํธ๋์ญ์ ๊ด๋ฆฌ ์์น์ ์ฌ๋ฌ ํธ๋์ญ์ ์ ํ๋์ ์คํ์ผ๋ก ๋ณํฉํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, API์์ ๋ค์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ๊ฐ ์๊ณ ์ด API์ ๋์ ์ ๊ทผ๋์ด ์๋์ ์ผ๋ก ๋์ ๊ฒฝ์ฐ, ๋๊ท๋ชจ ํธ๋์ญ์ ์ผ๋ก ์ธํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ณผ๋ํ ๋ฐ์ดํฐ๊ฐ Lock ์ํ๊ฐ ๋๋ฉฐ ๋ง์์์ block์ด ๋ฐ์ํ์ฌ ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ฐ๊ฒฐ ํ์ด ๊ณ ๊ฐ๋ ์ ์์ต๋๋ค. ์์ ์๋ฅผ ์์ ํ๋๊ฒ ์ข์ต๋๋ค.
๋ง์ ์ฌ๋๋ค์ด ์์ฑํ ๋น์ง๋์ค ์ฝ๋์์ ์ด๋ฌํ ์ข ๋ฅ์ ์ฝ๋๊ฐ ๋ฑ์ฅํ๋ค๊ณ ๋ฏฟ์ต๋๋ค. RPC์ ๊ฐ์ non-DB ์์ ์ด ์์ก์ฑ ๊ณ์ธต ์ฝ๋์ ํผํฉ๋์ด ์์ต๋๋ค. ์ด๋ฌํ ์ฝ๋๋ ํ์คํ ๋๊ท๋ชจ ํธ๋์ญ์ ์ ๋๋ค. ์ฌ์ฉ์์ ์ฃผ์๋ฅผ ์กฐํํ๊ณ ์ฌ๊ณ ๋ฅผ ์ฐจ๊ฐํ ํ์๊ฐ ์์ ๋ฟ๋ง ์๋๋ผ, ์ฃผ๋ฌธ ๋ฐ์ดํฐ์ ์ฃผ๋ฌธ ์ธ๋ถ ์ ๋ณด๋ฅผ insert(์ฝ์ ) ํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ์ผ๋ จ์ ์์ ์ ๋์ผํ ํธ๋์ญ์ ์ผ๋ก ๋ณํฉํด์ผ ํฉ๋๋ค. RPC ์๋ต์ด ๋๋ฆฐ ๊ฒฝ์ฐ, ํ์ฌ ์ค๋ ๋๊ฐ ํญ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์ฐจ์งํ์ฌ ๋์์ฑ ์๋๋ฆฌ์ค์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ๊ณ ๊ฐ๋ฉ๋๋ค. ๋ฟ๋ง ์๋๋ผ, ํธ๋์ญ์ ์ด ๋กค๋ฐฑ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ, ๋กค๋ฐฑ์ด ๋๋ ค์ API ์๋ต์ด ๋๋ ค์ง๋๋ค.
์ด๋, ๋น์ง๋์ค๋ฅผ ์ถ์ํ๋๊ฒ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ๋นํธ๋์ญ์ ์์ ๊ณผ ํธ๋์ญ์ ์์ ์ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
๋๋ ์คํ๋ง์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ธ ํธ๋์ญ์ ์ TransactionTemplate ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ ์ ํ ์ธ๋ฑ์ค ์ถ๊ฐ
์๋น์ค๊ฐ ์ด์ ์ด๊ธฐ ๋จ๊ณ์ ์์ ๋, ์์คํ ์ด ์ ์ฅํด์ผ ํ ๋ฐ์ดํฐ์ ์์ ์ ์ต๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ ์ฅํ๊ณ ์ ๊ทผํ๊ธฐ ์ํด ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ์ง ์์์ ์๋ ์์ต๋๋ค. ํ์ง๋ง ๋น์ง๋์ค๊ฐ ์ฑ์ฅํจ์ ๋ฐ๋ผ ๋จ์ผ ํ ์ด๋ธ์ ๋ฐ์ดํฐ์ ์์ด ๊ณ์ ์ฆ๊ฐํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ ์ฑ๋ฅ์ด ์ ํ๋ฉ๋๋ค. ์ด๋, ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ ์ ํ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ํ ์ด๋ธ์ ์ธ๋ฑ์ค๋ฅผ ๋ณด๋ ค๋ฉด ์๋์ ๊ฐ์ด ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. (์ฌ๊ธฐ์๋ MySQL๋ก ์๋ฅผ ๋ญ๋๋ค.)
SHOW INDEX FROM `your_table_name`;
ALTER TABLE ๋ช ๋ น์ด๋ฅผ ์ด์ฉํด ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํฉ๋๋ค.
ALTER TABLE `your_table_name` ADD INDEX index_name(username);
๋๋๋ก, ๋ช๋ช ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๋๋ผ๋ ๋ฐ์ดํฐ ์ฟผ๋ฆฌ๊ฐ ์ฌ์ ํ ๋๋ฆด ์ ์์ต๋๋ค. ์ด๋๋ explain ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ์คํ ๊ณํ์ ๋ณด๊ณ SQL ๋ฌธ์ด ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ๊ณ ์๋์ง ํ์ธํ ์ ์์ต๋๋ค. ์๋ฅผ๋ค์ด ์๋์ ๊ฐ์ด ๋ถ์๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
EXPLAIN SELECT * FROM product_info WHERE type=0;
์ผ๋ฐ์ ์ผ๋ก, ์ธ๋ฑ์ค ๋๋ฝ์ ๋ช ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
- ๊ฐ์ฅ์ผ์ชฝ ์ ๋์ฌ(prefix) ์์น์ด ์ถฉ์กฑ๋์ง ์์์ต๋๋ค. ์๋ฅผ ๋ค์ด, tb1 ์ ๋ํด ๊ฒฐํฉ ์ธ๋ฐ์ค idx(a,b,c) ๋ฅผ ์์ฑํ์ง๋ง, SQL๋ฌธ์ด select * from tb1 where b='xxx' and c='xxxx'; ์ ๊ฐ์ด ์์ฑ๋์์ ๊ฒฝ์ฐ์ ๋๋ค.
- ์ธ๋ฑ์ค ์ด์ ์ฐ์ ์ฐ์ฐ์ด ์๋ ๊ฒฝ์ฐ ์
๋๋ค.
- select * from tb1 where a%10=0;
- like ํค์๋๋ฅผ ์ฌ์ฉํ Fuzzy ์ฟผ๋ฆฌ์
๋๋ค.
- select * from tb1 where a like '%aaa';
- not in ๋๋ not exist ํค์๋๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ
์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ
๋ง์ฝ ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌ๋ก ์กฐํํ ๋, ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ ํ์๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ํ์ด์ง ํ์์ผ๋ก ์ ์ง์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋คํธ์ํฌ๋ฅผ ํตํด ์ ์ก๋๋ ๋ฐ์ดํฐ ์์ด ์ค์ด๋ค๊ณ , ๋ฐ์ดํฐ ์ธ์ฝ๋ฉ ๋ฐ ๋์ฝ๋ฉ ์๊ฐ์ด ์ค์ด๋ค๋ฉฐ, API ์๋ต ์๋๊ฐ ๋นจ๋ผ์ง๋๋ค.
๊ทธ๋ฌ๋ ์ ํต์ ์ผ๋ก limit offset ํ์ด์ง ๋ฐฉ๋ฒ์ด ์ฌ์ฉ๋ฉ๋๋ค. (select * from product limit 10000,20) ํ์ด์ง ์๊ฐ ๋ง์ ๋, ์ฟผ๋ฆฌ๋ ์ ์ ๋๋ ค์ง๋๋ค. ์ด๋ limit offset ํ์ด์ง ๋ฐฉ์์ ์์น์ด 10000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์๋ด๊ณ ์ด์ ์ 9980๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฒ๋ฆฌ๋ ใด๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ ์ง์ฐ๋ ์๊ด ๊ด๊ณ๋ฅผ ์ฌ์ฉํด SQL์ ์ต์ ํ ํ ์ ์์ต๋๋ค.
select * from product where id in (select id from product limit 10000,20);
์บ์ ์ฌ์ฉ
์บ์ฑ์ ๊ณต๊ฐ์ ์๊ฐ์ผ๋ก ๋ฐ๊พธ๋ ํด๊ฒฐ์ฑ ์ ๋๋ค. ์ผ๋ถ ์ฌ์ฉ์์ ์ํด ์์ฃผ ์ ๊ทผ๋๋ ๋ฐ์ดํฐ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ์บ์๋ฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ์ ์ฝ๊ธฐ ์๋๊ฐ ๋์คํฌ IO๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๊ฒ ๋๋ฌธ์ ์ ์ ํ ์บ์ฑ์ ์ฌ์ฉํ์ฌ API์ ์ฑ๋ฅ์ ํฅ์ ์ํฌ ์ ์์ต๋๋ค. ๊ฐ๋จํ ๋งํด, Java HashMap, ConcurrentHashMap ๋๋ ๋ก์ปฌ ์บ์(ex: caffeine), ๋ถ์ฐ ์บ์ ๋ฏธ๋ค์จ์ด(ex) Memcached, Redis)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ฒฐ๋ก
์ฌ๊ธฐ์์ ๋ค์ฏ๊ฐ์ง ์ผ๋ฐ์ ์ธ API ์ฑ๋ฅ ์ต์ ํ ์๋ น์ ๋์ดํ์ต๋๋ค. ์ด ์๋ น๋ค์ ์์คํ ์ ์ผ์ ํ ๋์์ฑ ์์ฒญ์ด ์์ ๋๋ง ํจ๊ณผ์ ์ ๋๋ค. ๋ง์ฝ ์ฌ๋ฌ๋ถ์ ์์คํ ํธ๋ํฝ์ด ํฌ์ง ์๋ค๋ฉด, ์์ ์ ์๋ค์ ์ ์คํ๊ฒ ๊ณ ๋ คํด์ฃผ์ธ์. ๋ ํจ๊ณผ์ ์ธ ํด๊ฒฐ์ฑ ์ ์ฐพ์๋ณด์ ์ผ ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ด ๊ธ์ด ์ฌ๋ฌ๋ถ๋ค์๊ฒ ๋์๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.