π DTO λΆλ¦¬: μ©λλ³ μ μ© DTO μ€κ³
π§ 무μμ΄ λ¬Έμ μΈκ°μ?
νμ¬ ChapterRequestDtoλ μ¬λ¬ κ°μ§ μν μ ν λ²μ μννλ €λ βλ§λ₯ DTOβ κ° λμμ΅λλ€.
μ΄λ API μ€κ³μ λͺ νμ±μ μ¬κ°νκ² ν΄μΉλ μν°ν¨ν΄(Anti-Pattern) μ λλ€.
1. APIμ μλκ° λΆλΆλͺ ν΄μ§λλ€
searchChapter λ©μλλ μ΄λ¦ κ·Έλλ‘ βκ²μβμ μν κΈ°λ₯μ
λλ€.
κ·Έλ°λ° νλΌλ―Έν°λ‘ λ°λ ChapterRequestDtoμλ κ²μκ³Ό 무κ΄ν chapterNumberλ detailChapter κ°μ νλλ€μ΄ ν¬ν¨λμ΄ μμ΅λλ€.
APIλ₯Ό μ¬μ©νλ κ°λ°μλ βκ²μνλλ° μ΄ νλλ€μ μ νμνμ§? nullλ‘ λ³΄λ΄λ λλ?β λΌλ νΌλμ λΉ μ§κ² λ©λλ€.
2. μλͺ»λ λ°μ΄ν°κ° μ λ¬λ μ μμ΅λλ€
λ€λ₯Έ κ°λ°μκ° μ€ν΄νμ¬ κ²μ μ chapterTitleλΏλ§ μλλΌ λΆνμν detailChapter μ 보κΉμ§ μ±μμ λ³΄λΌ μ μμ΅λλ€.
μ΄λ λ€νΈμν¬ λλΉμΌ λΏλ§ μλλΌ, μλ² μΈ‘μμ μλμΉ μμ λμμ μ λ°ν μλ μλ μ μ¬μ λ²κ·Έμ μμΈμ΄ λ©λλ€.
3. λ¨μΌ μ± μ μμΉ(SRP) μλ°°
νμ¬ ChapterRequestDtoλ βμ±ν° μμ±μ© λ°μ΄ν°βμ βμ±ν° κ²μμ© λ°μ΄ν°βλΌλ λ κ°μ§ μ±
μμ λμμ μ§κ³ μμ΅λλ€.
μ’μ μννΈμ¨μ΄ μ€κ³λ κ° ν΄λμ€κ° λ¨ νλμ μ± μλ§ κ°λλ‘ νλ κ²μ λλ€.
β ν΄κ²° λ°©μ: μν μ λ°λΌ DTOλ₯Ό λΆλ¦¬νμΈμ
κ°μ₯ μ’μ ν΄κ²°μ± μ βμ©λμ λ§λ μ μ© DTOβ λ₯Ό κ°κ° λ§λ€μ΄ μ¬μ©νλ κ²μ λλ€.
1. κ²μ μ μ© DTO μμ±
κ²μμ νμν chapterName νλλ§ κ°μ§ ChapterSearchRequestDtoλ₯Ό μλ‘ λ§λλλ€.
ν΄λμ€ μ΄λ¦λ§ λ΄λ μ΄ DTOμ μν μ΄ λ¬΄μμΈμ§ λͺ ννκ² μ μ μμ΅λλ€.
π dto/request/ChapterSearchRequestDto.java (μ κ· μμ±)
package com.kobe.koreahistory.dto.request;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* 'μ±ν° κ²μ'μ΄λΌλ μν λ§ μννλ μ μ© DTO
*/
@Getter
@NoArgsConstructor
public class ChapterSearchRequestDto {
private String chapterName;
}
2. μμ±/μμ μ© DTO μ΄λ¦ λ³κ²½ (μ νμ¬νμ΄μ§λ§ κΆμ₯)
κΈ°μ‘΄ ChapterRequestDtoλ μ΄λ¦λ§ λ΄μλ μν μ μκΈ° μ΄λ ΅μ΅λλ€.
βμ±ν° μμ±βμ μ¬μ©λλ€λ©΄ ChapterCreateRequestDtoμ κ°μ΄ λ λͺ
νν μ΄λ¦μΌλ‘ λ³κ²½νλ κ²μ΄ μ’μ΅λλ€.
π dto/request/ChapterCreateRequestDto.java (μ΄λ¦ λ³κ²½)
package com.kobe.koreahistory.dto.request;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 'μ±ν° μμ±'μ νμν λͺ¨λ μ 보λ₯Ό λ΄λ DTO
*/
@Getter
@NoArgsConstructor
public class ChapterCreateRequestDto {
private int chapterNumber;
private String chapterTitle;
private List<DetailChapterRequestDto> detailChapters;
}
3. Controllerμ μ¬λ°λ₯Έ DTO μ μ©
μ΄μ KoreanHistoryControllerμ searchChapter λ©μλλ κ²μ μ μ© DTOμΈ ChapterSearchRequestDtoλ₯Ό μ¬μ©νλλ‘ μμ ν©λλ€.
π μμ λ KoreanHistoryController.java
package com.kobe.koreahistory.controller;
import com.kobe.koreahistory.dto.request.ChapterSearchRequestDto;
import com.kobe.koreahistory.dto.response.ChapterResponseDto;
import com.kobe.koreahistory.service.ChapterService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class KoreanHistoryController {
private final ChapterService chapterService;
@PostMapping("/search/chapters")
public ResponseEntity<ChapterResponseDto> searchChapters(
@RequestBody ChapterSearchRequestDto requestDto
) {
return ResponseEntity.ok(
chapterService.findChapterWithDetails(requestDto.getChapterName())
);
}
}
β¨ κ°μ νμ μ₯μ
API λͺ μΈμ λͺ νμ±
μ΄μ searchChapters APIλ₯Ό 보λ κ°λ°μλ μμ² Bodyμ chapterName νλλ§ λ£μΌλ©΄ λλ€λ μ¬μ€μ DTOμ μ΄λ¦κ³Ό νλλ§ λ³΄κ³ λ μ¦μ μ μ μμ΅λλ€.
νΌλμ μ¬μ§κ° μ¬λΌμ§λλ€.
μ μ§λ³΄μ μ©μ΄μ±
λμ€μ κ²μ μ‘°κ±΄μ΄ μΆκ°λλ©΄ ChapterSearchRequestDtoλ§ μμ νλ©΄ λ©λλ€.
μμ± λ‘μ§μ μλ¬΄λ° μν₯μ μ£Όμ§ μμ΅λλ€.
μμ μ±
λΆνμν λ°μ΄ν°κ° μλ²λ‘ μ λ¬λ κ°λ₯μ±μ μμ²μ μΌλ‘ μ°¨λ¨νμ¬ λ κ²¬κ³ ν μ½λκ° λ©λλ€.
π‘ κ²°λ‘
βνλμ DTOλ₯Ό μ¬λ¬ APIμμ λλ €μ°μ§ λ§κ³ , κ° APIμ μν μ λ§λ μ μ© DTOλ₯Ό λ§λ€λΌβ
DTO μ€κ³ μμΉ
- β μ©λλ³ λΆλ¦¬: μμ±μ©, μμ μ©, κ²μμ© DTOλ₯Ό κ°κ° λ§λ€κΈ°
- β λͺ νν λ€μ΄λ°: DTO μ΄λ¦λ§ λ΄λ μ©λλ₯Ό μ μ μκ²
- β λ¨μΌ μ± μ: νλμ DTOλ νλμ μν λ§
- β νμν νλλ§: λΆνμν νλλ ν¬ν¨νμ§ μκΈ°