๐ ๋ ๋น ๋ฅด๊ฒ ๋ฌ๋ฆฌ๊ธฐ ์ํด ์ ๊น ๋ฉ์ถ๊ธฐ
์ฌ์ด๋ ํ๋ก์ ํธ, ๋ค๋ฆ์ ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ๊ธฐ (with. TestContainer)
๋ ๋น ๋ฅด๊ฒ ๋ฌ๋ฆฌ๊ธฐ ์ํด ์ ๊น ๋ฉ์ถ๋ค..
์ฝ๊ฐ ๋ชจ์์ด ๋๋ ๋ฌธ์ฅ์ด๊ธฐ๋ ํ๋ฐ์,
์ด๋ฒ ํฌ์คํ ์ ์ฃผ์ ๊ฐ ํ ์คํธ ์ฝ๋๋ผ๋ ๊ฒ์ ์๊ณ ๋ค์ ์ ๋ชฉ์ ์ฝ์ด๋ณธ๋ค๋ฉด
์ด๋์ ๋๋ ๋ค๋ค ๊ณต๊ฐ์ด ๊ฐ ๋งํ ์ ๋ชฉ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. (๐ ํฌํ )
์๋ 10์์ธ๊ฐ์?
๊ทธ๋๋ถํฐ ์์ํ ์ฌ์ด๋ ํ๋ก์ ํธ์ธ ๋ํผ๋ก
๋ 2 ๊ฐ์ ์์ ๊ธฐํ/๊ฐ๋ฐ/๋์์ธ์ด ์๋ฃ๋์ด
๋ฐ๋ชจ ์ดํ์ ์์ฐํ ์ ์์ด์ผ ํ์ด์.
์ค๊ฐ์ ๊ธฐํ์ด ๋ณ๊ฒฝ๋๊ธฐ๋ ํ๊ณ
์์ฐ ์ง์ ๊น์ง๋ ์๋ก์ด ์๊ตฌ์ฌํญ์ด ์ถ๊ฐ๋๊ฑฐ๋ ๊ธฐ์กด ๊ธฐ๋ฅ ์คํ์ด ์์ ๋๋ ์ผ์ด ๋งค์ฐ ๋ง์๊ธฐ ๋๋ฌธ์
์ฌ์ค์ ํ ์คํธ ์ฝ๋์ ํ ์ ํ ์๊ฐ๊ณผ ์ฌ๋ ฅ์ด ์์๋ ๊ฒ ๊ฐ์์โฆ
ํด์ปคํค ๊ฐ์ ๋๋์ผ๋ก ํ๋ฃจ ํ๋ฃจ ๊ฐ๋ฐํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๋ฒฝํ DDD (๋ฐ๋๋ผ์ธ ์ฃผ๋ ๊ฐ๋ฐ) ์ด์์ฃ ใ ใ ใ ใ ใ ใ ใ
์๋ ํ๋ฐ๊ธฐ๋ฅผ ๋ถํ์ ๋ ์ฌ์ด๋ ํ๋ก์ ํธ ๋ํผ๋ก๋,
์ฌ 2์๋ถํฐ ๋ค์ ๋ฌ๋ ค๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
์ ๐ ~
์๋ ํ๋ฐ๊ธฐ 2๊ฐ์ ๊ฐ,
์์ฌ๋ฒ๋ฆฐ ๊ธฐ์ ๋ถ์ฑ๋ฅผ ๋ฆฌ์คํธ์ ํ๊ณ ํ๋ํ๋ ํด๊ฒฐํด๋๊ฐ๋ ์ค์ธ๋ฐ์
์ด๋ฒ์ ์ด์ผ๊ธฐํ ๋ด์ฉ์ ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ์ ๋๋ค. (๋๋ฅ)
ํ ์คํธ ํ๊ฒฝ..?
๊ทธ๊ฑฐ ๊ทธ๋ฅ ํ๋ฉด ๋๋๊ฑฐ ์๋์ผ..?
๋ผ๊ณ ์๊ฐํ ์ ์์ง๋ง, ๋ํผ๋ก ๋ฐฑ์๋์์๋ ์ฌ์ค ๋ง์ ๊ณ ๋์ ์ํ์ฐฉ์ค๊ฐ ์์๋๋ฐ์..
์ฐจ๊ทผ์ฐจ๊ทผ ์๊ฐํ๋๋ก ํ๊ฒ ์ต๋๋ค.. ๐ญ
์ ๋ชฉ์ ์ ๊น ๋ค์ ๋ณด๋ฉดโฆ
๋ ๋น ๋ฅด๊ฒ ๋ฌ๋ฆฌ๊ธฐ ์ํด ์ ๊น ๋ฉ์ถ๊ธฐ.
์ด ๋ฌธ์ฅ์,
ํ ์คํธ ์ฝ๋๋ฅผ ์ ์์ฑํด์ผ ํ๋ ์ง ๊ทธ ์ด์ ๋ฅผ ํจ์ถ์ ์ผ๋ก ์์ฃผ ์ ๋ด๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์์ผ๋ก ๊ธฐํ์ด ๊ณ ๋ํ๋๋ฉด์
๊ธฐ์กด ๊ธฐ๋ฅ์ ํ์ฅ์ํค๊ฑฐ๋
์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ผ์ด ๋ถ๋ช ๋ง์์ง ๊ฒ ๊ฐ์๋ฐ์,
(์๋ํ ๋ ํ ์คํธ ์ฝ๋๋ ์๋ค๊ณ ๊ฐ์ )
A ์์ญ์ ์ด์ฌํ ์๋์ผ๋ก ํ
์คํธํด์ ๋ณด์ฅ๋ ๊ธฐ๋ฅ
์ด ๋์๋ค๊ณ ํด๋ด
์๋ค.
๊ทธ๋ฆฌ๊ณ ๊ณ ๋ํ ์์ ์ ์งํํ๋ฉฐ Aโ ๊ธฐ๋ฅ์ ํ์ฅํ์์ด์.
๋ฌผ๋ก A์ Aโ ์ด ๊ฒน์น์ง ์๋ ๋ถ๋ถ์ ์๋ก ํ ์คํธ๋ฅผ ์งํํด์ผ๊ฒ ์ง๋ง,
A ์ Aโ ์ด ๊ฒน์น๋ ๋ถ๋ถ๋ ๋ ๋ค์ ์๋์ผ๋ก ํ ์คํธ๋ฅผ ํด์ผ๊ฒ ์ฃ .
์ดํ์ B ๋ผ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด,
์์ ํ ์๋ก์ด ๊ธฐ๋ฅ์ธ B ๋ฟ๋ง์ด ์๋๋ผ A ์ B ๊ฐ ๊ฒน์น๋ ๊ตฌ๊ฐ๋ ํ ์คํธํด์ผ ํด์.
๊ธฐ์กด์ ํ ์คํธ๋ฅผ ํ๋ ์์ญ์ ๊ณ์ ๋ฐ๋ณต์ ์ผ๋ก ํ ์คํธํ๊ณ ์๋ ๋นํจ์จ์ ์ธ ์ํฉ์ ํ์ธํ ์ ์์ด์.
์์ ๊ฐ์ ์ํฉ์์๋ ๊ฒฌ๊ณ ํ ์์คํ ์ ๊ฐ๋ฐํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
์๋ก์ด ์๋น์ค ํผ์ณ๋ฅผ ๊ฐ๋ฐํ๋ ค๋ฉด, ํด๋น ๊ฐ๋ฐ ๊ฑด์ด ํ์ฌ ๋์ ์ค์ธ ์ด๋ค ๋ถ๋ถ์ ์ํฅ์ด ๊ฐ ์ง
์๋์ผ๋ก ํ์ธํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ฐ์ฑ์ด ํ์ ํ ๋จ์ด์ง๊ฒ ์ฃ .
๋ง์ฝ..
์ ์์ฑ๋, ์๋ํ ๋ ํ ์คํธ ์ฝ๋๊ฐ ์์๋๋ผ๋ฉด
์๋ก์ด ๊ธฐ๋ฅ์ ๊ตฌํํ๊ฑฐ๋, ๊ธฐ์กด ๊ธฐ๋ฅ์ ์์ ๊ฐ์์๋๋ผ๋ ์ ํ ๋๋ ค์ ์์ด ๊ฐ๋ฐํ ์ ์๊ฒ ์ฃ .
๋ ๋นจ๋ฆฌ ๋ฌ๋ฆฌ๊ธฐ ์ํด, ์ ๊น ๋ฉ์ถฐ์ผ ํ๋ค๋ ์๋ฏธ๋ ์ด๊ฑฐ์์.
์ฐ๋ฆฌ ์ฌ์ด๋ ํ๋ก์ ํธ์ธ ๋ํผ๋ก
๋,
์๋ 2๊ฐ์ ๊ฐ ๋ฐ๋ชจ๋ฐ์ด ์ถ์๋ผ๋ ๋จ๊ฑฐ๋ฆฌ ๊ฑฐ๋ฆฌ ์ง์ฃผ๋ ํด๋์ง๋ง
ํ ์คํธ ํ๊ฒฝ์ด ์ ํ ๊ตฌ์ถ๋์ด์์ง ์์๊ธฐ ๋๋ฌธ์
๋ ๋น ๋ฅด๊ฒ ์ค๋ ๋ฌ๋ฆด ์ ์๋ ์ฌ๋ ฅ์ด ๋จ์์์ง ์์์ต๋๋ค.
๊ทธ๋์ ์ง๊ธ์ ์ ๊น ๋ฉ์ถ๊ณ , ๋ ๋ฉ๋ฆฌ ๊ฐ๊ธฐ ์ํ ์ ๋น๋ฅผ ํด์ผํ ๋๋ผ๊ณ ๊ฒฐ์ ํ์ฃ .
์๋ก ์ด ๊ธธ์๋ ๊ฒ ๊ฐ๋ค์.
์์ฝํ์๋ฉด, ์ฌ์ด๋ ํ๋ก์ ํธ ๋ํผ๋ก
์ ๊ธฐ์ ๋ถ์ฑ ์ค ํ๋์ธ ํ
์คํธ ํ๊ฒฝ ๊ตฌ์ถ์ ์ง๊ธ ํด๊ฒฐํด์ผ๋ง ํ๋ค.
์ด๊ฑด๋ฐ์..!
๋ํผ๋ก ๋ฐฑ์๋์์ ํ ์คํธ ํ๊ฒฝ์ ์ฝ๊ฒ ๊ตฌํํ์ง ๋ชปํ๊ฒ ํ๋ ํ๋ค์ ๋ฌด์์ด ์์์๊น์?
๋ํผ๋ก์์ ์ ๊ณตํ๋ ํต์ฌ ๊ธฐ๋ฅ ์ค ํ๋๋ ํ์ฌ ์์น๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๊น์ด ๋ํผ์๋ค์ ์กฐํํ๋ API ์ ๋๋ค.
๊ฐ๊ฐ์ ์์น๋ ์๊ฒฝ๋ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์กฐํํ๋ฉฐ,
๋ํผ์์ ์ฌ์ฉ์ ๊ฐ ๊ฑฐ๋ฆฌ ๋ํ ์ค์๊ฐ์ผ๋ก ๊ณ์ฐ์ด ๊ฐ๋ฅํด์ผ ํ์ต๋๋ค.
์์ ๊ฐ์ด ๋ํผ๋ก๋ ๊ณต๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ต๋๋ค.
๊ณต๊ฐ ๋ฐ์ดํฐ ๊ด๋ จ ํ๋ถํ ๊ธฐ๋ฅ์ ์ ๊ณตํด์ฃผ๋ mysql ์ ๋ฉ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ง์ผ๋ก ์ ํํ ์ด์ ๋ ์ด๋๋ฌธ์ด์๋๋ฐ์..!
( ์ถํ์ ๊ณต๊ฐ ์ธ๋ฑ์ค ๊ด๋ จํ ์ฟผ๋ฆฌ ํ๋ ํฌ์คํ ์ด ์์ ๋์ด ์์ต๋๋ค ~ )
๋ณดํต ํ ์คํธ ํ๊ฒฝ์์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ ๋ง ๊ฐํธํ๊ฒ ๊ตฌ์ถํ ์ ์๋ h2 DB ๋ฅผ ๋ง์ด ์ฌ์ฉํ์ฃ .
๋ค๋ง ๋ํผ๋ก์์๋ ์ง๊ธ๋, ์์ผ๋ก๋ mysql ์์ ์ ๊ณตํ๋ ๊ณต๊ฐ ๋ฐ์ดํฐ ํ์ / ํจ์๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ์ฌ ์ฑ๋ฅ ๊ฐ์ ์ ํด๋๊ฐ ๊ณํ์ด๊ธฐ ๋๋ฌธ์
H2 ๊ธฐ๋ฐ์ ํ ์คํธ ํ๊ฒฝ์ผ๋ก๋ ์ ์ฝ์ด ๋ง์์ต๋๋ค.
ํ ์คํธ ์ฝ๋๋ฅผ ์ํํ๊ฒ ํ๊ธฐ ์ํด,
ํ๋ก๋์ ์ฝ๋์์ mysql ์ ์์กด์ ์ธ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ฐฉ๋ฒ๋ ์์๋๋ฐ์
๊ทธ๋ฌ๊ธฐ์๋ mysql ์์ ์ ๊ณตํด์ฃผ๋ ์์น ๊ธฐ๋ฐ ๊ธฐ๋ฅ์ด ๊ฐ๋ ฅํ๊ธฐ ๋๋ฌธ์ ์ข์ง ์๋ค๊ณ ํ๋จํ์ต๋๋ค.
์๋๋ฉด ํ ์คํธ ํ๊ฒฝ์์ ํด๋น ๊ธฐ๋ฅ๋ค์ ๋ชจ๋ mocking ํด๋ ๋ ํ ๋ฐ์,
์ธ๋ถ ์์คํ ์ด ์๋ ๋ํผ๋ก ์๋น์ค์ ํต์ฌ ๊ธฐ๋ฅ์ธ๋ฐ ์ด๋ฅผ mocking ํ๋ ๊ฒ ๊ณผ์ฐ ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๊น์?
๋น์ฐํ.. ์๋๊ฒ ์ฃ .
๊ทธ๋ฌ๋ฉด ๋จ์ ๋ฐฉ๋ฒ์ ๋จ ํ๋.
ํ ์คํธ ํ๊ฒฝ์ h2 ๊ฐ ์๋ mysql ์ ์ฌ์ฉํ๋ฉด ๋๋๊ฑฐ์ฃ ! (๋น์ฐ)
์ ๊ทธ๋ผ ๋ฌธ์ ์ ์๊ฐ ์กฐ๊ธ ๋ฐ๋์๋ค์.
ํ
์คํธ ํ๊ฒฝ์์ mysql ์ ์ด๋ป๊ฒ ๊ตฌ์ถํ๋ฉด ์ข์๊น์?
๊ฐ์ ๋ก์ปฌ์ mysql ์ demon ์ผ๋ก ์คํ์ํจ ๋ค, ํ๋ก๋์ db ๋ฅผ dump ํด์ ์ฌ์ฉํ๋๋ก ํ๋ฉด ์ด๋จ๊น์?
ํ โฆ
๋๋ฌด ๋ก์ปฌ ํ๊ฒฝ์ ์์กด์ ์ด์ฃ .
โ์ค ์ปด์์ ํ
์คํธ๊ฐ ๋ค ์ฑ๊ณตํ๋๋ฐ ์ ์ ์๋๋๊ฑฐ์ฃ ?โ
ํ๋ก๋์ db ์ ์คํค๋ง๋ฅผ ํญ์ ๋๊ธฐํํด์ฃผ์ด์ผ ํ๋ค๋ ๊ด๋ฆฌํฌ์ธํธ๋ ํ๋ ๋์ด๋ฉ๋๋ค..
ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ์ด ๋งค์ฐ ๊ฐํธํ๊ณ ํธ๋ฆฌํด์ผ,
๋ ๋ง์ ์๊ฐ์ ํ ์คํธ ์ฝ๋์ ํ ์ ํ๋๋ก ์ ๋ํ ์ ์๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์
์ด ๋ฐฉ๋ฒ์ ๊ธฐ๊ฐํ์ต๋๋ค.
์..
๋ค๋ฅธ ์ข์ ๋ฐฉ๋ฒ์ด ์์๊น์?
๋ก์ปฌ ํ๊ฒฝ์.. ์ข ์์ ์ด์ง ์์ ํ ์คํธ ํ๊ฒฝ์ด๋ผ..
์ ์ด๊ฑฐ ์์ ์ปจํ ์ด๋ ๊ฐ๋ ์๋๊ฐ์? (๋๋ฅ)
ํ ์คํธ๋ฅผ run ํ๋ฉด
ํ ์คํธ ์ฉ๋์ ๋์ปค ์ปจํ ์ด๋๊ฐ ๋์์ง๊ณ
ํ ์คํธ๊ฐ ๋๋๋ฉด ์ปจํ ์ด๋๋ฅผ ๋ด๋ ค์ฃผ๋ฉด ๋๊ฒ ๋ค์!
๋ผ๊ณ ์๊ฐํ๊ณ ๋ฐ๋ก ๊ตฌ๊ธ๋งํด๋ณด์๋๋ฐ,
์ ํํ ์ผ์นํ๋ ๊ฐ๋ ์ ๊ตฌํํด๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋ผ๊ตฌ์.. ( ์๋๊ฒ์๋ค์.. )
ํ ์คํธ ์ปจํ ์ด๋(TestContainers)
ํ ์คํธ ์ปจํ ์ด๋๋ฅผ ์ด์ฉํ๋ฉด, ์๋ฐ ์ฝ๋๋ง์ผ๋ก ํ ์คํธ ์ฉ ๋์ปค ์ด๋ฏธ์ง๋ฅผ ์์ฃผ ์์ฃผ ํธ๋ฆฌํ๊ฒ ์ ์ดํ ์ ์์ด์.
์ด๋ฒ ํฌ์คํธ์์ ๋ค๋ฃจ๋ mysql ๋ฟ๋ง์ด ์๋๋ผ, mongoDB, Kafka ์ ๊ฐ์ ๊ด๋ฆฌ ์์คํ ๋ค๋ ๋ชจ๋ ๋ค๋ฃฐ ์ ์์ผ๋ฏ๋ก ์ค์ ์๋น์ค ํ๊ฒฝ๊ณผ ๋งค์ฐ ์ ์ฌํ์ง๋ง ๊ฒฉ๋ฆฌ๋ ํ๊ฒฝ์์ ํ ์คํธ๋ฅผ ์งํํ ์ ์์ฃ .
๋จ์ ์ ๋ก์ปฌ ํ๊ฒฝ์์ ๋์ปค๊ฐ ๋์ํ๊ณ ์์ด์ผ ํ๋ค๋ ์ ๊ณผ,
ํ ์คํธ ์์ํ ๋ ์ปจํ ์ด๋๋ฅผ ๋์ฐ๋ ์ ๋์ ์์ ์๊ฐ์ด ๋์ด๋๋ค๋ ์ ์ด ์์ด์.
ํ์ง๋ง,
๋ชจ๋ ๊ฐ๋ฐ์๋ค์ ๋ก์ปฌ ํ๊ฒฝ์ ์ ํ ์ข ์์ ์ด์ง ์๊ณ , ๋งค์ฐ ๊ฐ๋จํ๊ณ ํธ๋ฆฌํ๊ฒ ์ค์ ์๋น์ค์ ์ ์ฌํ ํ ์คํธ ํ๊ฒฝ์ ๊ตฌ์ถํ ์ ์๋ค๋ ์์ฃผ ํฐ ์ฅ์ ์ด ์๊ธฐ ๋๋ฌธ์ ์ ๋จ์ ๋ค์ ์ด๋์ ๋ ๊ฐ์์ด ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
๋์ํ๋ ๋ชจ์ต์ ๋จผ์ ๋ณผ๊น์?
ํ ์คํธ ์ฝ๋๋ฅผ ์คํ์ํค๋ฉด,
๋ฏธ๋ฆฌ ์ค์ ํด๋ ์ปจํ ์ด๋๊ฐ ์คํ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
๊ทธ๋ฆฌ๊ณ ํด๋น ์ปจํ ์ด๋ ํ๊ฒฝ์์ ํ ์คํธ๋ฅผ ์งํํ ์ ์์ฃ .
mysql ์ปจํ ์ด๋๋ฅผ ๋์ ๊ธฐ ๋๋ฌธ์, mysql ์์ ์ ๊ณตํ๋ ์์น ๋ฐ์ดํฐ ํ์ ์ธ Point ์ ์์น ํจ์์ธ ST_DISTANCE_SPHERE ์ ์ฌ์ฉํ ์๋น์ค ๋ก์ง์ ํ ์คํธ ํ ์ ์๊ฒ ๋์๋ค์!
( ST_DISTANCE_SPHERE
์ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ๊ฐ ๊ณต๊ฐ ์ธ๋ฑ์ค R-tree
๋ฅผ ํ์ง ๋ชปํ๋ค๋ ์ด์๊ฐ ์๋๋ฐ, ์ด๋ ์ถํ ํฌ์คํ
์์ ๊ณต๊ฐ ์ฟผ๋ฆฌ ๊ฐ์ ์ฃผ์ ๋ก ๋ค์ ๋ค๋ค๋ณผ ์์ ์ด์์!! ์ฌ์ค ์ ๋ฐ์ ์ผ๋ก ๋นํจ์จ์ ์ธ ์ฟผ๋ฆฌ๊ฐ ๋๋ถ๋ถ์ด
๊ธฐ ๋๋ฌธ์, ์ ์ฒด์ ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๊ฐ์์์ด๋ณด๋ ค๊ณ ํฉ๋๋ค.. ๋๋ต 4~5์ ์์ ๋ชจ๋ ๊ต์ฒดํด๋ฒ๋ฆฌ๊ณ ์ถ๋ค์..ใ
ใ
)
ํ ์คํธ ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์๋์ ์์กด์ฑ์ ๋ฐ์์ฃผ์ด์ผ ํฉ๋๋ค.
testImplementation 'org.testcontainers:junit-jupiter:1.19.0'
testImplementation 'org.testcontainers:mysql'
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด ํด์ฃผ๋ฉด
@Container
MySQLContainer mySQLContainer = new MySQLContainer("mysql:8");
mysql:8 ์ด๋ฏธ์ง๋ก ๋์ปค ์ปจํ ์ด๋๋ฅผ ๋์์ฃผ๊ณ , ํ ์คํธ๊ฐ ๋๋๋ฉด ์ข ๋ฃ์์ผ์ค๋๋ค.
๋ค๋ง, ๋งค๋ฒ ๋ชจ๋ ํ ์คํธ์ ๋ํด์ ์ปจํ ์ด๋๋ฅผ ๋์์ฃผ๊ณ ๋ด๋ ค์ฃผ๋ ์์ ์ ๋ฐ๋ณตํ๋ค ๋ณด๋ ์ ์ฒด์ ์ธ ํ ์คํธ ์ฝ๋ ์คํ์๊ฐ์ด ๋ง์ด ์ง์ฒด๋๊ฒ ์ฃ .
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ปจํ ์ด๋๋ฅผ static ํ๋๋ก ์ ์ธํ๊ณ ์ด๊ธฐํํด์ฃผ๋๋ก ํฉ์๋ค.
๊ฐ ์ปจํ
์ด๋๋ง๋ค ํ์ํ ํ๊ฒฝ ๋ณ์๋ @DynamicPropertySource
์ ํตํด ๋์ ์ผ๋ก ์ฃผ์
๋ฐ์ ์ ์๋๋ฐ์,
๋ํผ๋ก์์๋ ์๋์ ๊ฐ์ด ์ฌ์ฉํ๊ณ ์์ด์!
@Slf4j
@SpringBootTest(classes = ServiceIntegrationTestConfiguration.class)
@Import({CoreTestConfiguration.class})
public abstract class ServiceIntegrationTestBase {
private static final String REDIS_DOCKER_IMAGE = "redis:5.0.3-alpine";
private static final String MYSQL_DOCKER_IMAGE = "mysql:8.0";
private static final String MYSQL_ROOT = "root";
private static final String MYSQL_PASSWORD = "1234";
private static final int REDIS_PORT = 6379;
@Container
protected static MySQLContainer mySQLContainer;
@Container
protected static GenericContainer redisContainer;
@DynamicPropertySource
static void configureProperties(final DynamicPropertyRegistry registry) {
// mysql env init
log.info("""
\n
โ
mysql property ๋ฅผ ์ฃผ์
ํฉ๋๋ค.
""");
registry.add("spring.datasource.url", mySQLContainer::getJdbcUrl);
registry.add("spring.datasource.username", () -> MYSQL_ROOT);
registry.add("spring.datasource.password", () -> MYSQL_PASSWORD);
// redis env init
log.info("""
\n
โ
redis property ๋ฅผ ์ฃผ์
ํฉ๋๋ค.
""");
registry.add("spring.redis.host", redisContainer::getHost);
registry.add("spring.redis.port", () -> "" + redisContainer.getMappedPort(REDIS_PORT));
}
static {
// mysql test container init
mySQLContainer = (MySQLContainer) new MySQLContainer(MYSQL_DOCKER_IMAGE)
.withUsername(MYSQL_ROOT)
.withPassword(MYSQL_PASSWORD)
.withDatabaseName("test")
.withEnv("MYSQL_ROOT_PASSWORD", MYSQL_PASSWORD);
log.info("""
\n
๐ณ MYSQL ํ
์คํธ ์ปจํ
์ด๋๋ฅผ ์์ํฉ๋๋ค.
- base image: {}
""", MYSQL_DOCKER_IMAGE);
mySQLContainer.start();
// redis test container init
redisContainer = new GenericContainer<>(REDIS_DOCKER_IMAGE)
.withExposedPorts(REDIS_PORT)
.withReuse(true);
log.info("""
\n
๐ณ Redis ํ
์คํธ ์ปจํ
์ด๋๋ฅผ ์์ํฉ๋๋ค.
- base image: {}
""", REDIS_DOCKER_IMAGE);
redisContainer.start();
}
}
์๋น์ค ๋ ์ด์ด ํตํฉ ํ ์คํธ๋ ๋ชจ๋ ์ ํด๋์ค๋ฅผ ์์๋ฐ๋๋ก ํด์,
Spring Context ๋ฅผ ์ค๋ณต์ผ๋ก ๋์์ ๋ฐ์ํ๋ ์๊ฐ ์ง์ฐ์ ์ต์ํํ๋ ค๊ณ ํฉ๋๋ค.
์์๋ก ์์ฑํด๋ ํ ์คํธ ์ฝ๋๋ ์๋์ ๊ฐ์์!
public class ShelterServiceTest extends ServiceIntegrationTestBase {
@Autowired
private ShelterService shelterService;
@Autowired
private ShelterRepository shelterRepository;
@DisplayName("1000 m ์ด๋ด์ ์์นํ ์ฃผ๋ณ ๋ํผ์ ๋ฆฌ์คํธ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.")
@Test
void getNearestShelterTest() {
// given
shelterRepository.save(Shelter.of(ShelterType.CIVIL_DEFENCE, "1000m ์ด๋ด์ ๋ํผ์ ๋ฏผ๋ฐฉ์๋ํผ์", 35.504, 35.5));
shelterRepository.save(Shelter.of(ShelterType.CIVIL_DEFENCE, "1000m ๋ณด๋ค ๋จผ ๋ํผ์", 36.504, 36.5));
// when
NearbyShelterListResponse response = shelterService.getNearbyShelterList(NearbyShelterRequest.of(35.5, 35.5, "๋ฏผ๋ฐฉ์"));
// then
Assertions.assertThat(response.getCount()).isEqualTo(1);
}
}
์ฌ์ค ์์ ์์ฑ๋ ๊ฐ๋จํ ํ ์คํธ ์ฝ๋๋ง ๋ณด๊ณ ๋, ํ๋ก๋์ ์ฝ๋์์ ๊ฐ์ ํด์ผ ํ ์ ์ ํ๋ ์ฐพ์๋ผ ์ ์์ด์.
๋ฌด์์ผ๊น์?
๋ฐ๋ก, 1000m ์ด๋ด๋ผ๋ ์กฐ๊ฑด์ธ๋ฐ์..!!
์ ํ ์คํธ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ง์ํ ์ ์๊ฒ ์ง๋ง Query ๋ ๋ฒจ์์ where ์ ์ 1000 m ์ดํ์ธ ๋ ์ฝ๋๋ง ์กฐํํ๋๋ก ํ๊ณ ์์ด์.
์ด๋ณด๋ค๋, 1000 ์ด๋ผ๋ ๊ฐ์ ์ธ๋ถ์ ํ๋ผ๋ฏธํฐ๋ก๋ถํฐ ์ฃผ์ ๋๋๋ก ํ๋ฉด
์กฐ๊ธ ๋ ํ ์คํธ๊ฐ ์ฌ์์ง๋ ์ฝ๋๊ฐ ๋จ๊ณผ ๋์์ ํ๋ก๋์ ์ฝ๋๋ ๋ ์ ์ฐํด์ง์ง ์์๊น์?
์ด์ ๊ฐ์ด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ค ๋ณด๋ฉด,
๋ฏธ์ฒ ๋ฐ๊ฒฌํ์ง ๋ชปํ๋ ํ๋ก๋์ ์ฝ๋ ์์ ๋ฌธ์ ์ ์ด ๋์ ๋ณด์ด๊ฒ ๋๋ค๋ ์์ฃผ ์ข์ ์ฅ์ ์ด ์์ด์..!
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ ํ๊ฒฝ์ ๊ตฌ์ฑํ์ผ๋,
๋น๋ถ๊ฐ์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉฐ
ํ๋ก๋์ ์ฝ๋์ ๋ฌธ์ ์ ์ ์ ๋๋ก ์ง๋จํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
Leave a comment