Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions keyword/chapter04/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
### 아키텍처 구조

프로젝트의 뼈대를 어떻게 구성할지 미리 설계하는 것

**아키텍처 구조를 설계하는 목적**

- 유지보수의 용이성
- 목적에 따라 코드 분리를 해놓기 때문에 나중에 기능 추가할 때 큰 수정 필요 없음
- 정형화된 구조를 사용한다면 타인이 알아보기가 쉬워져서 타인과 협업, 유지보수하기 좋아짐

→ 따라서 다른 사람이 쉽게 이해하고 불필요한 의사소통을 최소화할 수 있는 구조를 짜는게 중요!

**아키텍처 구조의 종류**

- 계층 기반 구조 : 시스템 계층(controller, service 등)을 기준으로 파일을 분류 하는 것


- 장점
- 프로젝트를 패키지 구조만 보고 전체적인 구조를 파악할 수 있다
- 애플리케이션의 API를 보고 흐름을 파악하고 싶다면 Controller 패키지 하나만 보고 파악할 수 있다
- 애플리케이션의 비즈니스 로직을 보고 싶다면 Service 패키지 하나만 보고 파악할 수 있다
- 계층별 응집도가 높아진다
- 계층별 수정이 일어날 때, 하나의 패키지만 보면 된다
- 각 계층별 독립적인 테스트 가능
- 단점
- 도메인 별 응집도가 낮다
- user 도메인의 흐름을 보고 싶을 때 모든 패키지를 봐야함
- 한 도메인의 기능 변경 시 변경 범위가 크다
- 유스케이스 별로 쪼개는 것이 어려워진다
- 한 클래스 안에 다 넣자니 코드가 너무 길어져서 읽기 힘들어지고
- 한 패키지 안에 유스케이스 별로 다 쪼개서 넣으면 패키지 속에 클래스가 너무 많아서 파일 찾기가 힘듦
- 규모가 커지면 하나의 패키지 안에 여러 클래스가 있어서 구분이 어려워진다
- 도메인 기반 구조 : 도메인을 기준으로 파일을 분류하는 것


- 장점
- 도메인 별 응집도가 높아짐
- 한 도메인의 흐름을 보고 싶을 때 하나의 패키지만 보면 됨!
- 도메인 기능 변경 시 변경 범위가 작아짐!
- 유스케이스 별 세분화해서 표현 가능
- 단점
- 애플리케이션의 전체적인 흐름 파악하기 어렵
- 개발자의 관점에 따라 어느 패키지에 둘지 애매한 클래스 존재
- 도메인 간 협력 어려움

**→ 따라서 단순하게 보자면 규모가 작고 도메인이 적다면 아키텍처, 규모가 크고 도메인이 많다면 도메인형으로 선택하자!**

### Swagger

api를 구현하면 그에 맞춰서 자동으로 문서화 해주는 도구

- 장점
- 일일히 작성하지 않고 개발만 끝나면 자동으로 바로 작성
- 화면에서 직접 API 테스트가 가능
- postman 같은 별도의 앱 없이 웹에서 바로 파라미터를 입력하고 api 호출해보기가 가능!
- 단점
- 개발 끝나기 전까지 프론트가 현황을 확인 불가

**자주 사용하는 어노테이션**

- @Tag: API 그룹 짓기
- 비슷한 API들을 묶어서 제목과 설명을 달아줌
- 사용처 예시 : controller 클래스 위
- @Operation: API 기능 설명
- 한 API가 구체적으로 어떤 기능을 하는지 설명
- @ApiResponse: 상태 코드별 응답 설명
- 성공하면 200번, 실패하면 404번 같은 상태 코드를 미리 설명
- @Parameter: 요청 변수 설명
- @PathVariable이나 @RequestParam이 어떤 의미인지, 예시 값은 무엇인지 적어줍니다
- @Schema: DTO 필드 설명
- 요청으로 어떤 값을 받을지, 응답으로 어떤 값이 나갈지를 설명

```java
@Tag(name = "학식 메뉴 API", description = "기숙사 및 학생식당 메뉴 관련 API입니다.")
@RestController
@RequestMapping("/api/menus")
public class MenuController {

@Operation(summary = "오늘의 메뉴 조회", description = "특정 식당의 오늘의 메뉴 목록을 가져옵니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "메뉴 조회 성공"),
@ApiResponse(responseCode = "404", description = "해당 식당을 찾을 수 없음")
})
@GetMapping("/{restaurantId}")
public List<MenuResponseDto> getTodayMenu(
@Parameter(description = "식당 ID (예: 1-학생회관, 2-기숙사)", example = "2")
@PathVariable Long restaurantId) {

// ... 메뉴 조회 로직 ...
return menuList;
}
}
```

```java
@Getter
public class MenuResponseDto {

@Schema(description = "메뉴 이름", example = "치즈돈까스")
private String menuName;

@Schema(description = "메뉴 가격", example = "5500")
private int price;

@Schema(description = "품절 여부", example = "false")
private boolean isSoldOut;
}
```

### 도메인형 아키텍처

도메인을 기준으로 파일을 분류하는 것


- 장점
- 도메인 별 응집도가 높아짐
- 한 도메인의 흐름을 보고 싶을 때 하나의 패키지만 보면 됨!
- 도메인 기능 변경 시 변경 범위가 작아짐!
- 유스케이스 별 세분화해서 표현 가능
- 단점
- 애플리케이션의 전체적인 흐름 파악하기 어렵
- 개발자의 관점에 따라 어느 패키지에 둘지 애매한 클래스 존재
- 도메인 간 협력 어려움

프로젝트 전반적으로 사용되는 config, auth, error 같은 클래스들은 domain과 같은 레벨에서 global이라는 패키징 안에 구성한다

### DDD vs 도메인형 아키텍처
- 도메인형 아키텍처는 패키지의 구조를 설계하는 방식이고 DDD(도메인 주도 설계)는 그것보다 더 거대한 개념으로 소프트웨어 시스템을 설계하고 개발하는 것에 대한 방법론이다

### DDD (Domain-Driven Design, 도메인 주도 설계)

도메인 모델을 기반으로 복잡한 소프트웨어 시스템을 설계하고 개발
여기서 도메인이란 비즈니스 문제 영역을 말한다 메뉴 도메인, 리뷰 도메인 같이 큰 문제 공간을 예시로 들 수 있다

- **이를 통해 각각 도메인을 철저히 분리하여 높은 응집력과 낮은 결합도로 변경과 확장에 용이하다!**

**DDD 핵심 개념**

- 도메인 모델 : 도메인 전문가와 개발자가 공유하는 비즈니스 지식을 소프트웨어로 표현한 핵심 모델입니다
- 엔티티
- 고유 식별자(ID)를 가진 객체입니다
- 데이터가 변해도 식별자를 통해 동일한 객체로 계속 추적할 수 있습니다 (예: 사용자, 미션, 가게)
- 밸류 오브젝트 (Value Object)
- 고유 식별자가 없고 값 자체가 중요한 불변 객체입니다
- 값이 같으면 완전히 동일한 객체로 취급하며, 변경 시 통째로 교체합니다 (예: 주소, 금액, 날짜)
- 애그리게이트 (Aggregate) & 애그리게이트 루트 (Aggregate Root)
- 애그리게이트**:** 데이터 일관성을 유지하기 위해 관련된 엔티티와 밸류 오브젝트를 한 덩어리트랜잭션 단위로 묶은 집합입니다
- 애그리게이트 루트: 이 덩어리를 대표하는 대장 엔티티입니다. 외부에서는 무조건 루트를 통해서만 내부 데이터를 변경할 수 있도록 철저히 통제합니다
- 리포지토리
- 도메인 객체를 DB 같은 영구 저장소에 저장하고 조회하는 인터페이스입니다
- DDD에서 리포지토리는 모든 엔티티마다 만드는 것이 아니라, 오직 애그리게이트 루트 단위로만 생성합니다.
- 애플리케이션 서비스 (Application Service)
- 정의: 사용자의 요청을 받아 도메인 객체들을 조종하는 흐름 제어자
- 특징: 서비스 클래스 안에 복잡한 계산이나 비즈니스 규칙을 직접 적지 않습니다. DB에서 엔티티를 꺼내고, 엔티티에게 로직을 실행하라고 명령한 뒤, 그 결과를 다시 DB에 저장하는 역할만 담당합니다.

**계층 구조**


- Presentation Layer
- controller에 해당
- 사용자의 요청을 받고 응답을 반환하는 api 정의
- Application Layer
- service에 해당
- 하지만 기존 아키텍처 구조에서의 service하고는 다름
- 절대로 비즈니스 로직이 들어가면 안되고 오직 도메인 객체를 불러와 작업을 위임하고 트랜잭션을 관리하는 흐름 제어 역할
- Domain Layer
- model에 해당
- 엔티티를 활용하여 도메인 로직이 실행되며, 업무 상황을 반영하여 상태를 제어하는 역할
- Infrastructure Layer
- Repository에 해당
- db등 외부와 통신해서 얻어 온 정보를 도메인 계층, 응용 계층 등에 전달하는 것이 주목적

| **구분** | **도메인형 아키텍처** | **DDD (도메인 주도 설계)** |
| --- | --- | --- |
| **정체** | 코드를 담는 **패키지 구조** | 소프트웨어를 설계하는 **거대한 방법론** |
| **핵심** | `Controller`, `Service` 등을 역할이 아닌 **기능(User, Mission 등) 단위로 같은 폴더에 묶음** | 현실의 비즈니스 규칙을 응용 계층(Service)이 아닌 **도메인 객체(Entity, Aggregate) 안에 직접 구현**함 |
| **목적** | 유지보수 편하게 | 복잡한 비즈니스 규칙 캡슐화 → 데이터의 일관성 |

### 왜 DTO를 사용하는가?
### DTO

계층 간 데이터 교환을 위해서 사용하는 객체
로직을 가지지 않고 순수하게 데이터를 주고 받을 수 있도록 Getter, Setter만 가짐

**<사용 목적>**

- entity와의 결합도 낮추기
- Entity는 데이터베이스의 테이블과 1:1로 매핑되는데 이를 api 응답으로 바로 사용하게 된다면 후에 데이터베이스의 구조나 칼럼명이 바뀔 때마다 api도 바뀌게 됨
- 민감한 정보 숨기기+클라이언트에게 딱 맞는 데이터 제공
- DB와 연결된 Entity 객체를 바로 클라이언트에게 주기에는 민감한 정보나 화면에 필요 없는 정보 등이 있을 수 있으니 DTO로 필요한 정보만 담아서 준다
- 입력값 검증 책임 분리
- 비즈니스 로직을 entity에 붙이지 않고 DTO에서 해결해서 entity는 비즈니스 로직에만 집중하게 한다
- 클라 - 서버 호출 최소화
- 여러 개의 api가 필요할 때 거기서 필요한 모든 데이터들을 가진 DTO 하나만 보낸다면 호출 비용을 최소화 가능

### 컨버터는 왜 사용하는가?
### **컨버터**

- Entity를 DTO로 변환하거나, 반대로 DTO를 Entity로 변환하는 매핑 로직만을 전담하는 객체

**<사용 목적>**

- **단일 책임 원칙(SRP) 준수 및 서비스 코드 정돈**
- Service 계층은 비즈니스 흐름을 제어하는 본연의 역할에만 집중해야 함
- 데이터를 하나하나 옮겨 담는 단순 매핑 코드를 컨버터로 분리하여, Service 코드가 노가다성 코드로 지저분해지는 것을 방지
- **코드 재사용성 극대화 (중복 방지)**
- 단건 조회, 전체 목록 조회, 추천 조회 등 여러 API에서 동일한 DTO 변환이 필요할 때, 세팅 코드를 복사/붙여넣기 할 필요 없이 컨버터의 메서드 한 줄로 재사용 가능
- **유지보수의 편의성 (수정 범위 최소화)**
- 추후 요구사항이 변경되어 DTO에 새로운 데이터 필드가 추가될 경우, 해당 DTO를 사용하는 모든 `Service` 파일을 일일이 찾아 고칠 필요 없이 컨버터 클래스 딱 한 곳만 수정하면 전체 시스템에 일괄 적용됨
13 changes: 13 additions & 0 deletions mission/chapter03/mission.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
### 워크북 캡쳐

![워크북.png](워크북.png)

### 워크북 리뷰

<aside>
🌟

나는 프록시의 개념밖에 조사하지 못했는데 구체적으로 프록시의 종류에 대해서 조사하신 것이 좋았다

</aside>

- **미션 기록**

### 스프링의 요청 및 응답 흐름 (Spring MVC 흐름)
Expand Down
Binary file added mission/chapter03/워크북.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.