μΌ | μ | ν | μ | λͺ© | κΈ | ν |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- νν΄νλ¬μ€ νκΈ°
- μμ°¨μ§ν₯
- λΉ μ€μ½ν
- fanout on write
- νν΄
- λ°μ΄ν° 쿼리
- API Aggregation
- νν νκΈ°
- μ±κΈν€ λΉ
- νΌλ ꡬν
- νν΄ νλ¬μ€ νκΈ°
- νν λ°±μλ
- pull model
- νν΄ λ°±μλ
- νν΄νλ¬μ€ νκ³
- TDD
- νν΄ νκΈ°
- νν΄νλ¬μ€ λ°±μλ
- νν΄νλ¬μ€νκΈ°
- push model
- fanout on read
- νν
- νν΄νλ¬μ€
- λμμΈ ν¨ν΄
- μμ± ν¨ν΄
- νν΄+
- OOP
- κΈ°λ₯ ν μ€νΈ
- νν΄νλ¬μ€λ°±μλ
- νλ‘ν νμ λΉ
- Today
- Total
deVlog
[λμμΈ ν¨ν΄] μμ± ν¨ν΄ - Singleton Pattern (μ±κΈν€ ν¨ν΄) λ³Έλ¬Έ
[λμμΈ ν¨ν΄] μμ± ν¨ν΄ - Singleton Pattern (μ±κΈν€ ν¨ν΄)
μλ£¨λ° 2025. 4. 3. 19:40λͺ©μ°¨
π κ°μ
μ±κΈν€ ν¨ν΄(Singleton Pattern)μ ν΄λμ€μ μΈμ€ν΄μ€κ° μ€μ§ νλλ§ μμ±λκ³ , μ΄λμλ κ·Έ μΈμ€ν΄μ€μ μ κ·Όν μ μλλ‘ νλ μμ± λμμΈ ν¨ν΄μ΄λ€. μ¦, μ μ λ³μλ₯Ό μ¬μ©νμ§ μκ³ λ κ°μ²΄λ₯Ό νλλ§ μμ±νμ¬ μ΄λμλ μ κ·Όν μ μκ² νλ ν¨ν΄μ΄λ€.
βοΈ νΉμ§
- μΈμ€ν΄μ€κ° μ€μ§ ν κ°λ§ μ‘΄μ¬νλλ‘ λ³΄μ₯νλ€.
- μ μμ μΈ μ κ·Όμ μ μ 곡νμ¬ μ΄λμλ λμΌν μΈμ€ν΄μ€μ μ κ·Όν μ μλ€.
- μ§μ° μ΄κΈ°ν(lazy initialization)κ° κ°λ₯νμ¬ νμν μμ μ μΈμ€ν΄μ€λ₯Ό μμ±ν μ μλ€.
π©π»π» μ½λλ‘ μμ보μ
μ±κΈν€ ν¨ν΄μ λ€μν ꡬν λ°©λ²μ μ΄ν΄λ³΄μ.
1. κΈ°λ³Έ μ±κΈν€ ν¨ν΄
public class BasicSingleton {
// 1. private static λ³μλ‘ μ μΌν μΈμ€ν΄μ€ μ μΈ
private static BasicSingleton instance;
// 2. private μμ±μλ‘ μΈλΆμμ μΈμ€ν΄μ€ μμ± λ°©μ§
private BasicSingleton() {
// μ΄κΈ°ν μ½λ
}
// 3. public static λ©μλλ‘ μΈμ€ν΄μ€ μ κ·Όμ μ 곡
public static BasicSingleton getInstance() {
// μΈμ€ν΄μ€κ° μμΌλ©΄ μμ± (μ§μ° μ΄κΈ°ν)
if (instance == null) {
instance = new BasicSingleton();
}
return instance;
}
// λΉμ¦λμ€ λ‘μ§ λ©μλ
public void doSomething() {
System.out.println("μ±κΈν€ κ°μ²΄μ κΈ°λ₯ μν");
}
}
2. μ€λ λ μμ ν μ±κΈν€ (Thread-Safe Singleton)
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {
// μ΄κΈ°ν μ½λ
}
// synchronized ν€μλλ‘ μ€λ λ μμ μ± λ³΄μ₯
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
3. DCL(Double-Checked Locking) μ±κΈν€
public class DCLSingleton {
// volatile ν€μλλ‘ λ³μμ κ°μμ± λ³΄μ₯
private static volatile DCLSingleton instance;
private DCLSingleton() {
// μ΄κΈ°ν μ½λ
}
public static DCLSingleton getInstance() {
// 첫 λ²μ§Έ κ²μ¬ (λ½ μμ΄ λΉ λ₯Έ 체ν¬)
if (instance == null) {
// μΈμ€ν΄μ€ν λΆλΆμλ§ λκΈ°ν μ μ©
synchronized (DCLSingleton.class) {
// λ λ²μ§Έ κ²μ¬ (λ½ νλ ν μ¬νμΈ)
if (instance == null) {
instance = new DCLSingleton();
}
}
}
return instance;
}
}
4. μ΄κΈ°ν μ¨ λ맨λ νλ(Initialization On Demand Holder) ν¨ν΄
public class InitOnDemandSingleton {
private InitOnDemandSingleton() {
// μ΄κΈ°ν μ½λ
}
// λ΄λΆ static ν΄λμ€λ₯Ό μ¬μ©ν΄ μ§μ° μ΄κΈ°ν ꡬν
private static class LazyHolder {
// JVMμ΄ ν΄λμ€ λ‘λ μμ μ μΈμ€ν΄μ€ μμ± (thread-safe)
private static final InitOnDemandSingleton INSTANCE = new InitOnDemandSingleton();
}
public static InitOnDemandSingleton getInstance() {
return LazyHolder.INSTANCE;
}
}
5. Enum μ±κΈν€
public enum EnumSingleton {
INSTANCE; // μ μΌν enum μμκ° μ±κΈν€ μΈμ€ν΄μ€ μν
// λΉμ¦λμ€ λ‘μ§
public void doSomething() {
System.out.println("Enum μ±κΈν€ κΈ°λ₯ μν");
}
}
// μ¬μ© μ
EnumSingleton singleton = EnumSingleton.INSTANCE;
singleton.doSomething();
6. μ€νλ§ νλ μμν¬μμμ μ±κΈν€
import org.springframework.stereotype.Component;
@Component // μ€νλ§ λΉμΌλ‘ λ±λ‘
public class SpringSingleton {
// μ€νλ§μ΄ μμμ μ±κΈν€μΌλ‘ κ΄λ¦¬
public void doSomething() {
System.out.println("μ€νλ§ μ±κΈν€ λΉμ κΈ°λ₯ μν");
}
}
// μ¬μ© μ
@Autowired
private SpringSingleton springSingleton;
βοΈ μ₯/λ¨μ
β μ₯μ
- λ©λͺ¨λ¦¬ ν¨μ¨μ±
- μΈμ€ν΄μ€κ° μ€μ§ ν λ²λ§ μμ±λλ―λ‘ λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μΌ μ μλ€.
- νΉν μΈμ€ν΄μ€ μμ± λΉμ©μ΄ ν° κ²½μ° ν¨μ¨μ μ΄λ€.
- μ μ μ κ·Όμ±
- μ΄λμλ λμΌν μΈμ€ν΄μ€μ μ½κ² μ κ·Όν μ μλ€.
- μ¬λ¬ μ»΄ν¬λνΈκ° λμΌν 리μμ€λ μλΉμ€λ₯Ό 곡μ ν΄μΌ ν λ μ μ©νλ€.
- μν 곡μ
- μ ν리μΌμ΄μ μ 체μμ λμΌν μνλ₯Ό 곡μ ν μ μλ€.
- μ€μ κ΄λ¦¬, μΊμ±, 리μμ€ νλ§ λ±μ μ ν©νλ€.
- μΈμ€ν΄μ€ μ μ΄
- μΈμ€ν΄μ€ μμ±μ μ격νκ² μ μ΄ν μ μλ€.
- μμ± μμ κ³Ό λ°©λ²μ μ λ°νκ² κ΄λ¦¬ν μ μλ€.
β λ¨μ
- λ¨μΌ μ±
μ μμΉ(SRP) μλ°
- μ±κΈν€ ν΄λμ€λ μμ μ μΈμ€ν΄μ€λ₯Ό κ΄λ¦¬νλ©΄μ λμμ λΉμ¦λμ€ λ‘μ§λ μ²λ¦¬νλ―λ‘ μ± μμ΄ μ¬λ¬ κ°κ° λλ€.
- μ΄λ SOLID μμΉ μ€ SRPλ₯Ό μλ°νλ€.
- ν
μ€νΈ μ΄λ €μ
- μ μ μνλ₯Ό κ°μ§λ―λ‘ λ¨μ ν μ€νΈκ° μ΄λ €μμ§ μ μλ€.
- ν μ€νΈ κ°μ μνκ° κ³΅μ λμ΄ κ²©λ¦¬λ ν μ€νΈκ° μ΄λ ΅λ€.
- μμ‘΄μ± μ¨κΉ
- ν΄λμ€ κ°μ μμ‘΄μ±μ΄ λͺ μμ μΌλ‘ λλ¬λμ§ μλλ€.
- μ±κΈν€μ μ¬μ©νλ μ½λκ° μ΄λμλ μ κ·Όν μ μμ΄ μ½λ μΆμ μ΄ μ΄λ €μμ§λ€.
- λ€μ€ μΈμ€ν΄μ€ λ¬Έμ
- ν΄λμ€ λ‘λκ° μ¬λ¬ κ°μΈ κ²½μ° μλμΉ μκ² μ¬λ¬ μΈμ€ν΄μ€κ° μμ±λ μ μλ€.
- μ§λ ¬ν/μμ§λ ¬ν μμλ μλ‘μ΄ μΈμ€ν΄μ€κ° μμ±λ μ μλ€.
- κ³Όλν μ¬μ©
- μ±κΈν€ ν¨ν΄μ λ¨μ©νλ©΄ μ μ μνμ μμ‘΄νλ μ½λκ° λ§μμ Έ μ μ§λ³΄μκ° μ΄λ €μμ§ μ μλ€.
- λͺ¨λ κ° κ²°ν©λκ° λμμ Έ μ½λ λ³κ²½μ΄ μ΄λ €μμ§λ€.
π‘ μλ°/μ€νλ§ νλ μμν¬μμμ μ±κΈν€
1. μ€νλ§ μ»¨ν μ΄λμ μ±κΈν€
μ€νλ§ νλ μμν¬λ κΈ°λ³Έμ μΌλ‘ λΉ(Bean)μ μ±κΈν€μΌλ‘ κ΄λ¦¬νλ€. μ΄λ μ€νλ§μ ν΅μ¬ νΉμ§ μ€ νλμ΄λ€.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class AppConfig {
// κΈ°λ³Έμ μΌλ‘ μ±κΈν€ μ€μ½νλ₯Ό κ°μ§
@Bean
public UserService userService() {
return new UserServiceImpl();
}
// λͺ
μμ μΌλ‘ μ±κΈν€ μ€μ½ν μ§μ
@Bean
@Scope("singleton")
public ProductService productService() {
return new ProductServiceImpl();
}
// νλ‘ν νμ
μ€μ½ν (λ§€λ² μ μΈμ€ν΄μ€ μμ±)
@Bean
@Scope("prototype")
public OrderService orderService() {
return new OrderServiceImpl();
}
}
2. μμ‘΄μ± μ£Όμ μ ν΅ν μ±κΈν€ μ¬μ©
μ€νλ§μμλ μ±κΈν€ λΉμ λν μμ‘΄μ±μ μ£Όμ λ°μ μ¬μ©νλ€.
@Service
public class ProductServiceImpl implements ProductService {
private final UserService userService;
// μμ±μ μ£Όμ
μ ν΅ν΄ μ±κΈν€ λΉ μ°Έμ‘°
@Autowired
public ProductServiceImpl(UserService userService) {
this.userService = userService;
}
@Override
public void processProduct() {
// userServiceλ μ±κΈν€ λΉ
userService.getUserInfo();
}
}
3. μ±κΈν€ λΉ λ±λ‘ λ°©λ²
μ€νλ§μμ μ±κΈν€ λΉμ λ±λ‘νλ μ¬λ¬ λ°©λ²μ μλμ κ°λ€.
// 1. @Component μ λ
Έν
μ΄μ
μ¬μ©
@Component
public class LogManager {
public void log(String message) {
System.out.println("Log: " + message);
}
}
// 2. @Service μ λ
Έν
μ΄μ
μ¬μ© (μλΉμ€ λ μ΄μ΄)
@Service
public class UserService {
// λΉμ¦λμ€ λ‘μ§
}
// 3. @Repository μ λ
Έν
μ΄μ
μ¬μ© (λ°μ΄ν° μ κ·Ό λ μ΄μ΄)
@Repository
public class UserRepository {
// λ°μ΄ν° μ κ·Ό λ‘μ§
}
// 4. @Controller μ λ
Έν
μ΄μ
μ¬μ© (μΉ λ μ΄μ΄)
@Controller
public class UserController {
// μΉ μμ² μ²λ¦¬ λ‘μ§
}
// 5. @Configurationκ³Ό @Bean μ¬μ©
@Configuration
public class AppConfig {
@Bean
public EmailService emailService() {
return new EmailServiceImpl();
}
}
π μ€μ μ¬μ© μ¬λ‘
- λ‘κΉ
μμ€ν
- λ‘κ·Έ μΈμ€ν΄μ€λ μ ν리μΌμ΄μ μ 체μμ νλλ§ μ‘΄μ¬ν΄μΌ ν¨
- μ: Javaμ java.util.logging.Logger
- λ°μ΄ν°λ² μ΄μ€ μ°κ²° ν
- DB μ°κ²°κ³Ό κ°μ λΉμ©μ΄ ν° λ¦¬μμ€λ₯Ό ν¨μ¨μ μΌλ‘ κ΄λ¦¬
- μ: 컀λ₯μ ν λΌμ΄λΈλ¬λ¦¬(HikariCP, DBCP λ±)
- μ€μ κ΄λ¦¬
- μ ν리μΌμ΄μ μ€μ μ μ€μμμ κ΄λ¦¬
- μ: νλ‘νΌν° κ΄λ¦¬μ, νκ²½ μ€μ λ§€λμ
- μΊμ ꡬν
- μ ν리μΌμ΄μ μ 체μμ λμΌν μΊμ μΈμ€ν΄μ€μ μ κ·Ό
- μ: λ©λͺ¨λ¦¬ μΊμ, λΆμ° μΊμμ ν΄λΌμ΄μΈνΈ
- μ€λ λ ν
- μ νλ μμ μ€λ λλ₯Ό ν¨μ¨μ μΌλ‘ κ΄λ¦¬
- μ: Javaμ ExecutorService ꡬν체
- λλ°μ΄μ€ κ΄λ¦¬μ
- νλ¦°ν°, μ€μΊλ λ± νλμ¨μ΄ μ₯μΉμμ ν΅μ κ΄λ¦¬
- μ: νλ¦°ν° μ€νλ¬, λλ°μ΄μ€ λλΌμ΄λ² μΈν°νμ΄μ€
- UI ꡬμ±μμ κ΄λ¦¬
- λνμμ, μ€νλμ νλ©΄ λ± UI μμ κ΄λ¦¬
- μ: JavaFXμ Stage κ΄λ¦¬, Androidμ ActivityManager
- μ€νλ§ λΉ
- μ€νλ§ νλ μμν¬μμ κΈ°λ³Έμ μΌλ‘ λͺ¨λ λΉμ μ±κΈν€μΌλ‘ κ΄λ¦¬λ¨
- μ: Service, Repository, Controller λ±μ λΉ
- νμΌ μμ€ν
μ κ·Ό
- νμΌ μμ€ν μ λν μ κ·Όμ μ€μμμ κ΄λ¦¬
- μ: νμΌ λ§€λμ , I/O μ νΈλ¦¬ν°
- λ€νΈμν¬ κ΄λ¦¬
- λ€νΈμν¬ μ°κ²° λ° μμΌ κ΄λ¦¬
- μ: HTTP ν΄λΌμ΄μΈνΈ, μμΌ μλ²
π μ 리
μ±κΈν€ ν¨ν΄μ μΈμ€ν΄μ€λ₯Ό μ€μ§ νλλ§ μμ±νκ³ μ μμ μΌλ‘ μ κ·Όν μ μκ² νλ λμμΈ ν¨ν΄μ΄λ€.
μ΄ ν¨ν΄μ μ ν리μΌμ΄μ μμ 곡μ 리μμ€λ μλΉμ€μ ν¨μ¨μ μΌλ‘ μ κ·Όν΄μΌ ν λ μ μ©νμ§λ§, κ³Όλν μ¬μ©μ μ½λμ κ²°ν©λλ₯Ό λμ΄κ³ ν μ€νΈλ₯Ό μ΄λ ΅κ² λ§λ€ μ μλ€. λ°λΌμ νμν κ²½μ°μλ§ μ μ€νκ² μ¬μ©ν΄μΌ νλ€.
β μΈμ μ¬μ©νλ©΄ μ’μκΉ?
- 곡μ 리μμ€μ λν μ κ·Ό κ΄λ¦¬κ° νμν λ(DB μ°κ²° ν, μ€λ λ ν λ±)
- μ μμ μΌλ‘ μ μΌν μ€μ μ΄λ μνλ₯Ό κ΄λ¦¬ν΄μΌ ν λ
- 리μμ€ μμ± λΉμ©μ΄ ν° κ°μ²΄λ₯Ό μ¬λ¬ λ² μμ±νμ§ μμμΌ ν λ
- μ¬λ¬ μ»΄ν¬λνΈκ° λμΌν μΈμ€ν΄μ€μ μ κ·Όν΄μΌ ν λ
β μΈμ νΌν΄μΌ ν κΉ?
- κ°μ²΄ μ§ν₯ μ€κ³ μμΉμ μ격ν μ€μν΄μΌ ν λ
- λ¨μ ν μ€νΈκ° μ€μν κ²½μ°
- μνλ₯Ό 곡μ νμ§ μλ κ²μ΄ λ μ ν©ν κ²½μ°
- μΈμ€ν΄μ€ μμ±μ μ μ΄ν νμκ° μλ κ²½μ°
π μ°Έκ³
'π οΈ Software Architecture' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Fanout On Write (Push Model) vs Fanout On Read (Pull Model) (3) | 2024.08.30 |
---|