
๊ฐ๋ฐ์๋ก์์ ์ปค๋ฆฌ์ด๋ ์ ๋ง ๋ค์ํ์ง๋ง ํ์๊ฐ ๋ณด๊ณ ๋ค์ ๊ฒฝํ์ ์์ฃผ ์ผ๋ฐํ ์์ผ ์ ๋ฆฌํด ๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ฒ์์ ์ ๊ณต/๋น์ ๊ณต์ ๋ถ๋ฌธํ๊ณ ์ ์
์ผ๋ก ๊ฐ๋ฐ์ ์์ํ์ฌ ๋ค์ํ ๊ฐ๋ฐ ๊ฒฝํ์ ํ๊ฒ ๋๋ค. ์ฌ์์๊ฒ ํผ๋๊ธฐ๋ ํด๋ณด๊ณ ๋๋ ํผ๋ด์ค ์ฌ์๊ฐ ์์ด ํผ์ ๋๋ ๋ฐค๋ ์๋ณด๊ณ , ๋คํฌ์ํด๊ณผ ๊ฑฐ๋ถ๋ชฉ์ ๊ฒธ๋นํ ์ด๋ฅธ๋ฐ “์ฝ์ง"์ ํ๋ฉฐ ๊ณ ํต์ ์์ ์ ๋ณด๋ด๊ณ ๋๋ฉด ์ด๋๋ง ์น์ง(์ง๊ธ)์ ํ๋ฉฐ ์ผ์ ๊ท๋ชจ์ “ํ์ฅ(ํน์ ๊ด๋ฆฌ์)“์ด ๋๋ค. ๊ทธ๊ฒ ์์๋ ํ์๋ . ๊ฐ๋ฐ์๋ ๋ค์ “๊ธฐ์ "์ด๋ผ๋ ํน์์ฑ์ ๊ฐ์ง๊ณ ์์ง๋ง ์ด๋ ์ง๊ตฐ์ด๋ ๊ฐ์ ์ด๋ฌํ ์ปค๋ฆฌ์ด ํจ์ค์ ํ๋ฆ์ ๋งค์ฐ ๋น์ทํ๊ฒ ํ๋ฌ๊ฐ๋ ๊ฒ ๊ฐ๋ค. ์ ์ด๋ ํ์๊ฐ ๋ณด๊ณ ๋ค์ ๊ฒ๋ง ๋ณด๋ฉด ๋ง์ด๋ค. (์์ธ ์ผ์ด์ค๋ ํญ์ ์์ง๋ง…)
ํ๋ฃจ๋ ํ์ฅ๋๊ณผ์ ๋ฉด๋ด ์ค์ “์ด์ ๋ ๋ง๋ฅ ๋์์ ์๋ ๊ฐ๋ฐ๋ง ํ ๊ฒ์ด ์๋๋ค. ๊ธฐ์ ์ ์ข ๋ ๊น๊ฒ ๋ค์ฌ๋ค๋ณด๋ ์๋ฆฌ์ ์ฌ๋์ ๊ด๋ฆฌํ๋ฉฐ ์ฃผ์ด์ง ๊ณผ์ ๋ฅผ ์งํํ๋ ์๋ฆฌ, ๋ ์ค ์ ํํด์ผ ํ๋ ์๊ธฐ๊ฐ ์จ ๊ฒ ๊ฐ๋ค. ๋ ๋๊ณ ๋ ๋ฉ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ๋ ๋๊ฒ ๋ณผ ์ค ์์์ผ ํ๋ค.“๋ผ๋ ๋ง์์ ๋ฃ๊ฒ ๋๋ค. ์ด๋๋ง “๊ทธ ์์ "์ด ๋ค๊ฐ์จ ๊ฒ์ด๋ค. ๊ฐ์ธ์ ์ผ๋ก ํ์๋ ํ์ฅ๋์ด ๋ง์ํ์ ๋ ๊ฐ์ง ์ค ์ ์์ ์ข ๋ ๊ฐ๊น๊ฒ ๋ค๊ฐ๊ฐ๊ณ ์ถ๋ค. ๊ทธ๋งํผ ์ค๋์ค๋ “์ค๋ฌด ๊ฐ๋ฐ"์ ํ๊ณ ์ถ๊ณ , ๋ ๊ทธ๋งํผ ๊ฐ๋ฐ์ด ์ฌ๋ฐ๊ธฐ ๋๋ฌธ์ด๋ค. ์์ง๋ ๋์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๊ฐ๋ฐํ๋ฉฐ ์๊ฐ ๊ฐ๋ ์ค ๋ชจ๋ฅผ ๋งํผ ๋ฐค์ ์์ฐ๋ ๊ฒ ์ฌ๋ฏธ์๋ ๊ฑธ ๋ณด๋ฉด…
์๋ฆฌํ๋ ๊ฑธ ์ข์ํ์ง๋ง ์ด์ํ๊ฒ ์นํจ์ง์ ํ๊ณ ์ถ์ง ์๋ค. ์ถ์ฒ : https://catapult.tistory.com/entry/%EC%B9%98%ED%82%A8%EC%A7%91%EC%9D%B4%EB%82%98-%EC%B0%A8%EB%A0%A4%EC%95%BC%EC%A7%80" ์๋ฆฌํ๋ ๊ฑธ ์ข์ํ์ง๋ง ์ด์ํ๊ฒ ์นํจ์ง์ ํ๊ณ ์ถ์ง ์๋ค. ์ถ์ฒ : https://catapult.tistory.com/entry/%EC%B9%98%ED%82%A8%EC%A7%91%EC%9D%B4%EB%82%98-%EC%B0%A8%EB%A0%A4%EC%95%BC%EC%A7%80 ์ด๋ ๋ SNS ํผ๋์ ๊ฐ๋ฐ ๊ด๋ จ๋ ์์๋ค์ ๋ฐ์๋ณด๋ค๊ฐ ๊ฐ๋ฐ 7๋
์ฐจ. ๋งค๋์ 1์ผ์ฐจ๋ผ๋ ์ ๋ชฉ์ ์ฑ
์ ๋ณด๊ฒ ๋๋ค. ๋ญ์ผ, ์ด๊ฑฐ ๋ด ์ด์ผ๊ธฐ ์๋์ผ? ํ๋ฉฐ ๊ท์ ์ ํ๋ฆฐ ๋ฏ ์ฌ์ ์ฝ์ด๋ณด๋ ค๋ ์ฐฐ๋, ๋ง์นจ ํ๋น๋ฏธ๋์ด ์์ ์ฃผ์ตํ๋ ๋๋ ๋ฆฌ๋ทฐ์ด๋ค ๋ผ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ฒฌํ๊ฒ ๋๋ค. ๊ฒฐ๊ตญ ๋ฆฌ๋ทฐ์ด์ ๋น์ฒจ์ด ๋๊ณ ์ด ์ข๊ฒ ํด๋น ์ฑ
์ ๋ฐ์๋ณผ ์ ์์๋ค. (์ด ์ฑ
์ ์ฝ๊ฒ ํด์ค ํ๋น๋ฏธ๋์ด ์ธก์๊ฒ ์ด ๊ธ๋ก๋๋ง ๊ฐ์ฌ์ ์ธ์ฌ๋ฅผ ์ ํ๊ณ ์ถ๋ค.)
ํ์์ SNS๋ฅผ ์ฅ์ํ๋ ‘๊ฐ๋ฐ 7๋
์ฐจ, ๋งค๋์ 1์ผ์ฐจ’" ํ์์ SNS๋ฅผ ์ฅ์ํ๋ ‘๊ฐ๋ฐ 7๋
์ฐจ, ๋งค๋์ 1์ผ์ฐจ’ ์ด๋ฒ ํฌ์คํ
์์๋ ์ฐ์ ์ฑ
์ ๋ํ ๋ฆฌ๋ทฐ๋ฅผ ๊ฐ๋จํ ์ ์ด๋ณด๊ณ ๊ฑฐ๊ธฐ์ ํ์์ ์๊ฐ์ ์กฐ๊ธ ๋ ์น์ด๋ณด๊ณ ์ถ๋ค. ํ์๋ฅผ ๋๊ณ ๋ง๋ค์ด์ง ์ฑ
๊ฐ์์ ์์ง๋ ์ฑ
ํ์ง๋ง ๋ด๋ ์ ๊ธฐํ๊ณ ์ค๋ ๋ค. ์ผ๋จ ์ฑ
ํ์ง๋ ์ ๋ชฉ์ด ๋ง์ ๋ ๊ฑด ๊ฐ์ถ ์ ์๋ ์ฌ์ค์ด๋ค.
์ ์
ํน์ ์ฃผ๋์ด ๊ฐ๋ฐ์๊ฐ ์ฝ์ด๋ด๋ ์ข์ ์ฑ
. ์ ๋ชฉ๋ง ๋ณด๋ฉด ์ด์ ๊ฐ ํ์ฅ ํน์ ๋งค๋์ ๋ฅผ ํ๊ฒ ๋๋ ์ฌ๋์๊ฒ๋ง ํด๋น๋๋ ์ฑ
์ผ๋ก ๋ณด์ธ๋ค. ํ์ง ์๋จ์ “๊ฐ๋ฐ๋ง ํด์๋ ๋ด๊ฐ, ์ด๋ ๋ ๊ฐ์๊ธฐ ‘ํ’์ ๋งก์๋ค!” ์ ํ์๊ธฐ๋ ํ์ผ๋๊น. ํ์ง๋ง ์ฑ
์ ์ฝ๋ค ๋ณด๋ฉด ๊ผญ ๊ทธ๋ ์ง๋ง๋ ์๋ค. ๋ฉํ ๋ง์ ํ ๋์ ๋ฉํ ์ ๋ฉํฐ ๊ฐ์์ ์์น์์ ์ด๋ค ์์ธ๋ก ์๋ก๋ฅผ ๋ง์ดํด์ผ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ ์๋ ค์ฃผ๊ธฐ๋ ํ๊ณ ๋ฌด์์ ๋์์ ์๋ ๊ธฐ๋ฅ ๊ฐ๋ฐ๋ง์ ํ๋ฉฐ ์๊ฐฏ์์ ๊ฑท๋ ์ฃผ๋์ด ๊ฐ๋ฐ์๊ฐ ๋ฏธ๋ฆฌ ๋ฏธ๋๋ฅผ ๊ฒฝํํด๋ณด๋ ์ข์ ์ฌ๋ก๋ฅผ ๋ค์ด ์๋ ค์ฃผ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ผญ ๋๊ตฐ๊ฐ ํน์ ๋ฌด์ธ๊ฐ๋ฅผ “๊ด๋ฆฌ"ํ๋ ์
์ฅ์ด ์๋ “ํ"์ด๋ผ๋ ๊ณต๋์ฒด ์ฌํ, ํนํ ๊ฐ๋ฐ ํ์์ ํ์๋ค๊ณผ ํ๋ ฅํ๋ ๋ฐฉ๋ฒ๋ก ์ ์ดํด๋ณด๊ณ ์๊ณ , ๊ฒฝ๋ ฅ์ด ๋ฎ์ผ๋ฉด ์ ๋ณด์ด๋ ๋ถ๋ถ๋ค๊น์ง ๋ง์น ๋ฉ๋ฆฌ ์๋ ๊ฒ์ ๋์ ๋ง์๊ฒฝ์ผ๋ก ๋ณด์ฌ์ฃผ๋ ๋๋์ด ๋ค์๋ค. ์๋ถ๋ถ์๋ “์ด ์ฑ
์ ์ฝ๋ ๋ฐฉ๋ฒ"์ด๋ผ๋ฉฐ ์ํฉ๋ณ๋ก ์ฝ๋ ์ฑํฐ๋ฅผ ๊ฐ์ด๋ ํด์ฃผ๊ณ ์์ง๋ง ์ฌ์ค ์ด๋ ํ๋ ์ค์ํ์ง ์์ ๋ด์ฉ์ด ์์ด์ ์ฒ์๋ถํฐ ๋ฌด์ธ๊ฐ์ ํ๋ฆฐ ๋ฏ ์ฝ์ ์๋ฐ์ ์์๊ณ ์ ๋ฐฐ๋์ด ์์ ์ง๋๊ฐ ๊ธธ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ง๋๊ฐ ์ ์๋๋ก ๊ฐ์ด๋ ํด์ฃผ๋ ๋๋์ผ๋ก ์ค๊ฐ์ค๊ฐ ์ฌ๋ก๊ฐ ์์ด์ ํ์
์ ์์ด์ ๊ทธ๋ฐ์ง ์ข ๋ ์ฝ๊ฒ ์ฝํ ์ ์์๋ค.
๋ค ์ฝ๊ณ ์์ผ ์์์ฐจ๋ฆฐ ๋ฒ์ญ์(?)๋ผ๋ ์ฌ์ค. ์ด๋ ํ XX ๊ธฐ์ ์์ ์์๋ Method๋ฅผ ‘๋ฐฉ๋ฒ’, Overriding ์ ‘๊ณผ์ ’์ด๋ผ๊ณ ๋ฒ์ญํ ์ฑ
๋ค์ด ์๋๊ฐ ๋ฐ๋ฉด, ์ด ์ฑ
์ ์ฝ๋ ๋ด๋ด ๊ตญ๋ด ์ด๋ค ๋ถ์ด ์ฐ์ ๊ฑฐ๋ผ ์๊ฐํ๊ณ ์ฝ์ด๋ด๋ ค ๊ฐ์ง๋ง ๋ค ์ฝ๊ณ ๋ณด๋ ์ธ๊ตญ์ ์ด๋ CTO๊ฐ ์ด ์ฑ
์ ์ฎ๊ฒจ์ ๋ค์ ์จ์ง ์ฑ
์ด์๋ค.

์น ์ดํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค๋ฉด์ ๊ผญ ํ๋ฒ ์ฏค ๋ง๋๊ฒ ๋๋ “RestTemplate”. ์ ๊ทผ ๊ฐ๋ฅํ ์ธ๋ถ HTTP URL(๋ณดํต API)์ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ค์ ํ๋๋ก springframework ์์ ์ ๊ณตํด์ฃผ๋ ๋ชจ๋์ด๋ค. ํนํ ํฐ ํ๋ฉ์ด๋ฆฌ๋ก ๊ด๋ฆฌ๋๋ Monolithic Architecture ์์ ์์ฒญ์ ํ๊ณ (client) ์๋ต์ ์ฃผ๋(server) ์ฆ, Endpoint๊ฐ ์์ ๋จ์๋ก ๋ถ๋ฆฌ๋๋ Microservice Architecture ๋ก ๋ฐ๋๋ฉด์ ๊ฐ ์๋น์ค๊ฐ ํธ์ถ๋ฐฉ์์ด HTTP ์ผ ๊ฒฝ์ฐ ์์ฃผ ์ฌ์ฉ๋๊ณค ํ๋ ๊ฒ ๊ฐ๋ค. (webClient ๋ฑ ๋ค๋ฅธ ์ฌ๋ฌ ํธ์ถ ๋ฐฉ๋ฒ๋ค์ด ์๋ค.) ๋ง์ฝ, ์์ฒญ์ ํ๋ ํด๋ผ์ด์ธํธ ์
์ฅ์์ ์๋ต์ ์ฃผ๋ ์๋ฒ์ ์ํ๊ฐ ๋ถ์์ ํ๋ค๊ณ ๊ฐ์ ํ์๋, ์ด๋ค์์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ ๊น? ์์ปจ๋, ์์ฒญ 10๋ฒ์ ํ๋ฒ์ ์ด๋ ํ ์ด์๋ก ์๋ต์ด ์ง์ฐ๋๊ฑฐ๋ ์๋ฒ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๊ณ ํ๋ฉด ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ๋ ์ฌ์ฉ์ ์
์ฅ์์๋ ๊ฐํ์ ์ธ ์ค๋ฅ์๋ต์ ๋ต๋ตํจ์ ํธ์ํ ์๋ ์๋ค. ๊ทธ๋ผ ์ ์ ๋์ ๊ฐ๊ณ ์๊ฐํด๋ณด์. ๊ฐ๋ณ๊ฒ ์๊ฐํ๋ฉด ์๋์ฒ๋ผ ์์ฃผ ๊ฐ๋จํ๊ฒ “์์ธ์ฒ๋ฆฌ"๋ฅผ ์ด์ฉํ ์๋ ์๋ค.
try { // http call } catch (Exception e){ // ์๋ฒ์๋ฌ๊ฐ ์๋ ์ฝ์๋ ์๋ฌ์๋ต์ ๋ฆฌํด } ํ์ง๋ง ์ด๊ฒ๋ ์ ๋ต์ด ์๋์ ์๋๊ฒ, “๊ฐํ์ ์ธ ์ค๋ฅ"๋ก ์ธํด ์ฌ์ฉ์๋ ์ค๋ฅํ๋ฉด์ ๋ด์ผํ๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ์ ๋ํ ์ ๋ขฐ๋ฅผ ์ ๋ฒ๋ฆด ์๋ฐ์ ์๋ค. ๊ทธ๋ผ ์ด๋ป๊ฒ ํด์ผํ ๊น? ์ฌ๋ฌ๊ฐ์ง ํด๊ฒฐ๋ฐฉ๋ฒ์ด ์๊ฒ ์ง๋ง ๊ฐ๋จํ๋ฉด์๋ ๊ฐ๋ ฅํ๋ค๊ณ ์๊ฐ๋๋ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก “์ฌ์๋” ๋ผ๊ณ ์๊ฐํ๋ค. ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ๋ ์ฌ์ฉ์๊ฐ ๋์น ๋ชป์ฑ๋งํผ ๋น ๋ฅด๊ฒ ์ฌ์๋๋ฅผ ํ๋ค๋ฉด ์๋ฌ๊ฐ ๋๋ ๋ค์ํ๋ฒ ํธ์ถํด์ ์ฑ๊ณตํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ด๋ค. (๊ทธ์น๋ง ๊ทผ๋ณธ์ ์ธ ์์ธ์ ํด๊ฒฐํด์ผ…)
์ค์ ๋ก ์กฐ๊ธ์๋ค ํด๋ณด๋ฉด ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ ์๋ ๋๋ ์กฐ๊ธ (์ฒ์ฒํ) ์๋ํด๋ณด์. ์ถ์ฒ : http://www.segye.com/newsView/20200302504384" ์ค์ ๋ก ์กฐ๊ธ์๋ค ํด๋ณด๋ฉด ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ ์๋ ๋๋ ์กฐ๊ธ (์ฒ์ฒํ) ์๋ํด๋ณด์. ์ถ์ฒ : http://www.segye.com/newsView/20200302504384 ์ด๋ฒ ํฌ์คํ
์์๋ RestTemplate ๋ฅผ ์ด์ฉํ ๋ “์ฌ์๋” ํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ณ ์ ํ๋ค. ์์ฃผ ๊ฐ๋จํ ์ง ๋ชจ๋ฅด์ง๋ง ๋
ธ๋ ฅ์ ๋นํด ํจ๊ณผ๊ฐ ์๋นํ๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ์ ๋ฆฌํด ๋๊ณ ์ถ์๋ค.
Spring Retry ๊ณต์ Github์ ์๊ฐ๋ฅผ ๋น๋ฆฌ์๋ฉด, Spring ์ดํ๋ฆฌ์ผ์ด์
์ ๋ํ ์ฌ์๋ ์ง์์ ์ ๊ณตํ๋ค๊ณ ํ๋ค. ์์์ ์ด์ผ๊ธฐ ํ๋ “RestTemplate"๊ณผ๋ ์ฌ์ค ๋ฌด๊ดํ๊ณ , ์ด๋ฅผ ํ์ฉํด์ ์ฌ์๋ ํ๋ “RetryRestTemplate"๋ฅผ ๊ตฌํํด๋ณด๋ ค ํ๋๊ฒ์ด๋ค. ์ฐ์ ์ด “Spring-Retry"์ ์์ ๋ฅผ ๋ณด๋ฉด ์์ฃผ ์ฌํํ๊ฒ ์ฌ์ฉํ ์ ์๋ค. ์ฐ์ pom์ ๊ตฌํ์ ํ์ํ dependency ๋ฅผ ์ถ๊ฐํ๊ณ ์๋ ์ฝ๋๋ฅผ ๋ณด์.
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> @Configuration @EnableRetry // 1 public class Application { @Bean public Service service() { return new Service(); } } @Service class Service { @Retryable(RemoteAccessException.class) // 2 public void service() { // ... do something } @Recover // 3 public void recover(RemoteAccessException e) { // ... panic } } @EnableRetry ์ด๋
ธํ
์ด์
์ @Configuration์ ์ง์ ํ ํด๋์ค ์ค ํ๋์ ์ถ๊ฐํ๋ค. ์ฌ์๋ ํ๋ ค๋ ๋ฉ์๋์ @Retryable ์ด๋
ธํ
์ด์
์ ์ง์ ํด์ค๋ค. ์ฌ์๋๊ฐ ์๋ฃ๋๋ ์์ ์์ ์คํํ๊ณ ์ถ์๋ ์ ์ธํ๋ ์ด๋
ธํ
์ด์
, @Retryable ๋์ผํ ํด๋์ค์์ ์ ์ธ๋์ด์ผ ํ๊ณ return type ์ @Retryable์ ์ง์ ํ ๋ฉ์๋์ ๋์ผํด์ผ ํ๋ค. Retry Rest Template ์ด๋ ๊ฒ springframework ์์ ์ ๊ณตํด์ฃผ๋ spring-retry ๋ฅผ ์ด์ฉํด์ ์ด๋ฒ ํฌ์คํ
์ ๋ชฉํ์ธ ์ฌ์๋๋ฅผ ํ๋ Retry Rest Template ๋ฅผ ๊ตฌ์ฑํด๋ณด์. ์ฐ์ , RestTemplate ๋ฅผ Bean ์ผ๋ก ๋ฑ๋กํ๊ณ , ์์์ ์ด์ผ๊ธฐ ํ ์ด๋
ธํ
์ด์
๋ค๋ก ๊ตฌ์ฑํด๋ณด์.
@EnableRetry @Configuration public class RetryableRestTemplateConfiguration { @Bean public RestTemplate retryableRestTemplate() { SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory(); // 1 clientHttpRequestFactory.setReadTimeout(2000); clientHttpRequestFactory.setConnectTimeout(500); RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory) { @Override @Retryable(value = RestClientException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) // 2 public <T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType) throws RestClientException { return super.exchange(url, method, requestEntity, responseType); } @Recover public <T> ResponseEntity<String> exchangeRecover(RestClientException e) { return ResponseEntity.badRequest().body("bad request T.T"); // 3 } }; return restTemplate; } } SimpleClientHttpRequestFactory ๋ฅผ ๋ง๋ค๊ณ ๊ฐ ํ์์์์ ์ค์ ํด์ค ๋ค์ RestTemplate ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ค๋ค. ์ฌ์ฉํ๋ ๊ณณ์์ exchange ๋ฉ์๋๋ฅผ ์ด์ฉํ ๊ฒ์ด๋ฏ๋ก ํด๋น ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํด์ค๋ค.

API๋ฅผ ๊ฐ๋ฐํ๊ณ ์ ๊ณตํ๊ธฐ ์ํด์๋ ๊ทธ์ ํด๋นํ๋ API ๋ช
์ธ๋ฅผ ์์ฑํด์ ์ฌ์ฉํ๋ ๊ณณ์ ์ ๋ฌํ๊ฒ ๋๋ค. ์ด๋ค URL์ ์ด๋ค ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํด์ ์ด๋ป๊ฒ ์์ฒญ์ ํ๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ์๋ต์ผ๋ก ๋ด๋ ค์ฃผ๋์ง์ ๋ํ ๊ด๋ จ ์ ๋ณด๋ค. ์ด๋ฌํ “API ๋ฌธ์” ๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ์์ ์ํฉ์ ๋ฐ๋ผ ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉ๋๊ณค ํ๋ค. API ์ฝ๋์ ํด๋น ๋ฌธ์์ ๋๊ธฐํ๊ฐ ์๋์ผ๋ก ๋์ด์ผ ์กฐ๊ธ ํธํด์ง๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์ถ์ฒ : https://dribbble.com/shots/3386291-API-Documentation" API ์ฝ๋์ ํด๋น ๋ฌธ์์ ๋๊ธฐํ๊ฐ ์๋์ผ๋ก ๋์ด์ผ ์กฐ๊ธ ํธํด์ง๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์ถ์ฒ : https://dribbble.com/shots/3386291-API-Documentation ํ์๋ ์ฃผ๋ก “์ํค”(๋๋ ์ผ๋ฐ ๋ฌธ์)๋ฅผ ํ์ฉํด์ ์ ๋ฌํ๊ณค ํ์๋๋ฐ API์ ํํ๊ฐ ๋ฌ๋ผ์ง ๋๋ง๋ค ํด๋น ์ํค๋ฅผ ์์ ํด์ผ๋ง ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์์๋ค. API ์์ ํ๋ฉด ์ํค๋ ์์ ํ๊ณ . ๊น๋ฐํ๊ณ ์ํค ์์ ์ ์ํ๊ฒ ๋ ๊ฒฝ์ฐ ์ API ๋ช
์ธ๊ฐ ๋ค๋ฅด๋๋ ๋ฌธ์๊ฐ… ๊ทธ๋ฌ๋ค ์๊ฒ๋ Spring Rest Docs. (์๋ฌด๋ฆฌ ์ข์ ๊ธฐ์ , ์ข์ ํด ์ด๋ผ ํด๋ ์ค์ ๋ก ๋ณธ์ธ์ด ํ์๋ก ํ๊ณ ์ฌ์ฉ์ ํด์ผํ๋ ์ด์ ๊ฐ ์๊ธธ๋ ๋น๋ก์ ๋น์ ๋ฐํ๋๊ฒ ๊ฐ์ ๋๋์ด๋ค.)
์ด ํฌ์คํ
์์๋ swegger ์ ๋น๊ตํ๋ ๋ด์ฉ์ ์ ์ธํ ๊น ํ๋ค. ์๋ ์ ๋ช
ํ ๋ ์๋ ์ฐ๋งฅ(?)์ด๋ผ ๊ฒ์ํด๋ณด๋ฉด ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ด ์์ธํ ๋์์๊ธฐ์…
์ต๊ทผ ๋ค์ด TestCode ์ ์ค์์ฑ์ ์ ์คํ๊ฒ ๋๋ผ๊ณ ์์๊ณ , TestCode ๋ฅผ ์์ฑํ๋ฉด ์์ฐ์ค๋ฝ๊ฒ ๋ฌธ์๋ฅผ ๋ง๋ค์ด ์ฃผ๋ ๋ถ๋ถ์ด ๊ฐ์ฅ ๋งค๋ ฅ์ ์ด๋ผ๊ณ ์๊ฐ์ด ๋ค์๋ค. ์ด๋ฅผ ๋ฐ๋๋ก ์๊ฐํ๋ฉด, TestCode ๊ฐ ์คํจํ ๊ฒฝ์ฐ ๋น๋ ์์ฒด๊ฐ ์๋๊ธฐ์ ์ด์ฉ์ ์์ด TestCode๋ฅผ ์ฑ๊ณต์์ผ์ผ๋ง ํ๊ณ , ์์ฐ์ค๋ฝ๊ฒ ์ ์์ ์ธ(์ต์ ํ ๋) API ๋ฌธ์๊ฐ ๋ง๋ค์ด์ง๊ฒ ๋๋ค.
์ด๋ฒ ํฌ์คํ
์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ชฉํ๋ฅผ ๋๊ณ ์ค๋ฌด์์ ์ธ์ ๋ ์ง ํ์ฉ์ด ๊ฐ๋ฅํ ์ฝ๊ฐ์ “๊ฐ์ด๋” ๊ฐ์ ๋ด์ฉ์ผ๋ก ์์ฑํด ๋ณด๊ณ ์ ํ๋ค.
Spring Boot ์ต์ ๋ฒ์ ์์ Spring Rest Docs ๋ฅผ ์ค์ ํ๋ค. ์์์ API ๋ฅผ ๋ง๋ค๊ณ ๊ทธ์ ๋ฐ๋ฅธ TestCase ๋ฅผ ์์ฑํ๋ค. Spring.profile ์ ๋ฐ๋ผ Spring Rest Docs Url ์ ์ ๊ทผ ๊ฐ๋ฅ/๋ถ๊ฐ๋ฅ ํ ์ ์๊ฒ ํ๋ค. ๋ฌผ๋ก ํ์์ ๋ฐฉ๋ฒ์ด ๋ค๋ฅผ์๋ ์์ง๋ง, ์ด๋ฌํ ๋ฐฉ๋ฒ์ ํ ๋๋ก ๋ณด๋ค ๋ ์ฐ์ํ๊ณ ์๋ฆ๋ค์ด ๋ฐฉ๋ฒ์ ์์๊ฐ์ ์์ง ์์๊น ํ๋ ๊ธฐ๋๋ก.
Spring Boot ์ Spring Rest Docs ์
ํ
ํ๊ณ TestCase ์์ฑํ๊ธฐ ์ฐ์ Spring Boot ํ๋ก์ ํธ๋ฅผ ๋ง๋ ๋ค. https://start.spring.io/ ์์ ๋ง๋ค์ด๋ ๋๊ณ IDE ์์ ์ ๊ณตํ๋ ํด๋ก ๋ง๋ค์ด๋ ๋๊ณ . ๋ง๋๋ ๋ฐฉ์์ ๋ฌด๋ฐฉํ๋ค. ๊ทธ ๋ค์ ํ์ํ dependency ๋ฅผ ์ถ๊ฐํด ์ค๋ค.
<dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <scope>test</scope> </dependency> ์์๋ก API๋ฅผ ์์ฑํ๊ณ
๋ชจ๋ธ @Getter @Setter public class Book { private Integer id; private String title; private String author; } ์ปจํธ๋กค๋ฌ @RestController public class BookController { @GetMapping("/book/{id}") public Book getABook(@PathVariable Integer id) { Book book = new Book(); book.setId(id); book.setTitle("spring rest docs in spring boot"); book.setAuthor("taetaetae"); return book; } } ํด๋น ์ปจํธ๋กค๋ฌ์ ๋ํ TestCase ๋ฅผ ์์ฑํ์.
@WebMvcTest(BookController.class) @AutoConfigureRestDocs // (1) public class BookControllerTest { @Autowired private MockMvc mockMvc; // (2) @Test public void test_์ฑ
์_์กฐํํ๋ฉด_null์ด_์๋_๊ฐ์ฒด๋ฅผ_๋ฆฌํดํ๋ค() throws Exception { mockMvc.perform(get("/book/{id}", 1) .accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(document("book", // (3) pathParameters( parameterWithName("id").description("book unique id") // (4) ), responseFields( fieldWithPath("id").description("book unique id"), fieldWithPath("title").description("title"), fieldWithPath("author").description("author") ) )) .andExpect(jsonPath("$.id", is(notNullValue()))) // (5) .andExpect(jsonPath("$.title", is(notNullValue()))) .andExpect(jsonPath("$.author", is(notNullValue()))); } } (1) Spring Boot ์์๋ ํด๋น ์ด๋
ธํ
์ด์
์ผ๋ก ์ฌ๋ฌ์ค์ ๊ฑธ์ณ ์ค์ ํด์ผ ํ Spring Rest Docs ๊ด๋ จ ์ค์ ์ ์์ฃผ ๊ฐ๋จํ๊ฒ ํด๊ฒฐํ ์ ์๊ฒ ๋๋ค. (์ฐธ๊ณ )
(2) ๊ณต์ ๋ํ๋จผํธ ์์๋ 4๊ฐ์ง ๋ฐฉ์์ ๋งํ๊ณ ์๋๋ฐ ์ด ํฌ์คํ
์์๋ “MockMvc” ์ ์ฌ์ฉํ๊ณ ์ ํ๋ค.
(3) “book” ์ด๋ผ๋ identifier ๋ฅผ ์ง์ ํ๋ฉด ํด๋น TestCase ๊ฐ ์ํ๋ ๋ snippets ๊ฐ ์์ฑ๋๋๋ฐ ํด๋น identifier ๋ฌถ์์ผ๋ก ์์ฑ์ด ๋๋ค.
(4) request์ ํ๋ผ๋ฏธํฐ ํ๋, response์ ํ๋์ ์ค๋ช
์ ์ ์ด์ค์ผ๋ก์จ ์ด ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ snippets ๊ฐ ์์ฑ์ด ๋๊ณ ๊ฒฐ๊ณผ์ ์ผ๋ก API ๋ฌธ์๊ฐ ๋ง๋ค์ด ์ง๋ค.
(5) ํ์๊ฐ ๊ฐ์ฅ ๋งค๋ ฅ์ ์ด๋ผ ์๊ฐ๋๋ ๋ถ๋ถ. ์ด ๋ถ๋ถ์์ ํ
์คํธ๋ฅผ ๋์์ ํจ์ผ๋ก์จ ์๋ต์ด ๋ฌ๋ผ์ง๊ฑฐ๋ ์๋ชป๋ ์๋ต์ด ๋ด๋ ค์ฌ ๊ฒฝ์ฐ TestCase๊ฐ ์คํจํ๊ฒ ๋์ด API๋ฌธ์ ๋ํ ์์ฑ๋์ง ์๊ฒ ๋๋ค.

ํ์ด์ฌ์ด๋ผ๋ ์ธ์ด๋ ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ค์ ๋นํด ์ฝ๊ณ ์ง๊ด์ ์ด๋ผ ๊ทธ๋ฐ์ง ํ๋ก๊ทธ๋๋ฐ์ ์ฒ์ ์์ํ๋ ์ฌ๋๋ค์๊ฒ ๋์ฑ์ด ์ฃผ๋ชฉ์ ๋ฐ๊ณ ์๋๊ฒ ๊ฐ๋ค. ์ ๋ง ๋ค์ํ ๋ชจ๋๋ค์ด ๋ง์ ์ฌ๋ฌ๋ถ์ผ์์ ํ์ฉ๋๊ณ ์๊ณ ํนํ ์ธ์ ๋ถํฐ์ธ๊ฐ ํซ! ํด์ง ๋ถ์ผ(?)๋ผ ํด๋ ๊ณผ์ธ์ด ์๋์ ๋์ธ “๋จธ์ ๋ฌ๋” ๋ถ์ผ์์๋ ๋ค์ํ๊ฒ ์ฌ์ฉ๋๊ณ ์๋๊ฒ ๊ฐ๋ค.
๋ง์นจ ํ์๊ฐ ์ํด ์๋ ํ ๋ด์ ๋จธ์ ๋ฌ๋ ์คํฐ๋๊ฐ ์์์ด ๋์๊ณ , ๊ทธ์ ํ์ด์ฌ์ ์ด์ฉํ์ฌ ์คํฐ๋๋ฅผ ํด์ผํ๋ ์ํฉ. ํ์ง๋ง ์คํฐ๋๋ฅผ ํ๋ ํ์ ์ ๋ฐ ์ด์์ด ํ์ด์ฌ์ ์ด์ฉํ ๊ฐ๋ฐ ๊ฒฝํ์ด ์์๊ณ , ์๋ก ๋ฐฐ์ด๊ฒ์ ๊ณต์ ๋ฅผ ํ๋ฉด์ ์คํฐ๋๋ฅผ ํ๋ฉด ๋ ์ข๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค๋ ์ฆ์. ์ธ์ ์ด๋์ ๊ฐ ๋ดค๋๊ฒ์ด ๋จธ๋ฆฟ์์ ์ค์ณ ์ง๋๊ฐ๋ค. ๊ทธ๊ฑด ๋ฐ๋ก Jupyter(์ดํ ์ฃผํผํฐ).
์ถ์ฒ : https://jupyter.org/" ์ถ์ฒ : https://jupyter.org/ ์ฃผํผํฐ๋ ์์ญ ๊ฐ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ๋ํ ํ ์ปดํจํ
์์ํ ์คํ ์์ค ์ํํธ์จ์ด, ์คํ ํ์ค ๋ฐ ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ธฐ ์ํ ํด์ด๋ผ๊ณ ํ๋ค. ์ด ํฌ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ ๊น์ง๋ง ํด๋ “์ฃผํผํฐ == ํ์ด์ฌ ์น ๊ฐ๋ฐํด” ์ด๋ผ๊ณ ๋ง ์๊ณ ์์๋๋ฐ ์ข๋ ์ฐพ์๋ณด๋ ๋ค์ํ ์ธ์ด๋ฅผ ์ง์ํ๋๊ฒ ๊ฐ๋ค.
๊ทธ๋ผ ์ด๋ฌํ ์ฃผํผํฐ๋ฅผ ํน์ ์๋ฒ์ ์ค์นํ๊ณ ๋ก์ปฌ์ ํ์ด์ฌ์ ์ค์นํ์ง ์์๋ ์๊ฒฉ์ผ๋ก ํ์ด์ฌ ์ฝ๋ฉ์ ํด๋ณด๋ฉด ์ข๋ ์คํฐ๋์ ๋์์ด ๋์ง ์์๊น ํ๋ ๋ง์์ด ๋ค์๋ค. ๋ํ ํ๊ต์์ ์ด๋์ฅ์ ์๋๋ฅผ ๊น์์ ๋ง๊ป ๋ฐ๋์ ์๊ฒ ํ๋ ๋๋์ผ๋ก ํ์๋ค์ ์ํด ์ค์น๋ฅผ ํด๋๊ณ ์๊ฒฉ์ผ๋ก ์ ์ํ ์ ์๊ฒ ํด๋๋ฉด ๋ชจ๋๊ฐ ํธํ๊ณ ์ฝ๊ฒ ํ์ด์ฌ์ ๋ํด ๊ฒฝํ์ ํด๋ณผ ์ ์์ง ์์๊น ํ๋ ๋ง์์ผ๋ก ์ฃผํผํฐ๋ฅผ ์ค์น๋ฅผ ํด ๋ณด๊ณ ์ ํ๋ค.
๋ณธ ํฌ์คํ
์ ๋ชฉํ๋ ๋ค์๊ณผ ๊ฐ๋ค.
ํ๊ฒฝ : CentOS 7.4 64Bit, python 2.7 (๊ธฐ๋ณธ) ๋ชฉํ anaconda ๋ฅผ ํ์ฉํ์ฌ ์์คํ
๊ธฐ๋ณธ ํ์ด์ฌ์ ๊ฑด๋๋ฆฌ์ง ์๋ ๊ฐ์ํ๊ฒฝ์ ๊ตฌ์ถํ๋ค. ์ฃผํผํฐ๋ฅผ ์ค์นํ๊ณ ์๊ฒฉ์ผ๋ก ์ ์ํ ์ ์๋๋ก ์ค์ ํ๋ค. ์ฌ๊ธฐ๊น์ง ๋ณด๋ฉด ํ์๊ฐ ์์ฒญ๋๊ฒ ํ์ด์ฌ์ ๋ํด ์ ์๋๊ฒ์ฒ๋ผ ๋ณด์ผ์๋ ์์ด ๋ฏธ๋ฆฌ ๋งํ์ง๋ง ํ์๋ ์ฐ ์๋ฐ ๊ฐ๋ฐ์์ด๋ฉด์ ํ์ด์ฌ ๊ฐ๋ฐ ์์ค์ ๊ธฐ๋ณธ์ ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๋ ์ ๋์ด๋ค. ๊ทธ๋ฌ๋ ์ด ํฌ์คํธ๋ฅผ ์ฝ๊ณ ์๋ ํ์๊ฐ์ ํ์๋ชป(?) ๋ถ๋ค๋ ์ถฉ๋ถํ ์ค์น๊ฐ ๊ฐ๋ฅํ๋ค. (์ต๋ํ ๋ฐ๋ผํ ์ ์์ ์ ๋์ ์นํธํค ์์ค์ผ๋ก ์์ฑ ํ๊ณ ์ ํ๋ค.)
์๋์ฝ๋ค ์ค์น (๋ค์ผ๋ก ์ค์น๋๋ ์ฃผํผํฐ) ์ฐ์ ์๋์ฝ๋ค๋ฅผ ์ค์นํ์. ์๋์ฝ๋ค๋ Anaconda(์ด์ : Continuum Analytics)๋ผ๋ ๊ณณ์์ ๋ง๋ ํ์ด์ฌ ๋ฐฐํฌํ์ผ๋ก, ์๋ฐฑ ๊ฐ์ ํ์ด์ฌ ํจํค์ง๋ฅผ ํฌํจํ๊ณ ์๋ค๊ณ ํ๋ค. ์ฆ, ์๋์ฝ๋ค๋ฅผ ์ค์นํ๊ณ ๋ง๋ค์ด์ง ๊ฐ์ํ๊ฒฝ์์ ํ์ด์ฌ ๊ฐ๋ฐ์ ํ๋ฉด ๋ค์ํ ๋ชจ๋์ด ์ด๋ฏธ ์ค์น๋์ด ์๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌํ๋ค๋ ์ด์ผ๊ธฐ.
์ถ์ฒ : https://www.anaconda.com/" ์ถ์ฒ : https://www.anaconda.com/ ๋๋ถ์ด ์์คํ
์ ๊ธฐ๋ณธ์ผ๋ก ์ค์น๋์ด ์๋ ํ์ด์ฌ์ ๊ฑด๋๋ฆฌ๋ฉด ์ฌ๋ฌ ๋ณต์กํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ์. ์๋์ฝ๋ค๋ฅผ ํ์ฉํ์ฌ ํ์ด์ฌ 3์ ์ฌ์ฉํ๋ ๊ฐ์ํ๊ฒฝ์ ๋ง๋ค์ด ๋ณด์. ์ค์น๋ ์์ฃผ ๊ฐ๋จํ๋ค. ์๋์ฝ๋ค ์ค์นํ์ผ์ ๋ค์ด๋ฐ๊ณ ์ด๋ฅผ ์คํํ๋ฉด ๋. (user ๋ ๋ฒจ์ด root ๋ฉด sudo ๋ช
๋ น์ด๋ฅผ ์๋ตํด๋ ๋๋ค.)
$ wget https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh $ sudo bash Anaconda3-2019.10-Linux-x86_64.sh Welcome to Anaconda3 2019.10 In order to continue the installation process, please review the license agreement. Please, press ENTER to continue >>> =================================== Anaconda End User License Agreement =================================== Copyright 2015, Anaconda, Inc. ~~~ ์ค๋ต ~~~ Do you accept the license terms? [yes|no] [no] >>> yes # yes!! Anaconda3 will now be installed into this location: /root/anaconda3 - Press ENTER to confirm the location - Press CTRL-C to abort the installation - Or specify a different location below [/root/anaconda3] >>> /home/anaconda3 # ์ค์น๋ ๊ฒฝ๋ก๋ฅผ ์ค์ ํด์ฃผ๊ณ ๊ธฐ๋ณธ ์ค์ ๊ฐ์ ์ค์นํ๋ ค๋ฉด ๊ทธ๋ฅ ์ํฐ ~~~๋ญ๊ฐ ์์ฒญ ์ค์น๋๋ค. ๋ฌผ ํ์ ๋จน๊ณ ์ค์.~~~ installation finished. Do you wish the installer to initialize Anaconda3 by running conda init? [yes|no] [no] >>> yes # yes!! ์ด๋ ๊ฒ ๋๋ฉด ์ค์น๋ ๋. ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํด์ ๊ธฐ๋ณธ ํ์ด์ฌ ํ๊ฒฝ์ ์๋์ฝ๋ค์ ์ํด ์ค์ ๋๋๋ก ๋ง์ถฐ์ฃผ์.
sudo vi .bashrc __conda_setup="$('/home/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" if [ $? -eq 0 ]; then eval "$__conda_setup" else if [ -f "/home/anaconda3/etc/profile.

์๋น์ค๋ฅผ ์ฒ์ ๋ง๋ค๊ธฐ ์์ํ ๋๋ฉด ๊ฐ ์ง๊ตฐ๋ณ๋ก ์๊ฐํ๋ ํฌ์ธํธ๊ฐ ๋ค์ํ๋ค. ์ค๊ณ, ๊ธฐํ, ๋์์ธ, ๊ฐ๋ฐ. ์ฌ๊ธฐ์ ๊ฐ๋ฐ์ ํ๋ก์ ํธ ์
ํ
์ ์ด๋ป๊ฒ ํด์ผํ์ง? ํ๋ ๊ณ ๋ฏผ์ ํ๊ธฐ ๋ง๋ จ์ด๋ค. ์์ฃผ ๊ฐ๋จํ๊ฒ ํ๋์ ๋ชจ๋๋ก ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ด๋นํ๋๋ก ๋ง๋ค ์ ์์ง๋ง ๊ธฐ๋ฅ๋ณ๋ก ๋ชจ๋์ ๋๋ ์ ์
ํ
ํ๋๊ฒ ๊ด๋ฆฌ์ธก๋ฉด์์ ์ฅ์ ์ด๋ผ ์๊ฐํ๋ค.์๋ฅผ ๋ค์ด๋ณด์. ๋์๊ด์ ๋ค์ด์จ ์ฑ
์ ๋ณด๋ฅผ ์ธ๋ถ์ ์ ๊ณตํ๋ “API”, ์ฃผ๊ธฐ์ ์ผ๋ก ์ฑ
์ ๋ณด๋ฅผ ์
๋ฐ์ดํธ ํ๋ “Batch”. ์ด๋ ๊ฒ ํฌ๊ฒ ๋๊ฐ์ง์ ๋ชจ๋์ด ์์ด์ผ ํ๋ค๊ณ ๊ฐ์ ํ์๋ ์ด๋ค์์ผ๋ก ๋ชจ๋์ ์ค๊ณํ ์ ์์๊น?
์ด๋ฒ ํฌ์คํ
์์๋ ์คํ๋ง ๋ถํธ์ ๋ฉ์ด๋ธ์ ํ์ฉํด์ ํ๋์ ํ๋ก์ ํธ(์ปดํฌ๋ํธ)์์ ์ฌ๋ฌ ๋ชจ๋์ ๊ด๋ฆฌํ ์ ์๋ Spring Multi Module์ ์
ํ
ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ณ ์ ํ๋ค. ํ์๋ ์
ํ
ํ๊ธฐ ์ ์๋ “๊ทธ๋ฅ ํ๋ฉด ๋๋๊ฑฐ ์๋์ผ?“๋ผ๋ฉฐ ์ฐ์ต๊ฒ ๋ณด๋ค ์์ฃผ ์ฌ์ํ ๋ถ๋ถ๋ค์์ ์์ฒญ๋ ์ฝ์ง์ ํด์ ๊ทธ๋ฐ์ง ๊ผญ ํฌ์คํ
์ผ๋ก ๋จ๊ฒจ๋์ผ ๊ฒ ๋ค๊ณ ๋ค์งํ๊ณ ์ด๋ ๊ฒ ์ ๋ฆฌ๋ฅผ ํ ์ ์๊ฒ ๋์ด์ ๋คํ์ด๋ผ ์๊ฐํ๋ค.
์ด์ฉ๋ฉด ์ฐ๋ฆฌ๊ฐ ์๋ ํ๋ ๋ฉํฐ๋ชจ๋์ด ์๋๊น? ์ถ์ฒ : https://bcho.tistory.com/813" ์ด์ฉ๋ฉด ์ฐ๋ฆฌ๊ฐ ์๋ ํ๋ ๋ฉํฐ๋ชจ๋์ด ์๋๊น? ์ถ์ฒ : https://bcho.tistory.com/813 ์ ๋ฉํฐ๋ชจ๋๋ก ์
ํ
ํ ๊น? ์์์ ์์๋ก ์ด์ผ๊ธฐ ํ๊ฒ์ฒ๋ผ ํ์ฌ ์ฐ๋ฆฌ๊ฐ ์
ํ
ํด์ผํ ๋ชจ๋์ ํฌ๊ฒ ๋๊ฐ์ง ์ด๋ค.
API : ์ธ๋ถ์ ๋์๊ด์ ๋ค์ด์จ ์ฑ
์ ๋ณด๋ฅผ ์๋ ค์ฃผ๋ ๋ชจ๋ Batch : ์ฃผ๊ธฐ์ ์ผ๋ก ๋์๊ด์ ์ฑ
์ ๋ณด๋ฅผ ๊ฐฑ์ ํ๋ ๋ชจ๋ ํ๋ฒ ์๊ฐ์ ํด๋ณด์. ์์์ ๋งํ ๋ชจ๋๋ค ์ค์ ๋์์ ์ฌ์ฉํ ๊ฒ๋ง ๊ฐ์ ์ ๋ณด๊ฐ ์๋ค. “์ฑ
์ ๋ณด”. ๊ฐ ๋ชจ๋๋ง๋ค “์ฑ
์ ๋ณด"๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง์ ์์ฑํ๋๊ฒ ๋ณด๋ค ํ๊ณณ์์ ํด๋น๋ก์ง์ ๊ตฌํํ๊ณ ์ด๋ฅผ ์ฌ๋ฌ๊ณณ์์ ์ฌ์ฉํ๋๊ฒ ์ฌ์ฉํ๋๊ฒ ์ค๋ณต์ฝ๋๋ฅผ ๋ฐฉ์งํ ์ ์๋ ๋ฐฉ๋ฒ์ด๋๊ฑด ์ฝ๊ฒ ์์์ฐจ๋ฆด์ ์๋ค. ๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ ๋ชจ๋์ ๋ถ๋ฆฌํ ์ ์์๊น?
ํ์์ ๊ฒฝํ์ผ๋ก ๋ฏธ๋ฃจ์ด ๋ณผ๋ ํฌ๊ฒ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋๊ฒ ๊ฐ๋ค.
๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๋ชจ๋์ jar๋ก ๋ง๋ค๊ณ ์ด๋ฅผ ๋ฉ์ด๋ธ ์๊ฒฉ ์ ์ฅ์์ deploy, ์ฌ์ฉํ๋ ๋ชจ๋์์ ๋ํ๋์์ ์ถ๊ฐํ์ฌ ์ฌ์ฉ ๋ฉํฐ๋ชจ๋๋ก ๊ตฌ์ฑํ๊ณ ์ฌ์ฉํ๋ ๋ชจ๋์์ ๋ํ๋์์ ์ถ๊ฐํ์ฌ ์ฌ์ฉ ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ์ ๊ฐ์ฅ ํฐ ๋จ์ ์, ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๋ชจ๋์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋ฒ์ ์ ๋ฐ๊ฟ์ฃผ๊ณ (์๋ฐ๊ฟ๋ ๋์ง๋ง ์ฌ์ฉํ๋ ๋ชจ๋์์ ์บ์ ๊ฐฑ์ ์ ํด์ผํ๋ ๋ถํธํจ์ด ์๊ธด๋ค.) ๋ฉ์ด๋ธ ์๊ฒฉ ์ ์ฅ์์ deploy๋ฅผ ํด์ค์ผ ํ๋ค. ๊ทธ์ ๋ฐํด ๋๋ฒ์งธ ๋ฐฉ๋ฒ์ ์ด๋ฐ๊ณผ์ ์์ด ํจ๊ป ๋น๋๋ง ํด์ฃผ๋ฉด ๋๋๊ณ IDE์์ ๊ฐ๋ฐ์ ํ ๋ชจ๋์์ ๋์์ ์์ ๊ณผ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ํจ์ฌ ํธ๋ฆฌํ๋ค.
์์ด์์ ์๋ค ๋ผ๋ ๋ง์ฒ๋ผ, ์ ๋ต์ ์๋ค. ํ์ง๋ง ์ด๋ฐ์ ๋ฐ ๋ฐฉ๋ฒ๋ค์ ๋ฏธ๋ฆฌ ์์๋๋ฉด ์ ์์ ์์ ์ฌ์ฉํ ์ ์๋. ํ์๊ฐ ๋ค๋ฅธ๊ธ๋ค์์๋ ์ธ๊ธ์ ์์ฃผํ๋ “๋๋ง์ ๋ฌด๊ธฐ"๊ฐ ๋์ง ์์๊น?
๋ฉํฐ๋ชจ๋ ์
ํ
ํ๊ธฐ ์์์ ์ด์ผ๊ธฐ ํ๋ “API”, “Batch"์๋ ๋ณ๋๋ก ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๋ชจ๋์ธ “Core” ์ด๋ ๊ฒ ์ด 3๊ฐ์ ๋ชจ๋์ ๋ง๋ค์์ ์ด๋ค.
๋ค๋ฅธ ์ด์ผ๊ธฐ์ง๋ง, ๊ณตํต์ผ๋ก ์ฌ์ฉํ ๊ฒ “๊ฐ์์” ๋ฏธ๋ฆฌ ๊ณตํต๋ก์ง์ ์์ฑํ๋ ์ต๊ด์ ์ข์ง ์๋๊ฒ ๊ฐ๋ค. ๊ทธ๋ฌ๋ค๋ณด๋ฉด ์ธ๋ฐ์์ด ๊ณตํต๋ก์ง์ด ๋ฌด๊ฑฐ์์ง๋ฏ๋ก ์ค์ ๋ก ์ฌ์ฉํ๋ฉด์ ์ค๋ณต์ฝ๋๊ฐ ๋ฐ์ํ ๋ ๊ทธ๋ ๊ณตํต๋ก์ง์ผ๋ก ๋ฆฌํํ ๋ง ํด๋ ๋ฆ์ง ์๋๊ฒ ๊ฐ๋ค. (๊ผฐ๋ฐ์ธ๊ฐ…)
๊ตฌํํ๋ ํ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ๋ค.
Spring Boot 2.2.3 Maven IntelliJ ์ฐ์ IDE์ ํ์ ๋น๋ ค ํ๋์ ์คํ๋ง ๋ถํธ ํ๋ก์ ํธ๋ฅผ ์์ฑํด๋ณธ๋ค.
๋ค์ > ๋ค์ > ๋ค์" ๋ค์ > ๋ค์ > ๋ค์ ๊ทธ ๋ค์ ๋ง๋ ํ๋ก์ ํธ์์ ์ฐํด๋ฆญ ํ ์๋ก์ด ๋ชจ๋์ ์ ํ. Maven ๋ชจ๋์ ์ ํํ๊ณ ์ ๋นํ ์ด๋ฆ์ ์ ์ด์ค๋ค. ๋ค์ > ๋ค์ > ๋ค์ 222" ๋ค์ > ๋ค์ > ๋ค์ 222
“API”, “Batch”, “Core” ๋ผ๋ ๋ชจ๋์ ์ถ๊ฐํ๊ณ ์ค์ ๋ชจ๋์ด ๋๋ “API”, “Batch"์ Build plugin ์ ์
ํ
ํด์ฃผ์. ๊ทธ๋ ๊ฒ ํ๊ณ ๊ฐ Pom.xml์ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค. (“API” ๋ชจ๋์ ๋ํด์๋ง ์ง์ค์ ์ผ๋ก ์ด์ผ๊ธฐ ํ๋ ค ํ๋ค. “Batch” ๋ชจ๋๋ ๋์ผํ ํ์์ผ๋ก ์์ฑํ๊ธฐ ๋๋ฌธ.)
์ต ์์ Pom.xml (library) modules ํ์์ ๋ฉํฐ๋ชจ๋๋ก ์ค์ ํ ๋ชจ๋๋ค์ ์ด๋ฆ์ด ๋ค์ด๊ฐ ์๋๊ฒ์ ํ์ธํ ์ ์๋ค. <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>pom</packaging> <modules> <module>api</module> <module>core</module> <module>batch</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.taetaetae</groupId> <artifactId>library</artifactId> <version>0.0.1-SNAPSHOT</version> <name>library</name> <description>Demo project for Spring Boot</description> <properties> <java.

“ํ๊ณ "๋ ๋น๋จ ๊ฐ๋ฐ ๋ธ๋ก๊ทธ ๋ฟ๋ง ์๋๋ผ ์ด๋ ํ ๊ณผ์ ์ ๋ง์ง๋ง์๋ ๊ผญ ํด์ผํ ์ค์ํ ์๊ฐ์ธ ๊ฒ ๊ฐ๋ค. ์๋ง๋ณด๊ณ ๋ฌ๋ ค๊ฐ์! ๋ฅ๊ณต! ๋ผ๋ ๋ง์ด ์์ง๋ง ์ฌ์ค ์ด ๋ง์ด ์ฑ๋ฆฝ๋๊ธฐ ์ํด์ ์ง๋ ๊ณผ๊ฑฐ์ ๋ํ ์ ๋ฆฌ์ ๋ฐ์ฑ ๊ทธ๋ฆฌ๊ณ ๋ฌด์์ ํ๋ ค๊ณ ํ๋๋ฐ ์ด๋ค ์ด์ ๋ก ๋ชปํ๋์ง์ ๊ทธ ๋์์ ๋ ์์ ์ ๋ฐ๋ผ๋ณผ ์ ์๋ ์ด “ํ๊ณ ” ์๊ฐ์ด ํ์ํ๋ค. ๋ฒ์จ 2019๋
๋ ๋ง๋ฌด๋ฆฌ๊ฐ ๋์ด๊ฐ๋ค. ์๋
๋ณด๋ค ๋ ์ ์ ์์ด ๋ฌ๋ ค์จ ์ฌํด. ๋ด๋
์ ์ฌํด๋ณด๋ค ๋ ๋ฉ์ง๊ณ ํ์ฐจ๊ฒ ์ถ๋ฐํ๊ธฐ ์ํด ํ์์ ํ ํด๋ฅผ ๋์๋ณด๊ณ ์ ํ๋ค.
๊ทธ๋ ๋ค๋ฉด ํ๊ณ ๋ ์ด๋ป๊ฒ ํ๋๊ฒ ๊ฐ์ฅ ์ข์๊น? ๋ฌด์์ ํ์๋ผ์ธ ๊ธฐ๋ฐ์ผ๋ก 1์์ ๋ญํ๊ณ 2์์ ๋ญํ๊ณ … ์ด ๋ฐฉ๋ฒ์ด ํ๋ฆฐ๊ฑด ์๋์ง๋ง ํ์๋ผ์ธ ๊ธฐ๋ฐ์ผ๋ก ์ ๋ฆฌ๋ฅผ ํ ๋ค ํค์๋๋ณ๋ก ๋ค์ ์ ๋ฆฌํ๋ ๋ฐฉ์์ด ๊ฐ์ฅ ๋ง์๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด๋ค. ๋ฌด์์ ํ๊ณ , ๋ญ๊ฐ ์ข์๊ณ ์ด๋ค๊ฑด ์์ฌ์ ๊ณ . ๊ทธ๋์ ๋ด๋
์ ์ด๋ป๊ฒ ํ ๊ฒ์ด๊ณ . ๊ฐ์์ ํ๊ณ ๋ฐฉ์์๋ ์ฐจ์ด๊ฐ ์๊ฒ ์ง๋ง ํ๊ณ ๋ฅผ ํ๋ ์ด์ , ๊ทธ๋ฆฌ๊ณ ํ๊ณ ๋ผ๋ ๋ชฉํ ์ค์ ๊ณตํต์ ์ “๋ค๋ฅผ ๋์๋ณด๊ณ , ์์ ๋ณด๊ธฐ์ํ ํ์ ์ฐพ๋๊ฒ” ์ด ์๋๊น ์ถ๋ค.
๋ด๋
ํ๊ณ ๋ฅผ ํ ๋๋ ํ๋ฐฑ์ด ์๋ ์ปฌ๋ฌ ์ฌ์ง์ ๋ฃ์ ์ ์๋ ๋ถ์๊ธฐ๊ฐ ๋ ๊น?… ์ถ์ฒ : http://www.nanum.com/site/poet_walk/820914" ๋ด๋
ํ๊ณ ๋ฅผ ํ ๋๋ ํ๋ฐฑ์ด ์๋ ์ปฌ๋ฌ ์ฌ์ง์ ๋ฃ์ ์ ์๋ ๋ถ์๊ธฐ๊ฐ ๋ ๊น?… ์ถ์ฒ : http://www.nanum.com/site/poet_walk/820914 ํ์ฌ๋ ์ฑ์ฅ์ ๊ณต๊ฐ์ด ์๋๊ฒ์ ๊นจ๋ณ๋ ์๊ฐ. (์ด์ผ๊ธฐ์ ์์ ํ์๋ ํ์ฌ ์๋น์ค ๊ฐ๋ฐ์์์ ๋ฐํ๋ค.)
๋ด๋
์ด ๋๋ฉด ์ปดํจํฐ์์ด๊ฐ ๋์ง ๋ฒ์จ 8๋
์ฐจ. ๋งค๋
์ฑ์ฅ์ ๊ทธ๋ํ๋ฅผ ๊ทธ๋ ค๋ณด๋ฉด ์๋
๊น์ง๋ง ํด๋ ์ฐ์ํฅ์ด์๋ค. (๊ทธ๋ํ์ ๊ธฐ์ธ๊ธฐ๋ ๋งค๋
๋ฌ๋์ง๋ง) ํ๋ ์ฌํด๋ ๊ธฐ์ธ๊ธฐ๊ฐ 0 ์ด๊ฑฐ๋ ์คํ๋ ค ๋ง์ด๋์ค๊ฐ ๋ ๊ฒ ๊ฐ์ ๋๋์ด๋ค. ์์ผ๊น.
ํค๋ ์ ๋์ด์ ์ฑ์ฅ์ ์ํ ๊น? (์ฐ์…) ์ถ์ฒ : http://www.guro1318.or.kr/bbs/board.php?bo_table=data&wr_id=1723" ํค๋ ์ ๋์ด์ ์ฑ์ฅ์ ์ํ ๊น? (์ฐ์…) ์ถ์ฒ : http://www.guro1318.or.kr/bbs/board.php?bo_table=data&wr_id=1723 ํ์ฌ๋ฅผ ๋ค๋๋ค ๋ณด๋ฉด ์์ฃผ ์ผ๋ฐ์ ์ผ๋ก “์ํค๋ ์ผ"์ ํ๊ณค ํ๋ค. ์ฃผ์ด์ง ์
๋ฌด๋ฅผ ์ ํด์ง ๊ธฐ๊ฐ ์์ ์คํ์ ๋ง์ถฐ ๊ฐ๋ฐํ๋. ์์ฃผ ๊ทน๋จ์ ์ผ๋ก ๋์๊ฒ ๋งํ๋ฉด “๋๊ตฌ"๋ก ์ ๋ฝ๋์ด๋ฒ๋ฆด ์๋ ์๋ ์๊ฐ๋ค. (๊ฐ๋ฐ์๊ฐ ๋๊ตฌ๊ฐ ๋๋ค๋ ๋ง์ ๋๋ฌด๋๋ ๋ฃ๊ธฐ ์ซ์ ๋ง์ค์ ํ๋.) ํํ ๋งํ๋ CRUD(Create, Read, Update, Delete) ์ฑ์ ๊ฐ๋ฐ ์
๋ฌด๋ฅผ ํ๊ณค ํ๋ค. ํ์ง๋ง ๊ผญ ์ฑ๊ณผ์ align(๋ ์ข์ ํ๊ตญ๋ง์ ์ฐพ๊ณ ์ถ์๋ฐ…) ํ๋ ์ผ ๋ง๊ณ ๋ ํ๋๋ ์ผ(์ผ์ข
์ ์์คํ
์ด๋?)์ ํ ๊ฒฝ์ฐ๋ ์๋๋ฐ ๊ทธ๊ฒ ๋ง์ฝ ์ฌ๋ฏธ์๋ ์ผ์ด๋ผ๋ฉด ์ด๋จ๊น?
ํ์๋ ๊ทธ๋ ๊ฒ “์ํค๋ ์ผ๋ง ํ๋ฉฐ ์ฌ๋ฏธ์๋ ํ์ฌ์ํ” ๋ณด๋ค “์ฌ๋ฏธ์๊ฒ ๊ฐ๋ฐํ๋ฉฐ ์ฑ์ฅ์ ํ ์ ์๋ ํ์ฌ์ํ” ์ด๋ผ๋ ๊ธฐ์ค์ ๊ฐ์ง๊ณ ํ ํด๋ฅผ ์ง๋ด์จ ๊ฒ ๊ฐ๋ค. ์ฆ, “์ํค๋ ์ผ"์ด ์๋ “์ํค์ง๋ ์์ ์ผ"์ ์ฐพ์์ ํด๊ฐ๋ฉฐ. ์์ปจ๋, ์ฒ์์ ์ก์๋ ์๋น์ค ๊ตฌ์กฐ๊ฐ ์ฌ์ฉ์๊ฐ ๋ง์์ง๊ณ ์๊ตฌ์ฌํญ์ด ๋ง์์ง์ ๋ฐ๋ผ ๋ณต์กํ๊ณ ์ฑ๋ฅ์ ์ ํดํ๋ ์ํฉ์ ๋ฐ๊ฒฌํ๊ณ ๋ฏธ๋ฆฌ ๊ตฌ์กฐ๊ฐ์ ์ ํตํด ์ฑ๋ฅ๊ณผ ํจ์จ์ด๋ผ๋ ๋๋ง๋ฆฌ์ ํ ๋ผ๋ฅผ ์ก๋๋ค๊ฑฐ๋. ์ง๋ ์ธ๋ถ ์ธ๋ฏธ๋์์ ๋ฃ๊ณ ์ธ์ฌ์ดํธ๋ฅผ ์ป์ด ํ๋ด์๋ ์ ์ฉํด๋ณธ ๋ฐฐ์น ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ธฐ๋ฅ. ํ ๋ด ์ฝ๋๋ฆฌ๋ทฐ์ ํ์ฑํ์ ์๋์ผ๋ก ํด์ผํ ์
๋ฌด๋ค์ ๋ฉ์ ์ ๋ด์ ํ์ฉํ์ฌ ์๋ํ ํ๋ค๊ฑฐ๋. ์๋น์ค ์งํ ๋์๋ณด๋๋ฅผ ๋ง๋ค์ด ํ๋์ ์๋น์ค ์ํฉ์ ๋ณผ ์ ์๊ฒ ๋ณ๋์ ๊ฐ๋ฐ ํ์ด์ง๋ฅผ ๋ง๋ค์ด ๋ณด๋ ๋ฑ. ๋ค์ํ ์
๋ฌด ๋ด/์ธ ์ ์ผ๋ก ์ผ์ ์ฐพ์๊ฐ๋ฉฐ + ํ์์ ๊ฐ์ธ ์๊ฐ์ ํ ์ ํด ๊ฐ๋ฉด์ ์ ๋ง ์ฌ๋ฏธ์๊ฒ ๋ณด๋ด์จ ๊ฒ ๊ฐ๋ค.
ํ์ง๋ง ๋ค๋ฅผ ๋์๋ณด๋ฉด “์ฑ์ฅ ํ๋๊ฐ?” ๋ผ๋ ์ง๋ฌธ์ด ์๋ค๋ฉด “๊ทธ๋ ๊ฒ ํ๊ณ ์๋๊ฒ ๊ฐ์์ ์ ๋๊ฒ ํด์๋๋ฐ ๋์๋ณด๋ ๋ง์ ๋ญํ๋ ํ๋ ๋๋์ด ๋ ๋ค” ๋ผ๊ณ ๋งํ ์ ์์ ์ ๋๋ก ์ฌ๋ฌ๊ฐ์ง๋ฅผ ๋ง์ด ํ๋ฉฐ ๋ค์ํ “๊ฒฝํ"์ ์ป๊ธด ํ์ง๋ง ์ค์ง์ ์ธ “์ฑ์ฅ"์ ์์ฝ์ง๋ง ๋ถ์กฑํ ํ ํด ์๋๊ฒ ๊ฐ๋ค.
ํ์ฌ๊ฐ ์ํ๋, ์ฐ์ฐจ์ ๋ง๋ ์
๋ฌด ์ญ๋๊ณผ ๊ฐ๋ฐ ํ์์์ ์์น๋ฅผ ์ถฉ์กฑ์ํค๊ธฐ์ ํ์ฌ ์์์ ์ฑ์ฅํ๊ธฐ์ ํ๊ณ๊ฐ ์๋ค๊ณ ํ๋จ์ด ๋ค์๋ค. (์ด ์๊ฐ์ด ์ ์ด์ ์์ผ ๋ค์์๊น.) ์คํ์์ค๋ ์๋ก์ด ์ธ์ด๋ฅผ ํ์ฌ ๋ฐ์์ ํผ์์ ๊ณต๋ถ ํ๋์ง ์ฌ๋ฌ๋ช
์ด์ ์คํฐ๋๋ฅผ ํตํด ์ต๋์ ํด์ผํ๊ณ ํ ์ดํ๋ก์ ํธ ๋ํ ํ์ฌ์ ๋ณ๋๋ก ์งํํ๋ฉฐ ๊ฐ๋ฐ ์คํฌ์ ๋๋ ค์ผ ํ ๊ฒ ๊ฐ๋ค. ๊ทธ ์ด์ ๋ ํ์ฌ์์์ ์ฑ์ฅ์ด ๊ฒฐ๊ตญ ๋์ ์ฑ๊ณผ๋ก ์กํ ์๋ ์๋๋ฐ ๊ด์๋ฆฌ ๊ธฐ๋๋ฅผ ํ๊ฒ ๋๊ธฐ๋ ํ๊ณ ํนํ ์๋น์ค๋ฅผ ์ด์ํ๋ ํ์์๋ ์์ฆ ํซ ํ๋ค๋ ๊ฐ๋ฐ ๋ฐฉ๋ฒ๋ก ์ด๋ ์๋ฃจ์
์ ๋์
ํ๊ธฐ์๋ ๋ค์ ๋ฌด๋ฆฌ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.

์ ์
์์ . ๋ฐฐ์์ผ ํ ๊ฒ๋ ํ์ฌ ์
๋ฌด๋ ๋ง์ ํ์ฐ์ ๋๋ ๋๊ฐ ์์๋ค. ๊ทธ๋ ๊ฒ ํ๋ฃจ์ 3~4์๊ฐ ์๋ฉฐ ์ ์ ์์ด ํ๋ฃจ๋ฅผ ๋ณด๋ด๋ ๋ ๋ฌธ๋ ๋๊ธฐ ํ์ด “๊ฐ๋ฐ์๋ ๊ธฐ์ ๋ธ๋ก๊ทธ๋ฅผ ํด์ผ ๋ผ!“๋ผ๋ ์ ํ ์ดํด๊ฐ ์ ๋๋ ๋ง์ ํด์จ๋ค. ์ด๋ ๊ฒ ๋ฐ๋น ์ฃฝ๊ฒ ๋๋ฐ ๋ธ๋ก๊ทธ์ ๊ธ๊น์ง ์ฐ๋ผ๊ณ ? ๋ง์ด ๋๋ ์๋ฆด ํ๋ผ๋ฉฐ ๋ฐ๋ฐํ๋ค ๋ชป๋ด ์ด๊ธฐ๋ ์ฒ ํ๋ ๋ ๊ธ์ ์ฐ๊ธฐ ์์ํ๊ณ , ๋ค๋ฅธ ์ ๋ช
๋ธ๋ก๊ฑฐ์ฒ๋ผ ์์ฒญ๋์ง ์์ง๋ง ํ๋ฃจ์ 1,000~2,000๋ช
์ ๋ ๋ค์ด์ค๋ฉฐ ์ ์ ์ฑ์ฅํด ๊ฐ๋ ๋๋ง์ ๊ธฐ์ ๋ธ๋ก๊ทธ๊ฐ ๋์๋ค.
๋ฏธ์ฝํ์ง๋ง ์ฒ์๋ณด๋ค๋ ์ฑ์ฅํ๊ณ ์๋ ๋ธ๋ก๊ทธ PV(Page View)" ๋ฏธ์ฝํ์ง๋ง ์ฒ์๋ณด๋ค๋ ์ฑ์ฅํ๊ณ ์๋ ๋ธ๋ก๊ทธ PV(Page View) ๋ํ ํ์์ ๊ฐ๋ฐ์ ๊ฒฝ๋ ฅ(?)์ ๋์ด์ผ ๋ณด์๋ฉด ๊ธฐ์ ๋ธ๋ก๊ทธ๋ฅผ ํ๊ธฐ ์ ๊ณผ ํ๊ณ ๋ ํ๋ก ๋๋ ๋งํผ ๊ธฐ์ ๋ธ๋ก๊ทธ๋ ๊ฐ์ธ์ ์ผ๋ก ์์ฒญ๋ ์ํฅ๋ ฅ์ด ๋์๋ค.
์ด ๊ธฐํ๋ฅผ ๋น์ด ๋๊ธฐ ํ์๊ฒ ๊ฐ์ฌ์ ์ธ์ฌ๋ฅผ ์ ํ๊ณ ์ถ๋ค. ํ. ๋ณด๊ณ ์์ฃ ? ;]
์ด๋ฒ ํฌ์คํ
์ ๊ผญ “๋ธ๋ก๊ทธ๋ฅผ ํ์” ๋ผ๊ธฐ ๋ณด๋ค “๊ธ์ ์ ์จ์ผ ํ๊ณ ์ด๋ป๊ฒ ์จ์ผ ํ๋์ง"์ ๋ํด ์ด์ผ๊ธฐํด๋ณด๊ณ ์ ํ๋ค. ์ฒ์ ์ด ๊ธ์ ์ฐ๋ ค๊ณ ๋ง์๋จน์์ ๋ ๊ฐ๋ฐ์๋ผ๋ ์ง๊ตฐ์ ๊ตญํ๋์ง ์๊ณ ๋๊ตฌ์๊ฒ๋ ์ ์ฉ๋ ์ ๋์ ๋ฒ์ฉ์ ์ธ ๊ธ์ ์ฐ๋ ค ํ์ผ๋ “S"์ ์กฐ์ธ์ผ๋ก ๋
์(ํ๊น)์ ์ต๋ํ ๊ฐ๋ฐ์์ ๋ง์ถฐ ์จ๋ณด๊ณ ์ ํ๋ค. thanks to “S”
์ฌ์ค ์กฐ๊ธ๋ง ๊ฒ์์ ํด๋ณด๋ฉด ํนํ ๊ฐ๋ฐ์์๊ฒ ๊ธ์ฐ๊ธฐ๊ฐ ์ผ๋ง๋ ์ค์ํ์ง ์ฐพ์๋ณผ ์ ์์ ์ ๋๋ก ๋ค์ํ ๊ธ๋ค์์ “๊ฐ๋ฐ์๊ฐ ์ ๊ธ์ ์จ์ผ ํ๋๊ฐ"์ ๋ํ ๋ด์ฉ์ด ์ธ๊ธ์ด ๋๊ณค ํ์๋ค. ๊ธ์ ์ฐ์ง ์๋ ๊ฐ๋ฐ์. ํ์ง๋ง ์ง๊ธ์ ๊ธ์ฐ๊ธฐ๊ฐ ์ ๋ง ์ค์ํ๋ค๊ณ ๋๋ผ๋ฉฐ ์ ์ด๋ 2์ฃผ์ ํ๋ ์ด์์ ๊ธ์ ์ฐ๋ ค๋ ํ์
๊ฐ๋ฐ์์ ์์ ์์ ์ ๋ฆฌ๋ฅผ ํด๋ณด๊ณ ์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ง์นจ ๋ฉํ ๋ง ํด์ฃผ๊ณ ์๋ ๋ถ๊ป๋ ๊ธ ์ฐ๋๊ฒ์ ๋ํ ์ค์์ฑ์ ์๋ ค์ฃผ๊ณ ์ถ์๊ณ , ํ ๋ด์๋ ๊ณต์ ๋ฅผ ํ๊ณ ์ถ์ด ๊ฒธ์ฌ๊ฒธ์ฌ.
์ ๊ธ์ ์จ์ผ ํ ๊น? ๋น๋ก์ ๋ด ๊ฒ์ด ๋๊ธฐ ์ํ ๊ณผ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ฒ์ ๋ฐฐ์ธ๋ ๊ผญ ๋ง๋๋ ๋ฌธ๊ตฌ Hello World๋ฅผ ์ถ๋ ฅํ์์ค. ์ด๊ฒ ์๋ฏธํ๋ ์๋ฏธ๊ฐ ๋ฌด์์ผ๊น? ์ ๋ง ์๋ก์ด ์ธ๊ณ๋ฅผ ์๋ ค์ฃผ๋ ค ํ๋ ๊ฒ ์ผ๊น?(๊ทธ๋ด์๋ ์๋ค…) ์ฐ๋ฆฌ๊ฐ ์ด์๊ฐ๋ฉฐ “๋ฐฐ์"์ด๋ผ๋ ๊ณผ์ ์ ๋๋ถ๋ถ ๋น์ทํ๊ฒ ์ง๋ง ํนํ IT ๊ธฐ์ ์ ์ฑ
์ ๋ค ์ฝ์๋ค๋ ์ง, ๋์์ ๊ฐ์๋ฅผ ๋ค ๋ค์๋ค๊ณ ํด์ ๋ด ๊ฒ์ด ๋์๋ค๊ณ ๋งํ๊ธฐ๋ ์ด๋ ค์ธ ๊ฒ ๊ฐ๋ค. ์ง์ ํค๋ณด๋๋ฅผ ๋๋๋ ค ๊ฐ๋ฉฐ ๊ฑฐ๊ธฐ์ ์ป์ ์ ์๋ ๋ ๋ค๋ฅธ “์ธ์ฌ์ดํธ” ๊ฐ ์๊ธธ ์๋ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ค๋ฅธ ์๋ก, ์ด์ํ๋ ์์คํ
์ด๋ ์๋น์ค์์ ์ฅ์ ๋ฅผ ๋ง์๋ค๊ณ ๊ฐ์ ํด๋ณด์. ํ์ง๋ง ์ฐ๋ฆฌ๋ ๋ ๊ทธ๋์๋ฏ ์ด๋ป๊ฒ๋ ์ฅ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ด๋ค. ์ด๋ฌํ ์ํฉ์์ ๋ถ๋ช
“๋ฌธ์ ์ ์์ธ"์ด ์์์ ํ
๊ณ “ํด๊ฒฐ ๊ณผ์ "์ด ์๊ธฐ ๋ง๋ จ์ธ๋ฐ ์ด๊ณณ์์๋ “์ธ์ฌ์ดํธ"๊ฐ ๋ถ๋ช
์์ ๊ฒ์ด๋ค.
์ด๋ฌํ “์ธ์ฌ์ดํธ"๋ฅผ ๊ธ๋ก ์ ๋ค ๋ณด๋ฉด ๊ทธ๋ฅ “์~ ๊ทธ๋ ๊ตฌ๋, ๊ทธ๋ฌ์์ง” ํ๋ ๋จธ๋ฆฟ์์์์ ๊ธฐ์ต๋ณด๋ค๋ ํจ์ฌ ๋ ์ค๋ ๋จ์ ๊ฒ์ด๊ณ ํน์ฌ ๊ธ์์ ์ ๋ฆฌ๋ฅผ ์๋ชปํด ๋ค๋ฅธ ์ฌ๋๋ค์ ํผ๋๋ฐฑ์ด ์๋ค๋ฉด ๋ํ ๋์ ์์ด ์ข์ ํจ๊ณผ๋ผ๊ณ ์๊ฐ์ด ๋๋ค. (์ด๊ฒ์ด ๋ฐ๋ก ๊ณต์ ์ ํ!)
๋๋ถ์ด ๊ธ์ ์ธ ๋ ์ฌ๋ฐ๋ฅธ ์ ๋ณด์ ๊ธฐ๋ฐํ์ฌ ์ฐ๋ ์ต๊ด์ด ์ค์ํ๋ฐ ๊ทธ๋ฌ๋ค ๋ณด๋ฉด ์๋ ์ฐ๋ ค๊ณ ํ๋ ๋ด์ฉ๋ณด๋ค ๋ ๊น๊ฒ ์์๊ฐ๋ ๊ณผ์ ์์์ ๋ ๋ค๋ฅธ ๋ฐฐ์์ ์ป์ ์ ์๋ ๋ฐ๊ฐ์ ์ ๊ธฐํ๊ฐ ์๊ธธ ์ ์๋ค. ๋๊ฐ ์ํค์ง ์์์ด๋ ๋ฐฐ์ด ๊ฒ์ ๋ํ ํ์ฉ์ ํ๊ณ ์ถ์ ์๊ฐ์ด ๋ค๊ณ ์ด๋ฅผ ๋ ๊ธ๋ก ์ฐ๊ณ . ๊ธ์ ์ ์ธ ์ํ ์์ ์๊ฒจ๋๋ ์์ ๋ฐ์๊ตญ์ผ์ง๋ผ๋ ์ฑ์ฅํด๊ฐ๋ ์์ ์ ๋๋ ์ ์์ ๊ฒ์ด๋ค.
๋ชธ์ด ๊ธฐ์ตํ๋ ์ ๋ฆฌํ๋ ์ต๊ด ๊ฐ๋ฐ์ ํ๋ค ๋ณด๋ฉด ์ ๋ง ๊ฐ๋จํ “CRUD”(Create, Read, Update, Delete) ๋ถํฐ ์์ํด์ ์์ฒญ๋๊ฒ ๋ณต์กํ ๋๋ฉ์ธ ์ง์์ ๊ธฐ๋ฐํ์ฌ ๊ฐ๋ฐ์ ํด์ผ ํ๋ ์ํฉ์ด ์๊ธด๋ค. ๊ทธ๋ด ๋๋ฉด ๋จธ๋ฆฟ์์ผ๋ก ์ ๋ฆฌํ๋ ๊ฒ๋ณด๋ค ๊ทธ๋ฆผ์ด๋ ๊ธ์ ์จ๊ฐ๋ฉด์ ์ ๋ฆฌํ๋ ๊ฒ ์ข๋ค๋ ๊ฑด ๊ตณ์ด ๋งํ์ง ์์๋ ์๋ ์ฌ์ค. ๊ธ์ ์ฐ๋ค ๋ณด๋ฉด ๊ธฐ์น์ ๊ฒฐ์ ์ ๋ฆฌ ๋ฐฉ๋ฒ๊ณผ ๋ชฉ์ ์ด ๋ฌด์์ด๊ณ ๊ทผ๊ฑฐ๊ฐ ๋ฌด์์ธ์ง์ ๋ํด ๊ตฌ๋ถํ๋ ์คํฌ์ด ๋์ด๋๋ ๊ฒ ๊ฐ๋ค.(์ ์ด๋ ํ์๋ ๊ธฐ์ ๋ธ๋ก๊ทธ๋ฅผ ์ด์ํ๋ฉด์ ์ ๋ฆฌํ๋ ์คํฌ์ด ๊ทธ์ ๋ณด๋ค ์์ฒญ๋๊ฒ ๋์ด๋ฌ๋ค๊ณ ์๋ถํ๋ค.)
์ค๊ตญ ์๋ด์ค์ ํ๋, ๋จธ๋ฆฟ์์ ๋ฐํ ๋์ค์ง ์๋๋ค.

์ง๋ ํฌ์คํ
, ๊ทธ๋ฌ๋๊น ์ฐ์ํ ํ์ ๋ค์์ ์ด๋๋ฅผ ๋ฐ์ Spring batch ์ ๋ํ ํ
ํฌ์ธ๋ฏธ๋์ ๋ค๋
์๋ค. ๊ทธ ์ค ๊ฐ์ฅ ์ธ์๊น์๋ ๋ถ๋ถ์ด ๋ฐ๋ก ๋ฌด์ค๋จ ๋ฐฐํฌ. ์ฐจ์ผํผ์ผ ๋ฏธ๋ฃจ๋ค ํ์๊ฐ ์ํ ํ์์๋ ๋ฐฐํฌ๋๋ง๋ค ๊ฐ์ฅ ๋ถํธ์ ๋๋ผ๊ณ ์์๋ ๋ถ๋ถ์ด์๊ธฐ๋ ํ๊ณ , ๊ทธ๋ฐ๊ฐ๋ณด๋ค ํ๋ฉฐ ๊ฐ๋
๋ง ์๊ณ ๋์ด๊ฐ๊ธฐ์ ๋ฌด์ธ๊ฐ ์์ฌ์ ์ฐ๋ ค ์ง์ ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ํ ์ ์๋๋ก ๊ตฌ์ฑ์ ํด๋ณด๊ณ ํ
์คํธ๊น์ง ํด๋ณด๊ณ ์ ํ๋ค.
์ํฉ ๋ฐ ๋ฌธ์ ์ ๋ฆฌ๋
์ค ์๋ฒ์ Jenkins๊ฐ ์ค์น๋์ด ์๊ณ , Spring batch ๋ชจ๋์ ์คํ์ํค๊ณ ์๋ค. ์๋์ผ๋ก ์คํ์ ํ๊ฑฐ๋, Jenkins RestApi๋ฅผ ์ด์ฉํด์ ์คํ์ ํ ์ ์์ง๋ง ์ฃผ๋ก ์ ํด์ง ์๊ฐ ์ฆ, ์ค์ผ์ฅด๋ง์ ์ํด ์คํ๋๊ณค ํ๋ค. ์ค์ผ์ฅด๋ง์ ๊ฐ์ฅ ์์ ๋จ์๋ 1๋ถ๋จ์ ๋ฐฐ์น๋ ์๊ธฐ ๋๋ฌธ์ 24์๊ฐ ๋ฉ์ถ์ง ์๊ณ ์คํ๋๊ณ ์๋ค๊ณ ๋ฌด๋ฐฉํ๋ค. ํ์ง๋ง ๋ฐฐ์น ๋ชจ๋์ด ์์ ๋๊ณ , ๋ฐฐํฌ๋ฅผ ํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค๋ก ์งํ์ด ๋๋ค.
Jenkins ์ค์ ์ ๋๊ธฐ์ ์ค๋น ๋ฅผ ์คํํ์ฌ ๋์ด์ Jenkins์ ์ํด Spring batch ๋ชจ๋(์ดํ Job)์ด ์คํ๋์ง ์๋๋ก ํ๋ค. ์๋ก์ด Job์ ๋์ด์ ์คํ๋์ง ์์ง๋ง ์ด๋ฏธ ์คํ์ค์ด์๋ Job ์ ๊ฐ์ ๋ก ์ค๋จ์ ํ๊ฑฐ๋ Job ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค. ์คํ์ค์ธ Job์ด ์์ ๊ฒฝ์ฐ ์ด์ ๋ฐฐํฌ๋ฅผ ์งํํ๋ค. ๋ฐฐํฌ๊ฐ ์๋ฃ๋๋ฉด Jenkins ์ค์ ์ ๋๊ธฐ์ ์ค๋น๋ฅผ ํด์ ํ๋ค. ์คํ์ค์ธ Job์ด ์๋๋๋ฉด ๋ง๋ฅ ๊ธฐ๋ค๋ฆดํ
๊ฐ? ์ถ์ฒ : https://m.post.naver.com/viewer/postView.nhn?volumeNo=14100660&memberNo=2032633" ์คํ์ค์ธ Job์ด ์๋๋๋ฉด ๋ง๋ฅ ๊ธฐ๋ค๋ฆดํ
๊ฐ? ์ถ์ฒ : https://m.post.naver.com/viewer/postView.nhn?volumeNo=14100660&memberNo=2032633 ์คํ๋๋ Job์ ์ค๋จํ์ง ๋ชปํ๋ ์ํฉ ์ฆ, ์คํ์ค์ ์ค๋จํ๋ฉด ํธ๋์ญ์
์ด ๊นจ์ ธ ๋ฌด์กฐ๊ฑด ๊ธฐ๋ค๋ ค์ผ๋ง ํ๋ ์ํฉ์ด๋ผ๋ฉด ๋ฐฐํฌ ๋ํ ๊ณ์ ์ง์ฐ๋ ์ ๋ฐ์ ์๋ ์ํฉ์ธ ๊ฒ์ด๋ค. Spring boot์ java config ๋ฅผ ํ์ฉํ๊ณ ๋ฑ jar ํ์ผ ํ๋๋ฅผ ์คํํ๋ ๋ฐฉ์์ด๋ผ๋ฉด jarํ์ผ์ ๋ฐ๊ฟ์น๊ธฐ ํ๋ ์์ผ๋ก ๊ณ ๋ฏผ์ ํด๋ณผ์๋ ์์๊ฒ ๊ฐ๋ค. ํ์ง๋ง Legacy ์ฝ๋๊ฐ ์์ง ์กด์ฌํ์ฌ ์ผ๋ฐ Spring ์ xml ๋ก config ํ๋ ๋ฐฉ์์ผ๋ก ์ด์์ค์ด๋ผ jarํ์ผ ํ๋๋ง ๋ฐ๊ฟ์น๊ธฐ ํ๊ธฐ์ ๋ฌด๋ฆฌ๊ฐ ์๋ ์ํฉ.
์์ด์์ฒ๋ผ ์ด๋์์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๋ง๋ณํต์น์ฝ ๊ฐ์ ๋ฐฉ๋ฒ์ ์๋ค. ์ธ์ ๋ ๊ทธ๋ฌ๋ฏ ํ์ฌ ์์คํ
(xml config ๋ฐฉ์)์ ๊ฐ์ฅ ์ต์ ํ๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ java config ๋ฐฉ์์์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ ๋ฐฉ๋ฒ์ ์๊ฐํด ๋ณด์๋ค.
๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๊ฐ๋ฅ์ผ ํ๋ 3๊ฐ์ง ํต์ฌ 1. ๋ฐฐํฌ๋ฅผ ๋งค๋ฒ ์๋ก์ด ๊ฒฝ๋ก์ ๋ฐฐํฌํ๋ค. ๊ฐ ํ์ฌ๋ง๋ค, ๊ทธ๋ฆฌ๊ณ ์๋น์ค๋ง๋ค ์ ๋ง ๋ค์ํ ๋ฐฐํฌ ์์คํ
์ด ์๋ค. ๊ทธ๋ค์ ๊ณตํต์ ์ ์๊ฒฉ์๋ฒ์ ํน์ ๊ฒฝ๋ก์ ๋น๋๋ ํ์ผ๋ค์ ๋ฐ์ด ๋ฃ์ด์ค๋ค๋ ๊ฒ. ์๋๋ฆฌ์ค๋ ๋ค์๊ณผ ๊ฐ๋ค.
๋ฐฐํฌํ ๋๋ง๋ค ๋ณ๋์ ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑํ๋ค ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ์ฐ๊ฒฐํด์ค๋ค. ๋ฐฐํฌ๋ 1์์ ์ฐ๊ฒฐํ ์ฌ๋ณผ๋ฆญ ๋งํฌ์ ๋ฐฐํฌ๋๋๋ก ์ค์ , ๊ฒฐ๊ตญ ๋งค๋ฒ ๋ง๋ค์ด์ง๋ ๋๋ ํ ๋ฆฌ์ ๋ฐฐํฌ๊ฐ ๋๊ฒ ๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ์ ์ “๋ฐฐํฌํ ๋๋ง๋ค ์๋ก์ด ๋๋ ํ ๋ฆฌ์ ๋ฐฐํฌ๊ฐ ๋๋ค” ์ ๋ฐฐํฌ์์๋ ํญ์ ์ฌ๋ณผ๋ฆญ ๋งํฌ์๋ง ๋ฐฐํฌ๋ฅผ ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ “๋ฐฐํฌ์์คํ
์ด ์๋ก ๋ง๋ค์ด์ง๋ ๋๋ ํ ๋ฆฌ์ ๊ฒฝ๋ก๋ฅผ ๋ชฐ๋ผ๋ ๋ฌด๋ฐฉํ๋ค"๋ ์ ์ด๋ค.
#!/bin/sh cd /~~~/deploy/ # ์์ ๋๋ ํ ๋ฆฌ DIRECTORY_NAME=batch_$(/bin/date +%Y%m%d%H%M%S) mkdir $DIRECTORY_NAME ์ ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ฉด batch_20191012205218 ์ ๊ฐ์ ๋๋ ํ ๋ฆฌ๊ฐ ์์ฑ์ด ๋๋ค. ์ฌ๋ณผ๋ฆญ ๋งํฌ ๊ด๋ จํด์๋ ๋ฐ๋ก ์๋ ์ด์ด์ ์ค๋ช
ํ๊ฒ ๋ค.
2. ์ฌ๋ณผ๋ฆญ ๋งํฌ์ ์๋ ๋งํฌ๋ฅผ ์ฆ์ ๋ณ๊ฒฝ ๋ณดํต ์ฌ๋ณผ๋ฆญ ๋งํฌ (์ฆ, ๋ฐ๋ก๊ฐ๊ธฐ) ์ ๊ฒฝ๋ก๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํด์๋ ์๋์ฒ๋ผ ์ง์ ๋ค๊ฐ ์ญ์ ํ๋ ์์ผ๋ก ํ์๋๋ฐ
$ mkdir directory_a $ mkdir directory_b $ ln -s directory_a asdf $ ll asdf -> directory_a directory_a directory_b # directory_a ์์ directory_b ๋ก ๋ฐ๊พธ๋ ๊ฒฝ์ฐ (์ฌ๋ณผ๋ฆญ ๋งํฌ ์์ฒด๋ฅผ ์ญ์ ํ๊ณ ๋ค์ ์ฌ๋ณผ๋ฆญ ๋งํฌ ์์ฑ) $ rm asdf $ ln -s directory_b asdf $ ll asdf -> directory_b directory_a directory_b ์ด๋ ๊ฒ ๋๋ฉด ์ญ์ ํ๊ณ ~ ๋ค์ ๋ง๋ค์ด์ง๋ ํ์ด๋ฐ์ ๋ฐฐํฌ๊ฐ ๋๊ฑฐ๋ ์คํ์ด ๋๋ ์ฆ, ํด๋น ๊ฒฝ๋ก์ ์์ธ์ค ํ๋ ๊ฒฝ์ฐ ์ด์ ์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ๋ณธ๋ค๊ฑฐ๋ ์๋ํ๋ ๋ฐฉ์์ผ๋ก ์คํ์ด ๋์ง ์๋ ์ํฉ์ด ๋ฐ์ํ๋ค. (์ฐฐ๋์ ํ์ด๋ฐ ์ด์ง๋ง ํ์๋ ์ด๋ฌํ ๋ฌธ์ ๋ก ์ด์ ์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ๋ณด๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋ค.) ๊ทธ๋์ ln ์ ์ต์
์ค์ธ -Tfs์ต์
์ผ๋ก ์ฆ์ ๋ณ๊ฒฝ์ ํด์ฃผ๋๋ก ํ์. (ln man ์ฐธ๊ณ )
# ๋ง๋ ์์ ๋๋ ํ ๋ฆฌ๋ก ๋ฐฐํฌ๋ ์ ์๋๋ก ์ค์ ํ๋ค.

์ง๋์ฃผ ์ฐ์ํ ํ์ ๋ค์์ ์งํํ์๋ “9์ ์ฐ์ํ ํ
ํฌ ์ธ๋ฏธ๋ - ์ฐ์ํ ์คํ๋ง ๋ฐฐ์น” ์ ๋ค๋
์๋ค. ํ์์๊ฒ ์ด๋ฒ 9์์ ์ ์ ์ด ์ด๋์ ์๋์ง ๋ชจ๋ฅผ๋งํผ ๋ฐ์๊ณ ํ๋ค์์ง๋ง ์์ ๋ถํฐ ๊ถ๊ธํ๊ธฐ๋ ํ๊ณ ์์ฆ๋ค์ด ๊ด์ฌ์ ๊ฐ๋ “๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
"์ ์ด๋ป๊ฒ ํ๋ฉด “์ฐ์ํ ๋ฐฉ๋ฒ"์ผ๋ก ์ฌ์ฉํ ์ ์์์ง์ ๋ํด ์ฌ๋ฌ ์๊ฐ๋ค์ด ์์๊ธฐ์ ํฐ ๊ธฐ๋๋ฅผ ๊ฐ์ง๊ณ ์ง์ฅ์ฒ ์ ๊ฒฌ๋๋ฉฐ ์ ์ค ๊ทผ์ฒ์ ์๋ ์ฐ์ํ ํ์ ๋ค ์์์ง์ผ๋ก ๊ฐ๊ฒ ๋์๋ค. ์ด๋ค ๋ด์ฉ์ ๋ฐํํ์๋์ง์ ๋ํด ๊ธฐ์ต์ํ๋ ๋๋ํ ์ต๋ฌด์๊ฐ ๋์ด ์ ๋ฆฌํ๊ธฐ ๋ณด๋ค ์ฃผ์ ํฌ์ธํธ์ ๋ํ ์๊ฐ๊ณผ ํจ๊ป ์ฐธ์ฌ๋ฅผ ๋ชปํ ๋ถ๋ค ์ํด์๋ผ๊ธฐ ๋ณด๋ค ๋ด ์ค์ค๋ก ์ ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด ํฌ์คํ
์ ์์ฑํด ๋ณด๊ณ ์ ํ๋ค. (์ด๋ฒ์๋ ๋ถ๋ฌ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค ^=^)
์ธํธ๋ก ์ฐ์ฌ์ ๋ถ์ ์๋์ ์ ๋ช
ํ์ ๋ถ์ด๋ผ ๋ณ๋์ ์ค๋ช
์ด ํ์ ์์ด ์ด์ํ์๋ ๋ธ๋ก๊ทธ ์ฃผ์๋ก ๋์ฒด๋ฅผ ํด๋ณธ๋ค. ์ด๋ฒ ํ์ฌ์ ์ด๋๋์ ๋ถ๋ค์ ํ๋ฒ์ด๋ผ๋ ์คํ๋ง ๋ฐฐ์น๋ฅผ ์จ๋ถ ๋ถ๋ค์ ๋์์ผ๋ก ์งํํ๊ฒ ๋์๋ค๊ณ ํ๋๋ฐ ๋ง์นจ ํ์๋ ํ ๋ด์์ ์ด์ํ๊ณ ์๋ ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ ๋ณด๋ค ํจ์จ์ ์ด๊ณ ์ฐ์ํ๊ฒ ๋ฐ๊ฟ๋ณด๊ณ ์ ํ๋ ๋์ฆ๊ฐ ์์๊ธฐ์ ์๋ง ์ด๋๋๊ฒ ์๋๊น ์ถ๋ค.
์๊ธฐ์๊ธฐํ ์ฐ์ํ ํ์ ๋ค ๊ฑด๋ฌผ ๋ด๋ถ" ์๊ธฐ์๊ธฐํ ์ฐ์ํ ํ์ ๋ค ๊ฑด๋ฌผ ๋ด๋ถ ๋๋ถ์ด ๋ฐํ์ ์ ๊ฐ๋ตํ ํ์ฌ๊ฐ ์ํ๋ ์ธ์ฌ์ ๋ํ์ฌ ์ธ๊ธํด์ฃผ์
จ๋๋ฐ ๊ทธ๊ฒ ์ด์ฐ๋ ๊ณต๊ฐ์ด ๊ฐ๋์ง. ์ญ์ ์๊ฐ์ด ๋จ๋ค๋ฅธ ํ์ฌ๊ตฌ๋ ํ๊ณ ๋ค์ํ๋ฒ ์๊ฐ์.
์๊ธฐ๋ณด๋ค ๊ฒฝํ์ด “์ ์” ์ฌ๋์๊ฒ “์ค๋์ ๋นํ ์” ์์ด์ผ ํ๊ณ , ์๊ธฐ๋ณด๋ค ๊ฒฝํ์ด “๋ง์ ์ฌ๋์ ์ค๋” ์ํฌ ์ ์์ด์ผ ํ๋ค.
๊ธฐ๋ณธํธ ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ด๋ ์ปดํจํฐ์์ ์ฌ๋์ ์ํธ์์ฉ์์ด ์ด์ด์ง๋ ํ๋ก๊ทธ๋จ(์์
)๋ค์ ์คํ์ด๋ผ๊ณ ์ํคํผ๋์์ ๊ฐ๊ฒฐ&๋ช
๋ฃํ๊ฒ ์ ๋ฆฌ๋์ด ์๋ค. ๊ทธ๋งํผ ์ผ๋ฐ์ ์ธ ์น ์ดํ๋ฆฌ์ผ์ด์
๊ณผ์ ์ฐจ์ด๊ฐ ์๋๋ฐ ์น ์ดํ๋ฆฌ์ผ์ด์
์ ์ค์๊ฐ ์ฒ๋ฆฌ๊ฐ ๊ธฐ๋ณธ์ด๊ณ ์์ฒญ์ ๋ํ ์๋ต์ ์ ๊ณตํด์ผ ํ๋ ์๋ฌด๋๋ ์๋๊ฐ ์๋์ ์ด๋ฉฐ QA์ ํธํ ๋ถ๋ถ์ด ์๋ค. ๊ทธ์ ๋ฐํด ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ ์น ์ดํ๋ฆฌ์ผ์ด์
์์ ๋งํ๋ ์์ฒญ์ด๋ผ๋ ๊ฐ๋
๋ณด๋ค ํ์์ฒ๋ฆฌ์ ๊ฐ๊น๊ณ , ์๋ ๋ํ ์ ๋์ ์ด๋ฉฐ QA๊ฐ ๋ณต์กํ๋ค๋๊ฒ ํน์ง์ด๋ค. ๋ฐ๋ผ์ ํ
์คํธ์ฝ๋๋ ์น ์ดํ๋ฆฌ์ผ์ด์
๋ณด๋ค ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ด ๋ ํ์ํ๋ค๊ณ ๋ณผ ์ ์๋ค. ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ด ํ์ํ ์ํฉ์ ํฌ๊ฒ ๋๊ฐ์ง๋ก ๋๋ ๋ณผ ์๊ฐ ์๋ค๊ณ ํ๋ค.
์ผ์ ์ฃผ๊ธฐ๋ก ์คํ ๋์ด์ผ ํ ๋ ์ค์๊ฐ ์ฒ๋ฆฌ๊ฐ ์ด๋ ค์ด ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ ํ ๋ ํ์ ์ฒซ๋ฒ์งธ ์ํฉ๋ง ์๊ฐํ๊ณ ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ ์์ฑํ๊ณค ํ์๋๋ฐ ๋๋ฒ์ฌ ์ํฉ์ ๋ํด ์๊ฐ์ ์๊ฐ์ ๋ ํด๋ณด๋ ์คํ๋ง ๋ฐฐ์น๋ฅผ ๊ฐ๋จํ๊ฒ๋ง (Tasklet) ์ฌ์ฉํ๊ณ ์๋๊ฑด ์๋๊ฐ ํ๋ ๋ฐ์ฑ์ ํด๋ณด๊ณค ํ๋ค. (Reader, Processor, Writer ๋ฑ ๋ค์ํ ๋ ์ด์ด๊ฐ ์๋๋ฐ๋…)
ํนํ ์คํ๋ง ๋ฐฐ์น์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์์ง ์๋ ์กฐํ๋ฐฉ์๋ผ๊ณ ํ๋ค. (DB๊ธฐ์ค) Paging ํน์ Cursor๋ก pageSize๋งํผ๋ง ์ฝ์ด์ค๊ณ chunkSize๋งํผ๋ง commit ํ๋ ํํ. ์ด๋ฌํ ๊ฐ ๋ ์ด์ด๋ณ size๋ฅผ ์ ์กฐ์ ํ๊ธฐ๋ง ํด๋ ์ ์ ๋
ธ๋ ฅ์ผ๋ก ํฐ ์ฑ๋ฅ์ ์ป์ ์ ์๋ ๋ถ๋ถ์ด ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ์๋๊น ๋ผ๊ณ ์๊ฐํด๋ณธ๋ค.
๋ํ @JobScope ๋ @StepScope๋ Late Binding ์ฆ ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ด ์คํ๋๋ ์์ ์ด ์๋๋ผ Job ์ด ์คํ๋ ๋ ์์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํ์ฉํ์ฌ ๋์ ์ผ๋ก reader / processor / wirter ๋ ์ด์ด๋ฅผ ๋ง๋ค ์ ์๋ค๊ณ ํ๋ค.
ํ์ฉํธ ์คํ๋ง ๋ฐฐ์น๋ฅผ ์ด์ฉํ ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ด ์๊ณ ์ด๋ฅผ ์ค์ผ์ฅด๋ง ๋ฑ ๊ด๋ฆฌ๋ฅผ ํด์ฃผ๋ ๋๊ตฌ๋ค์ ์ด์ผ๊ธฐ๋ฅผ ํด์ฃผ์
จ๋ค.
Cron ๋ฆฌ๋
์ค๋ฅผ ์ด๋์ ๋ ์ฌ์ฉํด๋ดค๋ค๋ฉด ์๋งํ ๋ฆฌ๋
์ค ๊ธฐ๋ณธ ์ค์ผ์ฅด๋ง ํ๋ก๊ทธ๋จ์ธ Cron. ํ์๋ Cron ์ผ๋ก ์ฃผ๊ธฐ์ ์ผ๋ก ์คํํ๋๋ก ์ค์ ํด๋ณด๊ธฐ๋ ํ์์ง๋ง ๋ฐฐ์น ์ดํ๋ฆฌ์ผ์ด์
์ ํน์ฑ์ ๋ก๊ทธ ๋ฐ ์คํ/์ข
๋ฃ ๋ฑ ์ ํ์ฌํญ์ด ๋ง์ ๊ฑด ์ฌ์ค์ธ๊ฒ ๊ฐ๋ค. Spring MVC + API Call ์ฃผ๋ณ์์ ์ฌ์ฉํ๊ณ ์๋ค๊ณ ํ๋ ๋ฐฉ์. ์ด ๋ฐฉ์์ ์ฅ์ ์ ํญ์ ๋ ์๊ธฐ ๋๋ฌธ์ ์ดํ๋ฆฌ์ผ์ด์
๊ตฌ๋์๊ฐ์ด ๋ณ๋๋ก ํ์ ์๋ค๋ ์ฅ์ ์ด ์์ง๋ง ์ ๋ฐ์ ์ธ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์ด ๋จ์ ์ด ์๋๊ฒ ๊ฐ๋ค. ๋ฌผ๋ก ์ธ๋ฉฐ ๊ฒจ์๋จน๊ธฐ ์์ผ๋ก ๋จ์ ์ ๊ทน๋ณตํ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๊ฒ ์ง๋ง ๋ชจ๋ ๊ฑด ํญ์ Trade off Spring Batch Admin (Deprecated) ์์ ํ๋ถ์ด ์๋ ค์ฃผ์
์ ์ ๊น ๋ดค๋ ๋ถ๋ถ์ด๊ธด ํ๋ฐ ์ด๋์ฌ์ด์ Deprecated ๋์๋ค๊ณ ํ๋ค. Quertz + Admin http://www.quartz-scheduler.org/ ์์ฃผ ์ค๋์ ์ ์จ๋ณธ ๊ธฐ์ต์ด ์์ง๋ง ๋ฐฐ๋ณด๋ค ๋ฐฐ๊ผฝ์ด ๋ ํฐ ์ํฉ๊ฐ์๋ ํ๋ค์๋ ๊ธฐ์ต๋ค๋ง ๋จ์์๋ ๊ตฌํ๋ฐฉ๋ฒ์ธ๊ฒ ๊ฐ๋ค.

๋ชจ๋ํฐ๋ง์ ์๋น์ค ๋ก์ง ๊ฐ๋ฐ ๋งํผ ํ๋ฒ์ฉ ๊ณ ๋ฏผํด๋ณด๊ณ ๊ฒฝํํด ๋ดค์ ์ค์ํ ์์ญ์ด๋ผ ํ ์ ์๋ค. ๊ทธ์ค ์น์๋ฒ์์ ์ ๊ณตํด์ฃผ๋ ์์ธ์ค ๋ก๊ทธ๋ ์ด์ํ๊ณ ์๋ ์น์๋น์ค์ ๋ํด ์ฌ๋ฌ๊ฐ์ง ์ธก๋ฉด์์ ๋ถ์ํ ์ ์๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ์์ดํ
์ค์ ํ๋๋ผ๊ณ ์๊ฐํ๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ค์ด ์ด๋ค url์ ๋ง์ด ํธ์ถํ๊ณ , ์ด๋ค user-agentํํ๋ฅผ ์ฌ์ฉํ๋์ง ์๊ฒ ๋๋ฉด ๊ทธ์ ๋ฐ๋ผ ์๋น์ค ์ ๋ต์ ๋ณ๊ฒฝํ ์๋ ์๊ณ ์
์์ ์ผ๋ก ๊ณต๊ฒฉ์ ์ธ ์์ฒญ์ ๋ํด ์น์๋ฒ๋จ์์ ์ฐจ๋จ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ๊ฒ inbound ํธ๋ํฝ(์ธ๋ถ์์ ๋ค์ด์ค๋ ์์ฒญ)์ ๋ํด์๋ ์์ธ์ค ๋ก๊ทธ๋ฅผ ์ ๋ถ์ํ๋ฉด ๊ธฐ์กด์ ์น ์ดํ๋ฆฌ์ผ์ด์
๊ณผ๋ ์ ํ ๋ฌด๊ดํ๊ฒ ๋ชจ๋ํฐ๋ง์ด ๊ฐ๋ฅํ์ง๋ง ๋ฐ๋๋ก outbund ํธ๋ํฝ(์ธ๋ถ๋ก ๋๊ฐ๋ ์์ฒญ)์ ๋ํด์๋ ์ด๋ค์์ผ๋ก ๋ชจ๋ํฐ๋ง์ ํ ์ ์์๊น?
์๊ธํต์ฅ์ inbound ํธ๋ํฝ๋ณด๋ค outbound ํธ๋ํฝ์ด ๋๋ฌด ๋ง์ ์์ฆ…์ด๋ฏธ์ง ์ถ์ฒ : https://www.app24moa.com/feedDetail/2/2002" ์๊ธํต์ฅ์ inbound ํธ๋ํฝ๋ณด๋ค outbound ํธ๋ํฝ์ด ๋๋ฌด ๋ง์ ์์ฆ…
์ด๋ฏธ์ง ์ถ์ฒ : https://www.app24moa.com/feedDetail/2/2002 ์์ปจ๋ฐ, ๋ ์จ ์๋น์ค๋ฅผ ํ๊ธฐ ์ํด ์ธ๋ถ์์ ์์ธ๋ ์จ๋ผ๋ ํ์ด์ง๋ฅผ ์กฐํํ์ ๊ฒฝ์ฐ ๊ธฐ์์ฒญ API์์ ๋๊ฒจ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ์ฌ ๋ณด์ฌ์ค๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ด๋ ๊ธฐ์์ฒญ์์ ์ ๊ณตํด์ฃผ๋ ํน์ API์ค์ ์ด๋ ํ๋๊ฐ ๋ฆ๊ฒ ์๋ต์ด ์จ๋ค๊ฑฐ๋, ํน์ ์๊ฐ๋์ ์๋ฌ์๋ต์ ๋ฐ์๊ฒฝ์ฐ ๊ณผ์ฐ ์ด๋ฅผ ์ด๋ค์์ผ๋ก ๋ชจ๋ํฐ๋ง ํ ์ ์์๊น? ์ดํ๋ฆฌ์ผ์ด์
์ฝ๋์ ๋ชจ๋ํฐ๋ง์ ์ํ ์ฝ๋๋ฅผ ์ถ๊ฐํ ๊ฒ์ธ๊ฐ? ํน ํ๋์ ์๋ฒ์์ A๋ชจ๋์ java๋ก, B๋ชจ๋์ python์ผ๋ก ๊ฐ๋ฐ๋์์ ๊ฒฝ์ฐ ๊ฐ๊ฐ ๋ชจ๋๋ง๋ค ๋ชจ๋ํฐ๋ง์ ์ํ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ ์์ผ๋ก ํ๋ค๋ณด๋ฉด ๋น์ง๋์ค ๋ก์ง์ ๋ฐฉํดํ๊ฑฐ๋ ์คํ๋ ค ์ถ๊ฐํ ์ฝ๋ ๋ํ ๊ด๋ฆฌํด์ผ ํ๋ ๋ฐฐ๋ณด๋ค ๋ฐฐ๊ผฝ์ด ๋ ์ปค์ ธ๋ฒ๋ฆด ์ํฉ๋ ์๊ธธ์ ์๋ค. ์ดํ๋ฆฌ์ผ์ด์
์ ๋น์ง๋์ค ๋ก์ง๊ณผ๋ ๋ฌด๊ดํ๊ฒ ์๋ฒ ์์ฒด์์ ์ธ๋ถ๋ก ๋๊ฐ๋ ๋คํธ์ํฌ ํธ๋ํฝ์ ๋ํด ๋ชจ๋ํฐ๋ง์ ํ ์ ์๋ ๊ฐ๋ฒผ์ฐ๋ฉด์๋ ์ฌํํ ๋ชจ๋์ ์ฐพ๊ณ ์ถ์๋ค. ์ดํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐ์ธ์ด๊ฐ ๋ฌด์์ด๋ ์๊ด์์ด ๋ณ๋์ ์์ด์ ํธ ํ์์ผ๋ก ๋์๋๊ธฐ๋ง ํ๋ฉด ๋คํธ์ํฌ ํธ๋ํฝ์ ์์ง ๋ฐ ๋ถ์, ๋์๊ฐ์๋ ๋ชจ๋ํฐ๋ง๊น์ง ํ ์์๋… ๊ทธ๋์ ์ฐพ๋ค๋ณด๋ ์ญ์๋ ์ด๋ฌํ ๊ณ ๋ฏผ์ ๋๊ตฐ๊ฐ๋ ํ๊ณ ์์๊ณ ์คํ์์ค๊น์ง ๋์ด์๋ Elastic Stack ์ Beat์ค Packetbeat๋ผ๋ ๋ฐ์ดํฐ ์์ง๋ชจ๋์ ์๊ฒ ๋์๋ค.
์ญ์ ๋ด๊ฐ ํ๊ณ ์๋ ๊ณ ๋ฏผ์ ์ด๋ฏธ ๋๊ตฐ๊ฐ ํ๋ ๊ณ ๋ฏผ๋ค… ์ด๋ฌํ ๊ณ ๋ฏผ์ ๋ํด ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ณด๋ค ๋นจ๋ฆฌ ์ฐพ๋๊ฒ ๊ฒฝ์๋ ฅ์ด ๋ ํ
๋ฐ…
์ด๋ฒ ํฌ์คํ
์์๋ Packetbeat ์ ๋ํด ๊ฐ๋จํ ์์๋ณด๊ณ ์ด๋ฅผ ํ์ฉํ์ฌ outbound ํธ๋ํฝ์ ๋ํด ๋ชจ๋ํฐ๋ง์ ํด๋ณด๋ฉฐ ์ด๋ค์์ผ๋ก ํ์ฉํ ์ ์๋์ง์ ๋ํด ์์๋ณด๊ณ ์ ํ๋ค.
Packetbeat ? ElasticStack ์ค์ ๋ฐ์ดํฐ ์์ง๊ธฐ ํ๋ซํผ์ธ Beats์ค ๋คํธ์ํฌ ํธ๋ํฝ ๋ฐ์ดํฐ์ ๋ํด ์์ง์ ํ ์ ์๋ ๋ฐ์ดํฐ ์์ง๊ธฐ๋ฅผ ์ ๊ณตํ๊ณ ์๋ค. pcap๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ์ฌ ์๋ฒ์ ๋คํธ์ํฌ ๋ ๋ฒจ์์ ๋ฐ์ดํฐ๋ฅผ ์์ง ๋ฐ ๋ถ์ํ ํ ์ธ๋ถ๋ก(Elasticsearch, Logstash, Kafka ๋ฑ) ์ ์กํด์ฃผ๋ ๊ฒฝ๋ ๋คํธ์ํฌ ํจํท ๋ถ์๊ธฐ๋ผ๊ณ ๊ณต์ ํํ์ด์ง์ ์๊ฐ๋๊ณ ์๋ค. ๋ช๋ฒ ์ฌ์ฉํด๋ณด๋ฉด์ ๋๋ ์ฅ์ ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
์ค์น ๋ฐ ์คํ์ด ๋๋ฌด ๊ฐ๋จํ๋ค. ์ค์ ๊ฐ ํ๋์ ํตํด ๊ฐ๋จํ์ง๋ง, ๊ทธ๋ฌํ ๊ฐ๋จํจ์ ๋นํด์ ๋๋ฌด ๊ฐ๋ ฅํ ์์ง์ด ๊ฐ๋ฅํ๋ค. ์์ ์ด์ผ๊ธฐ ํ๋ ์ดํ๋ฆฌ์ผ์ด์
์ฝ๋์๋ ์ ํ ๋ฌด๊ดํ๊ฒ ์๋ํ๋ค. ๋ฌด์์ ํด๋ณผ๊ฒ์ธ๊ฐ?! (a.k.a. ๋ชฉํ) ํ์๊ฐ ์ด์ํ๋ Daily-DevBlog ๋ผ๋ ์๋น์ค๊ฐ ์๋ค. (๊ฐ๋ถ ์๋น์ค ํ๋ณด) ์ฌ๋ฌ ์ฌ๋๋ค์ rss๋ฅผ ์กฐํํ๊ณ ํ์ฑํด์ ๋ฉ์ผ์ ๋ณด๋ด์ฃผ๋ ์๋น์ค ์ธ๋ฐ, packetbeat ์ฌ์ฉ ์์๋ฅผ ๋ค๊ธฐ์ํด ์กฐ๊ธ ๋ณํํ์ฌ ๋ชจ๋ rss๋ฅผ ์ ๊ทผํ๊ณ ๊ฐ์ฅ ์ต์ ๊ธ์ ์ ๋ชฉ์ ์ถ๋ ฅํ๋ ์์ฃผ ๊ฐ๋จํ python ์คํฌ๋ฆฝํธ๋ก outbound ํธ๋ํฝ์ ๋ฐ์์์ผ ๋ณด๊ณ ์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ packetbeat ๋ฅผ ์ด์ฉํ์ฌ ์ธ๋ถ๋ก ํธ์ถ๋๋ ํธ๋ํฝ์ ์์งํ๊ณ Elasticsearch ๋ก ์ธ๋ฑ์ฑ ํ์ฌ ์ต์ข
์ ์ผ๋ก๋ ์ด๋ rss์ ์๋๊ฐ ๊ฐ์ฅ ๋๋ฆฐ์ง ์คํ๋๋ python์ฝ๋์๋ ์ ํ ๊ด๋ จ์์ด ๋ชจ๋ํฐ๋ง ํด๋ณด๊ณ ์ ํ๋ค. python ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ฐธ๊ณ ๋ก ํ์๋ awesome-devblog์ ์ด์์๋ถ๊ป ํด๋น ๋ฐ์ดํฐ ์ฌ์ฉ์ ๋ํด ํ๋ฝ์ ๋ฐ์ ์ํ์ด๋ค.
import requests, yaml, feedparser blog_info_list_yml_url = 'https://raw.githubusercontent.com/sarojaba/awesome-devblog/master/db.yml' blog_info_list_yml = requests.get(url=blog_info_list_yml_url).text blog_info_yaml_parse_list = yaml.load(blog_info_list_yml) for blog_info in blog_info_yaml_parse_list : if 'rss' not in blog_info.keys() or not blog_info['rss']: continue rss_url = blog_info['rss'] try : parse_feed = feedparser.parse(rss_url) except : continue parse_feed_data = parse_feed.entries[0] print(blog_info['name'], '|', parse_feed_data['title'], '|', parse_feed_data['link']) ์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ์๋์ฒ๋ผ ์์ฃผ ๊ฐ๋จํ๊ฒ ๋ธ๋ก๊ทธ ์ฃผ์ธ์ ์ด๋ฆ๊ณผ ์ต์ ๊ธ ์ ๋ชฉ, ๋งํฌ๊ฐ ์ถ๋ ฅ์ด ๋๋ค.