๋ชจ๋ฐ์ผ์์์ Dependency Injection - Part1.
- #kotlin
- #dagger
- #hilt
- #android
- #ios
- #swift
- #swinject
๋ค์ด๊ฐ๋ฉฐ
๋ชจ๋ฐ์ผ ์ฑ๊ฐ๋ฐ์์๋ ์ํคํ ์ฒ๊ฐ ๊ณ ๋ํ ๋๋ฉด์ DI ์ฌ์ฉ์ ํ์์ ์ธ ์์๊ฐ ๋์ด๊ฐ๊ณ ์์ต๋๋ค. ์ ํฌ ํ๋กฌ ๋ชจ๋ฐ์ผํ๋ android, ios ๊ฐ๋ฐ ์ DI๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ๊ณ ์์ผ๋ฉฐ ๋ค์ํ DIํด์ ํตํด ๋ณด๋ค ์ฝ๊ฒ DI๋ฅผ ์ ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ฒ ํฌ์คํธ์์๋ DI์ ๋ํ ๊ฐ๋ ๊ณผ ๊ตฌํ์ ๊ฐ๋จํ ์์ ๋ฅผ ํตํด ์์๋ณด๊ณ ์ ํฉ๋๋ค. ๋ dagger๋ผ๋ di framework์ ์ฌ์ฉํ๋ฉด์ DI์ ๋ํด์ ์กฐ๊ธ ๋ ๊น์ ์ดํด๋ฅผ ๋๊ณ ์ํฉ๋๋ค.
Dependency Injection(DI) ์ด๋?
DI๋ Dependency Injection, ์์กด์ฑ ์ฃผ์ ์ ์ฝ์ ์ ๋๋ค. ์ํค๋ฐฑ๊ณผ์๋ โํ๋ก๊ทธ๋๋ฐ์์ ๊ตฌ์ฑ์์๊ฐ์ ์์กด ๊ด๊ณ๊ฐ ์์ค์ฝ๋ ๋ด๋ถ๊ฐ ์๋ ์ธ๋ถ์ ์ค์ ํ์ผ ๋ฑ์ ํตํด ์ ์๋๊ฒ ํ๋ ๋์์ธ ํจํด ์ค์ ํ๋์ด๋ค.โ ๋ผ๊ณ ์ ์๋์ด ์์ต๋๋ค. DI๋ฅผ ํ์ฉํ๋ฉด ํด๋์ค ๋ ๋ฒจ์์ ์์กด๊ด๊ณ๊ฐ ๊ณ ์ ๋์ง ์๋๋ก ํ๊ณ ๋์ ์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํด์ฃผ๋ฉด์ ์ฝ๋์ ์ ์ฐ์ฑ์ ํ๋ณดํ๊ณ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ ์ ์๊ฒ ๋ฉ๋๋ค. ๊ฐ๋จํ ์์ ์ฝ๋๋ฅผ ๋ง๋ค๋ฉด์ ์ด๋ค ๋ง์ธ์ง ์ดํดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฒ ํฌ์คํธ์ ์์ ์ฝ๋๋ Java๋ก ์งํํ๊ฒ ์ต๋๋ค. (๊ฐ ๋ชจ๋ฐ์ผ ํ๋ซํผ์์์ DI์ ์ฉ ๊ด๋ จํด์๋ ํฌ์คํ ์งํํ ์์ ์ธ๋ฐ ์ด๋๋ kotlin, swift ์์ ๋ก ์งํํ ์์ ์ ๋๋ค. ์ด๋ฒ ํฌ์คํธ๋ dagger๋ฅผ ํตํด DI์ ๋ํด์ ์์๋ณผ ์์ ์ด๋ผ dagger๊ฐ ๊ตฌ์ฑ๋ ์ธ์ด์ธ java๋ก ์์ ๋ฅผ ๊ตฌ์ฑํ์์ต๋๋ค.)
์์ ๋ Dagger ์์๋ ์ฌ์ฉํ๊ณ ์๋ Coffee Maker ์์ ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. ๋จผ์ DI ์์ด Coffee Maker ์์ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด๊ฒ ์ต๋๋ค. Coffee๋ฅผ ๋ด๋ฆฌ๋๋ฐ๋ ์ด์ ๊ฐํ๋ Heater ์ ์๋ ฅ์ ๊ฐํ๋ pump ๊ฐ ํ์ํฉ๋๋ค. Heater ๋ on / off ์ ๋จ๊ฑฐ์ด์ง๋ฅผ ํ์ธํ๋ ๊ธฐ๋ฅ(isHot)์ด ์๊ณ pump๋ pump ํ๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด๋ด ์๋ค.
public interface Heater { void on(); void off(); boolean isHot(); }
public interface Pump { void pump(); }
๊ทธ๋ฆฌ๊ณ Heater ์ Pump ๋ฅผ ์ฌ์ฉํด ์ปคํผ๋ฅผ ๋ด๋ ค์ฃผ๋ Coffee Maker ํด๋์ค๋ฅผ ๊ตฌํํด๋ด ์๋ค.
public class CoffeeMaker {
private final Heater heater;
private final Pump pump;
public CoffeeMaker(Heater heater, Pump pump) {
this.heater = heater; this.pump = pump;
}
public void brew(){
heater.on();
pump.pump();
System.out.println(" [_]P coffee! [_]P ");
heater.off();
}
}
์ด์ A_Heater ์ A_Pump ๋ผ๋ ์ธํฐํ์ด์ค ๊ตฌํ์ฒด๋ฅผ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
public class A_Heater implements Heater {
boolean heating;
public void on() {
System.out.println("A_Heater : ~ ~ ~ heating ~ ~ ~");
this.heating = true;
}
public void off() {
this.heating = false;
}
public boolean isHot() {
return heating;
}
}
public class A_Pump implements Pump {
private final Heater heater;
public A_Pump(Heater heater) { t
his.heater = heater;
}
public void pump() {
if (heater.isHot()) {
System.out.println("A_Pump => => pumping => =>");
}
}
}
์ด์ DI๋ฅผ ์ฌ์ฉํ์ง ์์ ์ํ์์ ๋ฉ์ธํจ์์์ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด๊ฒ ์ต๋๋ค.
Heater heater = new A_Heater();
Pump pump = new A_Pump(heater);
CoffeeMaker coffeeMaker = new CoffeeMaker(heater,pump);
coffeeMaker.brew();
์ปคํผ๋ฅผ ๋ด๋ฆฌ๊ธฐ ์ํด์๋ CoffeeMaker ๊ฐ์ฒด ์ฌ์ฉ์๊ฐ A_Heater ๋ผ๋ ์ธํฐํ์ด์ค ๊ตฌํ์ฒด์ A_Pump ๋ผ๋ ๊ตฌํ์ฒด๋ฅผ ์์์ผ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์์ต๋๋ค. ์ฌ์ค ์ปคํผ๋ฅผ ๋ง์๊ณ ์ถ์ ์ฌ๋์ ์ด๋ค heater ๋ฅผ ์ฐ๋์ง ์ด๋ค pump ๋ฅผ ์ฐ๋์ง ์๊ด์๋๋ฐ ๋ง์ด์ฃ . ์ฆ CoffeeMaker ์ฌ์ฉ์๊ฐ ์ด๋ค ๊ตฌํ์ฒด์ ์์กดํ๊ณ ์๋์ง ์์์ผ ํฉ๋๋ค.
DI๋ CoffeeMaker ์ฌ์ฉ์๊ฐ ์์กด์ฑ์ ๋ชจ๋ฅด๋ ์ํ์์๋ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์๋๋ก ํด์ค๋๋ค. ์ด๋ค heater ๊ตฌํ์ฒด๋ฅผ ์ฌ์ฉํด์ผํ๋์ง pump ๊ตฌํ์ฒด๋ฅผ ์ฌ์ฉํด์ผํ๋์ง ๋ชฐ๋ผ๋ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์๊ฒ ํด์ค๋๋ค. ๊ทธ๋ผ CoffeeMaker ์ฌ์ฉ์ ๋์ ์ ์์กด์ฑ์ ์ฃผ์ ํด์ฃผ๋ Injection ์ด๋ผ๋ ํด๋์ค๋ฅผ ํ๋ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
public class Injection {
public static Heater provideHeater(){
return new A_Heater();
}
public static Pump providePump(Heater heater){
return new A_Pump(heater);
}
public static CoffeeMaker provideCoffeeMaker(){
Heater heater = Injection.provideHeater();
return new CoffeeMaker(heater,providePump(heater));
}
}
Injection ํด๋์ค๋ DI, ์ฆ ์์กด์ฑ ์ฃผ์ ์ ํด์ฃผ๋ ์ค์ ํ์ผ์ด๋ผ๊ณ ๋ณด์๋ฉด ๋ฉ๋๋ค. ์ ํฌ๋ ์ด ์ค์ ํ์ผ์์ ์ธํฐํ์ด์ค ๊ตฌํ์ฒด๋ฅผ ๋ฆฌํดํด์ฃผ๊ณ ์์ต๋๋ค. ์ ๊ทธ๋ผ DI ๋ฅผ ๊ตฌํํ ์ํ์์ CoffeeMaker ์ฌ์ฉ์๋ ์ด๋ป๊ฒ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์์๊น์?
CoffeeMaker coffeeMaker = new CoffeeMaker(Injection.provideHeater(),Injection.providePump());
coffeeMaker.brew();
Injection ํด๋์ค์์ heater์ pump ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค. ์ด์ CoffeeMaker ์ฌ์ฉ์๋ A_Heater๋ฅผ ์ฌ์ฉํด์ผํ๋์ง B_Heater๋ฅผ ์ฌ์ฉํด์ผํ๋์ง ์ ํ์๊ฐ ์์ต๋๋ค. ๋ ๊ฐ๋จํ๊ฒ๋ ์ด๋ ๊ฒ ๊ตฌํ ํ ์๋ ์์ต๋๋ค.
Injection.provideCoffeeMaker().brew();
์ด ๊ฒฝ์ฐ CoffeeMaker ์ฌ์ฉ์๋ heater ๋ pump ๊ฐ ํ์ํ์ง ๋ชจ๋ฅด๋ ์ํ์์๋ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์๊ฒ ๋ค์. ๊ฐ์๊ธฐ A_Heater ๋ง๊ณ B_Heater ๋ฅผ ์ฌ์ฉํด์ผํ๋ ์ํฉ์ด ์์ ๋ DI ๊ฐ ๊ตฌํ๋ ์ฝ๋์์ CoffeeMaker๊ด๋ฆฌ์๋ ์ฌ์ฉ์์๊ฒ ์๋ฌด ์๊ธฐ ์์ด Injection ์ค์ ๋ง B_Heater๋ก ๋ฐ๊ฟ์ฃผ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ DI ๊ฐ ๊ตฌํ๋์ด ์์ง ์๋ค๋ฉด CoffeeMaker ๊ด๋ฆฌ์๋ ์ฌ์ฉ์์๊ฒ ์ปคํผ ๋ด๋ฆด๋ A_Heater ๊ฐ์ฒด ๋ง๊ณ B_Heater ๊ฐ์ฒด ์ฐ๋ ด ํ๋ฉฐ ์์ฒญํด์ผํ๋ ๋ฒ๊ฑฐ๋ก์ด ์ผ์ด ์๊ธฐ๊ฒ ์ฃ .
์ด๋ฐ ํํ์ ๋์์ธ ํจํด์ DI ๋ผ๊ณ ํฉ๋๋ค. DI๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ์ปคํ๋ง์ ๊ฐ์์ํฌ์ ์๊ณ ์ฌ์ฌ์ฉ ๋ฐ ์ ์ง๋ณด์๋ฅผ ์ฉ์ดํ๊ฒ ํ ์ ์์ต๋๋ค. ๋ํ ์ ๋ ํ ์คํธ ์์๋ ๊ฐ๊ฒฐํ ๊ตฌํ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด๋ฐ DI๋ฅผ ์ฝ๊ณ ๊ฐ๊ฒฐํ๊ฒ ํด์ฃผ๋ ํ๋ ์์ํฌ๊ฐ Dagger ์ ๋๋ค.
Dagger๋ฅผ ์ด์ฉํ DI
์ด์ ์์์ ๋ง๋ CoffeeMaker ๋ฅผ Dagger๋ฅผ ์ด์ฉํ์ฌ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค. ์์์ ์ฐ๋ฆฌ๋ Injection ์ด๋ผ๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ ์ด๊ณณ์ ์์กด์ฑ ์ฃผ์ ์ ๋ณด๋ฅผ ๋ฃ์ด๋จ์ต๋๋ค. Dagger์์๋ ์ด๋ฐ ์์กด์ฑ ์ฃผ์ ๊ด๊ณ๋ฅผ annotation ์ ์ด์ฉํ์ฌ ์ค์ ํ ์ ์์ต๋๋ค.
Dagger ์์ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ์ ์ธ annotation ์ ๋ค ๊ฐ์ง ์ ๋๊ฐ ์์ต๋๋ค.
@Component : ์ค์ ์์กด์ฑ ์ฃผ์ ์ด ๊ตฌํ๋ interface ๋๋ abstract class ์ ์ฌ์ฉ๋๋ annotation ์ ๋๋ค. dagger๋ ์ด annotation ์ด ๋ฌ๋ ค์๋ ์ธํฐํ์ด์ค์ ์์กด์ฑ ์ฃผ์ ์ฝ๋๋ฅผ generate ํฉ๋๋ค. Component ํด๋์ค๋ฅผ ํตํด ์ฐ๋ฆฌ๋ ์์กด์ฑ ์ฃผ์ ์ ํ ์ ์์ต๋๋ค.
@Module : ์์กด์ฑ ๊ด๊ณ๋ฅผ ์ค์ ํ๋ ํด๋์ค์ ์ฌ์ฉ๋๋ annotation. ์ค์ ๊ฐ์ฒด ์ฃผ์ ๊ด๊ณ์ ๋ํ ์ค์ ์ด ๋ค์ด๊ฐ ์์ต๋๋ค.
@Provides : ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๊ธฐ ์ํ ๋ฉ์๋์ ๋ฌ์์ฃผ๋ annotation ์ ๋๋ค.
@Inject : DI๋ฅผ ์งํํ ๋ฉค๋ฒ๋ณ์์ ์์ฑ์์ ๋ฌ์์ค์ผ๋ก์ DI ๋์์ ํ์ธํ ์ ์์ต๋๋ค. ๋๋ ์ ๊ณตํ๊ณ ์ ํ๋ ํด๋์ค์ ์์ฑ์์ ๋ฌ์์ค์ผ๋ก์ ์ ๊ณต ๋์์ ํ์ธ ํ ์ ์๊ฒ ํด์ค๋๋ค.
๋จผ์ ์์กด์ฑ ๊ด๊ณ๋ฅผ ์ค์ ํ๋ ํด๋์ค๋ฅผ ๋ง๋ค๊ฒ ์ต๋๋ค. Dagger์์๋ ์ด๋ฐ ํด๋์ค๋ฅผ ๋ชจ๋์ด๋ผ๊ณ ๋ถ๋ฅด๊ณ @Module ์ด๋ผ๋ annotation ์ ๋ฌ์ ๋์ต๋๋ค. ๋ชจ๋ ํด๋์ค์์๋ ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ๊ธฐ ์ํ ๋งค์๋๋ค์ ์ ์ํฉ๋๋ค. ์ฐ๋ฆฌ๋ heater ์ pump ์ธํฐํ์ด์ค ๊ตฌํ์ฒด๋ค์ ์ฃผ์ ํ๊ธฐ ์ํ ๋งค์๋๋ฅผ ๊ตฌํํ๊ฒ ์ต๋๋ค. ๊ตฌํ๋ ๋งค์๋์๋ @Provides annotation ์ ์ ์ฉ์ํต๋๋ค.
@Module public class CoffeeMakerModule {
@Provides Heater provideHeater(){
return new A_Heater();
}
@Provides Pump providePump(Heater heater){
return new A_Pump(heater);
}
}
์ฌ๊ธฐ์ ์ ์ฉ๋ @Module ๊ณผ @Provides๋ @Component ํด๋์ค์์ ์ค์ ์ฃผ์ ์ฝ๋๊ฐ ์์ฑ๋ ๋ ์ํฅ์ ์ค๋๋ค. ์ด์ ์ค์ ์ฝ๋๊ฐ generate ๋๋ ์ธํฐํ์ด์ค์ธ component๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค. component ์๋ ์ต์ ํ๊ฐ์ abstract ๋งค์๋๊ฐ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋งค์๋๋ฅผ ํตํด ์ฐ๋ฆฌ๋ ์์กด์ฑ ์ฃผ์ ์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก injection์ ์ํฌ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๊ฑฐ๋(provision method) ๋๋ ๋งด๋ฒ ํ๋ผ๋ฏธํฐ๋ก ์์กด์ฑ ์ฃผ์ ์ ์ํฌ ๊ฐ์ฒด๋ฅผ ๋๊ธฐ๋(Members-injection methods) ๋งค์๋์ฌ์ผ ํฉ๋๋ค.
@Component(modules = CoffeeMakerModule.class)
public interface CoffeeComponent {
//provision method
CoffeeMaker make();
// member-injection method
void inject(CoffeeMaker coffeeMaker);
}
CoffeeComponent ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ provision method ์ member-injection method ๋ ํ๋์ฉ ๊ตฌํํด ๋ณด์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ธํฐํ์ด์ค์ component์์ ์๋ฆฌ๋ @Component annotation์ ๋ฌ์์ฃผ์์ต๋๋ค. @Component ์๋ ์์กด์ฑ ์ฃผ์ ์ ๊ตฌํํ ๋ชจ๋๋ค์ ์๋ ค์ฃผ์ด์ผ ํฉ๋๋ค. annotation์ modules๊ฐ์ ์์์ ๊ตฌํํ CoffeeMakerModule์ ๋๊ฒจ์ค๋๋ค. ์ด์ dagger๋ CoffeeMakerModule ์์ @Provides๋ก ๊ตฌํํ ๋งค์๋๋ค์ ์ด์ฉํด์ ์์กด์ฑ์ ์ฃผ์ ์ํฌ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ์ด์ @Inject ๋ฅผ ํตํด์ ์ด๋์ ์ฃผ์ ํ๋ฉด ๋๋์ง ์๋ ค์ฃผ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
CoffeeComponent ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ provision method ์ member-injection method ๋ ํ๋์ฉ ๊ตฌํํด ๋ณด์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ธํฐํ์ด์ค์ component์์ ์๋ฆฌ๋ @Component annotation์ ๋ฌ์์ฃผ์์ต๋๋ค. @Component ์๋ ์์กด์ฑ ์ฃผ์ ์ ๊ตฌํํ ๋ชจ๋๋ค์ ์๋ ค์ฃผ์ด์ผ ํฉ๋๋ค. annotation์ modules๊ฐ์ ์์์ ๊ตฌํํ CoffeeMakerModule์ ๋๊ฒจ์ค๋๋ค. ์ด์ dagger๋ CoffeeMakerModule ์์ @Provides๋ก ๊ตฌํํ ๋งค์๋๋ค์ ์ด์ฉํด์ ์์กด์ฑ์ ์ฃผ์ ์ํฌ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ์ด์ @Inject ๋ฅผ ํตํด์ ์ด๋์ ์ฃผ์ ํ๋ฉด ๋๋์ง ์๋ ค์ฃผ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
@Inject
public CoffeeMaker(Heater heater, Pump pump){
this.heater = heater;
this.pump = pump;
}
CoffeeMaker์ ์์ฑ์์ @Inject ๋ฅผ ๋ฌ์์ฃผ์์ต๋๋ค. ์ด์ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด๋ ์ผ๋ง ๋จ์์ต๋๋ค. Dagger์์๋ @Component ์ธํฐํ์ด์ค๋ฅผ DaggerYourComponentName ํํ๋ก ๊ตฌํํฉ๋๋ค. ์ฌ๊ธฐ์๋ CoffeeComponent๋ก ํ์ผ๋ DaggerCoffeeComponent๋ก ๊ตฌํ๋์ด ์์ต๋๋ค. Component ๊ฐ์ฒด๋ create() ๋๋ build() ํจ์๋ก ๋ง๋ค์ ์์ต๋๋ค. ์ด์ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด๊ฒ ์ต๋๋ค.
DaggerCoffeeComponent.create().make().brew();
CoffeeComponent์์ ๊ตฌํํ๋ make ํจ์๋ฅผ ์ด์ฉํด์ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด์์ต๋๋ค. ๊ทธ๋ผ inject ํจ์๋ ์ด๋ป๊ฒ ์ฌ์ฉํ ๊น์? CoffeeMaker ํด๋์ค๋ฅผ ๋จผ์ ์กฐ๊ธ ๊ณ ์ณ๋ณด๊ฒ ์ต๋๋ค.
@Inject Heater heater;
@Inject Pump pump;
public CoffeeMaker(){}
์ด์ CoffeeMaker ๊ฐ์ฒด๋ฅผ ์์ฑํด์ inject ํจ์๋ก ๋๊ฒจ ์์กด์ฑ ์ฃผ์ ์ ํด๋ณด๊ฒ ์ต๋๋ค.
CoffeeMaker coffeeMaker = new CoffeeMaker();
DaggerCoffeeComponent.create().inject(coffeeMaker);
coffeeMaker.brew();
์ด๋ ๊ฒ ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์์ต๋๋ค.
Dagger์์๋ ์กฐ๊ธ ๋ ๋ณต์กํ๊ฒ DI๋ฅผ ํ์ฉํ ์ ์๋๋ก ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. Dagger๊ฐ ์ ๊ณตํ๋ ๋ช๊ฐ์ง ๊ธฐ๋ฅ๋ค์ ๋ํ ํค์๋๋ฅผ ์ดํด๋ณด๊ณ ์์ ๋ฅผ ํตํด์ ์ด๋ป๊ฒ ํ์ฉ๋๋์ง ๋ณด๊ฒ ์ต๋๋ค.
Subcomponent : dagger2 ์๋ subcomponent ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. subcomponent๋ ๋ง๊ทธ๋๋ก ๋ถ๋ชจ component๊ฐ ์๋ component๋ผ๊ณ ๋ณด์๋ฉด ๋ฉ๋๋ค. ๋ค๋ง ์ผ๋ฐ component์๋ ๋ฌ๋ฆฌ ์ฝ๋ ์์ฑ์ ๋ถ๋ชจ component์์ ์ด๋ฃจ์ด ์ง๋๋ค. subcomponent๋ component์ ๋ง์ฐฌ๊ฐ์ง๋ก interface๋ abstract class์ @Subcomponent ๋ฅผ ๋ฌ์์ฃผ๋ฉด์ ์์ฑ ํ ์ ์์ต๋๋ค.
Scope : dagger2 ๋ scope ๋ฅผ ์ง์ํฉ๋๋ค. Component ๋ณ๋ก @scope annotation ์ ์ด์ฉํ์ฌ ์ฃผ์ ๋๋ ๊ฐ์ฒด๋ค์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
@Binds : module์์ ์ ๊ณตํ๊ณ ์ ํ๋ ํด๋์ค์ ๊ตฌํ์ฒด(ex interface ๊ตฌํ์ฒด)๋ฅผ ๋ฐ์ธ๋ฉํ๊ณ ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
Multibinding : dagger2 ์์๋ Set ์ด๋ Map ์ ์ด์ฉํ Multibinding ์ ์ง์ํฉ๋๋ค.
์์ ๋ฅผ ํตํด์ ์ข ๋ ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฒ์๋ ์์ CafeApp ์ ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. Cafe๋ CafeInfo ์ CoffeMaker ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
public class CafeInfo {
private String name;
public CafeInfo(){}
public CafeInfo(String name){
this.name = name;
}
public void welcome(){
System.out.println("Welcome " + name == null? "":name );
}
}
public class CoffeeMaker{
private Heater heater;
@Inject public CoffeeMaker(Heater heater){
this.heater = heater;
}
public void brew(CoffeeBean coffeeBean){
System.out.println("CoffeeBeen("+coffeeBean.toString()+") [_]P coffee! [_]P ");
}
}
CafeInfo ์ CoffeeMaker ๋ฅผ ์์ ๊ฐ์ด ๊ตฌ์ฑํด๋ณด์์ต๋๋ค. CafeInfo ๋ ๋จ์ํ ์นดํ์ด๋ฆ์ ๊ฐ์ง๊ณ ์๋ ํด๋์ค์ด๋ฉฐ CoffeeMaker๋ Heater๋ผ๋ ๊ฐ์ฒด๋ก ๊ตฌ์ฑ๋์ด ์๊ณ CoffeeBean์ ๋ฐ์ ์ปคํผ๋ฅผ ๋ด๋ฆด ์ ์๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ( ์ง๋ ํฌ์คํธ ๋ณด๋ค ์ ๊ทธ๋ ์ด๋ ๋์์ต๋๋ค. ๐ )
public class CoffeeBean {
public void name(){
System.out.println("CoffeeBean");
}
}
์! ์ด์ ๊ธฐ๋ณธ์ ์ธ ์ค๋น๋ฅผ ๋ง์ณค์ต๋๋ค.
์ด์ ์ฐ๋ฆฌ๋ Dagger๋ฅผ ์ด์ฉํด ์นดํ์ ์ ๋ณด๋ฅผ ํธ์ถํ๊ณ ์ปคํผ๋ฅผ ๋ด๋ ค๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. CafeApp ์ฌ์ฉ์๋ ๋จ์ํ CafeInfo๋ฅผ ํตํด ์นดํ์ ๋ณด๋ฅผ ๋ณด๊ฑฐ๋ CoffeeMaker.brew ๋ฅผ ํตํด ์ปคํผ๋ฅผ ๋ด๋ฆด์ ์์ผ๋ฉด ๋ฉ๋๋ค. CafeComponent์ ํด๋น ๋ด์ฉ์ ์ ์ํด๋ณด๊ฒ ์ต๋๋ค.
@Component(modules = { CafeModule.class })
public interface CafeComponent {
CafeInfo cafeInfo();
CoffeeMaker coffeeMaker();
}
์ด์ ๊ฐ CafeInfo ์ CoffeeMaker ์ ๋ํ DI ์ค์ ์ ํ๋ CafeModule์ ์ ์ํด๋ณด๊ฒ ์ต๋๋ค.
@Module
public class CafeModule {
@Provides
CafeInfo provideCafeInfo(){
return new CafeInfo();
}
@Provides
CoffeeMaker provideCoffeeMaker(Heater heater){
return new CoffeeMaker(heater);
}
@Provides Heater provideHeater(){
return new Heater();
}
}
์ด๋ ๊ฒ ๊ตฌ์ฑ์ด ๋๋ค๋ฉด ์ง๋ ํฌ์คํธ์์ ํ๋ ๋ด์ฉ๊ณผ ๊ฐ์ต๋๋ค. ์ฌ๊ธฐ์ CafeInfo์ CoffeeMaker์ ์กฐ๊ธ ๋ ํ์ค์ ๋ฐ์ํด๋ณด๊ฒ ์ต๋๋ค. ํ๋์ ์นดํ์ CafeInfo๋ ํ๋๋ฟ์ด๋ฉฐ ๋๊ฐ ๋ณด๋์ง ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค์ผ ํฉ๋๋ค. ์นดํ๊ฐ ๋งํ๊ธฐ ์ ๊น์ง CafeInfo๋ ๋์ผํฉ๋๋ค. ์นดํ๊ฐ ๋งํ๋ฉด CoffeeMaker๋ ์์ด์ง๋๋ค. ํ์ง๋ง ์นดํ๊ฐ ๋งํ์ง ์์๋ CoffeeMaker๋ฅผ ์๋ก ๋ง๋ค๊ฑฐ๋ ๊ต์ฒดํ ์ ์์ต๋๋ค. CoffeeMaker๋ฅผ ๋ง๋ค ๋ ๋ค์ด๊ฐ๋ Heater๋ ๊ฐ์ CoffeeMaker์ ํญ์ ๊ฐ์ Heater๊ฐ ๋ค์ด๊ฐ๋ ๊ฒ์ผ๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๋ Subcomponent์ Scope ๋ฅผ ์ด์ฉํ์ฌ Dagger์์ ๊ฐ์ฒด๋ค์ ์์ ๊ฐ์ด ๊ด๋ฆฌ ํ ์ ์์ต๋๋ค. ๋จผ์ ๊ธฐ๋ณธ์ ์ผ๋ก java์์ ์ ๊ณตํ๋ @Singleton ๊ณผ @CoffeeScope ์ด๋ผ๋ ์ปค์คํ annotation ์ ํ์ฉํ์ฌ ๊ฐ ๊ฐ์ฒด๋ค์ ๋ฒ์๋ฅผ ๊ด๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
Component์ Scope annotation ์ ์ฌ์ฉํ๋ฉด ํด๋น Component์์ ๋ฐ์ธ๋ฉ ๋๋ ๊ฐ์ฒด๋ค์ Component ์ ๊ฐ์ ๋ผ์ดํ์ฌ์ดํด์ ๊ฐ์ง ์ ์๊ฒ ํ ์ ์์ต๋๋ค.
@Singleton @Component(modules = { CafeModule.class })
public interface CafeComponent {
CafeInfo cafeInfo();
CoffeeMaker coffeeMaker();
}
@Module
public class CafeModule {
@Singleton @Provides CafeInfo provideCafeInfo(){
return new CafeInfo();
}
@Provides CoffeeMaker provideCoffeeMaker(Heater heater){
return new CoffeeMaker(heater);
}
@Provides Heater provideHeater(){
return new Heater();
}
}
์์ ๊ฐ์ด Component ์ @Singleton scope ์ ๋ถ์ด๊ณ Module์ CafeInfo๋ฅผ ์ ๊ณตํ๋ ๋ฉ์๋์ @Singleton์ ๋ถ์ด๋ฉด ๊ฐ์ CafeComponent์์ CafeInfo ๊ฐ์ฒด ํธ์ถ์ ๋์ผํ CafeInfo ๊ฐ์ฒด๊ฐ ํธ์ถ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ @Singleton ์ด ์๋ CoffeeMaker๋ฅผ ํธ์ถ์์๋ ๋งค๋ฒ ๋ค๋ฅธ CoffeeMaker๊ฐ ํธ์ถ๋๊ฒ ๋ฉ๋๋ค.
CafeComponent cafeComponent = DaggerCafeComponent.create();
CafeInfo cafeInfo1 = cafeComponent.cafeInfo();
CafeInfo cafeInfo2 = cafeComponent.cafeInfo();
CoffeeMaker coffeeMaker1 = coffeeComponent1.coffeeMaker();
CoffeeMaker coffeeMaker2 = coffeeComponent1.coffeeMaker();
cafeInfo1 ๊ณผ cafeInfo2 ๋ ๋์ผํ ๊ฐ์ฒด๊ฐ ๋์ง๋ง coffeeMaker1 ๊ณผ coffeeMaker2 ๋ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ๋ฉ๋๋ค.
Cafe(CafeComponent)์ CafeInfo ์ Scope ๋ ๋ง์ถ์์ผ๋ ์ด์ CoffeeMaker ์ Heater ์ Scope ์ ๋ง์ถฐ๋ณด๊ฒ ์ต๋๋ค. CoffeeMaker ์ Scope์ ์ ์ํ๊ธฐ ์ํด์ CoffeeMaker๋ฅผ ๊ด๋ฆฌํ๋ CoffeeComponent๋ฅผ ์ ์ํ๊ฒ ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ CoffeeComponent์๋ @CoffeeScope ๋ผ๋ Scope๋ฅผ ์ ์ํด ์ฃผ์์ต๋๋ค. CoffeeComponent์์๋ CoffeeMaker ๋ฅผ ์ป์ ์ ์์ผ๋ฉฐ Scope ๋น๊ต๋ฅผ ์ํด์ CoffeeBean ๋ ์ป์ ์ ์๋๋ก ์ถ๊ฐํด ๋์์ต๋๋ค.
@CoffeeScope @Subcomponent(modules = { CoffeeModule.class })
public interface CoffeeComponent {
CoffeeMaker coffeeMaker();
CoffeeBean coffeeBean();
@Subcomponent.Builder interface Builder{
CoffeeComponent build();
}
}
CoffeeMaker๊ฐ Cafe์์ ์ํด์๊ธฐ ๋๋ฌธ์ Component ๊ด๊ณ ์ญ์ ์์-ํ์ ๊ฐ๋ ์ ์ฃผ์ด์ผ ํฉ๋๋ค.( Cafe ๋ฅผ ํตํ์ง ์๊ณ ์๋ CoffeeMaker์ ์ ๊ทผํ ์ ์๋๋ก encapsulate ํ๊ณ Scope ์ญ์ ๋์ ๋ฒ์์์ ์ข์ ๋ฒ์๋ก ์งํ๋๊ฒ ํ๊ธฐ ์ํด์๋ ์์-ํ์ ๊ฐ๋ ์ ํ์ํฉ๋๋ค. ) ์ด๋ ์ฌ์ฉ๋๋ ๊ฒ์ด Subcomponent ์ ๋๋ค. Subcomponent๋ component ์ ์ฌ์ฉ๋ฐฉ๋ฒ์ด ์ ์ฌํฉ๋๋ค. ๋ค๋ง @Subcomponent.Builder ๋ฅผ ์ ์ํด์ฃผ์ด์ผ ํฉ๋๋ค. @Subcomponent.Builder ์ ํ์ฉ์ ๋ํด์๋ ๋์ค์ ๋ ์ค๋ช ํ๊ฒ ์ผ๋ ์ผ๋จ์ @Subcomponent ๋ Builder ์ธํฐํ์ด์ค๊ฐ ์ ์ ๋์ด์ผ๋ง @Component ์์ ์ฝ๋์์ฑ์ด ๋๋ค๋ผ๊ณ ๋ง ์๊ณ ๋์ด๊ฐ๋๋ก ํฉ์๋ค.
์ ์ํ Subcomponent๋ฅผ Component์ encapsulate ํด์ผํ๋๋ฐ ์ด๋ ๋ชจ๋์ ํตํด์ subcomponent์ component๊ฐ ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค. ์์ CafeComponent ์ CafeModule ์ด ์ ์ฉ๋์ด ์๋๋ฐ์ ์ด๋ ๊ฒ ์์ Component์ ์ ์ฉ๋ ๋ชจ๋์ subcomponent๋ฅผ ์ ์ฉ์ํค๋ฉด component ๋ผ๋ฆฌ ์์-ํ์ ๊ด๊ณ๋ฅผ ๋งบ๊ฒ ๋ฉ๋๋ค. ์ฌ๊ธฐ์๋ CafeModule์ CoffeeComponent๋ฅผ ์ ์ฉ์ํค๊ฒ ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ CafeInfo provider ๋ฉ์๋๋ง ๋จ๊ธฐ๊ณ ๋ชจ๋ ์ญ์ ๋ฅผ ํฉ๋๋ค.(์ด์ ๋ CoffeeComponent์์ Heater ์ CoffeeMaker ๋ฅผ ์ ๊ณตํ๋ฏ๋ก.)
@Module(subcomponents = CoffeeComponent.class)
public class CafeModule {
//....
}
์ด๋ ๊ฒ @Module ์ subcomponents ๋ฅผ ์ ์ฉ ์ํฌ์ ์์ต๋๋ค. ์ด์ ์ด ๋ชจ๋์ ๊ฐ์ง๊ณ ์๋ CafeComponent๊ฐ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋๊ณ CoffeeComponent ๊ฐ ์์ ์ปดํฌ๋ํธ๊ฐ ๋ฉ๋๋ค. @Subcomponent ๋ @Component ๋ฟ๋ง ์๋๋ผ ๊ฐ์ @Subcomponent ๋ผ๋ฆฌ๋ ๊ด๊ณ์ฑ์ ์ค ์ ์์ต๋๋ค.
์ด์ CoffeeComponent ์ ์ ์ฉํ CoffeeModule์ ์ ์ํด๋ณด๊ฒ ์ต๋๋ค.
@Module
public class CoffeeModule {
@CoffeeScope
@Provides
CoffeeMaker provideCoffeeMaker(Heater heater){
return new CoffeeMaker(heater);
}
@CoffeeScope
@Provides
Heater provideHeater(){
return new Heater();
}
@Provides
CoffeeBean provideCoffeeBean(){
return new CoffeeBean();
}
}
CoffeeMaker ์ Heater ์ ๋ํ provider ๋ฉ์๋๋ฅผ ์์ฑํ์๊ณ Heater์ CoffeeMaker์๋ CoffeeComponent ์ ๊ฐ์ ๋ฒ์์ @CoffeeScope ๋ก ์ ์ํ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ CoffeeBean ์ ์ปคํผ๋ฅผ ๋ง๋ค๋๋ง๋ค ์๋ชจ๋๋ ๊ฒ์ด๋ฏ๋ก Scope ๋ฅผ ์ ์ํ์ง ์์์ต๋๋ค. ์ด์ CafeComponent์์ CoffeeComponent๋ฅผ ๋ถ๋ฅผ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ Scope ์ ์ฉ์ด ์ ๋์๋ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
@Singleton @Component(modules = { CafeModule.class })
public interface CafeComponent {
CafeInfo cafeInfo();
CoffeeComponent.Builder coffeeComponent();
}
CafeComponent ์์ CoffeeMaker ๋์ CoffeeComponent.Builder ๋ฅผ ๋ฐ์ ์ ์๊ฒ ๋์์ต๋๋ค. ์ด์ Scope ์ ์ฉ์ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
//Scope
CafeComponent cafeComponent = DaggerCafeComponent.create();
CafeInfo cafeInfo1 = cafeComponent.cafeInfo();
// ๋์ผํ singleton scope ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋ฆฌํด
CafeInfo cafeInfo2 = cafeComponent.cafeInfo();
System.out.println("Singleton scope CafeInfo is equal : " + cafeInfo1.equals(cafeInfo2));
//CoffeeScope
CoffeeComponent coffeeComponent1 = cafeComponent.coffeeComponent().build();
CoffeeComponent coffeeComponent2 = cafeComponent.coffeeComponent().build();
CoffeeMaker coffeeMaker1 = coffeeComponent1.coffeeMaker();
CoffeeMaker coffeeMaker2 = coffeeComponent1.coffeeMaker();
System.out.println("Maker scope / same component coffeeMaker is equal : " + coffeeMaker1.equals(coffeeMaker2));
CoffeeMaker coffeeMaker3 = coffeeComponent2.coffeeMaker();
//MakerScopeMethod
System.out.println("Maker scope / different component coffeeMaker is equal : " + coffeeMaker1.equals(coffeeMaker3));
//Non-scope
CoffeeBean coffeeBean1 = coffeeComponent1.coffeeBean();
CoffeeBean coffeeBean2 = coffeeComponent1.coffeeBean();
System.out.println("Non-scoped coffeebean is equal : " + coffeeBean1.equals(coffeeBean2));
๋งจ ์ ๋ถ๋ถ์ ์ด์ ์ ์ค๋ช ํ์ผ๋ ๋์ด๊ฐ๊ณ CoffeeScope ๋ถ๋ถ ๋ถํฐ ๋ณด๊ฒ ์ต๋๋ค. coffeeComponent1 ์์ coffeeMaker1, coffeeMaker2 ๋ฅผ ๋ง๋ค๊ณ coffeeComponent2 ์์ coffeeMaker3 ์ ๋ง๋ค์์ต๋๋ค. coffeeMaker ๋ provider ๋ฉ์๋๋ฅผ ์ ์ํ ๋ coffeeComponent ์ ๊ฐ์ @CoffeeScope ์ผ๋ก ์ ์ํ๊ธฐ๋๋ฌธ์ coffeeComponent ๋น ํ๊ฐ์ CoffeeMaker ๋ง ์กด์ฌํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ๊ฒฐ๊ณผ๋ coffeeMaker1 = coffeeMaker2 != coffeeMaker3 ์ด ๋ฉ๋๋ค.
์ด์ Non-scope ๋ถ๋ถ์ ํ์ธํ๊ฒ ์ต๋๋ค. CoffeeModule ์์ CoffeeBean provider๋ฉ์๋๋ scope์ค์ ์ ํ์ง ์์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ์ coffeeComponent ์์ CoffeeBean ์ ์์ฑํด๋ ์๋ก ๋ค๋ฅธ CoffeeBean ์ด ๋์ค๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก coffeeBean1 != coffeeBean2 ๊ฐ ๋ฉ๋๋ค.
์ด์ ์์์ ์ง๋์ณค๋ @Component.Builder ๊ณผ @Subcomponent.Builder ๋ฅผ ์ดํด๋ด ์๋ค. Dagger๋ component ๋ฅผ ์์ฑํ ๋ builder pattern์ ์ฌ์ฉํฉ๋๋ค. @Component ์ ๊ฒฝ์ฐ ์ฝ๋๊ฐ generate ๋๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ์ ์ผ๋ก builder ์ญ์ generate ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ @Subcomponent ๋ @Component ํด๋์ค ์์์ ์ฝ๋๊ฐ ์์ฑ๋ ๋ @Subcomponent.Builder ๊ฐ ๋ถ์ interface ๊ฐ ์์ผ๋ฉด builder ๊ฐ ์๋์ผ๋ก ์์ฑ๋์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก @Subcomponent.Builder ๊ฐ ๊ผญ ํ์ํฉ๋๋ค. Builder ์๋ build ํ๊ธฐ ์ ์ ๋ชจ๋์ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ์ ์ ์์ต๋๋ค. ์ด๋ ๋ฉค๋ฒ๋ณ์๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ชจ๋์ด ์์ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์์ ์ ์ํ CafeModule์ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํด๋ด ์๋ค.
@Module(subcomponents = CoffeeComponent.class)
public class CafeModule {
private String name;
public CafeModule(){ }
public CafeModule(String name){
this.name = name;
}
@Singleton
@Provides
CafeInfo cafeInfo(){
if(name == null || name.isEmpty())
return new CafeInfo();
else return new CafeInfo(name);
}
}
์ด์ CafeModule ์ ์์ฑ์์์ ์นดํ ์ด๋ฆ์ ๋ฐ์ ์ ์๊ณ ์ด๊ฒ์ CafeInfo ๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ ํ ์ ์๊ฒ ๋์์ต๋๋ค. ์ด์ CafeComponent ์์ Component Builder๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค.
public interface CafeComponent {
CafeInfo cafeInfo();
CoffeeComponent.Builder coffeeComponent();
@Component.Builder
interface Builder{
Builder cafeModule(CafeModule cafeModule);
CafeComponent build();
}
}
์ด๋ ๊ฒ build ํ๊ธฐ ์ ์ CafeModule ์ ์ ์ฉ ์ํฌ ์ ์๋๋ก ํด๋์์ต๋๋ค.
CafeComponent cafeComponent = DaggerCafeComponent.builder()
.cafeModule(new CafeModule("example cafe"))
.build();
cafeComponent.cafeInfo().welcome();
๊ทธ๋ผ ์ ์ฝ๋ ์ฒ๋ผ CafeComponent ์์ฑ์ ์นดํ์ด๋ฆ์ ์ ์ฉํ ๋ชจ๋์ ๋ฏธ๋ฆฌ bind ์ํฌ ์ ์๊ณ ์ด๋ฅผ ํตํด์ ์นดํ์ด๋ฆ์ ๊ฐ๊ฒ ๋ CafeInfo ๋ฅผ ์ ๊ณต ๋ฐ์์ ์๊ฒ ๋ฉ๋๋ค.
์ง๊ธ๊น์ง Subcomponent ๊ณผ ๊ทธ์ ๊ด๋ จ๋ ๋ด์ฉ์ ๋ํด์ ์์๋ณด์์ต๋๋ค.
์ด์ @Binds, MultiBinding ์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค. @Binds๋ ์ถ์๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์ข ๋ ๊ฐ๋ตํ๊ฒ binding์ ๊ตฌํํ ๋ ์ฌ์ฉํฉ๋๋ค. ์์ ๋ฅผ ํตํด์ ์์๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ CoffeeBean ์ ์์ํ EthiopiaBean ์ ์ ์ํด๋ณด๊ฒ ์ต๋๋ค.
public class EthiopiaBean extends CoffeeBean{
public void name(){
System.out.println("EthiopiaBean");
}
}
๋ง์ฝ ์ด๋ค ๋ชจ๋์์ EthiopiaBean ์ provider ๋ฉ์๋๋ฅผ ์ ๊ณตํ๊ณ ์๊ฑฐ๋ EthiopiaBean ์ด @Inject ๋ฅผ ํตํด Injectable ํ ๊ฒ์ผ๋ก ์ ์ ๋์ด ์๋ค๋ฉด
@Binds
abstract CoffeeBean provideCoffeeBean(EthiopiaBean ethiopiaBean);
์ด๋ ๊ฒ ์ถ์๋ฉ์๋๋ก ์ ์ํ๋ ๊ฒ๋ง์ผ๋ก CoffeeBean ๊ฐ์ฒด๋ฅผ ์ ๊ณต๋ฐ์ ์ ์์ต๋๋ค. ์ด์ MultiBinding ์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค. Dagger ๋ ํ ๊ฐ์ฒด๊ฐ ์ฌ๋ฌ๊ฐ์ง ํํ๋ก binding ๊ฐ๋ฅ ํ ๋ Set ์ด๋ Map์ ์ด์ฉํด์ MultiBinding ์ด ๊ฐ๋ฅํฉ๋๋ค. ์์ ๋ฅผ ๋ณด๋ฉฐ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฒ์๋ CoffeeBean ์ ์์๋ฐ์ GuatemalaBean ์ ํ๋ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
public class GuatemalaBean extends CoffeeBean {
public void name(){
System.out.println("GuatemalaBean");
}
}
๊ทธ๋ฆฌ๊ณ GuatemalaBean ๋ EthiopiaBean ์ฒ๋ผ CoffeeBean ์ผ๋ก ๋ฐ์ธ๋ฉ ์ํค๋ ค๊ณ ํ๋ฉด CoffeeBean ๊ฐ์ฒด ์ ๊ณต์ ํผ๋์ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค. ์ด๋ MultiBinding ์ ์ด์ฉํ์ฌ ํน์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉ ์ํฌ ์ ์์ต๋๋ค.
@Binds
@IntoMap
@StringKey("ethiopia")
abstract CoffeeBean provideEthiopiaBean(EthiopiaBean ethiopiaBean);
@Binds
@IntoMap
@StringKey("guatemala")
abstract CoffeeBean provideGuatemalaBean(GuatemalaBean guatemalaBean);
// EthiopiaBean ์ฒ๋ผ @Provide method ๋ฅผ ์ ๊ณตํ์ง ์์๋ @Inject annotation์ ์ด์ฉํด Injectable ํ ๊ฐ์ฒด๋ก ์ ์ํด๋ bind ๊ฐ๋ฅ.
@IntoMap ๊ณผ @StringKey ๋ฅผ ์ด์ฉํ์ฌ Map ํํ๋ก MultiBinding ํ ์ฝ๋์ ๋๋ค. Map์ผ๋ก MultiBinding ๋ ๊ฒ์ Map<key,object> ํํ๋ก ์ ๊ณต๋ฉ๋๋ค.
Map<String,CoffeeBean> coffeeBeanMap(); // in CoffeeComponent
CoffeeComponent coffeeComponent = DaggerCafeComponent.create().coffeeComponent().build();
coffeeComponent.coffeeBeanMap().get("guatemala").name();
์์ ๊ฐ์ด ํ์ฉ ๋ ์ ์์ต๋๋ค.
๋ง์น๋ฉฐ
์ด๋ฒ ํฌ์คํธ์์๋ ๊ฐ๋จํ DI์์ ๋ก DI์ ๋ํด์ ์ดํด๋ณด์๊ณ cafe์์ ๋ฅผ ๋ง๋ค์ด๋ณด๋ฉด์ DI๋ฅผ ํ์ฉํ์ ๋ ์ด๋ค ์ฅ์ ๋ค์ด ์๋์ง, DI tool ๋ค์ ์ด๋ฐ ์ฅ์ ์ ์ฝ๊ฒ ์ ์ฉ์ํค๊ธฐ ์ํด ์ด๋ค ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํ๋์ง dagger ๋ฅผ ํ์ฉํ์ฌ ์ดํด๋ณด์์ต๋๋ค. DI์ ๋ํด์ ์ดํดํ๊ณ ์ ํ์๋ ๋ถ๋ค๊ป ์กฐ๊ธ์ด๋๋ง ๋์์ด ๋์์ผ๋ฉด ํฉ๋๋ค.
์ ํฌ ๋ชจ๋ฐ์ผํ์์๋ Android์ ๊ฒฝ์ฐ Hilt, iOS์ ๊ฒฝ์ฐ Swinject์ ํตํด DI๋ฅผ ๊ตฌํํ๊ณ ์์ต๋๋ค. ๋ค์ Part2. ํฌ์คํธ์์๋ ๊ฐ ํ๋ซํผ ๋ณ๋ก ๋ค์ํ ์ํฉ์์์ DI๋ฅผ ์ด๋ป๊ฒ ์ ์ฉํ๋์ง, ๋ชจ๋ฐ์ผํ์์ DI๋ฅผ ์ ์ฉํ๋ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ๊ณผ Hilt, Swinject๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ๋์ง์ ๋ํด ์๊ฐํ๋๋ก ํ๊ฒ ์ต๋๋ค.