✅ 1. Singleton Pattern – Spring Bean 관리의 기본
📌 목적
- 객체를 하나만 생성해서 재사용한다
- Spring의 모든 @Component, @Service, @Repository, @Controller는 기본적으로 싱글턴으로 관리됨
💡 Spring 방식
@Service
public class UserService {
public String getUserName() {
return "홍찬";
}
}
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/user")
public String getUser() {
return userService.getUserName();
}
}
👉 Spring 컨테이너가 UserService 인스턴스를 하나만 생성해서 모든 곳에 주입 (DI)함
✅ 2. Factory Method Pattern – Bean 생성 로직 분리
📌 목적
- 조건에 따라 다른 객체를 생성하고 싶을 때
💡 Spring 방식 (@Bean 사용)
public interface NotificationService {
void send(String msg);
}
@Service
public class EmailService implements NotificationService {
public void send(String msg) {
System.out.println("EMAIL: " + msg);
}
}
@Service
public class SmsService implements NotificationService {
public void send(String msg) {
System.out.println("SMS: " + msg);
}
}
@Component
public class NotificationFactory {
private final Map<String, NotificationService> map;
public NotificationFactory(List<NotificationService> services) {
map = services.stream().collect(Collectors.toMap(
s -> s.getClass().getSimpleName(), s -> s
));
}
public NotificationService get(String type) {
return map.get(type);
}
}
@RestController
@RequiredArgsConstructor
public class NotificationController {
private final NotificationFactory factory;
@GetMapping("/notify")
public void notify(@RequestParam String type) {
factory.get(type + "Service").send("가입 축하!");
}
}
✅ 3. Builder Pattern – DTO 생성에 자주 사용
📌 목적
- 복잡한 객체 생성 시 필드 순서 없이 유연하게 설정
💡 Spring + Lombok 예시
@Getter
@Builder
@AllArgsConstructor
public class UserDTO {
private String name;
private String email;
private int age;
}
UserDTO user = UserDTO.builder()
.name("홍찬")
.email("hc@example.com")
.age(33)
.build();
✅ 4. Strategy Pattern – 유연한 정책 분리
📌 목적
- 런타임에 알고리즘을 교체 가능하게 설계
💡 할인 정책 서비스 예시
public interface DiscountPolicy {
int discount(int price);
}
@Component("fixed")
public class FixedDiscount implements DiscountPolicy {
public int discount(int price) {
return price - 1000;
}
}
@Component("rate")
public class RateDiscount implements DiscountPolicy {
public int discount(int price) {
return (int)(price * 0.9);
}
}
@Service
public class OrderService {
private final Map<String, DiscountPolicy> policyMap;
public OrderService(Map<String, DiscountPolicy> policyMap) {
this.policyMap = policyMap;
}
public int calculate(String type, int price) {
return policyMap.get(type).discount(price);
}
}
✅ 5. Template Method Pattern – 공통 처리 흐름 정의
📌 목적
- 처리 흐름은 고정, 세부 내용은 오버라이드
💡 공통 로깅 처리
public abstract class AbstractService {
public void execute() {
long start = System.currentTimeMillis();
call(); // 핵심 로직
long end = System.currentTimeMillis();
System.out.println("실행 시간: " + (end - start));
}
protected abstract void call();
}
@Component
public class UserJoinService extends AbstractService {
@Override
protected void call() {
System.out.println("회원 가입 처리");
}
}
// 사용 예
userJoinService.execute();
✅ 6. Proxy Pattern – AOP 기반 기능 확장
📌 목적
- 실제 로직 앞뒤로 공통 기능을 끼워 넣음 (트랜잭션, 로깅 등)
💡 Spring AOP 기반 로깅
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service..*(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 실제 메서드 실행
long end = System.currentTimeMillis();
System.out.println("[LOG] " + joinPoint.getSignature() + " 실행 시간: " + (end - start));
return result;
}
}
✅ 7. Observer Pattern – 이벤트 발행/구독
📌 목적
- 이벤트를 발행하면 여러 컴포넌트가 반응
💡 Spring Event 기반 예시
public class UserJoinedEvent extends ApplicationEvent {
private final String username;
public UserJoinedEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() { return username; }
}
@Component
public class UserEventListener {
@EventListener
public void handleUserJoined(UserJoinedEvent event) {
System.out.println("유저 가입 처리: " + event.getUsername());
}
}
// 발행
eventPublisher.publishEvent(new UserJoinedEvent(this, "hongchan"));
🔚 정리: Spring Boot 실무에서 자주 쓰는 패턴 요약
패턴 사용 예 적용 위치
Singleton | @Service, @Component | Bean 생성 방식 |
Factory | 전략 구현체 선택 | 인터페이스 기반 객체 생성 |
Builder | DTO 생성 | Lombok @Builder |
Strategy | 정책 변경 (할인, 로직) | Map DI로 유연한 선택 |
Template | 공통 처리 흐름 | 추상 클래스 기반 |
Proxy | AOP (로깅, 트랜잭션) | Aspect 구성 |
Observer | 이벤트 알림 | @EventListener |