์น์ ๊ฒฝ์ฐ์๋ ๊ณ ๊ฐ์ด ์ฌ๋ฌ๋ช ์ด๊ธฐ ๋๋ฌธ์ ์์ฒญํ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ์ ๋ง์ ๋ง ์ฌํ๋ค!
๊ทธ๋์ ํด๊ฒฐ์ ํด์ค์ผ ํ๋ค. ๋ฐฉ๋ฒ์๋ ๋๊ฐ์ง๊ฐ ์กด์ฌํ๋ค.
1. ์ง์ ์ฑ๊ธํค ์์ฑ
2. ์ฑ๊ธํค ์ปจํ ์ด๋ ์ด์ฉ
[ ์ง์ ์ฑ๊ธํค ์์ฑ ]
์ฑ๊ธํค ํจํด์ ์ ์ฉํ๋ฉด ๊ณ ๊ฐ์ ์์ฒญ์ด ์ฌ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ๊ณต์ ํด์ ์ฌ์ฉํ๋ค. ํ์ง๋ง ์ง์ ๋ง๋๋ ๊ฒ์ ์ฌ๋ฌ ๋จ์ ์ด ์กด์ฌํ๋ค.
- ์์ฑํด์ผํ ์ฝ๋๊ฐ ๋ง์์ง๋ค.
- DIP๋ฅผ ์๋ฐํ๋ค. ( ํด๋ผ์ด์ธํธ๊ฐ ๊ตฌ์ฒดํด๋์ค๋ฅผ ์์กดํ๋ค)
private static final SingletonService instance = new SingletonService();
- DIP๋ฅผ ์๋ฐํ๋ฉด OCP๋ ์๋ฐํ ๊ฐ๋ฅ์ฑ์ด ๋ง๋ค.
- ๋ด๋ถ์์ฑ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ด๊ธฐํ ํ๊ธฐ ์ด๋ ต๋ค.
- private ์์ฑ์๋ก ์์ ํด๋์ค๋ฅผ ๋ง๋ค๊ธฐ ์ด๋ ต๋ค.
private SingletonService(){} //private๋ก ์์ฑ์๋ฅผ ์ ์ธํด์ ์ธ๋ถ์์ new ํค์๋๋ฅผ ์ฌ์ฉํ ๊ฐ์ฒด ์์ฑ์ ๋ง๋๋ค.โ
์ฑ๊ธํค์ ์ฌ์ฉํ๋ฉด ๋์ด์์ ๊ฐ์ฒด ์์ฑ์ ๋ง์ ์๋ ์์ง๋ง ์ฌ๋ฌ ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค.
๊ทธ๋์ ์ฑ๊ธํค ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋๊ฒ ์ข๋ค!
[ ์ฑ๊ธํค ์ปจํ ์ด๋ ]
๊ทธ ์ ๊น์ง ์ฌ์ฉํ๋ ์คํ๋ง์ปจํ ์ด๋๊ฐ ์ฑ๊ธํค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด์๋ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ 1๊ฐ๋ง ์ฌ์ฉํ๋ค.
- ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์ฑ๊ธํค ์ปจํ ์ด๋์ ์ญํ ์ ํ๋ค.
- ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ฑ๊ธํค ๋ ์ง์คํธ๋ผ๊ณ ํ๋ค.
- ์ฑ๊ธํค์ ์ํด ์ฝ๋๋ฅผ ๋ฐ๋ก ๋ง์ด ์ถ๊ฐํ์ง ์์๋ ๋๋ค.
- DIP์ OCP๋ฅผ ์งํฌ ์ ์๋ค.
๐ ๋ฐ๋ผ์ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ฒ์์ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ค.
๊ทธ ํ ์๋ง์ ๊ณ ๊ฐ์ด ์์ฒญ์ ํ๋ค๊ณ ํด๋, ๋ง๋ค์ด์ง 1๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ์ด ๋๋ค.
์ฑ๊ธํค์ ์์ฑํ๋ ๊ฒ๋ ๊ฐ์ ์๋ฆฌ์ด์ง๋ง, ์ฑ๊ธํค์ ๋จ์ ์ ๋ณด์ํ๊ธฐ ๋๋ฌธ์ ์คํ๋ง์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ๋ค.
๐ ์์ฒญํ ๋๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๊ธฐ๋ ํ๋ค! (@Configuration ์ ๊ฑฐ)
๐ ์ฑ๊ธํค์ ์ฌ์ฉํ ๋๋ ํญ์ ๋ฌด์ํ(stateless)๋ฅผ ์ ์งํด์ผํ๋ค!!
- ํน์ ํด๋ผ์ด์ธํธ์ ์์กด์ ์ธ ํ๋๊ฐ ์์ผ๋ฉด ์๋๋ค.
- ํน์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ ํ๋๊ฐ ์์ผ๋ฉด ์๋๋ค.
- ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ ๊ฒ์ด ์ข๋ค.
- ํ๋ ๋์ ์ ์๋ฐ์์ ๊ณต์ ๋์ง ์๋ ์ง์ญ๋ณ์, ํ๋ผ๋ฏธํฐ, ThreadLocal๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
public class StatefulService {
private int price;
public int order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
this.price = price;
}
public int getPrice(){
return 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();
//ThreadB : ์ฌ์ฉ์A๋ 10000์์ ๊ธฐ๋ํ์ง๋ง, ๊ธฐ๋์ ๋ค๋ฅด๊ฒ 20000์ ์ถ๋ ฅ
System.out.println("price = " + price);
assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
static class TestConfig{
@Bean
public StatefulService statefulService() {
return new StatefulService();
}
}
}
์ด ์ฝ๋๋ฅผ ํ์ธํด๋ณด๋ฉด A์ B์ ๋ค๋ฅธ ๊ฐ์ ๋ฃ์์ง๋ง ์ถ๋ ฅ๋๋ ๊ฒ์ B์ ๊ฐ๊ฒฉ์ธ 2000์์ด ์ถ๋ ฅ๋๋ค.
this.price = price๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ B์ ๊ฐ๊ฒฉ์ด ๋ค์ด์ค์ ๋ณ๊ฒฝ๋ ๊ฒ์ด๋ค.
์ด์ฒ๋ผ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ๋์ค์ ์น ์๋น์ค์์ ๊ธ์ ์ ์ธ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ธฐ ๋๋ฌธ์ ์ฒ์๋ถํฐ ์ด๋ ๊ฒ ์์ฑํ์ง ์๋ ๊ฒ์ด ์ข๋ค.
package hello.core.singleton;
public class StatefulService {
public int order(String name, int price) {
System.out.println("name = " + name + " price = " + price);
return 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์ ์ฃผ๋ฌธ
int userAPrice = statefulService1.order("userA", 10000);
//ThreadB : B์ฌ์ฉ์ 20000์ ์ฃผ๋ฌธ
int userBPrice = statefulService2.order("userB", 20000);
// A์ฌ์ฉ์ ๊ฐ๊ฒฉ ์ถ๋ ฅ (10000์ ์ถ๋ ฅ๋จ)
System.out.println("price = " + userAPrice);
}
static class TestConfig{
@Bean
public StatefulService statefulService() {
return new StatefulService();
}
}
}
๋ฐ๋ผ์ ์ด๋ ๊ฒ ๋ณ๊ฒฝํด์ค์ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
๊ผญ๊ผญ ์คํ๋ง ๋น์ ๋ฌด์ํ๋ก ์ค๊ณํด์ผํ๋ค.
[ @Configuration ]
์ ์ ์์ฑํ๋ AppConfig ์ฝ๋๋ฅผ ๋ณด๋ฉด memberService์ OrderService๋ฅผ ํธ์ถํ ๋, memberRepository๊ฐ ๋๋ฒ ์์ฑ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ํ์ง๋ง ์ค์ ๋ก๋ ๋ค ํ๋ฒ ์ฉ๋ง ์์ฑ์ด ๋๋ค.
@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(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy(){
return new RateDiscountPolicy();
}
//์ญํ ์ด ๋๋ฌ๋๊ฒ ๋ณ๊ฒฝ
}
์๊ทธ๋ด๊น?
์ด AppConfig์ ํด๋์ค ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ฉด class.hello.core.AppConfig๋ผ๊ณ ์ถ๋ ฅ ๋ ๊ฒ๊ฐ์๋ฐ SpringCGLIB๊ฐ ๋ค์ ๋ถ์ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
๐ AppConfig๊ฐ ์๋ AppConfig@SpringCGLIB๊ฐ ์ฑ๊ธํค์ ๋ณด์ฅํด ์ค ๊ฒ์ด๋ค.
๐ AppConfig@SpringCGLIB๊ฐ ๋์๋ ์ด์ ๋ AppConfig ํด๋์ค ์์ @Configuration ์ ๋ ธํ ์ด์ ์ ๋ถ์๊ธฐ ๋๋ฌธ์ด๋ค.
@Configuration ์ ๋ ธํ ์ด์ ์ ๋ถ์ด์ง ์์ผ๋ฉด ์ฌ๋ฌ๋ฒ ํธ์ถ๋๊ณ , ์ฑ๊ธํค์ด ๊นจ์ง๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋์ @Configuration ์ ๋ ธํ ์ด์ ์ ๊ผญ ๋ถ์ฌ์ผํ๋ค!!
์ฌ๋ฌ ๊ฐ์๋ค์ ๋ณด๋ฉด์ ๋๋ ๊ฒ์, ์ค๋ณต์ฝ๋๋ฅผ ์ต๋ํ ์ค์ด๊ณ , ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๋ ์ฝ๋๋ฅผ ์ ํธํ๋ ๊ฒ ๊ฐ๋ค.
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ด๋ฉด์๋ ๊ฐ์ฅ ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค...ํด๋ฆฐ์ฝ๋๋ฅผ ์ค์ค๋ก ์ ์์ฑํ ์ ์๋ ๊ทธ ๋ ๊น์ง !!
์ด ๊ธ์ ์ธํ๋ฐ์ ๊น์ํ ๊ฐ์ฌ๋ ๊ฐ์๋ฅผ ๋ณด๊ณ ๋ณต์ต ํฌ์คํ ํ ๊ธ์ ๋๋ค. ์ ๋ง ์ด๋ณด์์๊ฒ ์ถ์ฒ๐๐
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring ํต์ฌ์๋ฆฌ-๊ธฐ๋ณธ [@Autowired/@Qualifier/@Primary] (0) | 2021.07.16 |
---|---|
Spring ํต์ฌ์๋ฆฌ-๊ธฐ๋ณธ [์ปดํฌ๋ํธ ์ค์บ] (0) | 2021.07.12 |
Spring ๊ธฐ๋ณธ [์คํ๋ง๋น ์กฐํ] (0) | 2021.07.09 |
Spring ๊ธฐ๋ณธ [ํ ์ธ์ ์ฑ ๋ณ๊ฒฝ/๊ฐ์ฒด ์งํฅ ์๋ฆฌ ์ ์ฉ/DI/์คํ๋ง์ปจํ ์ด๋] (0) | 2021.07.08 |
H2 DB ๋ค์ด๋ก๋ [์ค์น / ์๋ฒ ์คํ] (0) | 2021.06.27 |