title:
style: nestedList # TOC style (nestedList|nestedOrderedList|inlineFirstLevel)
minLevel: 0 # Include headings from the specified level
maxLevel: 0 # Include headings up to the specified level
includeLinks: true # Make headings clickable
hideWhenEmpty: false # Hide TOC if no headings are found
debugInConsole: false # Print debug info in Obsidian consoleνκ°: λ―Έλμ λμμ΄ λ μ μ - 9/10 (λ€μν μΈμ΄λ‘ μ€μ ꡬν μμλ₯Ό ν¬ν¨νκ³ λμμΈ ν¨ν΄μ ν΅μ¬ κ°λ μ μ€λͺ νλ―λ‘ λμ μ μ λΆμ¬)
μ λ΅ ν¨ν΄ - λ°νμ μκ³ λ¦¬μ¦ κ΅μ²΄
ν€μλ
- νλ λμμΈ ν¨ν΄
- λ°νμ μκ³ λ¦¬μ¦ κ΅μ²΄
- μΈν°νμ΄μ€ μΆμν
λ΄μ©
μ λ΅ ν¨ν΄ κ°μ
μ λ΅ ν¨ν΄(Strategy Pattern)μ μκ³ λ¦¬μ¦μ μΊ‘μννκ³ μ΄λ₯Ό κ΅μ²΄ κ°λ₯νκ² λ§λλ νλ λμμΈ ν¨ν΄μ΄λ€. μ΄ ν¨ν΄μ ν΄λΌμ΄μΈνΈ μ½λλ₯Ό λ³κ²½νμ§ μκ³ λ λ°νμμ μκ³ λ¦¬μ¦μ κ΅μ²΄ν μ μκ² ν΄μ€λ€. μ λ΅ ν¨ν΄μ μννΈμ¨μ΄μ νμ₯μ±κ³Ό μ μ§λ³΄μμ±μ ν¬κ² ν₯μμν¨λ€. μ΄ ν¨ν΄μ κ°μ²΄μ§ν₯ νλ‘κ·Έλλ°μ ν΅μ¬ μμΉμΈ βκ°λ°©-νμ μμΉ(OCP)βκ³Ό βλ¨μΌ μ± μ μμΉ(SRP)βμ μ μ©ν λνμ μΈ μμμ΄λ€. λ―Έλμ λ΄κ° μ΄ ν¨ν΄μ κΈ°μ΅ν΄μΌ νλ μ΄μ λ λ€μν μκ³ λ¦¬μ¦μ΄ νμν μν©μμ μ½λ μ€λ³΅μ μ€μ΄κ³ μ μ°μ±μ λμ΄λ λ° λ§€μ° ν¨κ³Όμ μ΄κΈ° λλ¬Έμ΄λ€.
μ λ΅ ν¨ν΄μ ꡬ쑰
μ λ΅ ν¨ν΄μ ν¬κ² μΈ κ°μ§ μ£Όμ κ΅¬μ± μμλ‘ μ΄λ£¨μ΄μ§λ€. 첫째, βμ λ΅(Strategy)β μΈν°νμ΄μ€λ μ§μλλ λͺ¨λ μκ³ λ¦¬μ¦μ λν κ³΅ν΅ λ©μλλ₯Ό μ μνλ€. λμ§Έ, βꡬ체μ μ λ΅(Concrete Strategy)β ν΄λμ€λ€μ μ λ΅ μΈν°νμ΄μ€λ₯Ό ꡬννλ©° κ°κ° λ€λ₯Έ μκ³ λ¦¬μ¦μ μ 곡νλ€. μ μ§Έ, β컨ν μ€νΈ(Context)β ν΄λμ€λ μ λ΅ κ°μ²΄λ₯Ό μ°Έμ‘°νκ³ μ΄λ₯Ό ν΅ν΄ μκ³ λ¦¬μ¦μ μ€ννλ€. 컨ν μ€νΈλ μ λ΅ κ°μ²΄λ₯Ό κ΅μ²΄ν μ μλ λ©μλλ₯Ό μ 곡νμ¬ λ°νμμ μκ³ λ¦¬μ¦μ λ³κ²½ν μ μκ² νλ€. μ΄λ¬ν ꡬ쑰λ₯Ό ν΅ν΄ μλ‘μ΄ μκ³ λ¦¬μ¦μ μΆκ°ν λ κΈ°μ‘΄ μ½λλ₯Ό λ³κ²½νμ§ μκ³ λ νμ₯μ΄ κ°λ₯νλ€.
νμ΄μ¬μΌλ‘ ꡬνν μ λ΅ ν¨ν΄
from abc import ABC, abstractmethod
from typing import List
# μ λ΅ μΈν°νμ΄μ€
class SortStrategy(ABC):
@abstractmethod
def sort(self, data: List) -> List:
pass
# ꡬ체μ μ λ΅ 1: λ²λΈ μ λ ¬
class BubbleSortStrategy(SortStrategy):
def sort(self, data: List) -> List:
print("λ²λΈ μ λ ¬ μν μ€...")
result = data.copy()
n = len(result)
for i in range(n):
for j in range(0, n - i - 1):
if result[j] > result[j + 1]:
result[j], result[j + 1] = result[j + 1], result[j]
return result
# ꡬ체μ μ λ΅ 2: ν΅ μ λ ¬
class QuickSortStrategy(SortStrategy):
def sort(self, data: List) -> List:
print("ν΅ μ λ ¬ μν μ€...")
result = data.copy()
if len(result) <= 1:
return result
pivot = result[len(result) // 2]
left = [x for x in result if x < pivot]
middle = [x for x in result if x == pivot]
right = [x for x in result if x > pivot]
return self.sort(left) + middle + self.sort(right)
# ꡬ체μ μ λ΅ 3: νμ΄μ¬ λ΄μ₯ μ λ ¬
class PythonSortStrategy(SortStrategy):
def sort(self, data: List) -> List:
print("νμ΄μ¬ λ΄μ₯ μ λ ¬ μν μ€...")
return sorted(data)
# 컨ν
μ€νΈ
class Sorter:
def __init__(self, strategy: SortStrategy = None):
self._strategy = strategy or PythonSortStrategy()
def set_strategy(self, strategy: SortStrategy):
self._strategy = strategy
def sort(self, data: List) -> List:
return self._strategy.sort(data)
# ν΄λΌμ΄μΈνΈ μ½λ
if __name__ == "__main__":
# λ°μ΄ν° μ€λΉ
data = [7, 1, 4, 6, 3, 8, 2, 5]
# 컨ν
μ€νΈ μμ±
sorter = Sorter()
# κΈ°λ³Έ μ λ΅ (νμ΄μ¬ λ΄μ₯ μ λ ¬) μ¬μ©
print(f"κΈ°λ³Έ μ λ ¬ κ²°κ³Ό: {sorter.sort(data)}")
# λ²λΈ μ λ ¬ μ λ΅μΌλ‘ λ³κ²½
sorter.set_strategy(BubbleSortStrategy())
print(f"λ²λΈ μ λ ¬ κ²°κ³Ό: {sorter.sort(data)}")
# ν΅ μ λ ¬ μ λ΅μΌλ‘ λ³κ²½
sorter.set_strategy(QuickSortStrategy())
print(f"ν΅ μ λ ¬ κ²°κ³Ό: {sorter.sort(data)}")νμ΄μ¬ μμμμλ μ λ ¬ μκ³ λ¦¬μ¦μ μ λ΅ ν¨ν΄μΌλ‘ ꡬννλ€. SortStrategy μΆμ ν΄λμ€λ λͺ¨λ μ λ ¬ μ λ΅μ΄ ꡬνν΄μΌ νλ μΈν°νμ΄μ€λ₯Ό μ μνλ€. μΈ κ°μ§ ꡬ체μ μ λ΅μΈ λ²λΈ μ λ ¬, ν΅ μ λ ¬, νμ΄μ¬ λ΄μ₯ μ λ ¬μ κ°κ° λ€λ₯Έ μκ³ λ¦¬μ¦μ μ 곡νλ€. Sorter ν΄λμ€λ 컨ν
μ€νΈ μν μ νλ©° λ°νμμ μ λ ¬ μ λ΅μ λ³κ²½ν μ μλ€. νμ΄μ¬μμλ abc λͺ¨λμ μ¬μ©ν΄ μΆμ ν΄λμ€λ₯Ό λ§λ€κ³ νμ
νν
μ ν΅ν΄ μ½λμ κ°λ
μ±μ λμλ€. μ΄ κ΅¬νμ μλ‘μ΄ μ λ ¬ μκ³ λ¦¬μ¦μ μΆκ°ν λ κΈ°μ‘΄ μ½λλ₯Ό μμ νμ§ μκ³ λ νμ₯ν μ μλ μ₯μ μ΄ μλ€.
μλ°μ€ν¬λ¦½νΈλ‘ ꡬνν μ λ΅ ν¨ν΄
// μ λ΅ μΈν°νμ΄μ€ (μλ°μ€ν¬λ¦½νΈμμλ λͺ
μμ μΈν°νμ΄μ€κ° μμΌλ―λ‘ μ묡μ μΌλ‘ ꡬν)
// ꡬ체μ μ λ΅ 1: μ μ©μΉ΄λ κ²°μ
class CreditCardPaymentStrategy {
constructor(cardNumber, name, cvv, expiryDate) {
this.cardNumber = cardNumber;
this.name = name;
this.cvv = cvv;
this.expiryDate = expiryDate;
}
pay(amount) {
console.log(`${amount}μμ μ μ©μΉ΄λλ‘ κ²°μ ν©λλ€: ${this.cardNumber.slice(-4)}`);
return true;
}
}
// ꡬ체μ μ λ΅ 2: νμ΄ν κ²°μ
class PayPalPaymentStrategy {
constructor(email, password) {
this.email = email;
this.password = password;
}
pay(amount) {
console.log(`${amount}μμ PayPalλ‘ κ²°μ ν©λλ€: ${this.email}`);
return true;
}
}
// ꡬ체μ μ λ΅ 3: μνΈνν κ²°μ
class CryptoPaymentStrategy {
constructor(walletAddress) {
this.walletAddress = walletAddress;
}
pay(amount) {
console.log(`${amount}μμ μνΈννλ‘ κ²°μ ν©λλ€: ${this.walletAddress.slice(0, 10)}...`);
return true;
}
}
// 컨ν
μ€νΈ
class PaymentProcessor {
constructor(paymentStrategy = null) {
this.paymentStrategy = paymentStrategy;
}
setPaymentStrategy(paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
processPayment(amount) {
if (!this.paymentStrategy) {
throw new Error('κ²°μ μ λ΅μ΄ μ€μ λμ§ μμμ΅λλ€.');
}
return this.paymentStrategy.pay(amount);
}
}
// ν΄λΌμ΄μΈνΈ μ½λ
function runExample() {
// μν κ°κ²©
const price = 15000;
// κ²°μ νλ‘μΈμ μμ±
const paymentProcessor = new PaymentProcessor();
// μ μ©μΉ΄λ κ²°μ μ λ΅ μ¬μ©
const creditCardStrategy = new CreditCardPaymentStrategy(
'1234-5678-9012-3456',
'νκΈΈλ',
'123',
'12/25'
);
paymentProcessor.setPaymentStrategy(creditCardStrategy);
paymentProcessor.processPayment(price);
// νμ΄ν κ²°μ μ λ΅μΌλ‘ λ³κ²½
const paypalStrategy = new PayPalPaymentStrategy(
'user@example.com',
'password123'
);
paymentProcessor.setPaymentStrategy(paypalStrategy);
paymentProcessor.processPayment(price);
// μνΈνν κ²°μ μ λ΅μΌλ‘ λ³κ²½
const cryptoStrategy = new CryptoPaymentStrategy(
'0x71C7656EC7ab88b098defB751B7401B5f6d8976F'
);
paymentProcessor.setPaymentStrategy(cryptoStrategy);
paymentProcessor.processPayment(price);
}
// μμ μ€ν
runExample();μλ°μ€ν¬λ¦½νΈ μμμμλ μ¨λΌμΈ κ²°μ μμ€ν
μ μ λ΅ ν¨ν΄μ μ μ©νλ€. μ΄ κ΅¬νμμλ μ μ©μΉ΄λ, νμ΄ν, μνΈννμ κ°μ λ€μν κ²°μ λ°©μμ κ°κ°μ μ λ΅μΌλ‘ μΊ‘μννλ€. μλ°μ€ν¬λ¦½νΈλ λͺ
μμ μΈ μΈν°νμ΄μ€λ₯Ό μ§μνμ§ μκΈ° λλ¬Έμ μ묡μ μΈ μΈν°νμ΄μ€λ₯Ό ν΅ν΄ κ° μ λ΅ ν΄λμ€κ° pay λ©μλλ₯Ό ꡬννλ€. PaymentProcessor ν΄λμ€λ 컨ν
μ€νΈ μν μ νλ©° λ€μν κ²°μ μ λ΅μ κ΅μ²΄ν μ μκ² νλ€. μ΄λ¬ν ꡬνμ μλ‘μ΄ κ²°μ λ°©μμ΄ μΆκ°λ λλ§λ€ κΈ°μ‘΄ μ½λλ₯Ό λ³κ²½νμ§ μκ³ νμ₯ν μ μμ΄ μ μ§λ³΄μκ° μ©μ΄νλ€.
PHPλ‘ κ΅¬νν μ λ΅ ν¨ν΄
<?php
// μ λ΅ μΈν°νμ΄μ€
interface LoggerStrategy {
public function log(string $message): void;
}
// ꡬ체μ μ λ΅ 1: νμΌ λ‘κ±°
class FileLogger implements LoggerStrategy {
private $filePath;
public function __construct(string $filePath) {
$this->filePath = $filePath;
}
public function log(string $message): void {
$timestamp = date('Y-m-d H:i:s');
$logMessage = "[$timestamp] $message" . PHP_EOL;
echo "νμΌμ λ‘κ·Έ κΈ°λ‘: $logMessage";
// μ€μ ꡬνμμλ μλμ κ°μ΄ νμΌμ κΈ°λ‘
// file_put_contents($this->filePath, $logMessage, FILE_APPEND);
}
}
// ꡬ체μ μ λ΅ 2: λ°μ΄ν°λ² μ΄μ€ λ‘κ±°
class DatabaseLogger implements LoggerStrategy {
private $connection;
public function __construct(string $connectionString) {
// μ€μ ꡬνμμλ DB μ°κ²° μ€μ
$this->connection = $connectionString;
}
public function log(string $message): void {
$timestamp = date('Y-m-d H:i:s');
echo "λ°μ΄ν°λ² μ΄μ€μ λ‘κ·Έ κΈ°λ‘: [$timestamp] $message" . PHP_EOL;
// μ€μ ꡬνμμλ μλμ κ°μ΄ DBμ κΈ°λ‘
// $query = "INSERT INTO logs (timestamp, message) VALUES (?, ?)";
// execute query...
}
}
// ꡬ체μ μ λ΅ 3: μ΄λ©μΌ λ‘κ±°
class EmailLogger implements LoggerStrategy {
private $recipientEmail;
public function __construct(string $recipientEmail) {
$this->recipientEmail = $recipientEmail;
}
public function log(string $message): void {
$timestamp = date('Y-m-d H:i:s');
echo "μ΄λ©μΌλ‘ λ‘κ·Έ μ μ‘: [$timestamp] $message (To: {$this->recipientEmail})" . PHP_EOL;
// μ€μ ꡬνμμλ μλμ κ°μ΄ μ΄λ©μΌ μ μ‘
// mail($this->recipientEmail, 'Log Notification', $message);
}
}
// 컨ν
μ€νΈ
class LogManager {
private $logger;
public function __construct(LoggerStrategy $logger = null) {
$this->logger = $logger;
}
public function setLogger(LoggerStrategy $logger): void {
$this->logger = $logger;
}
public function log(string $message): void {
if ($this->logger === null) {
throw new Exception('λ‘κ±°κ° μ€μ λμ§ μμμ΅λλ€.');
}
$this->logger->log($message);
}
}
// ν΄λΌμ΄μΈνΈ μ½λ
function runExample() {
// λ‘κ·Έ λ§€λμ μμ±
$logManager = new LogManager();
// νμΌ λ‘κ±° μ λ΅ μ¬μ©
$fileLogger = new FileLogger('/var/log/app.log');
$logManager->setLogger($fileLogger);
$logManager->log('μ¬μ©μκ° λ‘κ·ΈμΈνμ΅λλ€.');
// λ°μ΄ν°λ² μ΄μ€ λ‘κ±° μ λ΅μΌλ‘ λ³κ²½
$dbLogger = new DatabaseLogger('mysql:host=localhost;dbname=logs');
$logManager->setLogger($dbLogger);
$logManager->log('μ€μ λ°μ΄ν°κ° λ³κ²½λμμ΅λλ€.');
// μ΄λ©μΌ λ‘κ±° μ λ΅μΌλ‘ λ³κ²½ (μ¬κ°ν μ€λ₯ λ°μ μ)
$emailLogger = new EmailLogger('admin@example.com');
$logManager->setLogger($emailLogger);
$logManager->log('μ¬κ°ν μμ€ν
μ€λ₯κ° λ°μνμ΅λλ€!');
}
// μμ μ€ν
runExample();PHP μμμμλ λ‘κΉ
μμ€ν
μ μ λ΅ ν¨ν΄μ μ μ©νλ€. μ΄ κ΅¬νμμλ νμΌ, λ°μ΄ν°λ² μ΄μ€, μ΄λ©μΌκ³Ό κ°μ λ€μν λ‘κΉ
λ°©μμ κ°κ°μ μ λ΅μΌλ‘ μΊ‘μννλ€. LoggerStrategy μΈν°νμ΄μ€λ λͺ¨λ λ‘κ±°κ° κ΅¬νν΄μΌ νλ log λ©μλλ₯Ό μ μνλ€. LogManager ν΄λμ€λ 컨ν
μ€νΈ μν μ νλ©° λ€μν λ‘κΉ
μ λ΅μ κ΅μ²΄ν μ μκ² νλ€. PHPμμλ μΈν°νμ΄μ€λ₯Ό λͺ
μμ μΌλ‘ μ μΈνκ³ ν΄λμ€κ° μ΄λ₯Ό ꡬννλ λ°©μμΌλ‘ μ λ΅ ν¨ν΄μ ꡬννλ€. μ΄ ν¨ν΄μ λ‘κΉ
μꡬμ¬νμ΄ λ³κ²½λκ±°λ μλ‘μ΄ λ‘κΉ
λ°©μμ΄ νμν λ κΈ°μ‘΄ μ½λλ₯Ό μμ νμ§ μκ³ νμ₯ν μ μκ² νλ€.
μ λ΅ ν¨ν΄μ μ€μ μ¬μ© μ¬λ‘
μ λ΅ ν¨ν΄μ μ€μ μννΈμ¨μ΄ κ°λ°μμ κ΄λ²μνκ² μ¬μ©λλ€. λνμ μΈ μ¬λ‘λ‘λ κ²°μ κ²μ΄νΈμ¨μ΄, λ°μ΄ν° μμΆ μκ³ λ¦¬μ¦, μΈμ¦ λ©μ»€λμ¦, λΌμ°ν μκ³ λ¦¬μ¦, ν μ€νΈ ν¬λ§·ν λ±μ΄ μλ€. νλ μμν¬μ λΌμ΄λΈλ¬λ¦¬μμλ μ΄ ν¨ν΄μ μμ£Ό λ³Ό μ μλ€. μλ₯Ό λ€μ΄, Spring νλ μμν¬μ μμ‘΄μ± μ£Όμ , Javaμ Comparator μΈν°νμ΄μ€, Node.jsμ λ―Έλ€μ¨μ΄ λ±μ΄ μ λ΅ ν¨ν΄μ μ리λ₯Ό νμ©νλ€. μ΄ ν¨ν΄μ νΉν μκ³ λ¦¬μ¦μ λμμ΄ λ°νμμ κ²°μ λμ΄μΌ νλ κ²½μ°λ μ¬λ¬ μκ³ λ¦¬μ¦ μ€ νλλ₯Ό μ νν΄μΌ νλ κ²½μ°μ μ μ©νλ€.
μ λ΅ ν¨ν΄μ μ₯λ¨μ
μ λ΅ ν¨ν΄μ μ£Όμ μ₯μ μ μ¬λ¬ μκ³ λ¦¬μ¦μ μΊ‘μννκ³ λ°νμμ κ΅μ²΄ν μ μλ€λ μ μ΄λ€. μ΄λ₯Ό ν΅ν΄ μ½λμ μ¬μ¬μ©μ±κ³Ό νμ₯μ±μ΄ ν₯μλκ³ , 쑰건문(if-else, switch)μ 볡μ‘μ±μ μ€μΌ μ μλ€. λν μλ‘μ΄ μ λ΅μ μΆκ°ν λ κΈ°μ‘΄ μ½λλ₯Ό μμ νμ§ μμλ λλ―λ‘ κ°λ°©-νμ μμΉμ μ€μνλ€. λ¨μ μΌλ‘λ μ λ΅μ΄ λ§μμ§μλ‘ ν΄λμ€μ μκ° μ¦κ°νκ³ , ν΄λΌμ΄μΈνΈκ° μ λ΅μ μ ννκΈ° μν΄ μ λ΅ κ°μ μ°¨μ΄μ μ μμμΌ νλ€λ μ μ΄λ€. λν κ°λ¨ν μκ³ λ¦¬μ¦μμλ μ€νλ € 볡μ‘μ±μ΄ μ¦κ°ν μ μμΌλ―λ‘ μ μ ν μν©μμ μ¬μ©νλ κ²μ΄ μ€μνλ€.
κ²°λ‘ λ° μ‘μ μμ΄ν
μ λ΅ ν¨ν΄μ μκ³ λ¦¬μ¦μ μΊ‘μννκ³ κ΅μ²΄ κ°λ₯νκ² λ§λλ κ°λ ₯ν λμμΈ ν¨ν΄μ΄λ€. μ΄ ν¨ν΄μ μ½λμ μ μ°μ±, νμ₯μ±, μ¬μ¬μ©μ±μ ν₯μμν€λ©° κ°μ²΄μ§ν₯ μ€κ³ μμΉμ ν¨κ³Όμ μΌλ‘ μ μ©ν μ μκ² νλ€. μ λ΅ ν¨ν΄μ νμ©νλ©΄ 쑰건문μΌλ‘ μΈν μ½λ 볡μ‘μ±μ μ€μ΄κ³ μλ‘μ΄ μκ³ λ¦¬μ¦μ μ½κ² μΆκ°ν μ μλ€. λν ν μ€νΈ μ©μ΄μ±λ ν₯μλλ€.
μ‘μ μμ΄ν :
- κΈ°μ‘΄ νλ‘μ νΈμμ μ‘°κ±΄λ¬Έμ΄ λ§κ³ μκ³ λ¦¬μ¦μ΄ μμ£Ό λ³κ²½λλ λΆλΆμ μλ³νμ¬ μ λ΅ ν¨ν΄ μ μ©μ κ²ν νλ€.
- μΈ κ°μ§ μΈμ΄ μμλ₯Ό μ°Έκ³ νμ¬ μμ μ μ£Όλ ₯ μΈμ΄λ‘ μ λ΅ ν¨ν΄ μν μ½λλ₯Ό μμ±νκ³ μ°μ΅νλ€.
- λ€μ νλ‘μ νΈμμ κ²°μ , μΈμ¦, λ‘κΉ λ±κ³Ό κ°μ΄ λ€μν μκ³ λ¦¬μ¦μ΄ νμν κΈ°λ₯μ μ λ΅ ν¨ν΄μ μ μ©νλ€.
- μ λ΅ ν¨ν΄μ΄ μ€λ²μμ§λμ΄λ§μ΄ λμ§ μλλ‘ λ³΅μ‘μ±κ³Ό μ΄μ μ¬μ΄μ κ· νμ κ³ λ €νλ€.
- νμλ€κ³Ό λμμΈ ν¨ν΄ μ€ν°λλ₯Ό μ§ννμ¬ μ λ΅ ν¨ν΄κ³Ό λ€λ₯Έ νλ ν¨ν΄μ μ°¨μ΄μ μ νμ΅νλ€.