스프링 부트, 입문!

스프링 부트, 입문!

쉽고 빠르게 배우는, 스프링 부트 첫걸음!

29 IoC와 DI

# IoC와 DI ## 미션 IoC와 DI의 개념을 설명하고, 코드 예를 통해 훈련하시오. ![홍팍-스프링-부트-입문--미션](http://drive.google.com/thumbnail?export=view&sz=w960&id=1eM_ng1Dxi14ygqYxOCRUUwLVB1jsWw4G) ## 02:10 돈가스 요리하기 테스트 #### ../main/.../ioc/Chef ``` package com.example.firstproject.ioc; public class Chef { public String cook(String menu) { // 재료 준비 Pork pork = new Pork("한돈 등심"); // 요리 반환 return pork.getName() + "으로 만든 " + menu; } } ``` #### ../test/.../ioc/ChefTest ``` package com.example.firstproject.ioc; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class ChefTest { @Test void 돈가스_요리하기() { // 준비 Chef chef = new Chef(); String menu = "돈가스"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한돈 등심으로 만든 돈가스"; // 검증 assertEquals(expected, food); System.out.println(food); } } ``` #### ../main/.../ioc/Pork ``` package com.example.firstproject.ioc; public class Pork { private String name; public Pork(String name) { this.name = name; } public String getName() { return name; } } ``` ## 05:22 스테이크 요리하기 테스트 #### ../test/.../ioc/ChefTest ``` ... class ChefTest { ... @Test void 스테이크_요리하기() { // 준비 Chef chef = new Chef(); String menu = "스테이크"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한우 꽃등심으로 만든 스테이크"; // 검증 assertEquals(expected, food); System.out.println(food); } } ``` #### ../main/.../ioc/Chef ``` package com.example.firstproject.ioc; public class Chef { public String cook(String menu) { // 재료 준비 // Pork pork = new Pork("한돈 등심"); Beef beef = new Beef("한우 꽃등심"); // 요리 반환 // return pork.getName() + "으로 만든 " + menu; return beef.getName() + "으로 만든 " + menu; } } ``` #### ../main/.../ioc/Beef ``` package com.example.firstproject.ioc; public class Beef { private String name; public Beef(String name) { this.name = name; } public String getName() { return name; } } ``` ## 07:56 의존성 주입하기(DI) - 의존 객체를 외부에서 주입(dependency injection) #### ../test/.../ioc/ChefTest ``` package com.example.firstproject.ioc; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class ChefTest { @Test void 돈가스_요리하기() { // 준비 IngredientFactory ingredientFactory = new IngredientFactory(); Chef chef = new Chef(ingredientFactory); String menu = "돈가스"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한돈 등심으로 만든 돈가스"; // 검증 assertEquals(expected, food); System.out.println(food); } @Test void 스테이크_요리하기() { // 준비 IngredientFactory ingredientFactory = new IngredientFactory(); Chef chef = new Chef(ingredientFactory); String menu = "스테이크"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한우 꽃등심으로 만든 스테이크"; // 검증 assertEquals(expected, food); System.out.println(food); } } ``` #### ../main/.../ioc/Chef ``` package com.example.firstproject.ioc; public class Chef { private IngredientFactory ingredientFactory; public Chef(IngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } public String cook(String menu) { // 재료 준비 Ingredient ingredient = ingredientFactory.get(menu); // 요리 반환 return ingredient.getName() + "으로 만든 " + menu; } } ``` #### ../main/.../ioc/IngredientFactory ``` package com.example.firstproject.ioc; public class IngredientFactory { public Ingredient get(String menu) { switch (menu) { case "돈가스": return new Pork("한돈 등심"); case "스테이크": return new Beef("한우 꽃등심"); default: return null; } } } ``` #### ../main/.../ioc/Ingredient ``` package com.example.firstproject.ioc; public class Ingredient { private String name; public Ingredient(String name) { this.name = name; } public String getName() { return name; } } ``` #### ../main/.../ioc/Pork ``` package com.example.firstproject.ioc; public class Pork extends Ingredient { public Pork(String name) { super(name); } } ``` #### ../main/.../ioc/Beef ``` package com.example.firstproject.ioc; public class Beef extends Ingredient { public Beef(String name) { super(name); } } ``` ## 13:38 요구사항 변경에 유연한 확장 - 크리스피 치킨 요리하기 테스트 #### ../test/.../ioc/ChefTest ``` ... class ChefTest { ... @Test void 크리스피_치킨_요리하기() { // 준비 IngredientFactory ingredientFactory = new IngredientFactory(); Chef chef = new Chef(ingredientFactory); String menu = "크리스피 치킨"; // 수행 String food = chef.cook(menu); // 예상 String expected = "국내산 10호 닭으로 만든 크리스피 치킨"; // 검증 assertEquals(expected, food); System.out.println(food); } } ``` #### ../main/.../ioc/IngredientFactory ``` package com.example.firstproject.ioc; public class IngredientFactory { public Ingredient get(String menu) { switch (menu) { case "돈가스": return new Pork("한돈 등심"); case "스테이크": return new Beef("한우 꽃등심"); case "크리스피 치킨": return new Chicken("국내산 10호 닭"); default: return null; } } } ``` #### ../main/.../ioc/Chicken ``` package com.example.firstproject.ioc; public class Chicken extends Ingredient { public Chicken(String name) { super(name); } } ``` ## 16:36 IoC 컨테이너와 DI - @SpringBootTest, @Autowired, @Component #### ../test/.../ioc/ChefTest ``` package com.example.firstproject.ioc; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest class ChefTest { @Autowired IngredientFactory ingredientFactory; @Autowired Chef chef; @Test void 돈가스_요리하기() { // 준비 // IngredientFactory ingredientFactory = new IngredientFactory(); // Chef chef = new Chef(ingredientFactory); String menu = "돈가스"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한돈 등심으로 만든 돈가스"; // 검증 assertEquals(expected, food); System.out.println(food); } @Test void 스테이크_요리하기() { // 준비 // IngredientFactory ingredientFactory = new IngredientFactory(); // Chef chef = new Chef(ingredientFactory); String menu = "스테이크"; // 수행 String food = chef.cook(menu); // 예상 String expected = "한우 꽃등심으로 만든 스테이크"; // 검증 assertEquals(expected, food); System.out.println(food); } @Test void 크리스피_치킨_요리하기() { // 준비 // IngredientFactory ingredientFactory = new IngredientFactory(); // Chef chef = new Chef(ingredientFactory); String menu = "크리스피 치킨"; // 수행 String food = chef.cook(menu); // 예상 String expected = "국내산 10호 닭으로 만든 크리스피 치킨"; // 검증 assertEquals(expected, food); System.out.println(food); } } ``` #### ../main/.../ioc/IngredientFactory ``` package com.example.firstproject.ioc; import org.springframework.stereotype.Component; @Component public class IngredientFactory { public Ingredient get(String menu) { switch (menu) { case "돈가스": return new Pork("한돈 등심"); case "스테이크": return new Beef("한우 꽃등심"); case "크리스피 치킨": return new Chicken("국내산 10호 닭"); default: return null; } } } ``` #### ../main/.../ioc/Chef ``` package com.example.firstproject.ioc; import org.springframework.stereotype.Component; @Component public class Chef { private IngredientFactory ingredientFactory; public Chef(IngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } public String cook(String menu) { // 재료 준비 Ingredient ingredient = ingredientFactory.get(menu); // 요리 반환 return ingredient.getName() + "으로 만든 " + menu; } } ``` ## 🔥 구글링 훈련하기 - 의존성 주입이란 - 스프링 IoC 컨테이너란 - 팩토리 패턴이란 - @Component - 스프링 의존성 주입 방식 - 생성자 주입 vs 필드 주입