스프링 부트 포트폴리오 활용 사례
전략 패턴은 스프링의 의존성 주입(DI)과 결합될 때 매우 강력한 시너지를 냅니다.
사례 1: 사용자 등급별 할인 정책
쇼핑몰에서 사용자 등급(BRONZE, SILVER, GOLD)에 따라 할인율이나 포인트 적립률을 다르게 적용해야 할 때 사용할 수 있습니다.
- 컨텍스트: OrderService
- 전략 인터페이스: DiscountPolicy
- 구현체: BronzeDiscountPolicy, SilverDiscountPolicy, GoldDiscountPolicy
OrderService는 주문을 처리할 때, 사용자의 등급에 맞는 DiscountPolicy 구현체를 주입받아 할인 금액을 계산합니다. 새로운 'VIP' 등급이 생겨도 VipDiscountPolicy만 추가하면 되므로 OrderService는 변경되지 않습니다.
사례 2: 파일 업로드 처리
사용자가 업로드한 파일을 어디에 저장할지 동적으로 결정해야 할 때 유용합니다.
- 컨텍스트: FileUploadService
- 전략 인터페이스: StorageStrategy
- 구현체: LocalFileStorageStrategy (서버 로컬 디스크에 저장), AwsS3StorageStrategy (AWS S3에 저장), DatabaseStorageStrategy (DB에 BLOB으로 저장)
FileUploadService는 파일의 종류, 크기, 또는 시스템 환경설정 값에 따라 적절한 StorageStrategy를 선택하여 파일 저장을 위임합니다.
사례 3: 데이터 검증(Validation) 규칙
입력 데이터에 대해 여러 단계의 복잡한 검증 규칙을 적용해야 할 때, 각 검증 규칙을 하나의 전략으로 만들 수 있습니다.
- 컨텍스트: UserRegistrationService
- 전략 인터페이스: ValidationStrategy
- 구현체: PasswordStrengthValidation, EmailFormatValidation, DuplicateUsernameValidation
package ch03;
import java.util.Base64;
/**
* 전략 패턴이 없는 코드를 사용해 보자.
* 문제 : 텍스트를 인코딩하는 방식이 여러가지 일 때, 우리는 Encoder 클래스를 설계 해 볼 수 있다.
*/
/**
* OCP
* 기능에 확장에 있어서는 열려 있어야 한다.
* 기존 코드에 수정은 닫혀 있어야 한다.
* 새로운 인코딩 형태가 추가 된다면 매번 if else 구문을 직접 수정해야 된다.
*/
class Encoder {
public String encode(String text, String format) {
if ("base64".equalsIgnoreCase(format)) {
return Base64.getEncoder().encodeToString(text.getBytes());
} else if ("append".equalsIgnoreCase(format)) {
return "ABC:" + text;
} else {
return text;
}
}
}
// 클라이언트 클래스
public class BadEncode {
// 코드의 진입점
public static void main(String[] args) {
Encoder encoder = new Encoder();
String message = "Hello Java";
System.out.println(encoder.encode(message, "base64"));
System.out.println(encoder.encode(message, "append"));
}
}
package ch03.step01;
/**
* 전략 패턴이란?
* 동작 방식을 캡슐화하여
* 동적으로 전략을 변경할 수 있도록 허용하는 디자인 패턴
* 특정 기능을 수행할 여러 방법이 있을 때, 그 방법들을 정의(클래스)하고
* 필요에 따라서 적절한 전략을 선택해서 사용할 수 있습니다.
*/
public interface EncodingStrategy {
String encode(String text);
}
package ch03.step01;
public class AppendStrategy implements EncodingStrategy {
@Override
public String encode(String text) {
return "ABC:" + text;
}
}
package ch03.step01;
import java.util.Base64;
public class Base64Strategy implements EncodingStrategy{
@Override
public String encode(String text) {
return Base64.getEncoder().encodeToString(text.getBytes());
}
}
package ch03.step01;
/**
* 핵심 코드 - 전략을 사용하는 주체
*/
public class Encoder {
// 인터페이스 타입의 전략을(인코딩 형태 클래스) 필드로 가짐
private EncodingStrategy encodingStrategy;
// 전략을 동적으로 교체 하는 메서드
public void setEncodingStrategy(EncodingStrategy encodingStrategy) {
this.encodingStrategy = encodingStrategy;
}
public String getMessage(String message) {
return encodingStrategy.encode(message);
}
}
package ch03.step01;
public class MainTest {
public static void main(String[] args) {
String message = "hello java";
// 요청에 따라서 인코딩 하고 싶다.
Encoder encoder = new Encoder();
//Base64로 전략을 선택
encoder.setEncodingStrategy(new Base64Strategy());
System.out.println(encoder.getMessage(message));
encoder.setEncodingStrategy(new AppendStrategy());
System.out.println(encoder.getMessage(message));
encoder.setEncodingStrategy(new UrlStrategy());
System.out.println(encoder.getMessage(message));
}
}
'JAVA' 카테고리의 다른 글
| [1단계] 프로젝트 초기 설정과 핵심 도메인 설계 (0) | 2025.10.15 |
|---|---|
| 프로젝트생성 (0) | 2025.10.15 |
| 디자인 패턴 - 어댑터 패턴 (0) | 2025.10.02 |
| 디자인 패턴 - 팩토리 패턴 (0) | 2025.10.02 |
| 디자인 패턴 - 싱글톤 (0) | 2025.09.30 |