logo
logo
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
MySQL
StackOverflow ์งˆ๋ฌธ ์ˆ˜: 661984
์‚ฌ์šฉ ๊ธฐ์—…
๊ต์œก
์ด์ปค๋จธ์Šค
์ธ๊ณต์ง€๋Šฅ
๊ธˆ์œต/๋ณดํ—˜
๊ธฐํƒ€
์ง์žฅ
ํŒจ์…˜
๋ถ€๋™์‚ฐ/์ธํ…Œ๋ฆฌ์–ด
์†Œ์…œ/์ปจํ…์ธ 
๋ชจ๋นŒ๋ฆฌํ‹ฐ
์—ฌํ–‰
ํ‘ธ๋“œํ…Œํฌ
ํ—ฌ์Šค์ผ€์–ด
์ข…ํ•ฉ
๋ธ”๋ก์ฒด์ธ
techstack-logo
ํด๋ผ์ธ
techstack-logo
ํŠธ๋ Œ๋น„
techstack-logo
์Šˆํผ๋ธŒ์—์ด์•„์ด
techstack-logo
๋ Œ๋”ง
techstack-logo
์—”๋ผ์ดํŠผ
techstack-logo
ํ† ์Šค๋žฉ
techstack-logo
ํ•€๋‹ค
techstack-logo
๋”œ๋ฆฌ์…”์Šค
techstack-logo
ํŒŒ์šดํŠธ
techstack-logo
์ง๋ฐฉ
techstack-logo
์—์ด๋ธ”๋ฆฌ
techstack-logo
ํ”Œ๋ ‰์Šค
techstack-logo
๋“œ๋ผ๋งˆ์•ค์ปดํผ๋‹ˆ
techstack-logo
ํด๋ž˜์ŠคํŒ…
techstack-logo
์‹์Šค์ƒต
techstack-logo
๋“œ๋ฆผ์–ด์Šค์ปดํผ๋‹ˆ
techstack-logo
์ˆจ๊ณ 
techstack-logo
์Šคํ‘ผ
๋” ๋ณด๊ธฐ
๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ ๊ธ€
SKํ…”๋ ˆ์ฝค
FastAPI์—์„œ์˜ ์˜์กด์„ฑ ์ฃผ์ž…: ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค ๊ตฌ์กฐ ๋งŒ๋“ค๊ธฐ
FastAPI๋Š” ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, Python์„ ์‚ฌ์šฉํ•ด REST API๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.์ด ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋˜ํ•œ ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ, ๋” ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…์ด ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  FastAPI์—์„œ ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.SOLID ์›์น™๊ณผ ์˜์กด์„ฑ ์—ญ์ „ ์›์น™ (DIP)SOLID ์›์น™์€ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์˜ ๋‹ค์„ฏ ๊ฐ€์ง€ ์ฃผ์š” ์›์น™์„ ์˜๋ฏธํ•˜๋ฉฐ, ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ์—์„œ ์œ ์—ฐ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค.๊ทธ์ค‘์—์„œ๋„ DIP(Dependency Inversion Principle, ์˜์กด์„ฑ ์—ญ์ „ ์›์น™)์€ ์‹ค๋ฌด์—์„œ ํŠนํžˆ ๋งŽ์ด ํ™œ์šฉ๋˜๋Š” ์›์น™ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.DIP๋Š” ๊ณ ์ˆ˜์ค€ ๋ชจ๋“ˆ(๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง)์ด ์ €์ˆ˜์ค€ ๋ชจ๋“ˆ(๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์ฒด)์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , ์ถ”์ƒํ™”์— ์˜์กดํ•˜๋„๋ก ์„ค๊ณ„ํ•จ์œผ๋กœ์จ ์‹œ์Šคํ…œ์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ์œ ์—ฐ์„ฑ์„ ๋†’์ด๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.์•„๋ž˜๋Š” ์ด ๊ตฌ์กฐ๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•œ ๋‹ค์ด์–ด๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ๊ณ ์ˆ˜์ค€ ๋ชจ๋“ˆ์€ ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๊ณ , ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์ฒด๋Š” ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋ฉ๋‹ˆ๋‹ค.DIP๋Š” ์‰ฝ๊ฒŒ ๋งํ•ด ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„ ๋Œ€์‹  ์ถ”์ƒํ™”์— ์˜์กดํ•จ์œผ๋กœ์จ, ์ฝ”๋“œ์˜ ์ˆ˜์ • ์—†์ด๋„ ๊ตฌํ˜„์ฒด๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.์ด๋กœ ์ธํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ๋ณ€ํ™”์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์œผ๋ฉฐ, ์‹œ์Šคํ…œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ํฌ๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.DIP์™€ ์˜์กด์„ฑ ์ฃผ์ž… (DI)์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection, DI)์€ ์˜์กด์„ฑ ์—ญ์ „ ์›์น™(DIP)์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.DI๋Š” ๊ฐ์ฒด๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ฐธ์กฐํ•˜์ง€ ์•Š๊ณ , ์™ธ๋ถ€์—์„œ ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›๋„๋ก ํ•จ์œผ๋กœ์จ DIP๋ฅผ ์‹คํ˜„ํ•ฉ๋‹ˆ๋‹ค.์ด๋ฅผ ํ†ตํ•ด ์‹œ์Šคํ…œ์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ , ๊ตฌํ˜„์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๊ต์ฒดํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์˜์กด์„ฑ ์ฃผ์ž…์„ FastAPI์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€, ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.์˜์กด์„ฑ ์ฃผ์ž…์€ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์„œ๋กœ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.๋ณดํ†ต ์„œ๋น„์Šค ๋กœ์ง์€ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๋กœ์ง๊ณผ ๊ฐ™์€ ํŠน์ • ๋ชจ๋“ˆ์— ์ง์ ‘ ์˜์กดํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋Š” ์‹œ์Šคํ…œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ์„ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์˜์กด์„ฑ ์ฃผ์ž…์€ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์ฒด ๋Œ€์‹  ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋„๋ก ํ•˜์—ฌ ์œ ์—ฐ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.๊ฐ„๋‹จํžˆ ๋งํ•ด, ์˜์กด์„ฑ ์ฃผ์ž…์€ ํŠน์ • ๊ฐ์ฒด๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ํ•˜๊ณ , ์™ธ๋ถ€์—์„œ ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•จ์œผ๋กœ์จ ์‹œ์Šคํ…œ์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.์ด๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„์ฒด ๋ณ€๊ฒฝ์ด ์‰ฝ๊ณ , ํ…Œ์ŠคํŠธ ์‹œ ๋ชจ์˜ ๊ฐ์ฒด(mock)๋ฅผ ์ฃผ์ž…ํ•˜์—ฌ ๋…๋ฆฝ์ ์ธ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.FastAPI์—์„œ ์˜์กด์„ฑ ์ฃผ์ž…์˜ ํ•„์š”์„ฑFastAPI์—์„œ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…์„ ์‚ฌ์šฉํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๋กœ์ง ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ , ์œ ์—ฐํ•˜๊ฒŒ ์„œ๋น„์Šค ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ• 
fastapi
mysql
๋‹น๊ทผ
LLM์„ ํ™œ์šฉํ•œ ์Šค๋งˆํŠธํฐ ์‹œ์„ธ์กฐํšŒ ์„œ๋น„์Šค ๊ตฌ์ถ•
์Šค๋งˆํŠธํฐ์„ ๋ฐ”๊พผ ํ›„ ์ด์ „์— ์ผ๋˜ ๊ธฐ๊ธฐ๋ฅผ ์ค‘๊ณ ๋กœ ํŒ”์•„๋ณด์‹  ์  ์žˆ์œผ์„ธ์š”? โ€˜์ด ์ •๋„ ์ƒํƒœ์˜ ๊ธฐ๊ธฐ๋ฉด ์–ด๋А ์ •๋„ ๊ฐ€๊ฒฉ๋Œ€๊ฐ€ ์ ๋‹นํ•œ ๊ฑฐ์ง€?โ€™ ๊ณ ๋ฏผํ•˜๋ฉฐ, ์ˆ˜๋งŽ์€ ์ค‘๊ณ  ๋งค๋ฌผ ๊ฒŒ์‹œ๊ธ€์„ ์ผ์ผ์ด ํ™•์ธํ•˜์ง€๋Š” ์•Š์œผ์…จ๋‚˜์š”? ์ด์ œ๋Š” LLM(๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ) ๋•๋ถ„์— ์ด๋ ‡๊ฒŒ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์–ด๋ ค์› ๋˜ ์ž‘์—…์ด ํ›จ์”ฌ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ํ•ด๊ฒฐ๋˜๊ณ  ์žˆ์–ด์š”.์ด ๊ธ€์—์„œ๋Š” LLM์„ ํ™œ์šฉํ•ด ์ค‘๊ณ ๊ฑฐ๋ž˜ ๊ฒŒ์‹œ๊ธ€์—์„œ ์Šค๋งˆํŠธํฐ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์‹œ์„ธ๋ฅผ ์‚ฐ์ถœํ•œ ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•ด์š”. ๋จผ์ € ์Šค๋งˆํŠธํฐ ์‹œ์„ธ์กฐํšŒ ์„œ๋น„์Šค๋ฅผ ์™œ ๋งŒ๋“ค๊ฒŒ ๋๋Š”์ง€ ๋ฐฐ๊ฒฝ์„ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณธ ํ›„, LLM์œผ๋กœ ๊ฒŒ์‹œ๊ธ€์„ ๋ถ„๋ฅ˜ยท์ •์ œํ•˜๋Š” ๊ณผ์ •, BigQuery๋ฅผ ์ด์šฉํ•ด ์ •๋ณด๋ฅผ ํ›„์ฒ˜๋ฆฌํ•˜๊ณ  ์‹œ์„ธ๋ฅผ ์ง‘๊ณ„ํ•˜๋Š” ๊ณผ์ •, ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฒกํ„ฐ DB ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์‚ฌ ๊ฒŒ์‹œ๊ธ€์„ ์ถ”์ฒœํ•˜๋Š” ๊ณผ์ •์„ ๋‹จ๊ณ„๋ณ„๋กœ ์†Œ๊ฐœํ•ด ๋“œ๋ฆด๊ฒŒ์š”. LLM์œผ๋กœ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ฐœ์„ ํ•  ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผ ์ค‘์ธ ๋ถ„๋“ค์—๊ฒŒ ์ด ์‚ฌ๋ก€๊ฐ€ ํฐ ๋„์›€์ด ๋˜๋ฉด ์ข‹๊ฒ ์–ด์š”.์Šค๋งˆํŠธํฐ ์‹œ์„ธ์กฐํšŒ ์„œ๋น„์Šค์˜ ๋ชจ์Šต์Šค๋งˆํŠธํฐ ์‹œ์„ธ์กฐํšŒ๋Š” ์™œ ํ•„์š”ํ• ๊นŒ์š”?๋งŽ์€ ์ค‘๊ณ ๊ฑฐ๋ž˜ ํŒ๋งค์ž๋“ค์ด ๋ฌผํ’ˆ์˜ ์ ์ ˆํ•œ ๊ฐ€๊ฒฉ์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฑธ ์–ด๋ ค์›Œํ•ด์š”. ๊ฐœ์ธ ๊ฐ„ ๊ฑฐ๋ž˜๋Š” ์›Œ๋‚™ ๋‹ค์–‘ํ•œ ์ƒํ’ˆ์ด ํ˜ผ์žฌ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ์š”. ์ข…๋ฅ˜๋„ ์›Œ๋‚™ ๋‹ค์–‘ํ•œ๋ฐ ์ƒํƒœ๋„ ๊ฐ€์ง€๊ฐ์ƒ‰์ด๋ผ, ๋ฌผํ’ˆ์˜ ์ •ํ™•ํ•œ ์‹œ์„ธ๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฑฐ์ฃ . ์Šค๋งˆํŠธํฐ์„ ์˜ˆ๋กœ ๋“ค๋ฉด ๋‹จ์ˆœํžˆ ๊ฐ™์€ ๊ธฐ์ข…๋งŒ ๊ฒ€์ƒ‰ํ•ด์„œ ๋๋‚  ์ผ์ด ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉ ๊ธฐ๊ฐ„, ๋ฐฐํ„ฐ๋ฆฌ ํšจ์œจ, ์Šคํฌ๋ž˜์น˜ ์—ฌ๋ถ€ ๋“ฑ ์ƒํƒœ๊ฐ€ ๋น„์Šทํ•œ ๊ธฐ๊ธฐ๊ฐ€ ์–ผ๋งˆ์— ํŒ”๋ฆฌ๋Š”์ง€ ์ผ์ผ์ด ํ™•์ธํ•ด์•ผ ํ•˜๋Š” ๊ฑฐ์˜ˆ์š”.์ค‘๊ณ ๊ฑฐ๋ž˜ํŒ€์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌผํ’ˆ์˜ ์‹œ์„ธ๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•˜๊ณ  ๋” ์‰ฝ๊ฒŒ ๊ฐ€๊ฒฉ์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก, ์•„์ดํฐ, ๊ฐค๋Ÿญ์‹œ ๊ธฐ์ข…์„ ๋Œ€์ƒ์œผ๋กœ ํ•œ ์Šค๋งˆํŠธํฐ ์‹œ์„ธ ์กฐํšŒ ์„œ๋น„์Šค๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๋กœ ํ–ˆ์–ด์š”. ๋‹ค์–‘ํ•œ ๋ฌผํ’ˆ ์ค‘ ์Šค๋งˆํŠธํฐ์„ ๋ฒ ํƒ€ ํ…Œ์ŠคํŠธ ๋Œ€์ƒ์œผ๋กœ ์„ ์ •ํ•œ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”. ์Šค๋งˆํŠธํฐ์€ ์ œํ’ˆ ๋ชจ๋ธ์ด ๋ช…ํ™•ํ•˜๊ณ  ๊ฒŒ์‹œ๊ธ€ ์ˆ˜๊ฐ€ ๋งŽ์•„ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์‹œ์„ธ ๊ณ„์‚ฐ์— ์œ ๋ฆฌํ•ด์š”. ๋˜ ํŒ๋งค ๋‹จ๊ฐ€๊ฐ€ ๋†’์•„ ๊ฐ€๊ฒฉ ๊ฒฐ์ •์ด ์ค‘์š”ํ•œ ์ƒํ’ˆ์ด๊ธฐ๋„ ํ•˜๊ณ ์š”.๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ชจ๋ธ, ์šฉ๋Ÿ‰, ์ƒˆ ์ƒํ’ˆ ์—ฌ๋ถ€, ์Šคํฌ๋ž˜์น˜ ๋ฐ ํŒŒ์†, ๋ฐฐํ„ฐ๋ฆฌ ํšจ์œจ ๋“ฑ ๊ตฌ์ฒด์ ์ธ ๋ฌผํ’ˆ ์ƒํƒœ์— ๋”ฐ๋ผ ์‹œ์„ธ๊ฐ€ ์–ด๋А ์ •๋„์ธ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ โ€˜์•„์ดํฐ 16 Pro 128GBโ€™๋ฅผ ์„ ํƒํ•˜๊ณ  ํ•„ํ„ฐ์—์„œ ๊ตฌ์ฒด์ ์ธ โ€˜์‚ฌ์šฉ ์ƒํƒœโ€™๋‚˜ โ€˜๋ฐฐํ„ฐ๋ฆฌ ์„ฑ๋Šฅโ€™์„ ์„ค์ •ํ•˜๋ฉด, ๊ณง๋ฐ”๋กœ ๊ทธ์— ๋”ฐ๋ฅธ ์‹œ์„ธ ์ •๋ณด๋ฅผ โ€˜OOO๋งŒ์›-OOO๋งŒ์›โ€™๊ณผ ๊ฐ™์€ ๊ฐ€๊ฒฉ ๋ฒ”์œ„์˜ ํ˜•ํƒœ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” ๋จธ์‹ ๋Ÿฌ๋‹์„ ํ™œ์šฉํ•ด ๋‹น๊ทผ ์ค‘๊ณ ๊ฑฐ๋ž˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •ํ™•ํ•œ ์‹œ์„ธ๋ฅผ ์ œ๊ณตํ•œ ์ฒซ ๋ฒˆ์งธ ์‹œ๋„๋กœ, ํŒ€ ๋‚ด์—์„œ๋„ ์˜๋ฏธ๊ฐ€ ํฐ ํ”„๋กœ์ ํŠธ์ด๊ธฐ๋„ ํ–ˆ๋Š”๋ฐ์š”. ๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋‚˜๊ฐ„ ๊ณผ์ •์„ ๋‹จ๊ณ„๋ณ„๋กœ ์†Œ๊ฐœํ•ด ๋“œ๋ฆด๊ฒŒ์š”.Step 1. ์ƒํ’ˆ ์ •๋ณด ์ถ”์ถœ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ๊ฒŒ์‹œ๊ธ€์—์„œ ์ƒํ’ˆ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ฒƒ์ด์—์š”. ๋‹น๊ทผ์€ ํŒ๋งค์ž์˜ ๊ธ€์“ฐ๊ธฐ ํ—ˆ๋“ค์„ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ์ค‘๊ณ ๊ฑฐ๋ž˜ ๊ฒŒ์‹œ๊ธ€์— ๊ตฌ์ฒด์ ์ธ ๊ธฐ์ข…์ด๋‚˜ ๋ฌผํ’ˆ ์ƒํƒœ๋ฅผ ์ž…๋ ฅํ•˜๋„๋ก ์š”๊ตฌํ•˜์ง€ ์•Š์•„์š”. ํ•˜์ง€๋งŒ ๊ตฌ์ฒด์ ์ธ ๋ฌผํ’ˆ ์ƒํƒœ๋ณ„๋กœ ์Šค๋งˆํŠธํฐ ์‹œ์„ธ๋ฅผ ์ œ๊ณตํ•˜๋ ค๋ฉด ๋ชจ๋ธ, ์šฉ๋Ÿ‰, ์ƒˆ ์ƒํ’ˆ ์—ฌ๋ถ€, ์Šคํฌ๋ž˜์น˜ ๋ฐ ํŒŒ์† ์—ฌ๋ถ€, ๋ฐฐํ„ฐ๋ฆฌ ํšจ์œจ ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์„ ์•Œ์•„๋‚ด์•ผ ํ–ˆ์–ด์š”.๊ธฐ์กด์—๋Š” ์ด๋Ÿฐ
googlebigquery
mysql
์นด์นด์˜คํŽ˜์ด
JPA Transactional ์ž˜ ์•Œ๊ณ  ์“ฐ๊ณ  ๊ณ„์‹ ๊ฐ€์š”?
dory.m ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ตœ๊ทผ์— ๋“ค์–ด์„  ์‰ฝ๊ฒŒ ์Šค์ผ€์ผ ์•„์›ƒ ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ์ง€๋งŒ, ์•„์ง๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ท€์ค‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฆฌ์†Œ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋‹ค์‹œ๊ธˆ ์ƒ๊ฐํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธ€์ž…๋‹ˆ๋‹ค.wade.hong JPA๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๊ตฌ๋™๋˜๋Š” ์›๋ฆฌ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์•Œ์•„์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์ ์—์„œ ์ด ๋‚ด์šฉ์€ ํ•„์ˆ˜์ ์œผ๋กœ ๋ด์•ผ ํ•˜๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ๋” JPA Transactional๋ฅผ ์ ๊ฒ€ํ•  ๊ธฐํšŒ์ธ ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค.wonny.p ๋‹น์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋˜ Transactional์— ๋Œ€ํ•ด์„œ ๊ณ ์ฐฐํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์„ ๊ฐ–๊ฒŒ ํ•ด์ฃผ๋Š” ์ข‹์€ ๊ธ€์ด๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.๐Ÿ‘๐Ÿป ์‹ค์ œ ๊ฐœ์„ ํ–ˆ๋˜ ๋‚ด์šฉ๋“ค์ด ๋“ค์–ด ์žˆ์–ด์„œ ๋”์šฑ ์ฝ๊ธฐ ์ข‹์•˜์Šต๋‹ˆ๋‹ค.์•ˆ๋…•ํ•˜์„ธ์š” ์นด์นด์˜คํŽ˜์ด์—์„œ ์˜จ๋ผ์ธ๊ฒฐ์ œ ์„œ๋น„์Šค ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ๋งก๊ณ  ์žˆ๋Š” bri.ghten์ž…๋‹ˆ๋‹ค.๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” JPA Transactional๊ณผ ๊ทธ์— ๋”ฐ๋ฅธ DB ์ฟผ๋ฆฌ ์„ฑ๋Šฅ๊ณผ์˜ ๊ด€๊ณ„์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ DB Transaction๊ณผ Spring Transactional, JPA, Spring data source์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.DataSource๋กœ๋Š” Mysql์„ ๊ธฐ์ค€์œผ๋กœ ์„ค๋ช…ํ•˜๋ฉฐ ์ฟผ๋ฆฌ ํŠœ๋‹ ๋ฐ ์ธ๋ฑ์Šค ํŠœ๋‹์œผ๋กœ ์ธํ•œ ์„ฑ๋Šฅ ๊ฐœ์„ ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.์–ด๋А ๋‚  DBA ์—๊ฒŒ์„œ ์œ„ํ—˜ ์•Œ๋ฆผ์ด ์™”๋‹ค.์–ด๋А ๋‚ , DBA๊ฐ€ ์„œ๋น„์Šค ์œ„ํ—˜์„ ๊ฐ์ง€ํ•˜๊ณ  ์•Œ๋ฆผ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.๋‹น์‹œ ์ง€ํ‘œ๋ฅผ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.peak total qps๋Š” 24K ์ •๋„๋กœ ์žกํ˜€์žˆ์—ˆ์ง€๋งŒ select์™€ commit ์ฟผ๋ฆฌ๋Š” ์•ฝ 5K, update์™€ insert ์ฟผ๋ฆฌ๋Š” 3K ๋ฏธ๋งŒ์œผ๋กœ ์‹๋ณ„์ด ํž˜๋“ค์—ˆ๊ณ , set_option ์ฟผ๋ฆฌ๊ฐ€ ์•ฝ 14K ์ •๋„๋กœ ๋†’๋‹ค๋Š” ์ ์ด ์ˆ˜์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. set_option ์ฟผ๋ฆฌ๋ฅผ ์‚ดํŽด๋ณผ ํ•„์š”๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.Mysql์—์„œ์˜ set_option์€ ๋ง ๊ทธ๋Œ€๋กœ option setting ํ•˜๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์นด์นด์˜คํŽ˜์ด ์˜จ๋ผ์ธ๊ฒฐ์ œ ์„œ๋น„์Šค์˜ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ DB ๋กœ๊ทธ๋ฅผ ์•ฝ 4์ผ๊ฐ„ ์ผœ๋‘๊ณ  ์–ด๋–ค ์ฟผ๋ฆฌ๋“ค์ด ๊ฐ€์žฅ ๋งŽ์ด ํ˜ธ์ถœ๋˜๋Š”์ง€ 10์œ„๊นŒ์ง€์˜ ์ˆœ์œ„๋ฅผ ์ฐพ์•„๋ดค์Šต๋‹ˆ๋‹ค.์ด ์ค‘ set_option๊ณผ ์—ฐ๊ด€๋œ ์ฟผ๋ฆฌ๋“ค์„ ๋ณด๋‹ˆ , , , ๋“ฑ์ด ์žˆ๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €ํฌ๋Š” ์—ฌ๊ธฐ์„œ autocommit๊ณผ transaction ๊ด€๋ จ ์ฟผ๋ฆฌ๋ฅผ ๋ˆˆ์—ฌ๊ฒจ๋ณด์•˜์Šต๋‹ˆ๋‹ค.์นด์นด์˜คํŽ˜์ด ์˜จ๋ผ์ธ๊ฒฐ์ œ ์„œ๋น„์Šค ๋ฐฑ์—”๋“œ์—์„œ๋Š” JPA๋ฅผ ํ†ตํ•œ DB Access ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ์š”. ์—ฌ๊ธฐ์„œ JPA Transactional์ด DB ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ, ์ฆ‰ DB ์กฐํšŒ ์„ฑ๋Šฅ์— ์•Œ๊ฒŒ ๋ชจ๋ฅด๊ฒŒ ์˜ํ–ฅ์„ ๋ผ์น˜๊ณ  ์žˆ์Œ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.์‹ค์ œ๋กœ set_option๊ณผ commit์ด ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น ๊นŒ?autocommit๊ณผ transaction ๊ด€๋ จ ์ฟผ๋ฆฌ๊ฐ€ ์กฐํšŒ ์ฟผ๋ฆฌ๋„ ์•„๋‹ˆ๊ณ  DB cpu๋‚˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์žก์•„๋จน๋Š” ํฐ ํ—ˆ๋“ค์ด ๋ ๊นŒ ์‹ถ์—ˆ์ง€๋งŒ ์ง์ ‘ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด ํ™•์ธํ•ด ๋ณด๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋Š” ์šด์˜ ์ค‘์ธ ์„œ๋น„์Šค์—์„œ ์‹ค์ œ ์ตœ๋‹ค ์กฐํšŒ๋˜๋Š” ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.์•„๋ž˜ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ํ…Œ์ŠคํŠธํ•œ ์‹ค์ œ ์˜ˆ์ œ์ฝ”๋“œ์™€ ์ตœ๋Œ€ํ•œ ๋น„์Šทํ•˜๊ฒŒ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.ํ•ด๋‹น ์ฝ”๋“œ๋กœ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜์˜€๊ณ  ์™ธ๋ถ€ ์š”์ธ์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด osiv=false๋กœ ๋‘
mysql
spring
์—ฌ๊ธฐ์–ด๋•Œ์ปดํผ๋‹ˆ
Aurora Serverless ์•Œ์•„๋ณด๊ธฐ
์•ˆ๋…•ํ•˜์„ธ์š”, SREํŒ€์— DBA๋กœ ์ƒˆ๋กœ ํ•ฉ๋ฅ˜ํ•œ ๋ธŒ๋ผ์šฐ๋‹ˆ์ž…๋‹ˆ๋‹ค.AWS Service์— ์—ฌ๋Ÿฌ ์„œ๋น„์Šค๊ฐ€ ์žˆ์ง€๋งŒ ๊ทธ ์ค‘์—์„œ๋„ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์ œ๋ฅผ ๋‹ค๋ค„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์„ ํƒํ•œ ์ฃผ์ œ๋Š” AWS์—์„œ ์ œ๊ณตํ•˜๋Š” Aurora Serverless v2์ž…๋‹ˆ๋‹ค. Aurora Serverless v2๋Š” Aurora MySQL ํ˜ธํ™˜ ๋ฒ„์ „ ๋ฐ PostgreSQL ํ˜ธํ™˜ ๋ฒ„์ „์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋ช…์นญ์˜ ํ˜ผ์„ ์„ ์—†์• ๊ธฐ ์œ„ํ•ด Aurora Serverless(Aurora Serverless Mysql v2)์™€ Aurora MySQL(๊ธฐ์กด Aurora MySQL)๋กœ ์ง€์นญํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Aurora Serverless ์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•œ ์†Œ๊ฐœ์™€ ๋”๋ถˆ์–ด Aurora MySQL๊ณผ ๋Œ€์กฐ๋ฅผ ํ•ด ๋ณด๊ณ , ๊ทธ ์ค‘ ์ฃผ๋ชฉํ• ๋งŒํ•œ ์ ์— ๋Œ€ํ•ด ์„ฑ๋Šฅ ์œ„์ฃผ๋กœ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.์ฐธ์กฐ : Aurora Serverless v2 ์‚ฌ์šฉํ•˜๊ธฐโ€Šโ€”โ€ŠAmazon AuroraAmazon AuroraAurora Serverless์˜ ๊ฐœ์š” ๋ฐ ์ฃผ์š” ํŠน์ง•Aurora Serverless๋ž€?Aurora Serverless๋Š” Aurora MySQL์— ๋Œ€ํ•œ ์˜จ๋””๋งจ๋“œ ๋ฐฉ์‹์˜ ์ž๋™ ํฌ๊ธฐ ๊ตฌ์„ฑ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” AWS ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด์—๋Š” Aurora MySQL์„ ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ์ƒˆ๋กœ์šด ๋ถ€ํ•˜ ์ƒํ™ฉ์„ ๋ฏธ๋ฆฌ ์˜ˆ์ƒํ•˜์—ฌ ์ฆ์„คํ•ด์•ผ๋งŒ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, Aurora Serverless ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ž๋™์œผ๋กœ ํ™•์žฅ/์ถ•์†Œ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด์„œ๋Š” ์š”๊ธˆ์„ ์ง€๋ถˆํ•˜์ง€ ์•Š๊ณ  Aurora์˜ ๊ณ ๊ฐ€์šฉ์„ฑ, ํ™•์žฅ์„ฑ์„ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋น ๋ฅธ ์†๋„๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํŠธ๋ž˜ํ”ฝ์„ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์„ ๋•Œ ์ ์ ˆํ•œ ๊ตฌ์„ฑ์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹คAurora Serverless๋Š” v1, v2๋กœ ๋ฒ„์ „์ด ๋‚˜๋‰˜์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Aurora MySQL์€ v1,v2,v3๊ฐ€ ์žˆ๋Š”๋ฐ, ํ˜„์žฌ๋Š” Aurora MySQL v3์—์„œ Aurora Serverless v1 ์‚ฌ์šฉ์€ ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.์ฐธ์กฐ : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/Concepts.Aurora_Fea_Regions_DB-eng.Feature.ServerlessV1.html#Concepts.Aurora_Fea_Regions_DB-eng.Feature.ServerlessV1.amyAurora Serverless์—์„  ACU(Aurora Capacity Unit)๋ผ๋Š” ๋‹จ์œ„๋ฅผ ์ด์šฉํ•˜์—ฌ Resource๋ฅผ ์ •ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 0.5 ~ 128 ACU๊นŒ์ง€ ๋ฒ”์œ„๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ตœ์†Œ๋‹จ์œ„ ACU๋กœ ์ดˆ๋‹น ๊ณผ๊ธˆ๋ฉ๋‹ˆ๋‹ค. 1 ACU= ๋Œ€๋žต ์ ์œผ๋กœ 2GB Memory + CPU + Network ์˜ ์กฐํ•ฉ์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ACU๋Š” ServerlessDatabaseCapacity์™€ ACUUtilization, ๋‘ ๊ฐ€์ง€ ์ง€ํ‘œ๋ฅผ ํ†ตํ•ด ์†์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ฐธ์กฐ : Aurora Serverless v2์˜ ์„ฑ๋Šฅ ๋ฐ ํฌ๊ธฐ ์กฐ์ •โ€Šโ€”โ€ŠAmazon AuroraScale Up / Down์— ๋”ฐ๋ผ
awsauroradb
mysql
์—ฐ๊ด€ ๊ธฐ์ˆ  ์Šคํƒ
techstack-logo
AWS AuroraDB
techstack-logo
AWS MariaDB
techstack-logo
OracleDB
techstack-logo
PostgreSQL
Copyright ยฉ 2025. Codenary All Rights Reserved.