π¨π»βπ» νμ¬ νμλ€μ μ½λλ¦¬λ·°κ° μ§νμ€μΈ μ¬νμΌλ‘ ν¬μ€νΈμ μμ±λ μΌλΆ μ½λκ° νμ μμ λ μ μμ΅λλ€.
μμΈν μ½λλ κΉνμ ν΅ν΄ νμΈμ΄ κ°λ₯ν©λλ€.
Link: [Feat/κ²μκΈμμ±] κ²μκΈ μμ± #30
λ΄κ° λ§‘μ κ²μκΈ μλΉμ€λ₯Ό κ°λ°νκΈ° μν΄ λ¨Όμ κ²μκΈ μμ±μ λν APIλ₯Ό κ°λ°νλ€.
API κ°λ° μμμ μμ μ€κ³ν ERDμ API λͺ
μΈμλ₯Ό ν΅ν΄μ Entity νμΈκ³Ό API pathλ₯Ό νμΈνλ€.
μ€κ³ν Entityλ₯Ό νμΈμ ν μ΄ν, κ²μκΈ μμ±μ νμν Dtoλ₯Ό μμ±νλ€.
νμ§λ§, μ΄μ μ λΆνμν μ½λλ₯Ό 1μ°¨μ μΌλ‘ νμΈνκ³ μμ νκ±°λ μ£Όμμ²λ¦¬λ₯Ό νμμλ λΆκ΅¬νκ³ λλ½λ μ½λλ₯Ό νμΈν΄κ³ μ΄ λΆλΆλ€μ μ κ±°ν΄μ£Όμλ€.
κ·Έλ¦¬κ³ λμ, μ μλ Dtoμ μ΄ν΄κ° λΆμ‘±ν΄μ Entityμ λͺ¨λ κ°μ λκ°μ΄ λ£μ΄μ€μ μ¬μ©νμΌλ, νμ¬λ μμ²μ νμνμ§μλ Columeμ ν¬ν¨νλ κ²μ΄ λΉν¨μ¨μ μΌλ‘ μκ°ν΄μ μμ²μ νμν Columeλ§μ Dtoλ‘ μμ±ν΄μ νμμ λ§μΆ° Dtoλ₯Ό μ¬μ©νλ € νλ€.
κ²μκΈ μμ±μ λν Dtoκ° νμνκΈ° λλ¬Έμ BoardRequestDto ν΄λμ€λ₯Ό μμ±νκ³ νμ ν΄λμ€λ‘ SaveRequestDtoλ₯Ό μμ±ν΄ μ£Όμλ€.
μ΄λ κ² λ΄λΆ ν΄λμ€(inner class)λ‘ μ μνλ κ²μ μ½λμ ꡬ쑰νμ μΊ‘μνλ₯Ό μν΄ μ¬μ©λλ€κ³ νλ€.
public class BoardRequestDto {
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public static class SaveRequestDto {
@NotBlank(message = "μ λͺ©μ μ
λ ₯ν΄μ£ΌμΈμ.")
private String title;
@NotBlank(message = "λ΄μ©μ μ
λ ₯ν΄μ£ΌμΈμ.")
private String content;
@NotNull(message = "μΉ΄ν
κ³ λ¦¬λ₯Ό μ νν΄μ£ΌμΈμ.")
private Category category;
@NotNull(message = "μ¬μ©μμ κ³ μ λ²νΈκ° μ‘΄μ¬νμ§ μμ΅λλ€.")
private Long memberId;
private LocalDateTime deadLine;
}
}
νμκ° νμ ν΄λμ€μ μμ±ν μ΄μ λ κ°λ¨νλ€. μ¬λ¬κ°μ ν΄λμ€λ₯Ό μμ±ν μ μμ§λ§, ν΄λμ€ νμΌμ΄ λ§μμ§λ©΄ μ€νλ € κ΄λ¦¬κ° 볡μ‘ν΄μ Έμ λΉν¨μ¨μ μΈ κ΄λ¦¬κ° λ μ μμ κ²μ΄λΌκ³ μκ°νκΈ° λλ¬Έμ΄λ€.
(κ°μΈμ μΈ μ΄μ μ
λλ€.)
π¨π»βπ» λ΄λΆ ν΄λμ€λ₯Ό μ¬μ©νλ μ΄μ
- μ½λ ꡬ쑰ν
λ΄λΆ ν΄λμ€λ₯Ό μ¬μ©νλ©΄ μ°κ΄λ ν΄λμ€λ₯Ό λ Όλ¦¬μ μΌλ‘ κ·Έλ£Ήνν μ μλ€.
SaveRequestDto
λBoardRequestDto
μ κ΄λ ¨λ κΈ°λ₯μ μ 곡νλ―λ‘, ν΄λμ€ λ΄μμ ν¨κ» μ μΈν¨μΌλ‘μ¨ κ΄λ ¨λ μ½λλ₯Ό ν κ³³μ μμΉμν¬ μ μλ€.- μ κ·Ό μ μ΄
λ΄λΆ ν΄λμ€λ₯Ό μ¬μ©νλ©΄ μΈλΆ ν΄λμ€μμ λ΄λΆ ν΄λμ€μ λ©€λ²μ μ§μ μ κ·Όνλ κ²μ μ νν μ μλ€.
λ΄λΆ ν΄λμ€λ₯Ό privateμΌλ‘ μ μΈνκ±°λ, νμμ λ°λΌ public, protected λ±μ μ κ·Ό μ μ΄μλ₯Ό μ¬μ©νμ¬ μΈλΆμμμ μ κ·Όμ μ νν μ μλ€.- μ½λ μμ§μ±
λ΄λΆ ν΄λμ€λ₯Ό μ¬μ©νλ©΄ ν΄λμ€ κ°μ κ΄λ ¨λ λ°μ΄ν°μ λμμ ν κ³³μ μ μ§ν μ μλ€.
SaveRequestDto
κ°BoardRequestDto
μ μΌλΆλ‘ μ μλμ΄ μκΈ° λλ¬Έμ,SaveRequestDto
μ λ°μ΄ν°μ λμμBoardRequestDto
μ λ°μ νκ² μ°κ΄λμ΄ μμ κ²μ΄λ€.
λ΄λΆ ν΄λμ€λ₯Ό μ¬μ©νλ κ²μ μ νμ¬νμ΄κ³ , μ½λμ ꡬ쑰μ μ€κ³μ λ°λΌ μ μ°νκ² λμ²ν μ μλ€.
μ΄μ , Dto μμ±μ μλ£νκ³ Service μΈν°νμ΄μ€μ κ²μκΈ μμ±μ λν λ©μλ(saveBoard)λ₯Ό μμ±ν΄μ£Όκ³ ꡬνμ²΄μΈ BoardServiceImpl ν΄λμ€λ₯Ό μμ±νλ€.
public interface BoardService {
//κ²μκΈ λ±λ‘ μμ² Method
Board saveBoard(BoardRequestDto.SaveRequestDto requestDto);
}
@RequiredArgsConstructor
@Log4j2
@Service
public class BoardServiceImpl implements BoardService {
private final BoardRepository boardRepository;
private final MemberRepository memberRepository;
@Override
public Board saveBoard(BoardRequestDto.SaveRequestDto requestDto) {
// μμ²λ λ°μ΄ν°λ‘ Member κ°μ²΄λ₯Ό μ‘°ν
Member member = memberRepository.findById(requestDto.getMemberId())
.orElseThrow(() -> new IllegalArgumentException("μ¬μ©μλ₯Ό μ°Ύμ μ μμ΅λλ€."));
// μΉ΄ν
κ³ λ¦¬ κ° μ€μ
Category category = requestDto.getCategory();
// Board Entity μμ±
Board board = Board.builder()
.member(member)
.category(category)
.title(requestDto.getTitle())
.content(requestDto.getContent())
.build();
return boardRepository.save(board);
}
}
κ·Έλ¦¬κ³ API λμμ μν΄μ μμ±ν Controller μ½λλ μλμ κ°λ€.
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/board")
public class BoardController {
private final BoardService boardService;
@PostMapping("/register")
public ResponseEntity<?> createBoard(@RequestBody @Valid BoardRequestDto.SaveRequestDto requestDto) {
Board savedBoard = boardService.saveBoard(requestDto);
// μλ΅ λ°μ΄ν° μμ±
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("msg", "success");
// κ²μκΈ μ 보
response.put("data", savedBoard);
return ResponseEntity.ok(response);
}
}
μ΄λ κ² ν΄μ κ²μκΈ μμ± APIλ₯Ό κ°λ°ν μ μμκ³ PostManμ ν΅ν΄ APIκ° μ λμνλμ§ ν μ€νΈλ₯Ό ν΄λ³΄μλ€.
μκ°ν΄λ³΄λ μ΄λ² νλ‘μ νΈλ ν λͺ¨λμ Memberμ JWT μ€μ ν¨ν€μ§λ₯Ό κ°μ§κ³ μκΈ° λλ¬Έμ κ°λ°νλ λμ€μλ JWTμ μΈμ¦μ κ±°μΉκ² λλ€. μ μ JWTλ₯Ό λ€λ£¬ κ²½νμ΄ μμ΄μ 401 μλ¬μ νμμ΄ μ±μ¬κ» μμ±ν΄μ€ message λλΆμ μ΄λ€ κ²μ΄ λ¬Έμ μΈμ§ λ°λ‘ μμ차릴 μ μμλ€.
JWTλ₯Ό νμΈνλ κ³Όμ μμ λ΄κ° μ§μ λ pathκ° κ²μ¦λμμ΄ λμκ³ , Memberμ κ°λ°μ΄ μμ±λμ§ μμ μνμμ κ²μκΈμ μμ±νλ €λ, μ μ μ μ°¨λλ‘ ν΄κ²°ν μλ μμλ€.
κ·Έλμ κ°λ° λ¨κ³μ΄κΈ° λλ¬Έμ, νμκ° μ§μ ν΄λ API path κ²½λ‘λ₯Ό κ²μ¦νμ§ μλλ‘ μμλ‘ κ΅¬νν΄λ λ€μμ Memberμ Boardμ κ°λ°μ΄ μλ£λλ©΄ κ·Έ μ΄νμ μμλ‘ μ§μ ν configλ₯Ό μμ ν΄μ ν
μ€νΈ νκΈ°λ‘ νλ€.
μνλ κ°μ DBμ μ μ μ₯μν¨ κ²λ νμΈνλ€. (νμλ MariaDBλ₯Ό μ¬μ©ν΄ κ°λ°μ μ§ννκ³ Toolλ‘ DBeaverλ₯Ό μ¬μ©νκ³ μλ€.)
μ½λ 리뷰λ₯Ό ν΅ν΄ μμ λ λ΄μ©μ΄ μλ€λ©΄ μΆκ°λ‘ κΈ°λ‘μ ν μμ