์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- ํญํด99
- ์ค๋ฅ๊ฒ์ถ
- ๋น์ฃผ๊ธฐ์ ํธ
- til
- ์์๋ฒํธ
- git merge
- ํฐ์คํ ๋ฆฌ์ฑ๋ฆฐ์ง
- 99ํด๋ฝ
- tcp ํ๋กํ ์ฝ
- ์ค๋ธ์
- ํ๋ก์ด๋์์
- ์ค๋ ๋
- ์๋น์ค ํ๋ฆฌ๋ฏธํฐ๋ธ
- ์ฝ๋ฉํ ์คํธ์ค๋น
- tcp ์ธ๊ทธ๋จผํธ
- ํ๋ ์ ๊ตฌ์กฐ
- well known ํฌํธ
- ์ฐ๋ถํฌdb
- IEEE 802
- ์ค๋ฅ์ ์ด
- reducible
- ๊ฐ๋ฐ์์ทจ์
- i-type
- ํ ํฐ ๋ฒ์ค
- ์ฃผ๊ธฐ์ ํธ
- ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ
- xv6
- leetcode
- ๋ฐ์ดํฐ ์ ์ก
- mariadb
- Today
- Total
Unfazedโ๏ธ๐ฏ
SOLID ์์น(์ข์ ๊ฐ์ฒด ์งํฅ ์ค๊ณ)๊ณผ Spring์ ํ์์ฑ ๋ณธ๋ฌธ
SOLID ์์น(์ข์ ๊ฐ์ฒด ์งํฅ ์ค๊ณ)๊ณผ Spring์ ํ์์ฑ
9taetae9 2025. 1. 6. 16:11SOLID๋ ํด๋ฆฐ ์ฝ๋๋ก ์ ๋ช ํ ๋ก๋ฒํธ ๋งํด์ด ์ ์ํ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ ๋ฐ ์ค๊ณ์ ๋ค์ฏ ๊ฐ์ง ํต์ฌ ์์น์ด๋ค.
1. ๋จ์ผ ์ฑ ์ ์์น (Single Responsibility Principle, SRP)
"ํ ํด๋์ค๋ ์ค์ง ํ๋์ ์ฑ ์๋ง ๊ฐ์ ธ์ผ ํ๋ค"๋ ๊ฒ์ด SRP์ ํต์ฌ์ด๋ค. ์ฌ๊ธฐ์ '์ฑ ์'์ด๋ ๋ฌด์์ผ๊น?
์ฃผ๋ฌธ ์์คํ ์์ ๋ค์๊ณผ ๊ฐ์ ํด๋์ค๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ณด์.
// SRP๋ฅผ ์๋ฐํ๋ ์์
class Order {
public void calculateTotalPrice() { ... }
public void printOrder() { ... }
public void saveToDatabase() { ... }
}
// SRP๋ฅผ ์ค์ํ๋ ์์
class Order {
public void calculateTotalPrice() { ... }
}
class OrderPrinter {
public void printOrder(Order order) { ... }
}
class OrderRepository {
public void saveOrder(Order order) { ... }
}
์ฒซ ๋ฒ์งธ ์์๋ ์ฃผ๋ฌธ ๊ณ์ฐ, ์ถ๋ ฅ, ์ ์ฅ์ด๋ผ๋ ์ธ ๊ฐ์ง ์ฑ ์์ ๋ชจ๋ ๊ฐ์ง๊ณ ์์ด SRP๋ฅผ ์๋ฐํ๋ค.
๋ฐ๋ฉด, ๋ ๋ฒ์งธ ์์๋ ๊ฐ ํด๋์ค๊ฐ ํ๋์ ์ฑ ์๋ง ๊ฐ์ง๋๋ก ๋ถ๋ฆฌ๋์ด ์๋ ๊ฒ์ ์ ์ ์๋ค.
์ ์ฉ ์ด์ : ์ฝ๋์ ์ดํด์ ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒ ํ๊ณ , ํน์ ์ฑ ์ ๋ณ๊ฒฝ์ด ๋ค๋ฅธ ์ฑ ์์ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ก ํ๊ธฐ ์ํจ.
์ค์ ์ฌ์ฉ :
- MVC ํจํด์์ Controller๋ ์์ฒญ ์ฒ๋ฆฌ, Service๋ ๋น์ง๋์ค ๋ก์ง, Repository๋ ๋ฐ์ดํฐ ์ ๊ทผ์ผ๋ก ์ญํ ๋ถ๋ฆฌ
- ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ์ฌ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌ
2. ๊ฐ๋ฐฉ-ํ์ ์์น (Open/Closed Principle, OCP)
"์ํํธ์จ์ด ์์๋ ํ์ฅ์๋ ์ด๋ ค ์์ผ๋, ๋ณ๊ฒฝ์๋ ๋ซํ ์์ด์ผ ํ๋ค"๋ ์์น์ผ๋ก ์ถ์ํ์ ๋คํ์ฑ์ ํตํด ๊ตฌํํ ์ ์๋ค.
// OCP๋ฅผ ์๋ฐํ๋ ์์
class PaymentProcessor {
public void processPayment(String type) {
if (type.equals("CREDIT")) {
processCreditPayment();
} else if (type.equals("DEBIT")) {
processDebitPayment();
}
// ์๋ก์ด ๊ฒฐ์ ๋ฐฉ์์ ์ถ๊ฐํ ๋๋ง๋ค ์ฝ๋ ์์ ํ์
}
}
// OCP๋ฅผ ์ค์ํ๋ ์์
interface PaymentMethod {
void processPayment();
}
class CreditPayment implements PaymentMethod {
public void processPayment() { ... }
}
class DebitPayment implements PaymentMethod {
public void processPayment() { ... }
}
// ์๋ก์ด ๊ฒฐ์ ๋ฐฉ์ ์ถ๊ฐ๊ฐ ์ฉ์ดํจ
class CryptoPayment implements PaymentMethod {
public void processPayment() { ... }
}
์ ์ฉ ๋ฐฉ๋ฒ :
- ์ถ์ํ์ ๋คํ์ฑ์ ํ์ฉ
- ์ธํฐํ์ด์ค ๊ธฐ๋ฐ ์ค๊ณ๋ก ๊ธฐ๋ฅ ํ์ฅ์ด ํ์ํ ๋ ๊ตฌํ์ฒด๋ง ์ถ๊ฐ
์คํ๋ง ์ ์ฉ ์ฌ๋ก :
- DI๋ฅผ ํตํด ์๋ก์ด ๊ตฌํ์ฒด๋ฅผ ์ฃผ์ ํ๊ณ , ํด๋ผ์ด์ธํธ ์ฝ๋๋ ์์ ํ์ง ์์
3. ๋ฆฌ์ค์ฝํ ์นํ ์์น (Liskov Substitution Principle, LSP)
ํ์ ํด๋์ค๋ ์์ ํด๋์ค์ ๊ท์ฝ์ ์ง์ผ์ผ ํ๋ค๋ ์์น์ผ๋ก, ์์ ํ์ ์ ๊ฐ์ฒด๋ฅผ ํ์ ํ์ ์ ๊ฐ์ฒด๋ก ์นํํด๋ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ด ๋ณด์ฅ๋์ด์ผ ํจ์ ์๋ฏธํ๋ค.
// LSP๋ฅผ ์๋ฐํ๋ ์์
class Bird {
void fly() { ... }
}
class Penguin extends Bird {
void fly() {
throw new UnsupportedOperationException(); // ํญ๊ท์ ๋ ์ ์์!
}
}
// LSP๋ฅผ ์ค์ํ๋ ์์
interface FlyingBird {
void fly();
}
interface WalkingBird {
void walk();
}
class Sparrow implements FlyingBird {
public void fly() { ... }
}
class Penguin implements WalkingBird {
public void walk() { ... }
}
์ ์ฉ ์ด์ : ์์ ๊ด๊ณ์์์ ์ผ๊ด์ฑ ์ ์ง
์ ์ฉ ๋ฐฉ๋ฒ :
- ์๋ชป๋ ์์ ๊ตฌ์กฐ๋ฅผ ์ธํฐํ์ด์ค๋ก ์ฌ์ค๊ณ
- ๋น์ทํ ๊ธฐ๋ฅ์ ๊ณต์ ํ๋ ๊ฐ์ฒด๋ ์์๋ณด๋ค ์ปดํฌ์ง์ ์ ๊ณ ๋ ค
4. ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น (Interface Segregation Principle, ISP)
ํด๋ผ์ด์ธํธ๋ ์์ ์ด ์ฌ์ฉํ์ง ์๋ ๋ฉ์๋์ ์์กดํ์ง ์์์ผ ํ๋ค๋ ์์น์ด๋ค.
// ISP๋ฅผ ์๋ฐํ๋ ์์
interface Worker {
void work();
void eat();
void sleep();
}
// ISP๋ฅผ ์ค์ํ๋ ์์
interface Workable {
void work();
}
interface Eatable {
void eat();
}
interface Sleepable {
void sleep();
}
class Human implements Workable, Eatable, Sleepable {
public void work() { ... }
public void eat() { ... }
public void sleep() { ... }
}
class Robot implements Workable {
public void work() { ... }
}
์ ์ฉ ๋ฐฉ๋ฒ :
- ์์ ๋จ์์ ์ธํฐํ์ด์ค๋ก ๋ถ๋ฆฌ
- ํด๋ผ์ด์ธํธ๊ฐ ํ์ํ ๊ธฐ๋ฅ๋ง ์ ๊ณต
์ ์ฉ ์์ :
- ์คํ๋ง ๋น ๋ฑ๋ก ์ ํน์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ตฌํ์ฒด๋ง ์ฌ์ฉ ๊ฐ๋ฅ
5. ์์กด๊ด๊ณ ์ญ์ ์์น (Dependency Inversion Principle, DIP)
"์์ ๋ชจ๋์ ํ์ ๋ชจ๋์ ๊ตฌํ์ ์์กดํด์๋ ์ ๋๋ฉฐ, ๋ ๋ค ์ถ์ํ์ ์์กดํด์ผ ํ๊ณ ,
์ถ์ํ๊ฐ ์ธ๋ถ ์ฌํญ์ ์์กดํ๋ ๊ฒ์ด ์๋ ์ธ๋ถ์ฌํญ์ด ์ถ์ํ์ ์์กดํด์ผ ํ๋ค"
์ฆ, ์์์ ํ์ ๊ฐ์ฒด ๋ชจ๋๊ฐ ๋์ผํ ์ถ์ํ์ ์์กดํด์ผ ํ๋ค.
// DIP๋ฅผ ์๋ฐํ๋ ์์
class OrderService {
private MySQLOrderRepository repository = new MySQLOrderRepository();
}
// DIP๋ฅผ ์ค์ํ๋ ์์
interface OrderRepository {
void save(Order order);
}
class OrderService {
private final OrderRepository repository;
public OrderService(OrderRepository repository) {
this.repository = repository;
}
}
์ ์ฉ ์ด์ :
- ๋ชจ๋ ๊ฐ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ์ ์ฐ์ฑ์ ๋์
- ์์ ๋ชจ๋ ๋ก์ง ๋ณ๊ฒฝ ์์ด ํ์ ์์ค์ ๊ตฌํ ๋ณ๊ฒฝ ๊ฐ๋ฅ
์ ์ฉ ์์ :
- DI ์ปจํ ์ด๋๋ก ์์กด์ฑ์ ์ฃผ์
- ์ค์ ํ์ผ, ์ ๋ํ ์ด์ ์ ํตํด ์ ์ฐํ ๊ตฌ์กฐ ์ ๊ณต
SOLID ์์น์ ์ค์ ์ ์ฉ
SOLID ์์น๋ค์ ๊ฐ๋ณ์ ์ผ๋ก๋ ์ค์ํ์ง๋ง, ์๋ก ๊ธด๋ฐํ๊ฒ ์ฐ๊ด๋์ด ์๋ค. ์์น๋ค์ ์ ์ ํ ์ ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ด์ ์ ์ป์ ์ ์๋ค.
- ์ฝ๋์ ์ ์ง๋ณด์์ฑ ํฅ์
- ํ์ฅ์ฑ ์๋ ์ค๊ณ ๊ฐ๋ฅ
- ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ ์์ฑ
- ํ ์คํธ๊ฐ ์ฉ์ดํ ์ฝ๋ ์์ฑ
ํ์ง๋ง, ์ด๋ฌํ ์์น๋ค์ ๊ณผ๋ํ๊ฒ ์ ์ฉํ๋ฉด ์คํ๋ ค ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์์ผ๋ฏ๋ก, ์ํฉ์ ๋ง๊ฒ ์ ์ ํ ์ ์ฉํ๋ ๊ฒ์ด ์ค์ํ๋ค.
ํนํ, ์ด๊ธฐ ๋จ๊ณ์์๋ ๋จ์ํ ์ค๊ณ๋ก ์์ํ๊ณ , ํ์์ ๋ฐ๋ผ ์ ์ง์ ์ผ๋ก ์์น๋ค์ ์ ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
๋ฐ๋ผ์, ์ด๋ฌํ ์์น๋ค์ ๋จ์ํ ๊ท์น์ผ๋ก ์ธ์ฐ๊ธฐ๋ณด๋ค๋, ์ ํ์ํ์ง, ์ด๋ค ์ํฉ์์ ์ ์ฉํด์ผ ํ๋์ง๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ค์ํ๋ค.
์คํ๋ง ํ๋ ์์ํฌ์ ๊ฐ์ฒด ์งํฅ ์ค๊ณ์ ๋ง๋จ
์คํ๋ง์ด ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์
๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ ์์น์ธ OCP(๊ฐ๋ฐฉ-ํ์ ์์น)์ DIP(์์กด๊ด๊ณ ์ญ์ ์์น)๋ฅผ ์ค์ ์ฝ๋์ ์ ์ฉํ๋ ๊ฒ์ ์๊ฐ๋ณด๋ค ๋ง์ ์์ ์ ํ์๋ก ํ๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์คํ๋ง ํ๋ ์์ํฌ๊ฐ ํ์ํ๋ค.
์คํ๋ง์ด ์์ ๋์ ๋ฌธ์ ์
// ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด
interface PaymentService {
void processPayment();
}
class KakaoPayService implements PaymentService {
public void processPayment() {
System.out.println("์นด์นด์คํ์ด ๊ฒฐ์ ์ฒ๋ฆฌ");
}
}
class NaverPayService implements PaymentService {
public void processPayment() {
System.out.println("๋ค์ด๋ฒํ์ด ๊ฒฐ์ ์ฒ๋ฆฌ");
}
}
// ํด๋ผ์ด์ธํธ ์ฝ๋
class OrderService {
private PaymentService paymentService = new KakaoPayService(); // DIP ์๋ฐ!
public void order() {
paymentService.processPayment();
}
}
์ ์ฝ๋์ ๋ฌธ์ ์
- ๋ค๋ฅธ ๊ฒฐ์ ์๋น์ค๋ก ๋ณ๊ฒฝํ๋ ค๋ฉด OrderService ์ฝ๋๋ฅผ ์์ ํด์ผ ํจ (OCP ์๋ฐ)
- OrderService๊ฐ ๊ตฌ์ฒด์ ์ธ ๊ฒฐ์ ์๋น์ค์ธ KakaoPayService๋ฅผ ์ง์ ์์ฑ(์์ ๋ชจ๋์ด ํ์ ๋ชจ๋์ ์์กด)ํ๊ณ ์์ (DIP ์๋ฐ)
์คํ๋ง์ ํด๊ฒฐ์ฑ : DI(Dependency Injection)
// ์คํ๋ง ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝ
@Service
class OrderService {
private final PaymentService paymentService;
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void order() {
paymentService.processPayment();
}
}
@Service
class KakaoPayService implements PaymentService {
public void processPayment() {
System.out.println("์นด์นด์คํ์ด ๊ฒฐ์ ์ฒ๋ฆฌ");
}
}
OrderService๋ ์์ฑ์ ์ฃผ์ ์ ํตํด PaymentService์ ์ถ์ํ์ ์์กดํ๋ฏ๋ก, ์๋ก์ด ๊ฒฐ์ ์๋จ์ ์ถ๊ฐํ ๋ ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋ ํ์ฅ์ด ๊ฐ๋ฅํ๋ค. (OCP ์ค์)
OrderService๊ฐ PaymentService๋ผ๋ ์ถ์ํ์ ์์กดํ๊ณ ์์ผ๋ฉฐ, ๊ตฌํ์ฒด๋ ์ธ๋ถ์์ ์ฃผ์ ๋๋ค. (DIP ์ค์)
์ฅ์
- DI ์ปจํ ์ด๋๊ฐ ๊ฐ์ฒด์ ์์ฑ๊ณผ ์์กด๊ด๊ณ ์ฃผ์ ์ ๋ด๋น
- ์ค์ ๋ณ๊ฒฝ๋ง์ผ๋ก ๊ตฌํ์ฒด๋ฅผ ๋ณ๊ฒฝํ ์ ์์ (๋ชจํน(mocking)์ด๋ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ก์ ๊ต์ฒด๊ฐ ์ฉ์ด)
- ํด๋ผ์ด์ธํธ ์ฝ๋์ ๋ณ๊ฒฝ ์์ด ๊ธฐ๋ฅ ํ์ฅ ๊ฐ๋ฅ
์ญํ ๊ณผ ๊ตฌํ์ ๋ถ๋ฆฌ
์คํ๋ง์ ๊ฐ์ฒด ์งํฅ์ ํต์ฌ ์์น์ธ "์ญํ ๊ณผ ๊ตฌํ์ ๋ถ๋ฆฌ"๋ฅผ ๋งค์ฐ ์ ์ง์ํ๋ค.
// ์ญํ (์ธํฐํ์ด์ค)
public interface MemberRepository {
void save(Member member);
Member findById(Long id);
}
// ๊ตฌํ
@Repository
public class JpaMemberRepository implements MemberRepository {
@Override
public void save(Member member) {
// JPA๋ฅผ ์ฌ์ฉํ ๊ตฌํ
}
@Override
public Member findById(Long id) {
// JPA๋ฅผ ์ฌ์ฉํ ๊ตฌํ
}
}
@Repository
public class MongoMemberRepository implements MemberRepository {
// MongoDB๋ฅผ ์ฌ์ฉํ ๊ตฌํ
}
์ญํ ๊ณผ ๊ตฌํ์ ๋ถ๋ฆฌํ ์ค๊ณ์ ์ฅ์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ณ๊ฒฝํ๋๋ผ๋ ํด๋ผ์ด์ธํธ ์ฝ๋๋ ๋ณ๊ฒฝํ ํ์๊ฐ ์์
- ํ ์คํธ๊ฐ ์ฉ์ดํจ (Mock ๊ฐ์ฒด ์ฌ์ฉ ๊ฐ๋ฅ)
- ๊ธฐ๋ฅ ํ์ฅ์ด ์ฌ์
๊ฒฐ๋ก
์คํ๋ง ํ๋ ์์ํฌ๋ ๊ฐ์ฒด ์งํฅ์ ํต์ฌ ์์น๋ค์ ์ค์ฒํ ์ ์๋๋ก ๋์์ฃผ๋ ๋๊ตฌ์ด๋ค. DI ์ปจํ ์ด๋๋ฅผ ํตํด ์ ์ฐ์ฑ๊ณผ ํ์ฅ์ฑ์ ์ ๊ณตํด์ฃผ์ด, ๊ฐ๋ฐ์๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋ ์ง์คํ ์ ์๊ฒ ๋๋ค.
์ฐธ๊ณ ์๋ฃ :
์คํ๋ง ๊ธฐ๋ณธ ๊ฐ์ (๊น์ํ ๊ฐ์ฌ)
https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84)
SOLID (๊ฐ์ฒด ์งํฅ ์ค๊ณ) - ์ํค๋ฐฑ๊ณผ, ์ฐ๋ฆฌ ๋ชจ๋์ ๋ฐฑ๊ณผ์ฌ์
์ํค๋ฐฑ๊ณผ, ์ฐ๋ฆฌ ๋ชจ๋์ ๋ฐฑ๊ณผ์ฌ์ . ์ปดํจํฐ ํ๋ก๊ทธ๋๋ฐ์์ SOLID๋ ๋ก๋ฒํธ C. ๋งํด[1][2]์ด 2000๋ ๋ ์ด๋ฐ[3]์ ๋ช ๋ช ํ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ ๋ฐ ์ค๊ณ์ ๋ค์ฏ ๊ฐ์ง ๊ธฐ๋ณธ ์์น์ ๋ง์ดํด ํ๋์ค๊ฐ ๋๋ฌธ์
ko.wikipedia.org
'Web (back-end) > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot] ๋ฒ์ ์ฒด๊ณ Semantic Versioning (0) | 2025.02.27 |
---|---|
Spring @RequestParam vs @PathVariable ์ ๋ ธํ ์ด์ ๋น๊ต (0) | 2025.02.24 |