-
[Spring] ๊น์ํ ์คํ๋ง ํต์ฌ์๋ฆฌ <์น์ 3. ์คํ๋ง ํต์ฌ ์๋ฆฌ ์ดํด2 - ๊ฐ์ฒด ์งํฅ ์๋ฆฌ ์ ์ฉ> ์ ๋ฆฌ
2023. 10. 11.
์น์ 3. ์คํ๋ง ํต์ฌ ์๋ฆฌ ์ดํด2 - ๊ฐ์ฒด ์งํฅ ์๋ฆฌ ์ ์ฉ
์๋ก์ด ํ ์ธ ์ ์ฑ ๊ฐ๋ฐ
์๋ก์ด ํ ์ธ ์ ์ฑ ์ ํ์ฅํด๋ณด์.
- ์ ๋ ๊ธฐํ์: ์๋น์ค ์คํ ์ง์ ์ ํ ์ธ ์ ์ฑ ์ ์ง๊ธ์ฒ๋ผ ๊ณ ์ ๊ธ์ก ํ ์ธ์ด ์๋๋ผ ์ข ๋ ํฉ๋ฆฌ์ ์ธ ์ฃผ๋ฌธ ๊ธ์ก๋น ํ ์ธํ๋ ์ ๋ฅ % ํ ์ธ์ผ๋ก ๋ณ๊ฒฝ
⇒ ์ด์ ๊ฐ์ ์ํฉ์ ๋์ํ๊ธฐ ์ํด ๊ฐ์ฒด์งํฅ ์ค๊ณ ์์น์ ์ค์
- Agile software
- ๊ฐ์ธ๊ณผ ๊ฐ์ธ ๊ฐ์ ์ํธ์์ฉ์ด ํ๋ก์ธ์ค ๋ฐ ํด๋ณด๋ค ์ฐ์
- ์๋ํ๋ ์ํํธ์จ์ด๊ฐ ํฌ๊ด์ ์ธ ๋ฌธ์๋ณด๋ค ์ฐ์
- ๊ณ ๊ฐ๊ณผ์ ํ์ ์ด ๊ณ์ฝ ํ์๋ณด๋ค ์ฐ์
- ๋ณํ์ ๋์ํ๋ ๊ฒ์ด ๊ณํ์ ๋ฐ๋ฅด๋ ๊ฒ๋ณด๋ค ์ฐ์
- ์ํํธ์จ์ด ๊ฐ๋ฐ ๋ฐฉ์. 4๊ฐ์ง ์์น
RateDiscountPolicy ์ถ๊ฐ
package hello.core.discount; import hello.core.member.Grade; import hello.core.member.Member; public class FixDiscountPolicy implements DiscountPolicy{ private int discountFixAmount=1000;//1000์ ํ ์ธ @Override public int discount(Member member, int price) { if (member.getGrade() == Grade.VIP){ //VIP๋ฉด 1000์ ํ ์ธ return discountFixAmount; } else{ return 0; //VIP ์๋๋ฉด ํ ์ธ ์์ } } }
ํ ์คํธ ์์ฑ
import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; class RateDiscountPolicyTest { RateDiscountPolicy discountPolicy = new RateDiscountPolicy(); @Test @DisplayName("VIP๋ 10% ํ ์ธ์ด ์ ์ฉ๋์ด์ผ ํ๋ค") void vip_o(){ //vip๊ฐ ์ ์ ์ฉ๋๋์ง ํ ์คํธ //given Member member = new Member(1L, "memberVIP", Grade.VIP);//์์์ ๋ฉค๋ฒ ์์ฑ //when int discount= discountPolicy.discount(member, 10000); //then assertThat(discount).isEqualTo(1000); //ํ ์ธ๊ธ์ก์ด 1000์์ด ๋ง๋์ง ํ์ธ //Assertions-> static importํ๋ ๊ฒ์ด ์ข์ option+enter } @Test @DisplayName("VIP๊ฐ ์๋๋ฉด 10% ํ ์ธ์ด ์ ์ฉ๋์ง ์์์ผ ํ๋ค")//์ฑ๊ณต์ผ์ด์ค๊ฐ ์๋ ์คํจ์ผ์ด์ค๋ ํ ์คํธ void vip_x(){ //given Member member = new Member(1L, "memberBASIC", Grade.BASIC);// ์์์ ๋ฉค๋ฒ ์์ฑ //when int discount= discountPolicy.discount(member, 10000); //then assertThat(discount).isEqualTo(0); //ํ ์ธ์ด ๋์ง ์๋์ง ํ์ธ } }
- DiscoutPolicy์ ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉ → ๊ตฌํ์ฒด๋ก RateDiscountPolicy๋ง ์ถ๊ฐ๋ก ๊ฐ๋ฐ
์๋ก์ด ํ ์ธ ์ ์ฑ ์ ์ฉ๊ณผ ๋ฌธ์ ์
public class OrderServiceImpl implements OrderService { // private final DiscountPolicy discountPolicy = new FixDiscountPolicy(); private final DiscountPolicy discountPolicy = new RateDiscountPolicy(); }
- FixDiscountPolicy→ RateDiscountPolicy๋ก ๊ฐ์ฒด๋ฅผ ์ค์ ์์ค์ฝ๋๋ก ๋ฐ๊พธ์ด์ผ ํจ
- ๊ฐ์ฒด์งํฅ ์ค๊ณ ์์น์ ์ค์ํ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ์๋๋ค?
- DIP ์๋ฐ: ํด๋์ค์ ์ธํฐํ์ด์ค๊ฐ ์ธํฐํ์ด์ค๋ฟ๋ง ์๋๋ผ ํด๋์ค์๋ ์์กด
- OrderServiceImpl์ด DiscountPolicy ์ธํฐํ์ด์ค ๋ฟ๋ง ์๋๋ผFixDiscountPolicy์ธ ๊ตฌ์ฒด ํด๋์ค๋ ํจ๊ป ์์กด ⇒ ์ธํฐํ์ด์ค๋ง ์์กดํ๊ฒ ํ๋๋ก
- OCP ์๋ฐ: ์์กด์ฑ์ ๊ฐ์ง๋ฏ๋ก FixDiscountPolicy๋ฅผ RateDiscountPolicy๋ก ๋ณ๊ฒฝํ๋ ์๊ฐ OrderServiceImpl ์ ์์ค ์ฝ๋๋ ํจ๊ป ๋ณ๊ฒฝํด์ผ ํ๋ค ⇒ ๊ตฌํ์ฒด๋ฅผ ๋ฐ๊ฟ๋ ํด๋ผ์ด์ธํธ ์ฝ๋ ์ ๊ณ ์น๋๋ก
์ฝ๋ ๋ณ๊ฒฝ
public class OrderServiceImpl implements OrderService { //private final DiscountPolicy discountPolicy = new RateDiscountPolicy(); private DiscountPolicy discountPolicy; }
- NPE ๋ฐ์ : ํ ์คํธ๊ฐ createOrder()๋ฅผ ํธ์ถ → discountPolicy์ ์๋ฌด ๊ฐ๋ ํ ๋น์ด ์ ๋์ด ์์(๊ตฌ์ฒดํ๋ ๊ฐ์ฒด๊ฐ ์์)
ํด๊ฒฐ๋ฐฉ์
- ๋๊ตฐ๊ฐ๊ฐ ํด๋ผ์ด์ธํธ์ธ OrderServiceImpl ์ DiscountPolicy ์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ๋์ ์์ฑํ๊ณ ์ฃผ์
- static import
๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ
์ดํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ ์ธ ์ด์์์ ์ค์ํ๋ค!
- ์ด์ ์ ์ฝ๋๋ OrderServiceImpl(๊ตฌํ์ฒด)์ด discountPolicy(๊ตฌํ์ฒด)๋ฅผ ์์ฑํ๋ ์ ํํ๋ ๋ฐฉ์ (๋ง์น ๋ฐฐ์ฐ๊ฐ ๋ฐฐ์ฐ๋ฅผ ์ ํํ๋ฏ)
- ๋ฐฐ์ฐ๋ฅผ ์ง์ ํ๋ ๊ณต์ฐ ๊ธฐํ์์ ์ญํ ์ ๋ฐ๋ก ๋ง๋ค์ด ๋ฐฐ์ฐ์ ๊ณต์ฐ ๊ธฐํ์์ ์ฑ ์์ ๋ถ๋ฆฌํ์⇒ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ญํ (๊ตฌํ์ฒด)์ ์ง์ ํ๋ ๋ณ๋์ ๊ด๋ฆฌ์๋ฅผ ๋์! (AppConfig)
AppConfig
- ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฒด ๋์ ๋ฐฉ์์ ๊ตฌ์ฑ(config)ํ๊ธฐ ์ํด, ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ฐ๊ฒฐํ๋ ์ฑ ์์ ๊ฐ์ง๋ ๋ณ๋์ ์ค์ ํด๋์ค
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๋ํ ์ด์์ ๋ด๋น
- ์ด์ ์๋ memberservice ์์์ ์ธํฐํ์ด์ค, ๊ฐ์ฒด์ ํ ๋น์ ์ง์ ํจ ex) MemoryMemberRepository์ ์ง์ ์ MemberServiceImpl์ด ํจ ๋ง์น ๋ฐฐ์ฐ๊ฐ ๋ฐฐ์ฐ๋ฅผ ์ญ์ธํ๋ ๊ฒ์ฒ๋ผ..
AppConfig
package hello.core; import hello.core.discount.FixDiscountPolicy; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.member.MemoryMemberRepository; import hello.core.order.OrderService; import hello.core.order.OrderServiceImpl; public class AppConfig { public MemberService memberService() { return new MemberServiceImpl(new MemoryMemberRepository()); //impl์ repository๋ฅผ ์ธ ๊ฑฐ๋ผ๊ณ ์ฃผ์ ! } public OrderService orderService() { return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy()); }
- AppConfig๋ก ๋ฉค๋ฒ์๋น์ค ํธ์ถ → ๋ฉค๋ฒ์๋น์ค ๊ตฌํ์ฒด ์์ฑ ์ด๋ ๋ฉ๋ชจ๋ฆฌ๋ฉค๋ฒ๋ฆฌํ์งํ ๋ฆฌ๊ฐ ์์ฑ
- MemberServiceImpl์ MemoryMemberRepository ์ฝ๋๊ฐ ์๊ณ MemberRepository์ ์ฝ๋๋ง ์์(์ถ์ํ์๋ง ์์กด→ DIP ์์น ์ค์) ์์ฑ์๋ฅผ ํตํด์ ๊ฐ์ฒด๋ฅผ ์์ฑ⇒ ์์ฑ์ ์ฃผ์
- OrderService์ ์ฝ๋๋ ์์ ๊ตฌ์ฒด์ ์ธ ํด๋์ค๊ฐ ์๋ ์ธํฐํ์ด์ค์๋ง ์์กดํ๋๋ก
- AppConfig๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค์ ๋์์ ํ์ํ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑ MemberServiceImpl
- MemoryMemberRepository OrderServiceImpl FixDiscountPolicy
์ด์ ์๋ ๊ตฌํ์ฒด ์์์ newํ๊ณ ๊ฐ์ฒด ์์ฑํ๋๊ฒ ์ฌ๋ผ์ง. AppConfig๋ก ์ญํ ์ด ๋์ด๊ฐ
- AppConfig๋ ์์ฑํ ๊ฐ์ฒด ์ธ์คํด์ค์ ์ฐธ์กฐ(๋ ํผ๋ฐ์ค)๋ฅผ ์์ฑ์๋ฅผ ํตํด์ ์ฃผ์
(์ฐ๊ฒฐ)
- MemberServiceImpl→ MemoryMemberRepository
- OrderServiceImpl→MemoryMemberRepository, FixDiscountPolicy
ex) MemberServiceImpl์ด new๋ก MemoryMemberRepository๊ฐ์ฒด๋ฅผ ์์ฑํด์์ด์ ๋ํ ์ฐธ์กฐ๊ฐ์ ๋ฃ์ด์ค
MemberServiceImpl
package hello.core.member; //๋ฉค๋ฒ ์๋น์ค implement์ ๊ตฌํ์ฒด -> ํ์ ๊ฐ์ ๊ณผ ์กฐํ๋ฅผ ์ํด์ ์ด๋ค ๊ฒ์ด ํ์ํ ๊น? => ๋ฉค๋ฒ ๋ ํ์งํ ๋ฆฌ ์ธํฐํ์ด์ค๊ฐ ํ์ public class MemberServiceImpl implements MemberService { //์ค๋ฅธ์ชฝ ๋ถ๋ถ -> ์ค์ ํ ๋นํ๋ ๋ถ๋ถ์ด ๊ตฌํ์ฒด๋ฅผ ์์กด (์ถ์ํ, ๊ตฌ์ฒดํ ๋ ๋ค์ ์์กด) => DIP ์๋ฐ private final MemberRepository memberRepository; //= new MemoryMemberRepository(); ์ฝ๋์์ //๋จ์ํ ์ธํฐํ์ด์ค๋ง ์ ์ผ๋ฉด null point exception ๋ฐ์ -> ๊ตฌํ ๊ฐ์ฒด ์ ํ(MemoryMemberRepository) public MemberServiceImpl(MemberRepository memberRepository) { //์์ฑ์๋ฅผ ํตํด ๋ฉค๋ฒ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ด๋ค ๊ตฌํ์ฒด๊ฐ ๋ค์ด๊ฐ์ง ๊ฒฐ์ this.memberRepository = memberRepository; } @Override public void join(Member member) { memberRepository.save(member); //๋คํ์ฑ์ ์ํด memberRepository์ save๊ฐ ํธ์ถ๋จ } @Override public Member findMember(Long memberId) { return memberRepository.findById(memberId); } }
- ์ค๊ณ ๋ณ๊ฒฝ์ผ๋ก MemberServiceImpl ์ MemoryMemberRepository ๋ฅผ ์์กดํ์ง ์๋๋ค!
- ๋จ์ง MemberRepository ์ธํฐํ์ด์ค๋ง ์์กดํ๋ค.
- MemberServiceImpl ์ ์ฅ์์ ์์ฑ์๋ฅผ ํตํด ์ด๋ค ๊ตฌํ ๊ฐ์ฒด๊ฐ ๋ค์ด์ฌ์ง(์ฃผ์ ๋ ์ง)๋ ์ ์ ์๋ค.
- MemberServiceImpl ์ ์์ฑ์๋ฅผ ํตํด์ ์ด๋ค ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ ์ง๋ ์ค์ง ์ธ๋ถ( AppConfig )์์ ๊ฒฐ์ ๋๋ค.
- MemberServiceImpl ์ ์ด์ ๋ถํฐ ์์กด๊ด๊ณ์ ๋ํ ๊ณ ๋ฏผ์ ์ธ๋ถ์ ๋งก๊ธฐ๊ณ ์คํ์๋ง ์ง์คํ๋ฉด ๋๋ค.
๊ทธ๋ฆผ - ํด๋์ค ๋ค์ด์ด๊ทธ๋จ
- MemberService ์ธํฐํ์ด์ค
- ์ด๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด MemberServiceimpl์ด๊ณ , ์ด๋ MemberRepository ์ธํฐํ์ด์ค ์์กด
- AppConfig์ ์๋ก์ด ๋ฑ์ฅ → MemberServiceImpl๊ณผ MemmoryMemberRepository๊น์ง ์์ฑ ⇒ ๊ฐ์ฒด์ ์์ฑ๊ณผ ์ฐ๊ฒฐ์ AppConfig๊ฐ ๋ด๋น!
- ๊ฐ์ฒด์ ์์ฑ๊ณผ ์ฐ๊ฒฐ(Config) ์คํํ๋ ์ญํ (MemberServiceImpl)
๊ทธ๋ฆผ - ํ์ ๊ฐ์ฒด ์ธ์คํด์ค ๋ค์ด์ด๊ทธ๋จ
- AppConfig๊ฐ MemoryMemberRepository ์์ฑ → memberServiceImpl์ ์์ฑํ ๋ MemoryMemberRepository์ ์ฐธ์กฐ๊ฐ์ ์์ฑ์์ ๊ฐ์ด ์ ๋ฌ
- ํด๋ผ์ด์ธํธ์ธ memberServiceImpl ์ ์ฅ์์ ๋ณด๋ฉด ์์กด๊ด๊ณ๋ฅผ ๋ง์น ์ธ๋ถ์์ ์ฃผ์ ํด์ฃผ๋ ๊ฒ ๊ฐ๋ค๊ณ ํด์ DI(Dependency Injection) ์ฐ๋ฆฌ๋ง๋ก ์์กด๊ด๊ณ ์ฃผ์ ๋๋ ์์กด์ฑ ์ฃผ์ ์ด๋ผ ํ๋ค.
OrderServiceImpl
package hello.core.order; import hello.core.discount.DiscountPolicy; import hello.core.discount.FixDiscountPolicy; import hello.core.member.Member; import hello.core.member.MemberRepository; import hello.core.member.MemoryMemberRepository; //๋จ์ผ ์ฑ ์ ์์น์ ์ ์งํจ ๋ฐฉ์ ํ ์ธ์ ๋ํ ๋ณ๊ฒฝ์ด ํ์ํ๋ฉด ์ฃผ๋ฌธ์ชฝ ์ฝ๋๋ฅผ ๊ณ ์น ํ์๊ฐx public class OrderServiceImpl implements OrderService { private final MemberRepository memberRepository; // = new MemoryMemberRepository(); private final DiscountPolicy discountPolicy; // = new FixDiscountPolicy(); public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; } @Override public Order createOrder(Long memberId, String itemName, int itemPrice) { Member member=memberRepository.findById(memberId); //ํ์์ ๋ณด ์กฐํ int discountPrice=discountPolicy.discount(member, itemPrice); //ํ ์ธ์ ์ฑ ์ ํ์ ์ ๋ณด๋ฅผ ๋๊น ๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก ํ ์ธ๋ ๊ฐ๊ฒฉ์ ๋ฐํ return new Order(memberId, itemName, itemPrice, discountPrice); //์ต์ข ์์ฑ๋ ์ฃผ๋ฌธ ์ ๋ณด๋ฅผ ๋๊ธด๋ค } }
์ค๊ณ ๋ณ๊ฒฝ์ผ๋ก OrderServiceImpl ์ FixDiscountPolicy ๋ฅผ ์์กดํ์ง ์๋๋ค! ๋จ์ง DiscountPolicy ์ธํฐํ์ด์ค๋ง ์์กดํ๋ค.
OrderServiceImpl ์ ์ฅ์์ ์์ฑ์๋ฅผ ํตํด ์ด๋ค ๊ตฌํ ๊ฐ์ฒด๊ฐ ๋ค์ด์ฌ์ง(์ฃผ์ ๋ ์ง)๋ ์ ์ ์๋ค.
OrderServiceImpl ์ ์์ฑ์๋ฅผ ํตํด์ ์ด๋ค ๊ตฌํ ๊ฐ์ฒด์ ์ฃผ์ ํ ์ง๋ ์ค์ง ์ธ๋ถ( AppConfig )์์ ๊ฒฐ์ ํ๋ค. OrderServiceImpl ์ ์ด์ ๋ถํฐ ์คํ์๋ง ์ง์คํ๋ฉด ๋๋ค.
OrderServiceImpl ์๋ MemoryMemberRepository , `FixDiscountPolicy' ๊ฐ์ฒด์ ์์กด๊ด๊ณ๊ฐ ์ฃผ์ ๋๋ค.
AppConfig ์คํ
MemberApp
package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.order.AppConfig; public class MemberApp { public static void main(String[] args) { AppConfig appConfig = new AppConfig(); MemberService memberService = appConfig.memberService(); //memberService ์ธํฐํ์ด์ค์๋ memberserviceImpl์ด ๋ค์ด์์ //MemberService memberService = new MemberServiceImpl(); -> ๋ฉ์ธ๋ฉ์๋์์ ์ง์ ๊ตฌํ์ฒด๋ฅผ ์์ฑํ์๋ ์ด์ ๋ฐฉ์ -> ๊ตฌํ์ฒด์์ ๋ฆฌํ์งํ ๋ฆฌ๋ฅผ ๋ ์์ฑ Member member = new Member(1L, "memberA", Grade.VIP); //Long type์ด๋ผ L ๋ถ์ฌ์ค์ผ ๋จ memberService.join(member); //id๊ฐ 1, ์ด๋ฆ์ด memberA์ธ ๋ฉค๋ฒ์ ํ์๊ฐ์ ์ค์ ๋์ Member findMember = memberService.findMember(1L); //๊ฐ์ ๋ฉค๋ฒ์ findMember๊ฐ ์ผ์นํ๋ฉด ์ ๋๋ก ๋์ํ ๊ฒ System.out.println("member = " + member.getName()); //์ด๋ฆ์ ์ถ๋ ฅํด์ ํ์ธ System.out.println("fineMember = " + findMember.getName()); } }
OrderApp
package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.order.AppConfig; import hello.core.order.Order; import hello.core.order.OrderService; import hello.core.order.OrderServiceImpl; public class OrderApp { public static void main(String[] args) { AppConfig appConfig=new AppConfig(); MemberService memberService = appConfig.memberService(); OrderService orderService = appConfig.orderService(); //MemberService memberService = new MemberServiceImpl(null); //OrderService orderService = new OrderServiceImpl(null, null); Long memberId=1L; Member member= new Member(memberId,"memberA", Grade.VIP ); memberService.join(member); //ํ์์ ์์ฑํด์ ๊ฐ์ ์ํด -> ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ฒด์ ๋ฃ์ด๋์ Order order = orderService.createOrder(memberId, "itemA",10000); System.out.println("order = "+order); System.out.println("order.calculatePrice = "+ order.calculatePrice()); //์ด๋ฌํ ํ๋ฆฐํธ ๋ฐฉ์๋ณด๋ค๋ JUnit์ ์ด์ฉํ๊ธฐ } }
ํ ์คํธ ์ฝ๋ ์์
package hello.core.member; import hello.core.order.AppConfig; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class MemberServiceTest { MemberService memberService; @BeforeEach //ํ ์คํธ ์คํ ์ ๋ฌด์กฐ๊ฑด ์คํ๋จ public void beforeEach(){ AppConfig appConfig = new AppConfig(); memberService= appConfig.memberService(); } @Test void join() { //given => ์ด๊ฒ ์ฃผ์ด์ง๋ฉด Member member= new Member(1L, "memberA", Grade.VIP); //when => ์ด๋ ๊ฒ ํ๋ฉด memberService.join(member); Member findMember=memberService.findMember(1L); //then => ๊ฒฐ๊ณผ๊ฐ ์๋ ๋ค~ ๊ฒ์ฆํด๋ณธ๋ค Assertions.assertThat(member).isEqualTo(findMember); } }
์ ๋ฆฌ
- AppConfig๋ฅผ ํตํด์ ๊ด์ฌ์ฌ๋ฅผ ํ์คํ๊ฒ ๋ถ๋ฆฌ →AppConfig๋ ๊ตฌ์ฒด ํด๋์ค๋ฅผ ์ ํ/ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ป๊ฒ ๋์ํด์ผ ํ ์ง ์ ์ฒด ๊ตฌ์ฑ์ ์ฑ ์
- ๊ตฌํ์ฒด๋ค์ ๋ด๋น ๊ธฐ๋ฅ์ ์คํํ๋ ์ฑ ์๋ง → OrderServiceImpl ์ ๊ธฐ๋ฅ์ ์คํํ๋ ์ฑ ์๋ง ์ง๋ฉด ๋๋ค.
AppConfig ๋ฆฌํฉํฐ๋ง
ํ์ฌ AppConfig๋ฅผ ๋ณด๋ฉด ์ค๋ณต์ด ์๊ณ , ์ญํ ์ ๋ฐ๋ฅธ ๊ตฌํ์ด ์ ์๋ณด์ธ๋ค.
- ์ค๋ณต์ ์ ๊ฑฐํ๊ณ , ์ญํ ์ ๋ฐ๋ฅธ ๊ตฌํ์ด ๋ณด์ด๋๋ก ๋ฆฌํฉํฐ๋ง
- ๋ฐ์ ์ฝ๋๊ฐ ์ ๋ ์ญํ ์ ๋ฐ๋ฅธ ๊ตฌํ์ด ์ ๋ณด์ด๋๊ฑด์ง… ๋ชจ๋ฅด๊ฒ ๋ค..
์๋ก์ด ๊ตฌ์กฐ์ ํ ์ธ ์ ์ฑ ์ ์ฉ
- ์ด์ ์๋ ํ ์ธ ์ ์ฑ ์ ๋ณ๊ฒฝํ๋ฉด ํด๋ผ์ด์ธํธ ์ฝ๋๊น์ง ๋ณ๊ฒฝ → ์ง๊ธ์ ํ ์ธ ์ ์ฑ ์ ๋ณ๊ฒฝํด๋ AppConfig๋ง ๋ณ๊ฒฝํ๋ฉด ๋จ
- ๊ฐ์ฒด๋ฅผ ์์ฑ/๊ตฌ์ฑํ๋ ์์ญ๊ณผ ์ฌ์ฉ ์์ญ์ ๋ถ๋ฆฌ
- ํ ์ธ ์ ์ฑ ๋ณ๊ฒฝ ์ AppConfig ๊ตฌ์ฑ ์์ญ์ ์ฝ๋๋ง ๋ณ๊ฒฝํ๋ฉด ๋จ
ํ ์ธ ์ ์ฑ ๋ณ๊ฒฝ
public class AppConfig{ public DiscountPolicy discountPolicy(){ //return new FixDiscountPolicy(); return new RateDiscountPolicy(); } }
- ํ ์ธ ์ ์ฑ ์ ๋ํ ๊ตฌ์ฒด ๊ฐ์ฒด๋ฅผ RateDiscountPolicy()๋ก๋ง ๋ฐ๊พผ๋ค
๋๋ RateDiscountPolicy()๋ก ๋ฐ๊ฟ๋ ์ 1000์ ๊ณ ์ ์ ์ผ๋ก ํ ์ธ๋์ง..?
ํ ์ธ ์ ์ฑ ๋ณ๊ฒฝ
์ด ๊ทธ๋ฆผ ๊ต์ฅํ ์ค์ํ๋ค
์ฌ์ฉ์์ญ์ ์๋ ์ฝ๋๋ ์ ๋ ํ์๊ฐ ์๋ค
- ํด๋ผ์ด์ธํธ ์ฝ๋(OrderServiceImpl)๋ ์ถ์ํ์ ์์กด (DIP๋ฅผ ๋ง์กฑ)
- OCP ํ์ฅ์๋ ์ด๋ ค์๊ณ ๋ณ๊ฒฝ์๋ ๋ซํ์๋ค
์ง๊ธ๊น์ง์ ์ ์ฒด ํ๋ฆ ์ ๋ฆฌ
์๋ก์ด ํ ์ธ ์ ์ฑ ๊ฐ๋ฐ
๋คํ์ฑ ๋๋ถ์ ์๋ก์ด ์ ๋ฅ ํ ์ธ ์ ์ฑ ์ฝ๋๋ฅผ ์ถ๊ฐ๋ก ๊ฐ๋ฐํ๋ ๊ฒ ์์ฒด๋ ์๋ฌด ๋ฌธ์ ๊ฐ ์์
์๋ก์ด ํ ์ธ ์ ์ฑ ์ ์ฉ๊ณผ ๋ฌธ์ ์
- ์๋ก ๊ฐ๋ฐํ ์ ๋ฅ ํ ์ธ ์ ์ฑ ์ ์ ์ฉํ๋ ค๊ณ ํ๋ *ํด๋ผ์ด์ธํธ ์ฝ๋์ธ ์ฃผ๋ฌธ ์๋น์ค ๊ตฌํ์ฒด๋ ํจ๊ป ๋ณ๊ฒฝํด์ผํจ ⇒ OCP์ ์๋ฐ
- ์ฃผ๋ฌธ ์๋น์ค ํด๋ผ์ด์ธํธ๊ฐ ์ธํฐํ์ด์ค์ธ DiscountPolicy ๋ฟ๋ง ์๋๋ผ, ๊ตฌ์ฒด ํด๋์ค์ธ FixDiscountPolicy ๋ ํจ๊ป ์์กด => DIP ์๋ฐ
ํด๋ผ์ด์ธํธ ์ฝ๋์ธ ์ฃผ๋ฌธ ์๋น์ค ๊ตฌํ์ฒด๊ฐ ์ฃผ๋ฌธ๊ด๋ จ ๊ธฐ๋ฅ, ๊ฐ์ฒด ์์ฑ… ๋ฑ๋ฑ์ ๋๋ฌด ๋ง์ ๊ธฐ๋ฅ์ ๋ด๋น ⇒ ๋ถ๋ฆฌ
๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ
- ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๋์ ๊ณต์ฐ์ผ๋ก ์๊ฐ
- ๊ธฐ์กด์๋ ํด๋ผ์ด์ธํธ๊ฐ ์์กดํ๋ ์๋ฒ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๊ณ , ์คํํจ
- ๋ฐฐ์ฐ๊ฐ ๋ฐฐ์ฐ๋ฅผ ์ด๋นํ๋.. ๊ทธ๋ฐ ์ํฉ ⇒ ๊ณต์ฐ ๊ตฌ์ฑ๊ณผ ๋ฐฐ์ฐ ์ญ์ธํ๋ ์ฑ ์์ ๊ฐ์ง๋ ๋ณ๋์ ๊ณต์ฐ๊ธฐํ์(AppConfig)๊ฐ ๋ฑ์ฅ
- AppConfig๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฒด ๋์ ๋ฐฉ์์ ๊ตฌ์ฑ(config)ํ๊ธฐ ์ํด, ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ฐ๊ฒฐํ๋ ์ฑ ์
- ์ด์ ๋ถํฐ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ ์์ ์ ์ญํ ์ ์คํํ๋ ๊ฒ๋ง ์ง์ค, ๊ถํ์ด ์ค์ด๋ฌ(์ฑ ์์ด ๋ช ํํด์ง)
AppConfig ๋ฆฌํฉํฐ๋ง
๊ตฌ์ฑ ์ ๋ณด์์ ์ญํ ๊ณผ ๊ตฌํ์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌ ์ญํ ์ด ์ ๋๋ฌ๋จ ์ค๋ณต ์ ๊ฑฐ (new ๋ ๋ฒ ์๋ ๊ฑฐ ํ๋๋ง ํ๋๋ก)
์๋ก์ด ๊ตฌ์กฐ์ ํ ์ธ ์ ์ฑ ์ ์ฉ
์ ์ก ํ ์ธ ์ ์ฑ → ์ ๋ฅ % ํ ์ธ ์ ์ฑ ์ผ๋ก ๋ณ๊ฒฝ AppConfig์ ๋ฑ์ฅ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด ํฌ๊ฒ ์ฌ์ฉ ์์ญ๊ณผ, ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ****๊ตฌ์ฑ(Configuration)ํ๋ ์์ญ**์ผ๋ก ๋ถ๋ฆฌ ํ ์ธ ์ ์ฑ ์ ๋ณ๊ฒฝํด๋ AppConfig๊ฐ ์๋ ๊ตฌ์ฑ ์์ญ๋ง ๋ณ๊ฒฝํ๋ฉด ๋จ, ์ฌ์ฉ ์์ญ์ ๋ณ๊ฒฝํ ํ์๊ฐ ์์.
๋ฌผ๋ก ํด๋ผ์ด์ธํธ ์ฝ๋์ธ ์ฃผ๋ฌธ ์๋น์ค ์ฝ๋๋ ๋ณ๊ฒฝํ์ง ์์
⇒ DIP, OCP์ ์ค์
์ข์ ๊ฐ์ฒด ์งํฅ ์ค๊ณ์ 5๊ฐ์ง ์์น์ ์ ์ฉ
์ฌ๊ธฐ์๋ SRP, DIP, OCP ์ ์ฉ
SRP ๋จ์ผ ์ฑ ์ ์์น : “ํ ํด๋์ค๋ ํ๋์ ์ฑ ์๋ง ๊ฐ์ ธ์ผ ํ๋ค.”
- ํด๋ผ์ด์ธํธ ๊ฐ์ฒด(OrderServiceImpl๊ฐ์๊ฑฐ)๋ ์ง์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ฐ๊ฒฐํ๊ณ , ์คํํ๋ ๋ค์ํ ์ฑ ์์ ๊ฐ์ง๊ณ ์์
- SRP ๋จ์ผ ์ฑ ์ ์์น์ ๋ฐ๋ฅด๋ฉด์ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํจ
- ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฐ๊ฒฐํ๋ ์ฑ ์์ AppConfig๊ฐ ๋ด๋น
- ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ ์คํํ๋ ์ฑ ์๋ง ๋ด๋น
DIP ์์กด๊ด๊ณ ์ญ์ ์์น : ํ๋ก๊ทธ๋๋จธ๋ “์ถ์ํ์ ์์กดํด์ผ์ง, ๊ตฌ์ฒดํ์ ์์กดํ๋ฉด ์๋๋ค.” ์์กด์ฑ ์ฃผ์ ์ ์ด ์์น์ ๋ฐ๋ฅด๋ ๋ฐฉ๋ฒ ์ค ํ๋๋ค.**
- ๊ฐ์ฒด๋ ์ถ์ํ์ ์์กด! ๊ตฌ์ฒดํ์ ์์กดํ์ง ์๋๋ค + ์์กด ๊ด๊ณ์ ๋ํ ๋ฌธ์ , ๊ตฌ์ฒด์ ์ธ ํด๋์ค์ ๋ํ ์ ํ์ ์ธ๋ถ์์ ๋ฃ์ด์ค์ผ ํ๋ค ํด๋ผ์ด์ธํธ ์ฝ๋๊ฐ DiscountPolicy ์ถ์ํ ์ธํฐํ์ด์ค์๋ง ์์กดํ๋๋ก ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๋ค.
- ์๋ก์ด ํ ์ธ ์ ์ฑ ์ ๊ฐ๋ฐํ๊ณ , ์ ์ฉํ๋ ค๊ณ ํ๋ ํด๋ผ์ด์ธํธ ์ฝ๋๋ ํจ๊ป ๋ณ๊ฒฝํด์ผ ํ๋ค. ์๋ํ๋ฉด ๊ธฐ์กด ํด๋ผ์ด์ธํธ ์ฝ๋( OrderServiceImpl )๋ DIP๋ฅผ ์งํค๋ฉฐ DiscountPolicy ์ถ์ํ ์ธํฐํ์ด์ค์ ์์กดํ๋ ๊ฒ ๊ฐ์์ง๋ง, FixDiscountPolicy ๊ตฌ์ฒดํ ๊ตฌํ ํด๋์ค์๋ ํจ๊ป ์์กดํ๋ค.
- ํด๋ผ์ด์ธํธ ์ฝ๋๊ฐ DiscountPolicy ์ถ์ํ ์ธํฐํ์ด์ค์๋ง ์์กดํ๋๋ก ์ฝ๋๋ฅผ ๋ณ๊ฒฝ
- ํ์ง๋ง ํด๋ผ์ด์ธํธ ์ฝ๋๋ ์ธํฐํ์ด์ค๋ง์ผ๋ก๋ ์๋ฌด๊ฒ๋ ์คํํ ์ ์๋ค. AppConfig๊ฐ FixDiscountPolicy ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ํด๋ผ์ด์ธํธ ์ฝ๋ ๋์ ์์ฑํด์ ํด๋ผ์ด์ธํธ ์ฝ๋์ ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ ํ๋ค. ์ด๋ ๊ฒํด์ DIP ์์น์ ๋ฐ๋ฅด๋ฉด์ ๋ฌธ์ ๋ ํด๊ฒฐํ๋ค.
OCP : ์ํํธ์จ์ด ์์๋ ํ์ฅ์๋ ์ด๋ ค ์์ผ๋ ๋ณ๊ฒฝ์๋ ๋ซํ ์์ด์ผ ํ๋ค
- ๋คํ์ฑ ์ฌ์ฉํ๊ณ ํด๋ผ์ด์ธํธ๊ฐ DIP๋ฅผ ์งํด
- ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ ์์ญ๊ณผ ๊ตฌ์ฑ ์์ญ์ผ๋ก ๋๋
- AppConfig๊ฐ์์กด๊ด๊ณ๋ฅผ FixDiscountPolicy RateDiscountPolicy ๋ก ๋ณ๊ฒฝํด์ ํด๋ผ์ด์ธํธ์ฝ๋์ ์ฃผ์ ํ๋ฏ๋ก ํด๋ผ์ด์ธํธ ์ฝ๋๋ ๋ณ๊ฒฝํ์ง ์์๋ ๋จ ์ํํธ์จ์ด ์์๋ฅผ ์๋กญ๊ฒ ํ์ฅํด๋ ์ฌ์ฉ ์์ญ์ ๋ณ๊ฒฝ์ ๋ซํ ์๋ค!
- ๋ณ๊ฒฝ์ด ๋ซํ ์๋ค๋ ๋ง์ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค๋ ๋ง
IoC, DI, ๊ทธ๋ฆฌ๊ณ ์ปจํ ์ด๋
- ๊ฐ๋ฐ์๊ฐ ์ํ๋ ๋๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ํธ์ถํ๋, ์ง์ ๋ค ์ปจํธ๋กคํ๊ณ ์ ์ดํ๋ ์คํ์ผ์ ๊ฐ๋ฐ ↔ ๊ฐ๋ฐ์๊ฐ ํธ์ถํ๋ ๊ฒ ์๋๋ผ ํ๋ ์์ํฌ๊ฐ ์ฝ๋๋ฅผ ๋์ ํธ์ถ =์ ์ด๊ถ์ด ๋ค๋ฐ๋๋ค=์ ์ด์ ์ญ์
์ ์ด์ ์ญ์ IoC(Inversion of Control)
- ๊ธฐ์กด ํ๋ก๊ทธ๋จ์ ํด๋ผ์ด์ธํธ ๊ตฌํ ๊ฐ์ฒด๊ฐ ์ค์ค๋ก ํ์ํ ์๋ฒ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ฐ๊ฒฐํ๊ณ , ์คํ ⇒ ํ๋ง๋๋ก ๊ตฌํ ๊ฐ์ฒด๊ฐ ํ๋ก๊ทธ๋จ์ ์ ์ด ํ๋ฆ์ ์ค์ค๋ก ์กฐ์ข
- ↔ AppConfig๊ฐ ๋ฑ์ฅํ ์ดํ์ ๊ตฌํ ๊ฐ์ฒด๋ ์์ ์ ๋ก์ง์ ์คํํ๋ ์ญํ ๋ง ๋ด๋นํ๋ค. ํ๋ก๊ทธ๋จ์ ์ ์ด ํ๋ฆ์ ์ด์ AppConfig๊ฐ ๋ด๋น
- ex) OrderServiceImpl ์ ํ์ํ ์ธํฐํ์ด์ค๋ค์ ํธ์ถํ์ง๋ง ์ด๋ค ๊ตฌํ ๊ฐ์ฒด๋ค์ด ์คํ๋ ์ง ๋ชจ๋ฅธ๋ค.
- ํ๋ก๊ทธ๋จ์ ๋ํ ์ ์ด ํ๋ฆ์ ๋ํ ๊ถํ์ ๋ชจ๋ AppConfig๊ฐ ๊ฐ์ง๊ณ ์๋ค. ์ฌ์ง์ด OrderServiceImpl ๋ AppConfig๊ฐ ์์ฑ
- AppConfig๋ OrderServiceImpl ์ด ์๋ OrderService ์ธํฐํ์ด์ค์ ๋ค๋ฅธ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์คํํ ์ ๋ ์๋ค. OrderServiceImpl ์ ๋ฌต๋ฌตํ ์์ ์ ๋ก์ง์ ์คํ
์ด๋ ๋ฏ ํ๋ก๊ทธ๋จ์ ์ ์ด ํ๋ฆ์ ์ง์ ์ ์ดํ๋ ๊ฒ์ด ์๋๋ผ ์ธ๋ถ์์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ ์ด์ ์ญ์ (IoC)์ด๋ผ ํ๋ค.
ํ๋ ์์ํฌ vs ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ํ๋ ์์ํฌ๊ฐ ๋ด๊ฐ ์์ฑํ ์ฝ๋๋ฅผ ์ ์ดํ๊ณ , ๋์ ์คํํ๋ฉด ๊ทธ๊ฒ์ ํ๋ ์์ํฌ๊ฐ ๋ง๋ค. (JUnit) → ๋ผ์ดํ์ฌ์ดํด ์์์ ๋ด ๊ฒ๋ง ์ฝ๋ฐฑ์์ผ๋ก ๋ถ๋ ค์ง๋ ๊ทธ๋ฐ ๋๋
ํ์ํ ๋ถ๋ถ๋ง ๊ฐ๋ฐํ๋ฉด ํ๋ ์์ํฌ๊ฐ ์์์ ํธ์ถ์ด ๋๋ ๊ฒ
ํธ์ถํ๋ ์ ์ด๊ถ์ ๋๊ธฐ๋ ๊ฒ์ด ์ ์ด์ ์ญ์ ์ด๋ค!
- ๋ฐ๋ฉด์ ๋ด๊ฐ ์์ฑํ ์ฝ๋๊ฐ ์ง์ ์ ์ด์ ํ๋ฆ์ ๋ด๋นํ๋ค๋ฉด ๊ทธ๊ฒ์ ํ๋ ์์ํฌ๊ฐ ์๋๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. (java๊ฐ์ฒด๋ฅผ xml ํน์ JSON์ผ๋ก ๋ฐ๊พธ๋ ๋ฑ ์ง์ ํธ์ถํ๋ ๊ฒ)
์์กด๊ด๊ณ ์ฃผ์ DI(Dependency Injection)
OrderServiceImpl ์ DiscountPolicy ์ธํฐํ์ด์ค์๋ง ์์กด-> ์ค์ ์ด๋ค ๊ตฌํ ๊ฐ์ฒด๊ฐ ์ฌ์ฉ๋ ์ง๋ ๋ชจ๋ฆ => ์์กด๊ด๊ณ๋ ์ ์ ์ธ ํด๋์ค ์์กด ๊ด๊ณ์, ์คํ ์์ ์ ๊ฒฐ์ ๋๋ ๋์ ์ธ ๊ฐ์ฒด(์ธ์คํด์ค) ์์กด ๊ด๊ณ ๋์ ๋ถ๋ฆฌํด์ ์๊ฐํด์ผ ํ๋ค.
์ ์ ์ธ ํด๋์ค ์์กด๊ด๊ณ
- ํด๋์ค๊ฐ ์ฌ์ฉํ๋ import ์ฝ๋๋ง ๋ณด๊ณ (ํด๋์ค๋ ๊ฐ์ฒด๋ค๋ง ๋ณด๊ณ ) ์์กด๊ด๊ณ๋ฅผ ์ฝ๊ฒ ํ๋จํ ์ ์๋ค. ์ ์ ์ธ ์์กด๊ด๊ณ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ์ง ์์๋ ๋ถ์ํ ์ ์๋ ๊ด๊ณ
- ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ๋ณด์
- ์ธํ ๋ฆฌ์ ์ด ํด ์ค๋ฅธ์ชฝ ๋ง์ฐ์ค ํด๋ฆญ → show diagram → ์ค๋ฅธ์ชฝ ๋ง์ฐ์ค → show dependenciesํ๋ฉด ์์กด๊ด๊ณ์ ๋ํ ์ฝ๋๋ค์ด ๋ณด์.
ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ํตํด OrderServiceImpl ์ MemberRepository , DiscountPolicy ์ ์์กดํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
์ ์ ํ์ดํ ๋ฐฉํฅ์ผ๋ก ์์กดํจ FixDiscountPolicy๋ DiscountPolicy๋ฅผ ์์กดํจ ๊ทธ๋ฐ๋ฐ ์ด๋ฌํ ํด๋์ค ์์กด๊ด๊ณ ๋ง์ผ๋ก๋ ์ค์ ์ด๋ค ๊ฐ์ฒด๊ฐ OrderServiceImpl ์ ์ฃผ์ ๋ ์ง ์ ์ ์๋ค. (์คํ์์ผ๋ด์ผ ์๋ ๊ฒ!) => ๋์ ์ธ ๊ด๊ณ
๋์ ์ธ ๊ฐ์ฒด ์ธ์คํด์ค ์์กด ๊ด๊ณ
์ ํ๋ฆฌ์ผ์ด์ ์คํ ์์ ์ ์ค์ ์์ฑ๋ ๊ฐ์ฒด ์ธ์คํด์ค์ ์ฐธ์กฐ๊ฐ ์ฐ๊ฒฐ๋ ์์กด ๊ด๊ณ
- ํด๋ผ์ด์ธํธ๋ ์ฃผ๋ฌธ ์๋น์ค ๊ตฌํ์ฒด๋ฅผ ํธ์ถ → AppConfig์์ orderService ์์ฑํ ๋ ๊ตฌ์ฒดํ๋ ๊ฐ์ฒด๊ฐ ๋ค์ด๊ฐ. ๊ฐ์ฒด ์ธ์คํด์ค ๋ค์ด์ด๊ทธ๋จ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํํ ๋๋ง๋ค ๋์ ์ผ๋ก ๋ฐ๋๋ค
- ์ ํ๋ฆฌ์ผ์ด์ **์คํ ์์ (๋ฐํ์)**์ ์ธ๋ถ์์ ์ค์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ํด๋ผ์ด์ธํธ์ ์ ๋ฌํด์ ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ์ค์ ์์กด๊ด๊ณ๊ฐ ์ฐ๊ฒฐ ๋๋ ๊ฒ์ ์์กด๊ด๊ณ ์ฃผ์ ์ด๋ผ ํ๋ค.
- ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , ๊ทธ ์ฐธ์กฐ๊ฐ์ ์ ๋ฌํด์ ์ฐ๊ฒฐ๋๋ค. (์๋ฐ๋ ์ฐธ์กฐ๋ก ๋ค ์ธ์คํด์ค๋ค์ด ์ฐ๊ฒฐ)
- ์์กด๊ด๊ณ ์ฃผ์ ์ ์ฌ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ , ํด๋ผ์ด์ธํธ๊ฐ ํธ์ถํ๋ ๋์์ ํ์ ์ธ์คํด์ค๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค. (์ ์ก → ์ ๋ฅ ํ ์ธ์ ์ฑ )
- ์์กด๊ด๊ณ ์ฃผ์ ์ ์ฌ์ฉํ๋ฉด ์ ์ ์ธ ํด๋์ค ์์กด๊ด๊ณ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ , ๋์ ์ธ ๊ฐ์ฒด ์ธ์คํด์ค ์์กด๊ด๊ณ๋ฅผ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค. ⇒ ์์กด๊ด๊ณ ์ฃผ์ ์ ์ฌ์ฉํ๋ฉด ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ด ๋ณํ์ง x = ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค, ๊ฐ์ฒด ๋ค์ด์ด๊ทธ๋จ์ ๋ณํ
IoC ์ปจํ ์ด๋, DI ์ปจํ ์ด๋
IoC(์์กด๊ด๊ณ์ ์ญ์ ์ ์ผ์ผํด), DI(๋ฅผ ํด์ฃผ๋ ์ปจํ ์ด๋
AppConfig ์ฒ๋ผ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉด์ ์์กด๊ด๊ณ๋ฅผ ์ฐ๊ฒฐํด ์ฃผ๋ ๊ฒ์
IoC ์ปจํ ์ด๋ ๋๋ DI ์ปจํ ์ด๋๋ผ ํ๋ค. ์์กด๊ด๊ณ ์ฃผ์ ์ ์ด์ ์ ๋ง์ถ์ด ์ต๊ทผ์๋ ์ฃผ๋ก DI ์ปจํ ์ด๋๋ผ ํ๋ค. ๋๋ ์ด์๋ธ๋ฌ(๋ ๊ณ ๋ธ๋ญ์ฒ๋ผ ์กฐ๋ฆฝ), ์ค๋ธ์ ํธ ํฉํ ๋ฆฌ(์ค๋ธ์ ํธ๋ฅผ ์์ฑ) ๋ฑ์ผ๋ก ๋ถ๋ฆฌ๊ธฐ๋
์คํ๋ง์ผ๋ก ์ ํํ๊ธฐ
AppConfig ์คํ๋ง ๊ธฐ๋ฐ์ผ๋ก ๋ณ๊ฒฝ
package hello.core; import hello.core.discount.DiscountPolicy; import hello.core.discount.FixDiscountPolicy; import hello.core.discount.RateDiscountPolicy; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.member.MemoryMemberRepository; import hello.core.order.OrderService; import hello.core.order.OrderServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration //์คํ๋ง์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑ ์ ๋ณด, ์ค์ ์ ๋ณด๋ผ๋ ๋ป public class AppConfig { @Bean //์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } @Bean public MemoryMemberRepository memberRepository() { return new MemoryMemberRepository(); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(), new FixDiscountPolicy()); } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } }
AppConfig์ ์ค์ ์ ๊ตฌ์ฑํ๋ค๋ ๋ป์ @Configuration ์ ๋ถ์ฌ์ค๋ค. ๊ฐ ๋ฉ์๋์ @Bean ์ ๋ถ์ฌ์ค๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์คํ๋ง ์ปจํ ์ด๋์ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๋ค.
MemberApp์ ์คํ๋ง ์ปจํ ์ด๋ ์ ์ฉ
package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MemberApp { public static void main(String[] args) { // AppConfig appConfig = new AppConfig(); // MemberService memberService = appConfig.memberService(); //memberService ์ธํฐํ์ด์ค์๋ memberserviceImpl์ด ๋ค์ด์์ //MemberService memberService = new MemberServiceImpl(); -> ๋ฉ์ธ๋ฉ์๋์์ ์ง์ ๊ตฌํ์ฒด๋ฅผ ์์ฑํ์๋ ์ด์ ๋ฐฉ์ -> ๊ตฌํ์ฒด์์ ๋ฆฌํ์งํ ๋ฆฌ๋ฅผ ๋ ์์ฑ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); //์คํ๋ง์ ๋ชจ๋ ๊ฒ Application context๋ก ์์ -> Bean์ ๋ชจ๋ ๊ด๋ฆฌํด์ค. //AppConfig์ ์๋ ํ๊ฒฝ ์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ Bean์ด ๋ถ์ ์ ๋ค์ Spring ์ปจํ ์ด๋์ ๊ฐ์ฒด ์์ฑํด์ ๊ด๋ฆฌํด์ค. MemberService memberService= applicationContext.getBean("memberService", MemberService.class); //Config์์ ๋ฉ์๋ ์ด๋ฆ์ผ๋ก ์ด๋ฆ ๋ฑ๋ก์ด ๋จ. ๋ฉ์๋ ์ด๋ฆ์ธ memberService๋ก ๊ฐ์ฒด๋ฅผ ์ฐพ์ ๊ฑฐ๊ณ , ๋ฐํ ํ์ ์ MemberService์ผ! ๋ผ๋๊ฒ Member member = new Member(1L, "memberA", Grade.VIP); //Long type์ด๋ผ L ๋ถ์ฌ์ค์ผ ๋จ memberService.join(member); //id๊ฐ 1, ์ด๋ฆ์ด memberA์ธ ๋ฉค๋ฒ์ ํ์๊ฐ์ ์ค์ ๋์ Member findMember = memberService.findMember(1L); //๊ฐ์ ๋ฉค๋ฒ์ findMember๊ฐ ์ผ์นํ๋ฉด ์ ๋๋ก ๋์ํ ๊ฒ System.out.println("member = " + member.getName()); //์ด๋ฆ์ ์ถ๋ ฅํด์ ํ์ธ System.out.println("fineMember = " + findMember.getName()); } }
์คํ๊ฒฐ๊ณผ
- ์ ๋ค์ฏ ๊ฐ → ์คํ๋ง์ด ๋ด๋ถ์ ์ผ๋ก ํ์ํด์ ๋ฑ๋ก
- ๋ฐ ๋ค์ฏ ๊ฐ → ๋ฉ์๋ ์ด๋ฆ์ Key๋ก, Value๋ return์ ์๋ ๊ฐ์ฒด ์ธ์คํด์ค๋ก ํด์ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก
OrderApp์ ์คํ๋ง ์ปจํ ์ด๋ ์ ์ฉ
package hello.core; import hello.core.member.Grade; import hello.core.member.Member; import hello.core.member.MemberService; import hello.core.order.Order; import hello.core.order.OrderService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class OrderApp { public static void main(String[] args) { // AppConfig appConfig=new AppConfig(); // MemberService memberService = appConfig.memberService(); // OrderService orderService = appConfig.orderService(); //MemberService memberService = new MemberServiceImpl(null); //OrderService orderService = new OrderServiceImpl(null, null); ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); MemberService memberService = applicationContext.getBean("memberService", MemberService.class); OrderService orderService = applicationContext.getBean("orderService", OrderService.class); Long memberId=1L; Member member= new Member(memberId,"memberA", Grade.VIP ); memberService.join(member); //ํ์์ ์์ฑํด์ ๊ฐ์ ์ํด -> ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ฒด์ ๋ฃ์ด๋์ Order order = orderService.createOrder(memberId, "itemA",20000); System.out.println("order = "+order); System.out.println("order.calculatePrice = "+ order.calculatePrice()); //์ด๋ฌํ ํ๋ฆฐํธ ๋ฐฉ์๋ณด๋ค๋ JUnit์ ์ด์ฉํ๊ธฐ } }
์คํ๋ง ์ปจํ ์ด๋
- ApplicationContext ๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ ํ๋ค.
- ๊ธฐ์กด์๋ ๊ฐ๋ฐ์๊ฐ AppConfig ๋ฅผ ์ฌ์ฉํด์ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ DI๋ฅผ ํ์ง๋ง, ์ด์ ๋ถํฐ๋ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ํตํด์ ์ฌ์ฉ
- ์คํ๋ง ์ปจํ ์ด๋๋ @Configuration ์ด ๋ถ์ AppConfig ๋ฅผ ์ค์ (๊ตฌ์ฑ) ์ ๋ณด๋ก ์ฌ์ฉ -> ์ฌ๊ธฐ์ @Bean ์ด๋ผ ์ ํ ๋ฉ์๋๋ฅผ ๋ชจ๋ ํธ์ถํด์ ๋ฐํ๋ ๊ฐ์ฒด๋ฅผ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก
- ์ด๋ ๊ฒ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๊ฐ์ฒด๋ฅผ ์คํ๋ง ๋น์ด๋ผ ํ๋ค.
- ์คํ๋ง ๋น์ @Bean ์ด ๋ถ์ ๋ฉ์๋์ ๋ช ์ ์คํ๋ง ๋น์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๋ค. ( memberService ,orderService ) -> @Bean(name="mm") ์ด๋ฐ ์์ผ๋ก ์ง์ ๋ ๊ฐ๋ฅํ๊ธด ํจ but default๋ฅผ ๋ฐ๋ฅด๋ ๊ฒ ๋์
- ์ด์ ์๋ ๊ฐ๋ฐ์๊ฐ ํ์ํ ๊ฐ์ฒด๋ฅผ AppConfig ๋ฅผ ์ฌ์ฉํด์ ์ง์ ์กฐํํ์ง๋ง, ์ด์ ๋ถํฐ๋ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ํตํด์ ํ์ํ ์คํ๋ง ๋น(๊ฐ์ฒด)๋ฅผ ์ฐพ์์ผ ํ๋ค. ์คํ๋ง ๋น์ applicationContext.getBean() ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ์คํ๋ง ์ปจํ ์ด๋์์ ์ฐพ์ ์ ์๋ค.
- ๊ธฐ์กด์๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ์๋ฐ์ฝ๋๋ก ๋ชจ๋ ๊ฒ์ ํ๋ค๋ฉด ์ด์ ๋ถํฐ๋ ์คํ๋ง ์ปจํ ์ด๋์ ๊ฐ์ฒด๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๊ณ , ์คํ๋ง ์ปจํ ์ด๋์์ ์คํ๋ง ๋น์ ์ฐพ์์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝ๋์๋ค.
์ฝ๋๊ฐ ์ฝ๊ฐ ๋ ๋ณต์กํด์ง ๊ฒ ๊ฐ์๋ฐ, ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ค ์ฅ์ ์ด ์์๊น?
์ฅ์ ์ ์ด๋ง์ด๋งํ๋ค!!
⇒ AppConfig๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ํตํด์ DI์ ๊ฐ์ ๊ฒ๋ค์ ํธ๋ฆฌํ๊ฒ ํด์ฃผ๋ ๋ฒ์ฉ์ ํ๋ ์์ํฌ์ ์ญํ
๋ ์์๋ณผ ๊ฒ
- static import
- ์์กด์ฑ ์ฃผ์ DI
- ์คํ๋ง ์ด๋ ธํ ์ด์
- ์๋ฐ์ ๋ ํผ๋ฐ์ค (์ฐธ์กฐ)
๋จ์ถํค
command+shift+T : create new Test
command+b: go to declaration or usage
command+e: ์ด์ ํ์คํ ๋ฆฌ
command+e+enter: ๋ฐ๋ก ์ด์ ์ผ๋ก ๋์๊ฐ
command+o: ์ฐพ๊ธฐ
command+option+m: extract method
command+/: ๊ทธ ์ค ์ฃผ์์ฒ๋ฆฌ
command+d: ๋ผ์ธ ๋ณต์
option+ ์ ํค๋ณด๋: extend selection
control: ๋ง์ง๋ง์ผ๋ก ์คํ๋๋ ๊ฒ ์คํ๋จ
command+option+v: introduce variable
'๐ญ Study > : Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ