쿼츠 블로그를 위해 대공사

This commit is contained in:
2026-04-08 13:07:41 +09:00
parent 123642831e
commit 1319881195
606 changed files with 50625 additions and 2 deletions
@@ -0,0 +1,7 @@
객체가 특정한 작업이나 기능을 수행하는 역할을 맡고 있다는 의미
자신이 가지고 있는 자신을 표현하는 데이터인 프로퍼티(속성)을 변경하거나 사용하는 과정을
남(다른 객체)에게 위임하는 것이 아니라 자신의 멤버함수를 통해 스스로 하도록 하는 것을 의미
예를들면
자동차 객체는 자신이 어떻게 움직여야 하는지와 관련된 Move 기능을 남에게 위탁하지 않음.
@@ -0,0 +1,24 @@
{
"nodes":[
{"id":"33d7d950058b35a0","type":"file","file":"3.Resource (자료실)/클린 코드의 기술/단일 책임 원칙.md","x":-333,"y":-166,"width":513,"height":266},
{"id":"7642a3e2561f5690","type":"text","text":"SRP를 지키려면 하나의 클래스 파일에 하나의 class(객체)만 선언하고 사용하는게 좋다.\n이렇게 하려면 클래스파일이 많아질 수 밖에 없는데\n별도의 파일들로 분리하는게 SRP를 지키는 자연스러운 해결책이라고 한다.\n - 그럼 클래스파일이 너무 많아질텐데?\n : [[파일 분리]]\n- 패키지(폴더)구조를 어떻게 가져가는게 일반적인가?\n : [[패키지 구조]]","x":-333,"y":200,"width":693,"height":240},
{"id":"05b38eceabbfff37","type":"text","text":"클래스마다 메소드가 하나만 있어야 한다는 이야기인가?","x":280,"y":-166,"width":297,"height":80},
{"id":"dd42f36c7e4e5b80","type":"text","text":"하나의 책임을 위해 여러개의 메서드가 사용 될 수 있다.\n클래스가 이 메서드들을 통해 수행하는 업무가 하나여야 한다.","x":280,"y":-340,"width":460,"height":120},
{"id":"ec406bdee9ca8b36","type":"text","text":"책임이라는 기준이 모호하기 때문에 변경을 기준으로 잡으면 설계에 용이할 수 있다.","x":280,"y":-60,"width":400,"height":93},
{"id":"abdc5fc4589917d0","type":"text","text":"단일 책임의 원칙을 지키려다 보면 한계에 봉착하게 된다.\n'결국 누군가는 여러개의 기능을 가지고 있을 수 밖에 없는데?'\n라는 생각에 빠지게 되었음.\n이걸 DI 기능을 제공해주는 framework 사용해서 해결하던가\n애그리게이터 패턴의 객체를 하나 만들던가 하는식으로 해결 할 수 있음.","x":820,"y":-86,"width":580,"height":166},
{"id":"b14a217bb0fd0b6a","x":1040,"y":180,"width":520,"height":400,"type":"file","file":"3.Resource (자료실)/클린 코드의 기술/애그리게이터의 주요 역할.md"},
{"id":"249ebdc4eafa6e80","x":620,"y":180,"width":400,"height":280,"type":"file","file":"3.Resource (자료실)/클린 코드의 기술/애그리게이터.md"},
{"id":"e69cff2fb722aa5e","x":1520,"y":-240,"width":640,"height":360,"type":"text","text":"애그리게이터 활용 예시\n- **사용자 인터페이스(UI)** \n 복잡한 UI 컴포넌트들을 조합하여 상위 UI 컴포넌트를 관리하는 데 애그리게이터를 사용할 수 있습니다. 예를 들어, 여러 개의 버튼, 텍스트 필드, 드롭다운 등을 하나의 큰 UI 컴포넌트로 묶을 수 있습니다.\n \n- **게임 개발** \n 게임에서는 캐릭터, 아이템, 맵 등의 다양한 객체들이 함께 동작하므로, 이를 조합하여 관리하는 애그리게이터가 필요합니다. 예를 들어, `GameEngine`이 여러 게임 객체들을 관리하는 역할을 할 수 있습니다.\n \n- **서비스 관리 시스템** \n 여러 서비스를 하나의 통합된 시스템에서 관리해야 할 때, 각 서비스 객체들을 애그리게이터로 묶어서 상위 시스템에서 관리할 수 있습니다."}
],
"edges":[
{"id":"6030b838f141758b","fromNode":"33d7d950058b35a0","fromSide":"bottom","toNode":"7642a3e2561f5690","toSide":"top"},
{"id":"3be70f6875fbc19b","fromNode":"33d7d950058b35a0","fromSide":"right","toNode":"05b38eceabbfff37","toSide":"left"},
{"id":"26cbb4e52b3c67bb","fromNode":"05b38eceabbfff37","fromSide":"top","toNode":"dd42f36c7e4e5b80","toSide":"bottom"},
{"id":"551424005689dc8d","fromNode":"33d7d950058b35a0","fromSide":"right","toNode":"ec406bdee9ca8b36","toSide":"left"},
{"id":"a4d3d983b072903f","fromNode":"05b38eceabbfff37","fromSide":"right","toNode":"abdc5fc4589917d0","toSide":"top"},
{"id":"9f0d95e70e7e4eb5","fromNode":"ec406bdee9ca8b36","fromSide":"right","toNode":"abdc5fc4589917d0","toSide":"left"},
{"id":"d201db751400f333","fromNode":"abdc5fc4589917d0","fromSide":"bottom","toNode":"249ebdc4eafa6e80","toSide":"top"},
{"id":"964cd9d639e29127","fromNode":"abdc5fc4589917d0","fromSide":"bottom","toNode":"b14a217bb0fd0b6a","toSide":"top"},
{"id":"d438a973851a5405","fromNode":"abdc5fc4589917d0","fromSide":"right","toNode":"e69cff2fb722aa5e","toSide":"left"}
]
}
@@ -0,0 +1,9 @@
==S==ingle ==R==esponsibility ==P==rinciple -> SRP
==클래스는 단 하나의 변경 이유만 가져야 한다.==
즉, **하나의 클래스는 하나의 책임([[객체의 책임]])을 가져야 한다**.
SRP가 함수에도 적용될 수는 있지만 기본적으로 SRP는 클래스의 책임을 다루는 원칙
함수는 함수의 단일 책임이라고 부를 수 있다.
@@ -0,0 +1,18 @@
객체가 다른 객체와 상호작용 할 때, 그 객체의 내부 구조나 구현에 대해 알지 못하도록 하는 원칙
객체가 자신이 직접적인 책임을 지고 있는 객체와만 상호작용 해야한다. [[객체의 책임]]
디미터의 법칙을 지키려면 다음의 상호작용만 하도록 해야함.
1. 자기 자신과만 상호작용한다.
2. (매개변수 등으로) 전달받은 객체하고만 상호작용 한다.
3. 반환값이 자신과 직접 연결된 객체가 아니면 그 객체의 메서드를 호출하지 않는다.
뭔소리냐? GPT에게 물어봤더니
getDriverName(){ return this.driver.name; } 이렇게 직접 driver의 property 에 접근하지 말고 this.driver.getName(); driver가 제공하는 함수를 통해서만 사용하라는 의미인거야?
맞습니다! 정확히 그런 의미입니다.
==디미터의 법칙을 지키려면, `Car` 객체가 `Driver` 객체의 **속성(property)**에 직접 접근하는 것을 피하고, `Driver` 객체가 제공하는 **메서드**를 통해서만 정보를 얻도록 해야 합니다.==
즉, `this.driver.name`처럼 `Driver` 객체의 **속성에 직접 접근**하는 것이 아니라, `this.driver.getName()`과 같은 **메서드를 통해** 정보를 요청해야 한다는 것입니다. 이렇게 하면 `Car` 객체는 `Driver` 객체의 구현 세부 사항을 알지 못하고, `Driver` 객체가 제공하는 인터페이스만을 사용하게 됩니다.
@@ -0,0 +1,3 @@
**애그리게이터(Aggregator)**는 **여러 개의 객체나 컴포넌트를 하나로 묶어서 관리하고, 이를 통해 상위 객체의 동작을 쉽게 조정하는 패턴**
**객체들이 직접적으로 서로 의존하지 않게** 하고, **하나의 객체로 통합**하여 기능을 제공할 수 있게 합니다.
@@ -0,0 +1,11 @@
1. **여러 객체를 통합하고 조정**
- 서로 다른 객체들이 개별적으로 동작하는 것이 아니라, 애그리게이터가 이들을 조합하여 전체적인 흐름을 제어합니다.
2. **객체들의 결합도를 낮추고 관리 용이성 제공**
- 애그리게이터는 하위 객체들을 **단일 진입점**으로 통합하여 외부에서 각 객체를 따로 조작하는 대신, 하나의 객체만을 조작하면 되므로 관리가 용이합니다.
3. **하위 객체의 책임을 숨기고, 상위 객체에만 집중**
- 애그리게이터는 하위 객체들의 **세부 구현**을 숨기고, **상위 객체에 필요한 기능**만 제공합니다.
@@ -0,0 +1,14 @@
1. 모든 요구 사항에 의문을 제기하라
(모든 사람은 종종 틀리기 마련이고 잘못 지시된 일에 시간을 투자하면 안된다.)
2. **부품이든 프로세스든 최대한 단순화하라**
(이건 다시 넣어야 할 것 같은데? 라는 생각이 들지 않으면 충분히 제거하지 않은 것)
(필요하지 않은 모든 요소를 제거해야한다.)
(혹시나 하는 마음에 쓸데없는 보험을 들지마라.)
3. 항상 단순화하고 최적화하라
(단, 정말 꼭 필요한 것들에 대해서만 단순화하고 최적화해라.)
(쓸데없는 문제를 해결하고 최적화하는 실수를 하지말자.)
4. 개발/생산 사이클을 빠르게 돌려라
(단, 앞의 3가지 원칙을 지키면서 달려야한다. 반드시)
(밍기적대지말고 열심히 달려라)
5. 모든 과정을 자동화하라.
(절대 이 순서를 반대로 진행하지마라.)
@@ -0,0 +1,5 @@
- **[[단일 책임 원칙]](SRP, Single Responsibility Principle)**을 따를 것
- **자신의 데이터는 스스로 관리할 것 (캡슐화)**
- **다른 [[객체의 책임]]을 침범하지 않을 것**
@@ -0,0 +1 @@
[[디미터의 법칙]]
@@ -0,0 +1,19 @@
[[단일 책임 원칙]]을 지키기 위한 방법 중 가장 자연스럽고 좋은 방법
하나의 책임만을 가지는 객체를 여러개의 클래스파일들에 분리해서 선언하고 관리하는것을 의미
![[Pasted image 20250319091803.png]]+
### **파일 분리를 하면 얻는 이점**
1. **가독성 증가**
- 한 파일에 여러 책임이 섞여 있으면 관리하기 어려움.
- 각 파일에 하나의 책임만 부여하면 **코드를 빠르게 이해할 수 있음**.
2. **유지보수 용이**
- 기능이 추가/수정될 때 필요한 클래스만 보면 됨.
- 특정 기능이 필요할 때 **어느 파일을 수정해야 할지 명확**함.
3. **재사용성 증가**
- 한 클래스가 한 가지 역할만 하면, **다른 프로젝트에서도 재사용하기 쉬움**.
- 예를 들어, `ReportGenerator`만 다른 시스템에서도 쉽게 활용 가능.
4. **충돌 방지**
- 여러 사람이 개발할 때, **같은 파일을 수정할 확률이 낮아짐**.
- 병합(merge) 충돌이 줄어들어 협업이 쉬워짐.
@@ -0,0 +1,93 @@
Node.js의 일반적인 패키지 구조 설계
MVC패턴
`controllers/`**HTTP 요청 처리** (Express 라우트에서 직접 연결)
`models/`**데이터베이스 모델** (Mongoose, Sequelize 등 ORM 사용)
`services/`**비즈니스 로직** (컨트롤러에서 서비스 호출)
`routes/`**라우팅 관리** (각 엔드포인트 정의)
`middlewares/`**공통 미들웨어** (인증, 예외 처리, 유효성 검사)
`utils/`**공통 유틸리티 함수**
Java에서는?
- **기능(도메인)별로 분리**
- **변경될 가능성이 높은 부분과 낮은 부분을 분리**
- **상위 패키지는 안정적이고, 하위 패키지는 유연하게 유지**
(1) 계층별 패키지 구조 (Layered Architecture)
com/example/app/
├── controller/ (API, UI 관련 로직)
├── service/ (비즈니스 로직)
├── repository/ (데이터 접근)
├── model/ (엔티티, DTO, VO)
├── config/ (설정 관련 클래스)
└── exception/ (예외 처리)
📌 **각 패키지가 역할별로 분리되어 있어 유지보수가 쉬움**
📌 하지만, **기능이 많아지면 서비스 계층이 너무 커질 수 있음**
(2) 기능(도메인)별 패키지 구조 (Domain-Driven Design, DDD 스타일)
com/example/app/
├── user/
│ ├── controller/
│ ├── service/
│ ├── repository/
│ ├── model/
│ └── exception/
├── order/
│ ├── controller/
│ ├── service/
│ ├── repository/
│ ├── model/
│ └── exception/
└── product/
├── controller/
├── service/
├── repository/
├── model/
└── exception/
📌 **각 기능(user, order, product 등)이 독립적이어서 관리가 쉬움**
📌 **각 기능을 모듈화하여 재사용 가능**
📌 **대규모 프로젝트에서 효과적** (ex. 마이크로서비스)
**➡ 장점: 변경이 한 기능에만 영향을 주므로 확장성이 좋음**
**➡ 단점: 작은 프로젝트에서는 과도할 수 있음**
: 작은 프로젝트도 DDD를 채택하고 패키지 구조를 단순화하면 된다.
**작은 프로젝트**라면, 패키지를 지나치게 분리할 필요 없이 다음과 같이 간단하게 유지할 수도 있습니다.
/com.example.simpleproject
├── **domain/**
│ ├── User.java
│ ├── Order.java
│ ├── Product.java
│ ├── UserRepository.java
│ ├── OrderRepository.java
│ ├── ProductRepository.java
│ └── OrderStatus.java (enum)
├── **service/**
│ ├── UserService.java
│ ├── OrderService.java
│ └── ProductService.java
├── controller/
│ ├── UserController.java
│ ├── OrderController.java
│ └── ProductController.java
├── repository/ => 선택
│ ├── JpaUserRepository.java
│ ├── JpaOrderRepository.java
│ └── JpaProductRepository.java
└── MainApplication.java
📌 **이 구조의 특징**
**도메인 로직(`domain`)과 서비스(`service`)를 나누되, 인프라 부분은 따로 관리하지 않음**
**필요하면 `repository` 패키지를 따로 만들어 DB 구현체를 분리**
**application 패키지를 없애고 서비스 계층을 단순화**
👉 **작은 프로젝트라면 위와 같은 구조로도 충분히 유지보수 가능**합니다.
![[Pasted image 20250319154830.png]]
- **도메인**은 핵심 비즈니스 로직과 모델을 다루고,
- **서비스**는 도메인 객체를 활용해 애플리케이션 로직을 처리하며,
- **인프라**는 외부 시스템과의 연결 및 구현을 담당합니다.
infra의 일부로 repository 가 있을 수 있다.
infra는 외부와의 상호작용 그 자체를 의미,
repository는 외부와의 상호작용 중 데이터베이스(DBMS 혹은 File in/output 등) 관련된 부분을 의미