-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Seminar3] 필수 과제 구현 #10
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다! 어떤 구조로 가져갈지 고민하시고 잘 분리하신 것 같아 많이 배울 수 있었습니다 🤗
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 enum은 어디에 분리할지 고민을 했었는데 entity에 분리하셨군요!!
diaryRepository.save( | ||
new DiaryEntity(diaryRequest.title(), | ||
diaryRequest.content(), | ||
diaryRequest.category(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diaryRequest의 category가 Category타입이면 all도 category로 저장될 수 있을 것 같은데 이 부분에 대해선 의도하신걸까요!?
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Transactional(readOnly=true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Transactional에 readOnly true가 어떤 역할인가요!?
import java.time.LocalDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
@Component |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DiaryFormatter에 Component 어노테이션을 붙인 이유가 있을까요!?
} | ||
|
||
|
||
public DiaryListRes getDiariesResponse(Category category, SortType sortType, boolean isMine, Long userId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
세미나 시간에 getDiariesResponse가 if else가 너무 많다고 하ㅅ셨는데, /diaries/my 와 /diaries에서 둘다 호출되고 있는 경우때문에 그렇군용!
두 api에서 하나의 함수를 사용하면 중복되는 코드가 줄여지는 장점이 있겠지만, 코드가 너무 길어져서 함수의 역할이 많아질 수도 있지 않을까요?!
|
||
@GetMapping("/my") | ||
public ResponseEntity<DiaryListRes> getMyDiaries( | ||
@Valid @RequestHeader("userId") long userId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시 존재하지 않는 유저 아이디가 들어왔을 때는 어떻게 처리하나용?
import java.util.Optional; | ||
|
||
public interface UserRepository extends JpaRepository<UserEntity,Long> { | ||
Optional<UserEntity> findByLoginIdAndPassword(String loginId, String password); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 findByLoginId 이후 해당 user의 비번을 비교하는 과정을 거쳤는데 해당 메서드를 사용하는게 훨 깔끔할 것 같네요 !! 👍🏻
BAD_REQUEST(HttpStatus.BAD_REQUEST, "USER004", "로그인 정보가 올바르지 않습니다."), | ||
|
||
//diary | ||
INVALID_INPUT_LENGTH(HttpStatus.LENGTH_REQUIRED, "diary001", "글자수를 다시 확인해주세요"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
title이나 content의 글자수는 특정 필드의 규칙이므로 400 error가 좀 더 적합하지 않을까요?! 저도 411 Error에 대해서 잘 알진 못하지만 Content-Length header가 잘못되었을 때 보내는 에러 같아서요!
https://www.holisticseo.digital/technical-seo/status-code/400s/411/
🔥 Pull requests
⛳️ 작업한 브랜치
👷 작업한 내용
Entity와 도메인의 차이
DAO
와 구분 없이Repository
가 사용되기도 합니다.패키지 구조
계층형: 각 계층을 대표하는 디렉터리를 기준으로 만들어집니다.
도메인형: 도메인 디렉터리를 기준으로 구분합니다.
제가 선택한 방법은 계층형입니다. 그 이유는, 도메인으로 나눌 만큼 구조가 복잡하지 않아서 계층형으로도 충분하다고 생각했기 때문입니다. 제가 생각한 패키지 및 클래스 구조는 아래와 같습니다.


DTO를 사용한다고 했을 때,
Request
와Response
는 어떻게 구분해야 할까요?RequestDTO
,ResponseDTO
도 DTO의 일종입니다. 제가 이해한 DTO는 엔티티가 외부에 노출되지 않도록 하고, 역할을 명확하게 분리하기 위해 Controller와 Service 사이에서 중간 다리 역할을 해주는 객체입니다. 따라서 세 가지를 따로 구분할지 고민하던 중, DTO를 InnerCase로 관리하는 방법을 알게 되었습니다. DTO를Response
,Request
마다 생성하면 너무 많아질 수 있지만, InnerCase로 관리하면 이를 줄일 수 있습니다. 그러나 코드의 가독성을 위해 최종적으로는 따로 분리하여 구현했습니다.목록 구현 방법
isPrivate
이어도 보이도록 구현했습니다. 처음에는 이러한 조건이 없어서 JPQL과 Spring Data JPA를 사용해 구현했으나, 코드의 가독성이 떨어졌고 더 효율적인 구현 방법을 찾고자 UML 다이어그램을 작성하여 구체화했습니다.목록 조회를 할 때 생각해 본 방안은 세 가지입니다. 최종적으로 선택한 것은 3번 방법입니다.
findAll()
로 가져와서 서비스 레이어에서 필터링 및 정리하기 → 성능 이슈 발생/my
로 들어오는 요청 →findByUserId
/
로 들어오지만userId
가 없는 요청 (유저의 일기인지 필터링할 필요 없음) →findAllByIsPrivateFalse
/
로 들어오는데userId
가 있는 요청 (유저의 일기인지 필터링할 필요 있음) →findByUserIdOrIsPrivateFalse
그 외에 공통적으로 처리해야 하는
sortType
관련 부분은Comparator
를 이용해 처리하고,limit()
함수를 사용해 개수를 제한하며,filter()
를 통해 카테고리를 필터링했습니다.Comparator, Comparable
객체를 비교하는 방법으로 두 가지 인터페이스인
Comparator
와Comparable
을 사용할 수 있습니다. 이 두 인터페이스의 가장 큰 차이는 자기 자신과 비교할 수 있는지 여부입니다.Comparable
compareTo(T o)
메서드를 사용합니다.ClassName.compareTo(o)
로 호출할 수 있으며, 들어온 파라미터o
가 비교할 객체가 됩니다.Comparator
compare(T o1, T o2)
메서드를 사용합니다.java.util
패키지에 포함되어 있으므로import
가 필요합니다.🚨 참고 사항
노션 페이지
@Transactional
에 대한 개념이 아직 완전히 잡히지 않아서 추가적으로 공부가 필요할 것 같습니다. 이 부분에 대해 조금 더 피드백을 주시면 감사하겠습니다