Skip to content

Conversation

@jongmee
Copy link

@jongmee jongmee commented Apr 16, 2024

안녕하세요 수달! Level 2 첫 미션 잘 부탁드립니다 🙇🏻‍♀️

웹 개발 경험

  • 웹 어플리케이션의 Restful 서버를 만들고 배포해 본 경험이 2회 있습니다. (Thymeleaf를 활용한 프로젝트 경험은 없습니다.)
  • 미션에서 사용할 Springboot, Java, JPA, H2를 사용해본 적 있습니다.
  • Springboot 공부 및 프로젝트를 시작한 지는 1년이 조금 넘었습니다.

ay-eonii and others added 18 commits April 16, 2024 14:19
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Copy link

@her0807 her0807 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 미아!

리뷰어 수달입니다 ㅎㅎ
빠르게 구현해주셔서 놀랐어요~
커밋 시간을 보니 어제 2시부터 10시 까지 내리 했던데
열정이 대단합니다.

미아는 스프링에 대해서 구현 경험이 있다고 하셨는데요!
그래서 적절한 annotation 을 사용해서 spring 으로 view 를 적절히 반환하도록 요구사항이 충족된 것 같아요. 아주 잘하셨습니다.

그런데 레벨 1 때 저희가 연습했던 도메인 객체에 대해서 직접 요구사항을 도출해보고 검증하고, 단위테스트를 해보았던 것들이 코드에서 잘 보이지 않더라고요 ㅠㅠ

물론 요구사항에 적혀있지 않아서 그럴수도 있지만, 저희는 점진적으로 더 나음을 도모해야하니까요! 레벨 1 때 것들도 함께 챙겨나가볼까요?

import java.util.concurrent.atomic.AtomicLong;

@Controller
public class AdminController {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller 에서 repository 를 바로 의존하고 있는데요,

그러다보니 도메인에서 DTO 를 만드는 형태로 간결함에 초점을 두고 개발해주신 것 같아요!!

가독성 좋고 읽기 깔끔하지만, 도메인에 뷰의 변경에 따른 전파가 가기 때문에

service layer 를 두어 검증과 계층 별 의존성 분리 역할을 주면 어떨까요? 😁

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기능 요구 사항을 만족하는 간결한 프로그램을 생각하며 구현하다 보니 전체적으로 도메인이 뷰의 변경에 영향을 받는 구조가 되었네요 🥲

Service layer를 추가하여 계층 분리를 하고, 검증(예약 id 검증)을 service layer에서 하도록 변경하였습니다. 우선 Presentation 계층인 controller만 dto를 사용하도록 하여 service에서는 dto를 생성하거나, dto에서 entity를 변환하는 로직 등은 존재하지 않도록 구현하였는데, 수달은 이에 대해 어떻게 생각하시나요?

저는 DTO의 역할이 아래와 같다고 생각합니다. (DTO를 controller에서만 사용한 이유)

  1. 뷰의 변경에 도메인이 영향을 받지 않고, 도메인 자체를 뷰에 노출시키지 않는다.
  2. 현재 DTO(ReservationResponse, ReservationSaveRequest)는 요청과 응답에서 데이터를 전달하고, 컨트롤러의 역할에서 필요하다.

이것저것 레퍼런스를 찾아보니 의견이 나뉘는 것 같은데(controller에서만 사용한다, controller와 service에서 모두 사용한다) 수달은 현재 현업에서 어떤 의견을 가지고 사용하고 계신지 궁금합니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 고민이네요!

저는 dto는 controller에서 dto -> domain 으로 변환하여 의존성을 끊어서 사용하고 있어요.
이유는 미아가 말씀해주신 영역도 있고, service layer 가 여러 곳에서 재사용될 여지가 큰데, dto 의 형태가 일정하지 않으니
재사용성에도 좋지 않고, 뷰 변경에 대한 영향도 전파되기 때문이에요!

그러나 재사용성이 적고, 뷰와 도메인이 항상 핏하게 떨어질 경우 혹은 개발 초기 단계에 빠르게 치고 나가야하는 경우에서는
controller와 service 모두 혼용해서 사용하기도 하는 것 같아요.

transfer 한다는 것은 여러 고민들이 수반되어야하기 때문인데요. (어느곳에서 어떤 형태로 변환해줄것인지 등등 또 얼마나 잘게 나눌 것인가에 대한 고민도요!)

다만,service 에서 controller 로 응답값을 반환할 때는 domain -> reseponse dto 로 꼭 변환해주는 편이에요.
controller 는 model 과 view 사이에 중개자 역할을 하는 것인데 도메인을 반환하게되면
controller 영역에서 의도치 않게 도메인에 상태를 변경할 수도 있기 때문인데요! JPA 를 써보셨다고 하셔서 첨언드리면
JPA 의 장점 중 하나인 Dirty Checking 이 일어나서 의도치 않게 변경점이 DB 까지 이어지기도 하고요!

@jongmee
Copy link
Author

jongmee commented Apr 18, 2024

안녕하세요 수달! 리뷰에 코멘트 및 질문 남겨놓았습니다 :)

  • 추가로, 리팩토링 및 추가 검증을 구현하면서 최대한 단위 테스트를 진행하려고 하였습니다!

Copy link

@her0807 her0807 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 미아! ㅎㅎ

워밍업 제대로 된 것 같은데요? 🎉
질문주신 내용과 간단한 코멘트들 남겼습니다 :)
해당 코멘트들은 다음 단계 진행하면서 함께 반영해주시면 좋을 것 같아요👍🏻


import java.util.List;

@RestController
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻


@PostMapping
public ResponseEntity<ReservationResponse> createReservation(@RequestBody ReservationSaveRequest request) {
var reservation = request.toReservation();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dto, -> domain 변환할 때 toModel 이라는 메서드명을 자주 사용하는 것 같아요 🙂

import java.util.List;

@RestController
@RequestMapping("/reservations")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공통된 url 를 묶어두셨군요 👍🏻 잘하셨습니다

Comment on lines +27 to +32
if (existingSameUser) {
throw new IllegalArgumentException("동일한 시간에 같은 사용자가 예약할 수 없습니다.");
}
if (reservationsInSameDateTime.size() >= MAX_RESERVATION_PER_TIME) {
throw new IllegalArgumentException("해당 시간대에 예약이 모두 찼습니다. (최대 4팀)");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

검증 로직을 따로 추출해볼까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private 메소드로 추출하였습니다 :)

return reservationRepository.save(reservation);
}

public void deleteReservation(Long id) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

Comment on lines +1 to +3
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 해당 속성들은 어떤 이유로 추가하셨나요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스크린샷 2024-04-19 오후 2 35 49

처음에 MockMvc로 컨트롤러 슬라이싱 테스트를 할 때 json의 String을 검증했는데 한글 인코딩 때문에 제대로 검증이 되지 않아 해당 설정을 추가했습니다! 하지만 아래처럼 jsonPath로 변경하니(단순 문자열 체크를 하지 않으니) 인코딩 문제가 발생하지 않아 더 이상 해당 설정은 필요 없습니다..!

.andExpect(jsonPath("$[0].name").value(USER_MIA))

삭제해야 했는데 빠뜨렸네요 🥲 삭제하였습니다!

@DisplayName("이미 초기화된 예약 ID를 초기화(수정)할 경우 예외가 발생한다.")
void initializeId() {
// given
Reservation reservation = new Reservation(USER_MIA, MIA_RESERVATION_DATE, MIA_RESERVATION_TIME);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트를 위해 반복 생성되는 객체들은 Test Fixture 로 추출해도 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇네요! Reservation 객체도 TestFixture로 추출하였습니다.

}

@Test
@DisplayName("동일한 시간대에 최대 4팀이 예약할 수 있다. 초과되면 예외가 발생한다.")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

귀여운 요구사항을 적용시켰군요 고마워요 🤩

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants