2021. 10. 5. 08:00ใBack-End ์์ ์ค/Spring Framework
์๋ ํ์ธ์? ์ฃผ๋ํ๋ ์ ๋๋ค.
์ค๋์ Spring์ Singleton Container์ ๋ํด์ ๊ณต๋ถ ํด ๋ณด๋๋ก ํ๋ ๊ฒ์ด์์.
์ด ๋ด์ฉ์ ์ธํ๋ฐ - ๊น์ํ ๊ฐ์ฌ๋์ ์คํ๋ง ํต์ฌ ์๋ฆฌ๋ฅผ ๊ณต๋ถํ๋ฉด์ ์ ๋ฆฌ ํ์์ต๋๋ค.
"์ด ํฌ์คํ ์ ์ฟ ํก ํํธ๋์ค ํ๋์ ์ผํ์ผ๋ก, ์ด์ ๋ฐ๋ฅธ ์ผ์ ์ก์ ์์๋ฃ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค."
๐ ๋ชฉ์ฐจ
01. [Spring] ์คํ๋ง ํต์ฌ ์๋ฆฌ
02. [Spring] ์ข์ ๊ฐ์ฒด ์งํฅ ์ค๊ณ์ 5๊ฐ์ง ์์น (SOLID)
03. [Spring] ๊ฐ์ฒด ์งํฅ ์ค๊ณ์ ์คํ๋ง
04. [Spring] OCP์ DIP ๊ณ ๋ คํ๊ธฐ
05. [Spring] ๊ฐ์ฒด ์งํฅ ์๋ฆฌ ์ ์ฉ - ์๋ก์ด ํ ์ธ ์ ์ฑ
๊ฐ๋ฐ
06. [Spring] AppConfig ๋ฆฌํฉํฐ๋ง
07. [Spring] Ioc, DI Container
08. [Spring] ์คํ๋ง ์ปจํ
์ด๋ ์์ฑ
09. [Spring] ์ฑ๊ธํค ์ปจํ
์ด๋
10. [Spring] Component Scan And Auto wired Start
11. [Spring] ์์กด๊ด๊ณ ์ฃผ์
๋ฐฉ๋ฒ
12. [Spring] Bean Life Cycle Call Back
13. [Spring] Bean Scope
๐ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ์ฑํดํค
์๋ ์คํ๋ง์ Enterprise์ฉ์ผ๋ก ์จ๋ผ์ธ ์๋น์ค ๊ธฐ์ ์ ์ง์ํ๊ธฐ ์ํด ํ์ํ๋ค๊ณ ํฉ๋๋ค.
๋๋ถ๋ถ์ ์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ธ ๊ฒ์ด์์. ๋ฌผ๋ก ์น์ด ์๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ๋ ์ผ๋ง๋ ์ง ์คํ๋ง์ ์ด์ฉํด์ ํ ์ ์๋ ๊ฒ์ด์์.
์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค์ํ ๋ถ๋ถ์ด ์ฌ๋ฌ ๊ณ ๊ฐ์ด ๋์์ ์์ฒญ์ ํ๋ค๋ ์ ์ธ๊ฒ์ด์์.
์์ ๊ฐ์ด ์ฐ๋ฆฌ๊ฐ ์๋ ๊ฐ์ฒด ์์ฑ ๊ฐ๋ ๋๋ก๋ผ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ ๋๋ง๋ค new๋ฅผ ํตํด ํด๋น ์๋น์ค ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ๋ฐํํด ์ฃผ๋ ๊ฒ์ด์์.
๐ Test ๊ฒฐ๊ณผ
์์ ๊ฐ์ด ์ด ์ ์ ๋ง๋ค์๋ ์คํ๋ง ์๋ ์์ DI Container์ธ AppConfig๋ ์์ฒญ์ ํ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ ๊ฒ์ด์์.
๊ณ ๊ฐ ํธ๋ํฝ์ด ์ด๋น 100์ด ๋์ค๋ฉด ์ด๋น 100๊ฐ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ , ๊ฐ๋น์ง์ปฌ๋ ํฐ์ ์ํด ์๋ฉธ๋๋ ๊ฒ์ด์์. ๋๋ฌธ์ Memory ๋ญ๋น๊ฐ ๋งค์ฐ ์ฌํด์ง ๊ฒ์ด์์.
์ด๊ฒ์ ํด๊ฒฐํ๊ธฐ ์ํด์๋ ํด๋น ๊ฐ์ฒด๊ฐ ๋ฑ 1๊ฐ๋ง ์์ฑ๋๊ณ , ๊ณต์ ํ๋๋ก ๋ง๋ค๋ฉด ๋๋ ๊ฒ์ด์์. ๊ทธ๊ฒ์ด ๋ฐ๋ก ์ฑ๊ธํค ํจํด์ด๋๋๋ค!
๐์ฑ๊ธํค ํจํด
์ฑ๊ธํค ํจํด์ด๋ ํด๋์ค์ ์ธ์คํด์ค๊ฐ ๋ฑ ํ๊ฐ๋ง ์์ฑ๋๋ ๊ฒ์ ๋ณด์ฅํ๋ ๋์์ธ ํจํด์ธ ๊ฒ์ด์์.
๊ทธ๋์ ๊ฐ์ฒด ์ธ์คํด์ค 2๊ฐ๋ฅผ ์์ฑํ์ง ๋ชปํ๋๋ก ๋ง์์ค๋ต๋๋ค! private ์์ฑ์๋ฅผ ํตํด ์ธ๋ถ์์ ์์๋ก new๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋๋ก ๋ง์ผ๋ฉด ๋๋ ๊ฒ์ด์์.
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด static ์์ญ์ ๊ฐ์ฒด instance๋ฅผ ๋ฏธ๋ฆฌ ํ๋ ์์ฑํด์ ์ฌ๋ ค๋๋ ๊ฒ์ด์์.
์ด ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ํ์ํ๋ฉด ์ค์ง getInstance() Method๋ฅผ ํตํด์๋ง ์กฐํํ ์ ์๋ ๊ฒ์ด๊ณ , ์ด๊ฒ์ ํธ์ถํ๋ฉด ํญ์ ๊ฐ์ ์ธ์คํด์ค๋ง์ ๋ฐํํ๋ ๊ฒ์ด์์.
๋ฑ ํ ๊ฐ์ ์ธ์คํด์ค๋ง ์กด์ฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ฑ์๋ฅผ private์ผ๋ก ๋ง์ ํน์๋ผ๋ ์ธ๋ถ์์ new๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ๋ค๋ฅธ ๊ฒ์ด ์์ฑ๋๋ ๊ฒ์ด ๋ง์์ผ ํ๋ ๊ฒ์ด์์.
๐ก์ฐธ๊ณ : Static์ด๋?
์๋ฐ์ Static์ ๋ํด ์ ๋ชจ๋ฅด์๊ฑฐ๋, ํท๊ฐ๋ฆฌ์๋ ๋ถ์ ์ฌ๊ธฐ์ ๊ด์ฌ์ ์ฃผ์ธ์!
์์ ์ฝ๋๋ ์ฑ๊ธํค ํจํด์ ์ฌ์ฉํ๋ ํ ์คํธ ์ฝ๋์ธ ๊ฒ์ด์์.
์์ ์ฝ๋์์ ์์ฑ์๋ฅผ private์ผ๋ก ๋ง๊ฒ ๋๋ฉด ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด์์.
private์ผ๋ก ํ๋ฉด new๋ฅผ ํตํด์ ๊ฐ์ฒด ์์ฑ์ ๋ง์ ์ ์๋ต๋๋ค!
๐ Test ๊ฒฐ๊ณผ
์์ ํ ์คํธ ์ฝ๋๋ฅผ ์คํํด ๋ณด๋ฉด ๊ฐ์ ์ธ์คํด์ค(๊ฐ์ฒด)๊ฐ ๋ฐํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ ๊ฒ์ด์์.
๐ก์ฐธ๊ณ :
1. ์ฑ๊ธํค ํจํด์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค. ์ฌ๊ธฐ์๋ ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด๋๋ ๊ฐ์ฅ ๋จ์ํ๊ณ , ์์ ํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค.
2. isSameAS๋ ==์ฒ๋ผ ์ธ์คํด์ค๋ฅผ ๋น๊ตํ๋ ๊ฒ์ด๊ณ , isEqual๋ Equals Mehotd์ฒ๋ผ ๋น๊ตํ๋ ๊ฒ
์ฑ๊ธํค ํจํด์ ์ ์ฉํ๋ฉด Client์ ์์ฒญ์ด ์ฌ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ๊ณต์ ํด์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ต๋๋ค. ํ์ง๋ง, ์ฑ๊ธํค ํจํด์ ๋ค์๊ณผ ๊ฐ์ ์ ๋ง์ ๋ฌธ์ ์ ์ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ด์์.
์ฑ๊ธํค ํจํด์ ๋ฌธ์ ์
- ์ฑ๊ธํค ํจํด์ ๊ตฌํํ๋ ์ฝ๋ ์์ฒด๊ฐ ๋ง์ด ๋ค์ด๊ฐ๋ค.
- ์์กด ๊ด๊ณ์ Client๊ฐ ๊ตฌ์ฒด ํด๋์ค์ ์์กด -> DIP ์๋ฐ ์ฌํญ
- Client๊ฐ ๊ตฌ์ฒด ํด๋์ค์ ์์กดํด์ OPC ์์น ์๋ฐ ๊ฐ๋ฅ์ฑ ๋์
- ํ ์คํธ๊ฐ ์ด๋ ค์
- ๋ด๋ถ ์์ฑ ๋ณ๊ฒฝ ๋ฐ ์ด๊ธฐํ ์ด๋ ค์
- private ์์ฑ์๋ก ์์ ํด๋์ค ๋ง๋ค๊ธฐ ์ด๋ ค์
- ์ ์ฐ์ฑ์ด ๋จ์ด์ง
- ์ํฐ ํจํด์ด๋ผ๊ณ ๋ถ๋ฆฌ๊ธฐ๋ ํจ.
๐ ์ฑ๊ธํค ์ปจํ ์ด๋
์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํค ํจํด์ ๋ชจ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด์๋ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ฑ๊ธํค(1๊ฐ๋ง ์์ฑ)์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ ๊ฒ์ด์์.
์ง๊ธ๊น์ง ๊ณต๋ถํ ์คํ๋ง ๋น์ด ๋ฐ๋ก ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌ๋๋ ๋น์ด๋ผ๊ณ ํฉ๋๋ค!
์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํค ํจํด์ ์ ์ฉํ์ง ์์๋๋ผ๋ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด์์.
์ด์ ์ ์ปจํ ์ด๋ ์์ฑ ๊ณผ์ ์ ๋ณด๋ฉด ์ปจํ ์ด๋๋ ๊ฐ์ฒด๋ฅผ ํ๋๋ง ์์ฑํด์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ ์ ์์ฃ !
์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํค ์ปจํ ์ด๋ ์ญํ ์ ํ๋ ๊ฒ์ด์์. ์ด๋ ๊ฒ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ฑ๊ธํค ๋ ์ง์คํธ๋ฆฌ๋ผ ํ๋ต๋๋ค!
์คํ๋ง ์ปจํ ์ด๋์ ์ด๋ฐ ๊ธฐ๋ฅ ๋์ ์ฑ๊ธํค ํจํด์ ๋ชจ๋ ๋จ์ ์ ํด๊ฒฐํ๋ฉด์ ๊ฐ์ฒด๋ฅผ ์ฑ๊ธํค์ผ๋ก ์ ์งํ ์ ์๊ฒ ๋ ๊ฒ์ด์์.
๊ฒฐ๊ตญ ์ฑ๊ธํค ํจํด์ ์ํ ์ง์ ๋ถํ ์ฝ๋๊ฐ ํ์๊ฐ ์๊ณ , DIP ๋ฐ OCP, ํ ์คํธ, private ์์ฑ์๋ก๋ถํฐ ์์ ๋กญ๊ฒ ์ฑ๊ธํค์ ์ฌ์ฉํ ์ ์๊ฒ ๋ ๊ฒ์ด์์!
๐์ฑ๊ธํค ์ปจํ ์ด๋ ์ ์ฉ ๋ค
์คํ๋ง ์ปจํ ์ด๋ ๋์ Client ์์ฒญ์ด ์ฌ ๋ ๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋ ์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ๊ณต์ ํด์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋ ๊ฒ์ด์์.
๐ก์ฐธ๊ณ :
์คํ๋ง์ ๊ธฐ๋ณธ ๋น ๋ฑ๋ก ๋ฐฉ์์ ์ฑ๊ธํค์ด๋, ์ฑ๊ธํค ๋ฐฉ์๋ง ์ง์ํ๋ ๊ฒ์ ์๋๋ค. ์์ฒญ๋ ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๋ฐํํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณต.
๐์ฑ๊ธํค ๋ฐฉ์์ ์ฃผ์์
์ฑ๊ธํค ํจํด, ์คํ๋ง ๊ฐ์ ์ฑ๊ธํค ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋์ง ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ํ๋๋ง ์์ฑํด์ ๊ณต์ ํ๋ ์ฑ๊ธํค ๋ฐฉ์์ ์ฌ๋ฌ Client๊ฐ ํ๋์ ๊ฐ์ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค ๊ฐ์ฒด๋ ์ํ๋ฅผ ์ ์ง(stateful)ํ๊ฒ ์ค๊ณํ๋ฉด ์๋๋ ๊ฒ์ด์์. ์ฆ, ๋ฌด์ํ(stateless)๋ก ์ค๊ณํด์ผ ํ๋ต๋๋ค!
๊ทธ๋ง์ธ ์ฆ ํน์ Client์ ์์กด์ ์ธ ํ๋(๋ฉค๋ฒ๋ณ์)๊ฐ ์์ผ๋ฉด ์๋๋ ๊ฒ์ด์์.
๋ํ, ํน์ Client๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ ํ๋๊ฐ ์์ผ๋ฉด ์๋๋ ๊ฒ์ด์์.
์ด๊ฒ์ ๊ฐ๊ธ์ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํด์ผ ํ๋ฉฐ, ํ๋ ๋์ ์๋ฐ์์ ๊ณต์ ๋์ง ์๋ ์ง์ญ๋ณ์, ํ๋ผ๋ฏธํฐ, ThreadLocal ๋ฑ์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒ์ด์์.
์คํ๋ง ๋น์ ํ๋์ ๊ณต์ ๊ฐ์ ์ค์ ํ๊ฒ ๋๋ฉด ์ ๋ง ๋ฌด์๋ฌด์ํ ์ผ๊ทผ์ ์๋ฌ๋ฆฌ๊ฒ ๋ ์๋ ์๋ ๊ฒ์ด์์!
๐ก์ฐธ๊ณ :
Thread(์ฐ๋ ๋)๋? ํ๋ก์ธ์ค๋ ์คํ์ค์ธ ํ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ด๊ณ , ์ฐ๋ ๋๋ ํ ํ๋ก์ธ์ค ๋ด์ ๋์๋๋ ์ฌ๋ฌ ์คํ ํ๋ฆ
ํ๋ก์ธ์ค๋ OS๋ก ๋ถํฐ ํ ๋น ๋ฐ์ ์์ ๋จ์, ์ฐ๋ ๋๋ ํ๋ก์ธ์ค๊ฐ ํ ๋น ๋ฐ์ ์์์ ์ด์ฉํ๋ ์คํ์ ๋จ์
์๋ฐ์์๋ JVM(Java Virtual Machin)์์ ํ๋์ ํ๋ก์ธ์ค๊ฐ ๋์๊ฐ๊ณ , ํ๋์ ํ๋ก์ธ์ค ์์์ main Method ํ๋์ ์ฐ๋ ๋๊ฐ ์คํ๋๋ค. ๋ํ, ์ฐ๋ ๋๋ ์ถ๊ฐ๊ฐ ๊ฐ๋ฅ
ThreadLocal์ด๋? ThreadLocal์ Java Class๋ก ThreadLocal์ ์ค์ง ํ ์ฐ๋ ๋์ ์ํด์ ์ฐ์ฌ์ง ์ ์๋ ๋ณ์์ ๊ฐ์ ๊ฐ๋ ์ผ๋ก ๋ ์ฐ๋ ๋๊ฐ ๊ฐ์ ์ฝ๋๋ฅผ ์คํํ๊ณ , ์ด ์ฝ๋๊ฐ ํ๋์ ThreadLocal ๋ณ์๋ฅผ ์ฐธ์กฐ ํ๋๋ผ๋ ์๋ก์ ThreadLocal ๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
์ฆ, ThreadLocal ๋ณ์ ์ ์ธ ์ ๋ฉํฐ ์ฐ๋ ๋ ํ๊ฒฝ์์ ๊ฐ ์ฐ๋ ๋๋ง๋ค ๋ ๋ฆฝ์ ์ธ ๋ณ์๋ฅผ ๊ฐ์ง๊ณ ์ ๊ทผ ๊ฐ๋ฅ.
ThreadLocal ํ์ฉ : ํ ์ฐ๋ ๋์์ ์คํ๋๋ ์ฝ๋๊ฐ ๋์ผํ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํด์ฃผ๊ธฐ ๋๋ฌธ์ ๊ด๋ จ๋ ์ฝ๋์์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , ๊ฐ์ฒด๋ฅผ ๊ฐ๊ฐ๋ก ๊ฐ์ ธ๋ค ์ธ ๋ ์ฌ์ฉ.
1. ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด Spring Security์์ ์ฌ์ฉ์๋ง๋ค ๋ค๋ฅธ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ๋๋ Session ์ ๋ณด
2. ์ฐ๋ ๋์ ์์ ํด์ผ ํ๋ Data ๋ณด๊ด ์
ThreadLocal ์ฃผ์์ฌํญ : ์ด๊ฒ์ Memory ๋์์ ์ํ์ด ์๊ธฐ์ ์ฃผ์ํด์ผ ํ๋ค.
Thread pool ํ๊ฒฝ์์ ThreadLocal์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ณ์์ ๋ณด๊ด๋ Data ์ฌ์ฉ์ด ๋๋๋ฉด ๋ฐ๋์ ํด๋น Data๋ฅผ ์ญ์ ํด์ค์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ฌ ์ฌ์ฉ๋๋ ์ฐ๋ ๋๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ Data๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
package hello.core.singleton;
public class StatefulService {
private int price; //์ํ๋ฅผ ์ ์งํ๋ ํ๋
public void order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
this.price = price; //์ฌ๊ธฐ๊ฐ ๋ฌธ์ !
} // order() ๋
public int getPrice() {
return price;
} // getPrice() ๋
} // Class ๋
์์ ๊ฐ์ ์ฝ๋๋ก ์ํ๋ฅผ ์ ์ง ํ์ ๋ ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊น์?
package hello.core.singleton;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
public class StatefulServiceTest {
@Test void statefulServiceSingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean("statefulService", StatefulService.class);
StatefulService statefulService2 = ac.getBean("statefulService", StatefulService.class);
//ThreadA: A์ฌ์ฉ์ 10000์ ์ฃผ๋ฌธ
statefulService1.order("userA", 10000);
//ThreadB: B์ฌ์ฉ์ 20000์ ์ฃผ๋ฌธ
statefulService2.order("userB", 20000);
//ThreadA: ์ฌ์ฉ์A ์ฃผ๋ฌธ ๊ธ์ก ์กฐํ
int price = statefulService1.getPrice();
//ThreadA: ์ฌ์ฉ์A๋ 10000์์ ๊ธฐ๋ํ์ง๋ง, ๊ธฐ๋์ ๋ค๋ฅด๊ฒ 20000์ ์ถ๋ ฅ
System.out.println("price = " + price);
Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
static class TestConfig {
@Bean public StatefulService statefulService() {
return new StatefulService();
}
}
}
์์ ๊ฐ์ด ์ฌ์ฉ์ A๊ฐ 10,000์์ด์น์ ์ฃผ๋ฌธ์ ํ๊ณ ๋ ๋ค ์์ ์ ์ฃผ๋ฌธ ๊ธ์ก์ ์กฐํํ๊ธฐ ์ ์ ์ฌ์ฉ์ B๊ฐ 20,000์์ ์ฃผ๋ฌธ์ ํด ๋ฒ๋ฆฌ๋ฉด ์ฌ์ฉ์ A๊ฐ ์ฃผ๋ฌธํ ๋, 20,000์์ด ์ถ๋ ฅ๋๋ ์ด๋ง๋ฌด์ํ ์ผ์ด ๋ฐ์ํ๋ ๊ฒ์ด์์.
StatefulService์ price ํ๋(๋ฉค๋ฒ ๋ณ์)๋ ๊ณต์ ๋๋ ๊ณณ์ธ๋ฐ, ํน์ Client๊ฐ ๊ฐ์ ๋ฐ๊ฟ ๋ฒ๋ฆฌ๋ ๊ฒ์ด์์.
๊ณต์ ํ๋๋ ์ ๋ง ์กฐ์ฌํด์ผ ํ๊ณ , ์คํ๋ง ๋น์ ํญ์ ๋ฌด์ํ(stateless)๋ก ์ค๊ณํด์ผ ํ๋ ๊ฒ์ด์์.
๐ @Configuration๊ณผ ์ฑ๊ธํค
์ด์ํ ์ ์ด ์๋ ๊ฒ์ด์์.
์์ ์ฝ๋์์ memberService Bean์ ๋ง๋๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด memberRepository()๋ฅผ ํธ์ถํ๊ณ , ์ด๊ฒ์ ๋ค์ new MemoryMemberRepository()๋ฅผ ํธ์ถํ๋ ๊ฒ์ด์์.
๋, orderService Bean์ ๋ง๋๋ ์ฝ๋ ์ญ์ memberRepository()๋ฅผ ํธ์ถํ๊ณ , ์ด๊ฒ์ ๋ค์ new MemoryMemberRepository()๋ฅผ ํธ์ถํ๋ ๊ฒ์ด์์.
๊ฐ๊ฐ ๋ค๋ฅธ 2๊ฐ์ MemoryMemberRepository๊ฐ ์์ฑ๋๋ ์ฑ๊ธํค์ด ๊นจ์ ธ์ผ ํ๋๋ฐ, ์คํ๋ง ์ปจํ ์ด๋๋ ์ด๊ฑธ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น์?
MemberServiceImpl.java
OrderServiceImpl.java
์์ ํด๋์ค์ Test์ฉ Getter์ ์ฃผ๋ชฉํด ์ฃผ์๊ธธ ๋ฐ๋ผ๋ ๊ฒ์ด์์.
ํ ์คํธ๋ฅผ ์ํด MemberRepository๋ฅผ ์กฐํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๊ฒ์ด์์. ๊ธฐ๋ฅ ๊ฒ์ฆ์ ์ํด ์ ๊น ์ถ๊ฐํ ๊ฒ์ด๋ผ ์ธํฐํ์ด์ค๊น์ง ๊ฑด๋ค์ง ์์๊ฒ์ด์์.
ํ ์คํธ ์ฝ๋
๐ Test ๊ฒฐ๊ณผ
memberRepository ์ธ์คํด์ค๋ ๋ชจ๋ ๊ฐ์ ์ธ์คํด์ค๊ฐ ๊ณต์ ๋๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ ๊ฒ์ด์์.
AppConfig์ ์๋ฐ ์ฝ๋์์ ๋ณด๋ฉด ๋ถ๋ช ๊ฐ๊ฐ 2๋ฒ new MemoryRepository๋ฅผ ํธ์ถํด์ ๋ค๋ฅธ ์ธ์คํด์ค๊ฐ ์์ฑ๋๋๊ฑด๋ฐ, ๋๋ ์ ๊ธฐํ ๊ฒ์ด์์.
๐@Configuration๊ณผ Bytecode ์กฐ์
์คํ๋ง ์ปจํ ์ด๋๋ ์์์๋ ์ธ๊ธํ์ง๋ง, ์ฑ๊ธํค ๋ ์ง์คํธ๋ฆฌ์ธ ๊ฒ์ด์์. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์คํ๋ง ๋น์ด ์ฑ๊ธํค์ด ๋๋๋ก ๋ณด์ฅํด์ค์ผ ํ๋ ๊ฒ์ด์์. ๊ทธ๋ฐ๋ฐ, ์คํ๋ง์ด ์๋ฐ ์ฝ๋๊น์ง ์กฐ์ํ๊ธด ์ด๋ ค์ด ๊ฒ์ด์์. ์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ถ๋ช 3๋ฒ์ด ํธ์ถ๋์ด์ผ ํ๋๊ฒ์ธ๋ฐ ๋ง์ด์์.
๊ทธ๋์ ์คํ๋ง์ ํด๋์ค์ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์กฐ์ํ๋ Library๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด์์.
๋ชจ๋ ๋น๋ฐ์ @Configuration์ ์ ์ฉํ AppConfig๊ฐ ๋ฒ์ธ์ธ ๊ฒ์ด์์.
AnnotaionConfigApplicationContext์ ๋งค๊ฐ ๋ณ์(ํ๋ผ๋ฏธํฐ)๋ก ๋๊ธด ๊ฐ์ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก๋๋ ๊ฒ์ด์์. ๊ทธ๋์ AppConfig ์์ฒด๋ ์คํ๋ง ๋น์ด ๋๋ต๋๋ค!
AppConfig ์คํ๋ง ๋น์ ์กฐํํด์ ํด๋์ค ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๊ฐ ๋์ฌ๊น์?
bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$cae3c7e2
๋ง์ฝ ์์ ์๋ฐ ํด๋์ค ์๋ค๋ฉด ์๋์ ๊ฐ์ด ์ถ๋ ฅ์ด ๋์์ ๊ฒ์ด์์.
class hello.core.AppConfig
ํ์ง๋ง ๊ฒฐ๊ณผ๋ ~~~CGLIB๊ฐ ๋ถ์ผ๋ฉด์ ์๋นํ ๋ณต์กํ๊ฒ ์ถ๋ ฅ์ด ๋ ๊ฒ์ด์์.
์ด๊ฒ์ ํ์ฌ ๊ฐ๋ฐ์๊ฐ ๋ง๋ ํด๋์ค๊ฐ ์๋๋ผ ์คํ๋ง์ด CGLIB๋ผ๋ ๋ฐ์ดํธ ์ฝ๋ ์กฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ AppConfig ํด๋์ค๋ฅผ ์์๋ฐ์ ์์์ ๋ค๋ฅธ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ ๊ฒ์ด์์.
๊ทธ ์์์ ๋ค๋ฅธ ํด๋์ค๊ฐ ๋ฐ๋ก ์ฑ๊ธํค์ด ๋๋๋ก ๋ณด์ฅํ๋ ๊ฒ์ด์์.
๊น์ํ ๊ฐ์ฌ๋์ ์๋ง๋ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ์ดํธ ์ฝ๋๋ฅผ ์กฐ์ํด์ ์์ฑ ๋์ด ์์ ๊ฒ์ด๋ผ๊ณ ์์ํ์ จ์ด์.
(์ค์ CGLIB์ ๋ด๋ถ ๊ธฐ์ ์ ์ฌ์ฉํ๋๋ฐ, ๋งค์ฐ ๋ณต์ก)
@Bean public MemberRepository memberRepository() {
if (memoryMemberRepository๊ฐ ์ด๋ฏธ ์คํ๋ง ์ปจํ
์ด๋์ ๋ฑ๋ก๋์ด ์์ผ๋ฉด?) { return ์คํ๋ง ์ปจํ
์ด๋์์ ์ฐพ์์ ๋ฐํ;
} else { //์คํ๋ง ์ปจํ
์ด๋์ ์์ผ๋ฉด
๊ธฐ์กด ๋ก์ง์ ํธ์ถํด์ MemoryMemberRepository๋ฅผ ์์ฑํ๊ณ ์คํ๋ง ์ปจํ
์ด๋์ ๋ฑ๋ก
return ๋ฐํ
}
}
@Bean์ด ๋ถ์ ๋ฉ์๋๋ง๋ค ์ด๋ฏธ ์คํ๋ง ๋น์ด ์กด์ฌํ๋ฉด ์กด์ฌํ๋ ๋น์ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ฑํด์ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ์ฌ ๋ฐํํ๋ ์ฝ๋๊ฐ ๋์ ์ผ๋ก ๋ง๋ค์ด์ง ๊ฒ์ด์์.
๊ทธ ๊ฒฐ๊ณผ ์ฑ๊ธํค์ด ๋ณด์ฅ๋๋ต๋๋ค!
๐ก์ฐธ๊ณ :
AppConfig@CGLIB๋ AppConfig์ ์์ ํ์ ์ด๋ฏ๋ก, AppConfig ํ์ ์ผ๋ก ์กฐํ ๊ฐ๋ฅ
@Configuration์ ์ ์ฉํ์ง ์๊ณ , @Bean๋ง ์ ์ฉํ๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
@Configuration์ ๋ถ์ด๋ฉด ๋ฐ์ดํธ ์ฝ๋๋ฅผ ์กฐ์ํ๋ CGLIB ๊ธฐ์ ์ ์ฌ์ฉํด์ ์ฑ๊ธํค์ ๋ณด์ฅํ์ง๋ง, ๋ถ์ด์ง ์๊ณ , @Bean๋ง ์ฌ์ฉํ๋ฉด ์ฑ๊ธํค์ ๋ณด์ฅ ๋ฐ์ ์ ์๋ ๊ฒ์ด์์.
์ ๋ฆฌํ์๋ฉด
@Bean๋ง ์ฌ์ฉํด๋ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก์ ๋๋, ์ฑ๊ธํค์ ๋ณด์ฅํ์ง๋ ์๋ ๊ฒ์ด์์.
memberRepository()์ฒ๋ผ ์์กด๊ด๊ณ ์ฃผ์ ์ด ํ์ํด์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ ๋ ์ฑ๊ธํค์ ๋ณด์ฅํ์ง ์๋ ๊ฒ์ด์ง์.
๋ฐ.๋ผ.์ ์คํ๋ง ์ค์ ์ ๋ณด๊ฐ ๋ด๊ธด Class์๋ ๋ฌด์กฐ๊ฑด @Configuration์ ๋ถ์ด๋ ๊ฒ์ด ์ข์ ๊ฒ์ด์์!
"์ด ํฌ์คํ ์ ์ฟ ํก ํํธ๋์ค ํ๋์ ์ผํ์ผ๋ก, ์ด์ ๋ฐ๋ฅธ ์ผ์ ์ก์ ์์๋ฃ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค."
์ฃผ๋ํ๋์ ๊ธ์ด ๋ง์์ ๋์ จ๋์? ๊ตฌ๋ ๊ณผ ๊ณต๊ฐ! ๊ทธ๋ฆฌ๊ณ , ๋๊ธ ๊ทธ๋ฆฌ๊ณ ๋ฐฉ๋ช ๋ก์ ์ฃผ๋ํ๋์๊ฒ ๋ง์ ํ์ด ๋ฉ๋๋ค
'Back-End ์์ ์ค > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPQL] left ( outer ) join (0) | 2021.10.05 |
---|---|
[JPA] @ManyToOne (0) | 2021.10.05 |
[Spring] ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ (0) | 2021.10.03 |
[Spring] Ioc, DI Container (0) | 2021.10.01 |
[Spring] AppConfig ๋ฆฌํฉํฐ๋ง (0) | 2021.09.30 |