Conversation
There was a problem hiding this comment.
리뷰 늦어서 죄송합니다 🙇
PR 타이틀 바꿔주시구 체크리스트와 리뷰들 확인해주세요~
리뷰 남긴 부분 외에도 전체적으로 훑어보시고 수정이 필요해 보이시면 수정해주세요~
Controller와 RestController의 차이를 아셨다면 아래처럼 정리해보세요
- View를 반환해야하는 경우만 모아서 Controller에 작성
- JSON을 반환해야하는 경우만 모아서 RestController에 작성
6주차 실습 과제 요구사항 체크리스트
- CRUD API 작성
- GET /posts : 모든 article 보여주는 html view를 반환합니다.
- GET /articles : 모든 article을 조회합니다.
- GET /articles/{id} : 특정 article을 조회합니다.
- POST /articles : 새로운 article을 생성합니다.
- PUT /articles/{id} : 특정 article의 정보를 수정합니다.
- DELETE /articles/{id} : 특정 article을 삭제합니다.
- 본 실습에서도 DB는 사용하지 않는다
- 데이터 저장을 위해서 자료구조를 사용한다.
- Model을 주어진 조건에 맞게 구성한다.
- 회원 (Member)
- 고유 id
- 이름
- 이메일
- 비밀번호
- 게시글 (Article)
- 고유 id
- 작성자 id
- 게시판 id
- 제목
- 내용
- 작성일자
- 수정일자
- 게시판 (Board)
- 고유 id
- 게시판 이름
- 회원 (Member)
- Controller에는 비즈니스로직이 없어야한다.
- 비즈니스 로직을 수행하는 역할은 Service에서 수행한다.
- 저장되는 데이터를 읽고, 쓰는 역할은 Repository에서 수행한다.
| @@ -0,0 +1,15 @@ | |||
| package com.example.bcsd; | |||
| private Long boardId; | ||
| private LocalDateTime createTime; | ||
| private LocalDateTime modifiedTime; | ||
| private String authorName; |
| private final Map<Long, Article> articleStorage = new ConcurrentHashMap<>(); | ||
| private final AtomicLong articleIdCounter = new AtomicLong(); | ||
| private final Map<Long, Member> memberStorage = new ConcurrentHashMap<>(); | ||
| private final AtomicLong memberIdCounter = new AtomicLong(); | ||
| private final Map<Long, Board> boardStorage = new ConcurrentHashMap<>(); | ||
| private final AtomicLong boardIdCounter = new AtomicLong(); |
There was a problem hiding this comment.
이런 데이터를 저장하는 부분을 Repository로 분리하시면 됩니다.
Repository로 분리하실때 각 엔티티별로 분리하셔야 합니다. (e.g. ArticleRepository, MemberRepository, ...)
| List<Article> articles = new ArrayList<>(articleStorage.values()) | ||
| .stream() | ||
| .map(this::populateArticleDetails) | ||
| .collect(Collectors.toList()); |
There was a problem hiding this comment.
Repository로 분리했다면, 데이터를 가져와서 처리를 하는 비즈니스 로직은 작업은 어디서 해야할까요?
| public void setBoardId(Long boardId) { this.boardId = boardId; } | ||
|
|
||
| public LocalDateTime getCreateTime() { return createTime; } | ||
| public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } |
There was a problem hiding this comment.
변경되지 않아야 하는 값에 setter가 있다면 어떻게 될까요?
getter와 setter를 만들때, 정말로 필요한지 잘 생각해보고 만드시는 습관을 들이는게 좋습니다.
작성일자가 변경되는 경우가 있을까요?
| public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; } | ||
|
|
||
| public LocalDateTime getModifiedTime() { return modifiedTime; } | ||
| public void setModifiedTime(LocalDateTime modifiedTime) { this.modifiedTime = modifiedTime; } |
There was a problem hiding this comment.
수정 일자는 setter가 필요하겠지만 꼭 외부에서 값을 넘겨 받아야 할까요?
게시글이 수정되는 타이밍은 api가 호출되었을때 호출이 될테니 now()가 수정 시간이 되게 될겁니다.
그렇다면
public void updateModifiedTime() { this.modifiedTime = LocalDateTime.now(); }처럼 작성해도 되지 않을까요?
| if (article == null) { | ||
| return ResponseEntity.notFound().build(); | ||
| } |
There was a problem hiding this comment.
private final Map<Long, Article> articleRepo = new ConcurrentHashMap<>();를 Repository로 분리했다면, null처리는 어디서 하는게 좋을까요?
| @@ -0,0 +1,51 @@ | |||
| package com.example.bcsd; | |||
There was a problem hiding this comment.
이 Controller는 패키지 밖에 존재하는 이유가 있을까요?
이름이 겹쳐서 그런걸까요?
그렇다면 이름을 달리 해보는건 어떨까요? (e.g. ArticleRestController)
어노테이션을 사용하는 것까지는 이해하고 사용할 수 있었는데 그 안에 메소드를 생성하는 것이 어려웠습니다;; 여기저기서 자료를 찾아보고 구성하긴 했는데 이러한 형식으로 하는게 맞는지 잘 모르겠습니다. 처음 써보는 메소드도 많아서 너무 어렵네요...