์น ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ์ฑ๊ธํค
๋๋ถ๋ถ์ ์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ค.
์น ์ ํ๋ฆฌ์ผ์ด์
์ ๋ณดํต ์ฌ๋ฌ ๊ณ ๊ฐ์ด ๋์์ ์์ฒญ์ ํ๋ค.
@Test
@DisplayName("์คํ๋ง ์๋ ์์ํ DI ์ปจํ
์ด๋")
void pureContainer() {
AppConfig appConfig = new AppConfig();
// 1. ์กฐํ : ํธ์ถํ ๋ ๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑ
MemberService memberService1 = appConfig.memberService();
// 2. ์กฐํ : ํธ์ถํ ๋ ๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑ
MemberService memberService2 = appConfig.memberService();
AppConfig๋ ์์ฒญ์ ํ ๋ ๋ง๋ค ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ค.
// ์ฐธ์กฐ๊ฐ์ด ๋ค๋ฅธ ๊ฒ์ ํ์ธ
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
//memberService1 != memberService2
assertThat(memberService1).isNotSameAs(memberService2);
๊ณ ๊ฐ ํธ๋ํฝ์ด ์ด๋น 100์ด ๋์ค๋ฉด ์ด๋น 100๊ฐ ์ด์์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ ์๋ฉธ๋๋ค! ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ์ฌํ๋ค.
ํด๊ฒฐ๋ฐฉ์์ ํด๋น ๊ฐ์ฒด๊ฐ ๋ฑ 1๊ฐ๋ง ์์ฑ๋๊ณ , ๊ณต์ ํ๋๋ก ์ค๊ณํ๋ฉด ๋๋ค. ์ฑ๊ธํค ํจํด
์ฑ๊ธํค ํจํด
ํด๋์ค์ ์ธ์คํด์ค๊ฐ ๋ฑ 1๊ฐ๋ง ์์ฑ๋๋ ๊ฒ์ ๋ณด์ฅํ๋ ๋์์ธ ํจํด์ด๋ค.
๊ทธ๋์ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ 2๊ฐ ์ด์ ์์ฑํ์ง ๋ชปํ๋๋ก ๋ง์์ผ ํ๋ค.
public class SingletonService {
private static final SingletonService instance = new SingletonService();
}
static : ์ ์ ๋ณ์๋ ๋ชจ๋ ์ธ์คํด์ค๊ฐ ํ๋์ ์ ์ฅ๊ณต๊ฐ์ ๊ณต์ ํ๊ธฐ์ ํญ์ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ค
private ์์ฑ์๋ฅผ ์ฌ์ฉํด์ ์ธ๋ถ์์ ์์๋ก new ํค์๋๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋๋ก ๋ง์์ผ ํ๋ค.
static ๋ณ์
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ HouseLee ํด๋์ค๊ฐ ์๋ค๊ณ ํ์.
class HouseLee {
String lastname = "์ด";
}
public class Sample {
public static void main(String[] args) {
HouseLee lee1 = new HouseLee();
HouseLee lee2 = new HouseLee();
}
}
์์ ๊ฐ์ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด ๊ฐ์ฒด๋ง๋ค ๊ฐ์ฒด๋ณ์ lastname์ ์ ์ฅํ๊ธฐ ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ณ๋๋ก ํ ๋น๋๋ค.
ํ์ง๋ง ๊ฐ๋งํ ์๊ฐํด ๋ณด๋ฉด HouseLee ํด๋์ค์ lastname์ ์ด๋ค ๊ฐ์ฒด์ด๋์ง ๋์ผํ ๊ฐ์ธ "์ด" ์ด์ด์ผ ํ ๊ฒ ๊ฐ์ง ์์๊ฐ?
์ด๋ ๊ฒ ํญ์ ๊ฐ์ด ๋ณํ์ง ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด static ์ฌ์ฉ์ ๋ฉ๋ชจ๋ฆฌ์ ์ด์ ์ ์ป์ ์ ์๋ค.
class HouseLee {
static String lastname = "์ด";
}
lastname ๋ณ์์ static ํค์๋๋ฅผ ๋ถ์ด๋ฉด ์๋ฐ๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ๋ฑ ํ๋ฒ๋ง ํ๊ฒ ๋์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ด์ ์ด ์๋ค.
static์ ์ฌ์ฉํ๋ ๋ ํ๊ฐ์ง ์ด์ ๋ก ๊ณต์ ๊ฐ๋ ์ ๋ค ์ ์๋ค.
static ์ผ๋ก ์ค์ ํ๋ฉด ๊ฐ์ ๊ณณ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง์ ๋ฐ๋ผ๋ณด๊ธฐ ๋๋ฌธ์ static ๋ณ์์ ๊ฐ์ ๊ณต์ ํ๊ฒ ๋๋ ๊ฒ์ด๋ค.
private static final SingletonService instance = new SingletonService();
1. static ์์ญ์ ๊ฐ์ฒด instance๋ฅผ ๋ฏธ๋ฆฌ ํ๋ ์์ฑํด์ ์ฌ๋ ค๋๋ค.
์ธ๋ถ์์๋ ์์ฑํด ๋์๊ฒ์ ๊ฐ์ ธ๋ค ์ฐ๋๊ฒ์ด๋ค ( getInstance() )
์ฐธ๊ณ : ์ฑ๊ธํค ํจํด์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค. ์ฌ๊ธฐ์๋ ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด๋๋ ๊ฐ์ฅ ๋จ์ํ๊ณ ์์ ํ ๋ฐฉ๋ฒ์ ์ ํํ๋ค.
public static SingletonService getInstance() {
return instance;
2. ์ด ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ํ์ํ๋ฉด ์ค์ง getInstance() ๋ฉ์๋๋ฅผ ํตํด์๋ง ์กฐํํ ์ ์๋ค.
์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ํญ์ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ค. (static)
void singletonServiceTest() {
new SingletonService();
}
3. ๋ฑ 1๊ฐ์ ๊ฐ์ฒด ์ธ์คํด์ค๋ง ์กด์ฌํด์ผ ํ๋ฏ๋ก, ์์ฑ์๋ฅผ private์ผ๋ก ๋ง์์
ํน์๋ผ๋ ์ธ๋ถ์์ new ํค์๋๋ก ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ง๋๋ค.
์ฑ๊ธํค ํจํด์ ์ฌ์ฉํ๋ ํ ์คํธ ์ฝ๋๋ฅผ ๋ณด์.
@Test
@DisplayName("์ฑ๊ธํค ํจํด์ ์ ์ฉํ ๊ฐ์ฒด ์ฌ์ฉ")
void singletonServiceTest() {
SingletonService singletonService1 = SingletonService.getInstance();
SingletonService singletonService2 = SingletonService.getInstance();
getInstance() ๋ฉ์๋๋ฅผ ํตํด์ ์กฐํ
//์ฐธ์กฐ๊ฐ ํ์ธ
System.out.println("singletonService1 = " + singletonService1);
System.out.println("singletonService2 = " + singletonService2);
assertThat(singletonService1).isSameAs(singletonService2);
isSameAs : ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋์ง ๋น๊ต (์ฃผ์ ๋น๊ต)
isEqualTo : ๊ฐ์ฒด๊ฐ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ณ ์๋์ง ๋น๊ตํ๋ค.
ํธ์ถํ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋์ง ํ์ธ ํด๋ณด์ .
์ฐธ์กฐ๊ฐ์ ํ์ธํ์ฌ ๋น๊ตํ๋ค .
์ฐธ์กฐ๊ฐ์ด ๊ฐ๋ค.
๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๋๋ค .
์ด๋ฏธ ์์ฑํด ๋์๊ฒ์ ๊ฐ์ ธ๋ค ์ฐ๋๊ฒ์ด๋ค .
์ฑ๊ธํค ํจํด ๋ฌธ์ ์
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {
}
- ์ฑ๊ธํค ํจํด์ ๊ตฌํํ๋ ์ฝ๋ ์์ฒด๊ฐ ๋ง์ด ๋ค์ด๊ฐ๋ค.
- ์์กด๊ด๊ณ์ ํด๋ผ์ด์ธํธ๊ฐ ๊ตฌ์ฒด ํด๋์ค์ ์์กดํ๋ค. DIP๋ฅผ ์๋ฐํ๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ ๊ตฌ์ฒด ํด๋์ค์ ์์กดํด์ OCP ์์น์ ์๋ฐํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค. ํ ์คํธํ๊ธฐ ์ด๋ ต๋ค.
- private ์์ฑ์๋ก ์์ ํด๋์ค๋ฅผ ๋ง๋ค๊ธฐ ์ด๋ ต๋ค.
- ๊ฒฐ๋ก ์ ์ผ๋ก ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ค.
- ์ํฐํจํด์ผ๋ก ๋ถ๋ฆฌ๊ธฐ๋ ํ๋ค.
- ๋ด๋ถ ์์ฑ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ด๊ธฐํ ํ๊ธฐ ์ด๋ ต๋ค.
์คํ๋ง ํ๋ ์์ํฌ(์ฑ๊ธํค ์ปจํ ์ด๋)๋ ์ด ์ฑ๊ธํค ํจํด์ ๋ฌธ์ ์ ์ ์ ๋ถ๋ค ํด๊ฒฐํ๊ณ ๊ด๋ฆฌํด์ค๋ค .
์ฑ๊ธํค ์ปจํ ์ด๋
์คํ๋ง ์ปจํ
์ด๋๋ ์ฑ๊ธํค ํจํด์ ๋ฌธ์ ์ ์ ํด๊ฒฐํ๋ฉด์, ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ฑ๊ธํค(1๊ฐ๋ง ์์ฑ)์ผ๋ก ๊ด๋ฆฌํ๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํด ํจํด์ ์ ์ฉํ์ง ์์๋, ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๋ค.
์ด์ ์ ์ค๋ช
ํ ์ปจํ
์ด๋ ์์ฑ ๊ณผ์ ์ ์์ธํ ๋ณด์.
์ปจํ ์ด๋๋ ๊ฐ์ฒด๋ฅผ ํ๋๋ง ์์ฑํด์ ๊ด๋ฆฌํ๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํค ์ปจํ ์ด๋ ์ญํ ์ ํ๋ค. ์ด๋ ๊ฒ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ฑ๊ธํค ๋ ์ง์คํธ๋ฆฌ๋ผ ํ๋ค.
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {
}
์ฑ๊ธํค ํจํด์ ์ํ ์ด๋ฐ ์ง์ ๋ถํ ์ฝ๋๊ฐ ๋ค์ด๊ฐ์ง ์์๋ ๋๋ค.
DIP, OCP, ํ ์คํธ, private ์์ฑ์๋ก ๋ถํฐ ์์ ๋กญ๊ฒ ์ฑ๊ธํค์ ์ฌ์ฉํ ์ ์๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ ํ ์คํธ ์ฝ๋
@Test
@DisplayName("์คํ๋ง ์ปจํ
์ด๋์ ์ฑ๊ธํค")
void springContainer() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig ์ค์ ํ์ผ์ ๊ตฌ์ฑ์ ๋ณด๋ก ์ฌ์ฉํ๋ ์ปจํ ์ด๋ ์์ฑ
MemberService memberService1 = ac.getBean("memberService",MemberService.class);
MemberService memberService2 = ac.getBean("memberService",MemberService.class);
ํธ์ถํ ๋ ๋ง๋ค ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํ
์คํ๋ง์ด ์ปจํ ์ด๋์์ ์ฒ์์ ๋ฑ๋กํ ๋น์ ๋ฐํํด์ฃผ๋ ๊ฒ์ด๋ค ( ์ฑ๊ธํค )
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
//memberService1 == memberService2
assertThat(memberService1).isSameAs(memberService2);
์ฐธ์กฐ ๊ฐ์ด ๊ฐ์ ๊ฒ์ ํ์ธ
์ฑ๊ธํค ์ปจํ ์ด๋ ์ ์ฉ ํ
์คํ๋ง ์ปจํ ์ด๋ ๋๋ถ์ ๊ณ ๊ฐ์ ์์ฒญ์ด ์ฌ ๋ ๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ,
์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ๊ณต์ ํด์ ํจ์จ์ ์ผ๋ก ์ฌ์ฌ์ฉํ ์ ์๋ค.
์ฐธ๊ณ : ์คํ๋ง์ ๊ธฐ๋ณธ ๋น ๋ฑ๋ก ๋ฐฉ์์ ์ฑ๊ธํค์ด์ง๋ง, ์ฑ๊ธํค ๋ฐฉ์๋ง ์ง์ํ๋ ๊ฒ์ ์๋๋ค.
์์ฒญํ ๋ ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๋ฐํํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค. ์์ธํ ๋ด์ฉ์ ๋ค์ ๋น ์ค์ฝํ์์ ์ค๋ช ํ๊ฒ ๋ค.
์ฑ๊ธํค ๋ฐฉ์์ ์ฃผ์์
์ฑ๊ธํค ํจํด์ด๋ , ์คํ๋ง ๊ฐ์ ์ฑ๊ธํค ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ , ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ํ๋๋ง ์์ฑํด์ ๊ณต์ ํ๋ ์ฑ๊ธํค ๋ฐฉ์์
์ฌ๋ฌ ํด๋ผ์ด์ธํธ๊ฐ ํ๋์ ๊ฐ์ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค ๊ฐ์ฒด๋ ์ํ๋ฅผ ์ ์ง(stateful)ํ๊ฒ ์ค๊ณํ๋ฉด ์๋๋ค.
๋ฌด์ํ(stateless)๋ก ์ค๊ณํด์ผ ํ๋ค!
ํน์ ํด๋ผ์ด์ธํธ์ ์์กด์ ์ธ ํ๋๊ฐ ์์ผ๋ฉด ์๋๋ค.
ํน์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ ํ๋๊ฐ ์์ผ๋ฉด ์๋๋ค!
๊ฐ๊ธ์ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํด์ผ ํ๋ค. ( ์์ X)
ํ๋ ๋์ ์ ์๋ฐ์์ ๊ณต์ ๋์ง ์๋, ์ง์ญ๋ณ์, ํ๋ผ๋ฏธํฐ, ThreadLocal ๋ฑ์ ์ฌ์ฉํด์ผ ํ๋ค.
์คํ๋ง ๋น์ ํ๋์ ๊ณต์ ๊ฐ์ ์ค์ ํ๋ฉด ์ ๋ง ํฐ ์ฅ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค!!!
์ํ๋ฅผ ์ ์งํ ๊ฒฝ์ฐ ๋ฐ์ํ๋ ๋ฌธ์ ์ ์์
public class StatefulService {
private int price; // ์ํ๋ฅผ ์ ์งํ๋ ํ๋
public void order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
this.price = price; //์ฌ๊ธฐ๊ฐ ๋ฌธ์ !
}
public int getPrice() {
return price;
}
}
StatefulService ์ price ํ๋๋ ๊ณต์ ๋๋ ํ๋์ธ๋ฐ, ํน์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ๋ค.
class StatefulServiceTest {
@Test
void statefulServiceSingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(StatefulService.class);
ํธ์ถํ ๋ ๋ง๋ค ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํ
์คํ๋ง์ด ์ปจํ ์ด๋์์ ์ฒ์์ ๋ฑ๋กํ ๋น์ ๋ฐํํด์ฃผ๋ ๊ฒ์ด๋ค ( ์ฑ๊ธํค )
// ThreadA : A ์ฌ์ฉ์ 10000์ ์ฃผ๋ฌธ
statefulService1.order("userA", 10000);
// ThreadB : B ์ฌ์ฉ์ 20000์ ์ฃผ๋ฌธ
statefulService2.order("userB", 20000);
// ThreadA : A ์ฌ์ฉ์ ์ฃผ๋ฌธ ๊ธ์ก ์กฐํ
int price = statefulService1.getPrice();
System.out.println("price = " + price);
ThreadA๊ฐ ์ฌ์ฉ์A ์ฝ๋๋ฅผ ํธ์ถํ๊ณ ThreadB๊ฐ ์ฌ์ฉ์B ์ฝ๋๋ฅผ ํธ์ถํ๋ค ๊ฐ์ ํ์.
์ฌ์ฉ์A์ ์ฃผ๋ฌธ๊ธ์ก์ 10000์์ด ๋์ด์ผ ํ๋๋ฐ, 20000์์ด๋ผ๋ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.
ํ๋ ๋์ ์ ์๋ฐ์์ ๊ณต์ ๋์ง ์๋, ์ง์ญ๋ณ์, ํ๋ผ๋ฏธํฐ, ThreadLocal ๋ฑ์ ์ฌ์ฉํด์ผ ํ๋ค.
public class StatefulService {
public int order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
return price;
}
}
์ง์ญ๋ณ์๋ฅผ ์ฌ์ฉ
// ThreadA : A ์ฌ์ฉ์ 10000์ ์ฃผ๋ฌธ
int userAPrice = statefulService1.order("userA", 10000);
// ThreadB : B ์ฌ์ฉ์ 20000์ ์ฃผ๋ฌธ
int userBPrice = statefulService2.order("userB", 20000);
// ThreadA : A ์ฌ์ฉ์ ์ฃผ๋ฌธ ๊ธ์ก ์กฐํ
System.out.println("price = " + userAPrice);
์ง์ง ๊ณต์ ํ๋๋ ์กฐ์ฌํด์ผ ํ๋ค! ์คํ๋ง ๋น์ ํญ์ ๋ฌด์ํ(stateless)๋ก ์ค๊ณํ์.