๐ง ๋ค์ด๊ฐ๊ธฐ ์ ...
๋ง์ ํด๋์ค๋ ํ๋ ์ด์์ ๊ธฐ๋ณธ ์์์ ์์กดํ๋ค.
๊ฐ์ฒด ์งํฅ ์ธ์ด์์๋ ๊ฐ๊ฐ์ ๊ฐ์ฒด๋ค์ด ์๋ก๋ฅผ ํ์๋ก ํ๋ฉฐ, ๋น์ฆ๋์ค ๋ก์ง์ ์ํํด๋๊ฐ๋ค.
๊ฐ์ฒด๋ ์๋ก์ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ๊ตํํ๋ฉด์ ํ๋ ฅํ๋ฉฐ,
์ด๋ฌํ ์ํธ์์ฉ์ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฃผ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.
์ด ๊ณผ์ ์์ ํ๋์ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์์กดํ๋ ๊ตฌ์กฐ๋ ์์ฐ์ค๋ฝ๊ฒ ๋ํ๋์ง๋ง,
์๋ชป๋ ์ค๊ณ ๋ฐฉ์์ผ๋ก ์ธํด ์ฝ๋์ ์ ์ฐ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ด ์ ํ๋ ์ํ์ด ์๋ค.
๋จ์ํ new ์์ฑ์๋ฅผ ํตํด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ ์๋ชป๋ ๋ฐฉ์์ผ๊น?
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๋ฐฉ์์ผ๋ก ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผํ๊ณ , ์ด๋ป๊ฒ ์์กด์ฑ์ ๊ด๋ฆฌํด์ผ ์ฌ๋ฐ๋ฅธ ์ค๊ณ๋ฅผ ํ ์ ์์๊น?
โ ๊ธฐ์กด์ ๋ฌธ์ ์
1๏ธโฃ ์ ์ ์ ํธ๋ฆฌํฐ ํด๋์ค์ ๋ถ์ ์ ํ ์ฌ์ฉ
public class SpellChecker {
private static final Lexicon dictionary = new Lexicon();
// ์ธ์คํด์คํ ๋ถ๊ฐ
private SpellChecker() {
throw new AssertionError();
}
public static boolean isValid(String word) {
return false;
}
public static List<String> suggestions(String type){
return null;
}
}
์ ์ ์ ํธ๋ฆฌํฐ ํด๋์ค:
ํด๋์ค์ ๋ฉ์๋๋ฅผ ๋ชจ๋ static์ผ๋ก ๋ง๋ค์ด ํ ๋ฒ ์ ์๋ ์์(์: ์ฌ์ )์ ๋ฐ๊ฟ ์ ์๊ฒ ๋๋ค.
์ฆ, ํญ์ ๊ณ ์ ๋ ์์์ ์ฌ์ฉํ๊ฒ ๋๋ฏ๋ก, ๋ค๋ฅธ ์ธ์ด์ ์ฌ์ ์ด๋ ํ ์คํธ์ฉ ์ฌ์ ๊ฐ์ ๋ค์ํ ์์์ ์ฌ์ฉํ ์ ์๋ค.
2๏ธโฃ ์ฑ๊ธํค์ ๋ถ์ ์ ํ ์ฌ์ฉ
public class SpellChecker {
private final Lexicon dictionary = new Lexicon();
public static SpellChecker2 INSTANCE = new SpellChecker2();
// ์ธ์คํด์คํ ๋ถ๊ฐ
private SpellChecker2() {
throw new AssertionError();
}
public boolean isValid(String word) {
return false;
}
public List<String> suggestions(String type){
return null;
}
public static void main(String[] args) {
SpellChecker2 spellChecker2 = SpellChecker2.INSTANCE;
spellChecker2.isValid("test");
}
}
์ฑ๊ธํค ํจํด:
์์(์: ์ฌ์ )์ ํ๋์ ๊ณ ์ ๋ ๊ฐ์ฒด๋ก ๋ง๋ค์ด ํด๋์ค ์ ์ฒด์์ ๊ณต์ ํ๋๋ก ๊ฐ์ ํ๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋ฌ ๊ฐ์ ์์์ ์ฌ์ฉํ๋ ๋ค์ํ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๊ฒ ๋๋ค.
์์์ ๋ค๋ฃจ๋ ๋ ๋ฐฉ์์ด ์ ์ ํ์ง ์์ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ ์ฐ์ฑ ๋ถ์กฑ
์ ์ ์ ํธ๋ฆฌํฐ ํด๋์ค์ ์ฑ๊ธํค ํด๋์ค์์ ์ฌ์ฉํ๋ ์ฌ์ Lexicon์ด ํ๋์ ์ธ์คํด์ค๋ก ์ ํ๋๋ค.
ํ์ง๋ง, ์ฌ์ ํน์ฑ์ ์ฌ๋ฌ ๊ตฐ๋ฐ์์ ์ ์ฝ๊ฒ ์ ๊ทผ ๊ฐ๋ฅํด์ผํ๋ฏ๋ก ์์ ๊ฐ์ ๋ฐฉ์์ ์ ์ฐ์ฑ์ ๋จ์ด๋จ๋ฆฐ๋ค. - ํ
์คํธ ์ด๋ ค์
์ธ์ด๋ณ, ์ฉ๋๋ณ๋ก ๋ค๋ฅธ ์์์ด ํ์ํ๊ฑฐ๋ ํ ์คํธ ์ ํน์ ์์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ ํฉํ์ง ์๋ค. - ํ์ฅ์ฑ ์ ํ
๋์์ ๋งค๊ฐ๋ณ์ํํ๊ธฐ ์ด๋ ต๊ณ , ๋์์ฑ ํ๊ฒฝ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๋ค.
๐ฉNOTE
ํด๋์ค์ ๋์์ด ํน์ ์์(์: ์ฌ์ , ๋ฐ์ดํฐ๋ฒ ์ด์ค, ์ค์ ํ์ผ ๋ฑ)์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ๊ฒฝ์ฐ,
์ ์ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ ์ฑ๊ธํค ํจํด์ ์ฌ์ฉํ๋ฉด ์ ์ฐ์ฑ์ด ๋ถ์กฑํด์ง๊ณ ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
โ ์์กด์ฑ ์ฃผ์ ์ ์ฌ์ฉํ๋ผ
์์กด์ฑ ๊ด๋ฆฌ๊ฐ ๋ณต์กํด์ง์๋ก ๊ฐ์ฒด ๊ฐ ๊ฒฐํฉ๋๊ฐ ๋์์ง๊ณ ํ ์คํธ๊ฐ ์ด๋ ค์์ง ์ ์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ์์กด์ฑ ์ฃผ์ (Dependency Injection) ์ด๋ค.
์์กด์ฑ ์ฃผ์ ์ ๊ฐ์ฒด๊ฐ ์ง์ ํ์ํ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๋์ , ์ธ๋ถ์์ ์ฃผ์ ๋ฐ๋๋ก ์ค๊ณํ๋ ๋ฐฉ์์ผ๋ก,
๊ฐ์ฒด ๊ฐ์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ์ค๊ณ์ ์ ์ฐ์ฑ๊ณผ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ํฌ๊ฒ ํฅ์์ํจ๋ค.
1๏ธโฃ ์์กด์ฑ ์ฃผ์ ๊ตฌํ
public class SpellChecker {
private final Lexicon dictionary;
// ์์กด์ฑ ์ฃผ์
public SpellChecker3(Lexicon dictionary) {
this.dictionary = dictionary;
}
public boolean isValid(String word) {
System.out.println("call is Valid");
return false;
}
public List<String> suggestions(String type){
System.out.println("call suggestions");
return null;
}
}
์์กด์ฑ ์ฃผ์ ์ ์์ ๊ฐ์ด ์์ฑ์์ ๊ฐ์ฒด๋ฅผ "์ฃผ์ "ํจ์ผ๋ก์จ ๊ฐ์ฒด๊ฐ์ ์์กด์ฑ์ ์๊ธฐ๊ฒ ํ๋ค.
์ด๋ ์ธ๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ๋ค๊ณ ํํํ๋๋ฐ ์ ๊ทธ๋ด๊น?
public class Main {
public static void main(String[] args) {
Lexicon dictionary = new Lexicon();
SpellChecker spellChecker = new SpellChecker(dictionary); // ์ธ๋ถ์์ ์ฃผ์
spellChecker.isValid("hello");
}
}
์ธ๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ๋ค๊ณ ํํํ๋ ์ด์ ๋,
๊ฐ์ฒด๊ฐ ์์ ์ด ์ง์ ์์กด์ฑ์ ์์ฑํ๊ฑฐ๋ ๊ด๋ฆฌํ์ง ์๊ณ ์ธ๋ถ์ ๋ค๋ฅธ ์ฃผ์ฒด๊ฐ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๋ ๊ฐ์ฒด๊ฐ ์์ ์ ์ฑ ์์ ๋ช ํํ ํ๊ณ ์์กด์ฑ ์์ฑ๊ณผ ๊ฐ์ ๋ถ๊ฐ์ ์ธ ์์ ์์ ๋ฒ์ด๋ ์์ ์ ์ญํ ์๋ง ์ง์คํ๊ฒ ํ๋ค.
๐ฉ ์ธ๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ฃผ์ ๋ฐ๋ ์ค๊ณ๋ ์ฑ ์์ ๋ถ๋ฆฌ๋ฅผ ํตํด ์ฝ๋์ ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์ด๋ ๋ฐ ๊ธฐ์ฌํ๋ค.
2๏ธโฃ ์์ ํฉํ ๋ฆฌ๋ฅผ ํ์ฉํ ์์กด์ฑ ์ฃผ์
public class SpellChecker {
private final Lexicon dictionary;
// ์์กด์ฑ ์ฃผ์
(์์ ํฉํ ๋ฆฌ ํ์ฉ)
public SpellChecker(Supplier<? extends Lexicon> dictionaryFactory) {
this.dictionary = Objects.requireNonNull(dictionaryFactory.get());
}
public boolean isValid(String word) {
System.out.println("call isValid");
return false;
}
public List<String> suggestions(String type) {
System.out.println("call suggestions");
return null;
}
}
์์กด์ฑ ์ฃผ์ ์ ๋ณํ๋ ํจํด ์ค ํ๋๋ ์์ ํฉํ ๋ฆฌ(Resource Factory)๋ฅผ ์์ฑ์์ ์ ๋ฌํ๋ ๋ฐฉ์์ด๋ค.
์์ ํฉํ ๋ฆฌ: ํน์ ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์์ฑํ๊ฑฐ๋ ์ ๊ณตํ ์ ์๋ ์ญํ ์ ๋ด๋นํ๋ค.
ํด๋น ์ฝ๋์์์ ํน์ดํ ์ ์ Supplier<T> ์ ์ฌ์ฉ์ด๋ค.
Supplier<T>๋ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ง ์๊ณ ๊ฐ์ ๋ฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
์ด ์ธํฐํ์ด์ค๋ ์ฃผ๋ก ๊ฐ์ฒด๋ฅผ ์ง์ฐ ์์ฑํ๊ฑฐ๋ ๋์ ์ผ๋ก ์ ๊ณตํ ๋ ์ฌ์ฉ๋๋ค.
Supplier<Car> carFactory = Car::new;
Car car = carFactory.get(); // ์๋ก์ด Car ๊ฐ์ฒด ์์ฑ
๋ฐ๋ผ์ ์์ ๊ฐ์ ์ฝ๋์ฒ๋ผ ์ฝ๊ฒ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ๊ตฌํํ ์ ์๋ค.
์ด๋ฌํ ํน์ง์ ๊ฐ์ฒด ์์ฑ ๋ก์ง์ ์บก์ํํ๋ฉด ์ฝ๋ ์ค๋ณต์ ์ค์ด๊ณ , ์ ์ง๋ณด์์ฑ์ ๋์ผ ์ ์๋ค.
3๏ธโฃ ๋๊ท๋ชจ ํ๋ก์ ํธ์์์ ์์กด์ฑ ์ฃผ์
์์กด์ฑ ์ฃผ์ ์ ๊ฐ์ฒด ๊ฐ์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ์ ์ฐ์ฑ๊ณผ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ํฌ๊ฒ ํฅ์์ํค๋ ์ค๊ณ ๋ฐฉ์์ด๋ค.
ํ์ง๋ง, ๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ ์ด๋ก ์ธํด ์๋ก์ด ๋์ ๊ณผ์ ์ ๋ณต์ก์ฑ์ด ๋ฐ์ํ ์ ์๋ค.
๐ฉ ๋๊ท๋ชจ ํ๋ก์ ํธ์์์ ๋ฌธ์ ์
๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฒ ๊ฐ์ ํด๋์ค์ ๊ฐ์ฒด๋ค๋ก ๊ตฌ์ฑ๋๋ฉฐ, ์ด๋ค ๊ฐ์ ์์กด ๊ด๊ณ๋ ๋งค์ฐ ๋ณต์กํ ์ ์๋ค.
์ด๋ฌํ ์ํฉ์์ ์๋์ผ๋ก ์์กด์ฑ์ ๊ด๋ฆฌํ๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ด๋ํ ์ ์๋ค
- ์ฝ๋์ ๊ฐ๋
์ฑ ์ ํ
- ์์กด์ฑ์ ์ง์ ์์ฑ์๋ ํฉํ ๋ฆฌ๋ก ๊ด๋ฆฌํ๋ค ๋ณด๋ฉด ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง๊ณ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์์ง๋ค.
- ์ ์ง๋ณด์์ ์ด๋ ค์
- ์๋ก์ด ์์กด์ฑ์ ์ถ๊ฐํ๊ฑฐ๋ ๊ธฐ์กด ์์กด์ฑ์ ๋ณ๊ฒฝํ ๋, ๊ด๋ จ๋ ์ฝ๋ ์ ๋ฐ์ ์์ ํด์ผ ํ ์ ์๋ค.
๐ง ํด๊ฒฐ ๋ฐฉ์ : ์์กด์ฑ ์ฃผ์ ํ๋ ์์ํฌ
์์กด์ฑ ์ฃผ์ ํ๋ ์์ํฌ๋ ๊ฐ์ฒด ๊ฐ ์์กด์ฑ์ ์๋์ผ๋ก ์ค์ ํ๊ณ ๊ด๋ฆฌํ๋ ๋๊ตฌ์ด๋ค.
์ด๋ฌํ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ์์กด ๊ด๊ณ๋ฅผ ๋จ์ํํ๊ณ , ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์ผ ์ ์๋ค.
๋ํ์ ์ธ ์์กด์ฑ ์ฃผ์ ํ๋ ์์ํฌ
- Dagger
- ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ ๊ฒฝ๋ DI ํ๋ ์์ํฌ.
- ์ ์ ์ปดํ์ผ ํ์์ ์์กด์ฑ์ ํ์ธํ๊ณ ์์ฑํ๋ฏ๋ก ๋ฐํ์ ์ค๋ฒํค๋๊ฐ ์ ์.
- Android ๊ฐ๋ฐ์ ์์ฃผ ์ฌ์ฉ.
- Guice
- ๊ตฌ๊ธ์ด ๊ฐ๋ฐํ Java ๊ธฐ๋ฐ DI ํ๋ ์์ํฌ.
- ๋ฐํ์์ ์์กด์ฑ์ ์ฃผ์ ํ๋ฉฐ, ๊ฐ๋จํ ์ค์ ๊ณผ ๊ฐ๋ ฅํ ํ์ฅ์ฑ์ ์ ๊ณต.
- Java ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋๋ฆฌ ์ฌ์ฉ.
- Spring
- ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ DI ํ๋ ์์ํฌ๋ก, Java์ ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ํ์ค์ผ๋ก ์๋ฆฌ ์ก์.
- DI๋ฟ๋ง ์๋๋ผ ์น ์ ํ๋ฆฌ์ผ์ด์ , ๋ฐ์ดํฐ๋ฒ ์ด์ค, ๋ฉ์์ง ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณต.
๐ข REF
์ดํฉํฐ๋ธ ์๋ฐ 3/E