-
Notifications
You must be signed in to change notification settings - Fork 169
[Spring JDBC] 서현진 5,6,7 단계 미션 제출합니다. #525
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
[Spring JDBC] 서현진 5,6,7 단계 미션 제출합니다. #525
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.
안녕하세요, 서현진님 😄
핵심 내용을 너무 잘 설명해주셔서 Spring을 처음 공부하셨다는 걸 보고선 놀랐네요!
궁금한 점에 대한 답변과 제가 코드 리뷰를 하며 궁금했던 점을 몇 가지 남겨봤는데, 확인해주시고 천천히 답변 부탁드릴게요!
저도 잘 부탁드립니다😄
궁금한 점에 대한 답변
DTO 변환 위치: 현재는 Controller에서 requestDto.toEntity()를 호출하여 Service에는 엔티티를 넘겨주고 있습니다. Service가 DTO를 모르게 하려는 의도였는데, Service가 DTO를 받아서 변환하는 방식과 현재 방식 중 어떤 것을 더 선호하시는지 궁금합니다.
- 저는 검증이 어디서 이루어지느냐에 따라 기준을 두는 편이에요!
- 만약
@Valid어노테이션이나 생성자 단계에서 검증이 끝난다면 컨트롤러에서 변환 후 서비스로 넘겨주고, 서비스 계층에서 비즈니스 로직과 결합된 복잡한 검증이 필요하다면 DTO 그대로 넘겨서 서비스 내부에서 변환하기도 합니다. - 다만 이렇게 혼용하면 변환 로직이 분산될 수 있어서, 팀이나 프로젝트의 컨벤션에 맞춰 한 곳으로 통일하는 것이 유지보수에 더 좋다고 생각해요!
멱등성 키 생성: 클라이언트가 키를 보내지 않았을 때 Controller에서 UUID(Universally Unique Identifier)로 생성해주고 있습니다. 이 처리가 적절한지, 혹은 더 나은 처리 방식이 있을지 조언 부탁드립니다.
- 작성해주신 코드를 보니
Reservation의 PK는 DB에서KeyHolder를 통해 관리하고, 멱등성 키는 별도 테이블인idempotency_keys로 잘 분리해서 관리하고 계시네요! 구조를 고민하신 흔적이 보입니다 👍 - 다만 Controller에서 키를
UUID로 랜덤 생성하는 부분은 다시 생각해보시면 좋을 것 같아요. - 멱등성 키의 핵심은 클라이언트가 같은 요청을 다시 보냈을 때 서버가 이건 아까 처리한 요청이네 하고 알아차리는 것입니다.
- 그런데 지금처럼 키가 없을 때 서버가 매번 새로운
UUID를 발급해버리면, 클라이언트가 실수로 요청을 두 번 보냈을 때 서버는 서로 다른 요청으로 인식하게 됩니다. - 현재 작성해주신
existsByDateAndTime메서드 덕분에 데이터가 중복 저장되진 않겠지만, 앞단에서 의도하신 멱등성 로직은 사실상 통과되어버리는 상태가 됩니다. - 멱등성 패턴을 사용하는 이유는 단순히 중복 저장을 막는 것을 넘어, 네트워크 오류로 응답을 못 받은 클라이언트가 재요청을 했을 때 에러 대신 성공 응답을 다시 내려주기 위함도 큽니다.
- 따라서 이 이점을 제대로 살리려면 클라이언트가 헤더에 유니크한 키를 필수로 담아 보내도록 강제하거나, Request Body 내용을 기반으로 키를 생성하는 방식이 더 적절합니다!
전달드린 답변이 도움이 되셨으면 좋겠네요!
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.
현재 테스트 코드를 count로 체크하고 있는데, 저장의 경우에는 어떤 데이터가 올바르게 저장되었는지 확인하는 과정이 필요하진 않을까요?
실제로 내부 로직에 의해 값이 변하는 형태(타입 변환 등)라면 데이터 저장 시 저희가 예측하지 못한 값이 저장될 가능성이 높기 때문에 테스트 코드는 단순히 갯수를 통해 검증하는 것이 아닌 실제 예측한 값이 정상적으로 저장되었는지 확인하는 과정이 필요해요!
그리고, 성공 케이스가 아닌 실패 케이스도 같이 고려해서 작성해주시면 더 좋을 것 같아요😊
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.
준수 님의 리뷰를 정리해보니 다음과 같이 정리되는 것 같습니다.
- 무조건 데이터를 입력 후 카운트를 1을 찍는 것은 클라이언트가 원하는 값이 잘 들어갔나 확인해 보기엔 너무 테스트 코드로서 가치가 없다.
- 따라서 어떤 값이 들어갔는지 확인해보는 코드가 필요하다. -> 그래서 db에 접근해서 그 값인지 확인해 보는 코드가 있으면 좋을 것 같다.
- 실패와 성공에 대한 테스트 코드가 필요하다. 고의적으로 데이터 형식에 맞지 않는 값을 만들어서 집어 넣어보는 테스트도 필요해 보인다.
위 내용들을 기반으로 실제 db에 접근해서 의도했던 입력 값이 들어갔는지 확인 하는 "성공"테스트 코드를 작성해보았습니다.
또한 "실패" 테스트 코드도 작성해보았습니다.
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.
작성해 주신 테스트 코드를 보니 JdbcTemplate을 사용하여 DB에 데이터가 실제로 잘 저장되었는지 직접 검증해 주셨네요! 👍
이렇게 실제 DB 값을 확인하는 방식은 테스트의 신뢰도가 높다는 장점이 있습니다. 하지만 실제 DB를 조작하기 때문에, 만약 운영 환경 설정이 연결된 상태에서 이 테스트가 실행되면 실제 데이터가 수정되거나 삭제될 위험이 있습니다.
따라서, 이런 테스트를 작성할 때는 반드시 로컬이나 테스트 전용 DB 환경에서만 실행되도록 환경 분리에 신경 써야 한다는 점을 기억해 주시면 좋을 것 같습니다!
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.
##테스트를 위한 DB 준비 방법
준수님의 리뷰를 읽고나서 어떤 방식으로 테스트DB를 만들 수 있을까 찾아보았습니다.

H2+ @transactional 을 사용하여 db에서 테스트 코드를 작동시키는 방식이 좋은 방식이 인 것 같아 어떻게 사용되는지도 찾아보았습니다.
# src/test/resources/application.yml
spring:
config:
activate:
on-profile: test # test 프로파일에서만 동작
datasource:
url: jdbc:h2:mem:testdb;MODE=MySQL # 메모리 DB 사용 (MySQL 모드)
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create # 테스트 시작 때 테이블 다 새로 만듦
show-sql: true
@SpringBootTest
@ActiveProfiles("test") // 위에서 설정한 'test' 환경 적용
@Transactional // 테스트 끝나면 데이터 롤백 (뒷정리)
class MemberServiceTest {
@Test
void 회원가입_테스트() {
// given
// when
// then
}
}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.
좋네요! 저도 이전에 프로젝트 진행할 때 사용했던 방식입니다!
테스트 환경에서는 일반적으로 ddl-auto 설정으로 create-drop 을 주로 사용합니다. 참고해주시면 좋겠네요!
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.
Database의 url과 h2에 대한 설정으로 보이네요!
각각 어떤 설정을 의미하는지 설명해주실 수 있을까요?
추가로 설정 가능한 것들이 어떤게 있는지도 같이 설명해주시면 좋을 것 같네요.
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.
설정 파일 방식을 현재 properties로 하고 계시는데 yaml 방식을 알고 계신지도 궁금하네요! 만약 처음 들어보시는거라면 아래 블로그나 구글링 혹은 LLM을 통해 찾아보시면 도움이 될 것 같습니다!
(변경을 하라는 의미는 아니고 그냥 단순히 정보성 글입니다...!)
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.
spring.h2.console.enabled=true
위 코드는 H2 데이터베이스는 보안 때문에 웹으로 접근하는 것을 막기 위해 항상 false로 유지되어 있지만 true로 해줌으로서 d웹에서 데이터베이스로 접근할 수 있게 해주는 역할을 합니다.spring.datasource.url=jdbc:h2:mem:test
사용할 데이터 베이스는 h2이고 mem은 memory의 약자로 파일로 저장하지 않고 RAM에 저장하여 서버가 켜지고 꺼질 때마다 초기화가 됩니다. 마지막으로 이름을 test라고 정의한 코드입니다.spring.h2.console.path=/h2-console
웹 상에서 DB관리자 화면으로 접속 하기 위한 url을 정의하는 코드입니다.
추가적으로 찾아본 설정 가능한 것들
1. JdbcTemplate이 실행하는 SQL을 보여주는 코드 (DEBUG 레벨)
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
2. 물음표(?)에 어떤 값이 들어갔는지 보여주는 코드 (TRACE 레벨)
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE
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.
친절하게 설명해 주셔서 감사합니다! 😄
추가로 찾아보신 내용을 바로 적용해 주신 점이 인상 깊네요👍
다만, 쿼리나 파라미터를 로그로 남기는 설정은 개발 단계에서는 유용하지만 실제 운영 환경에서는 보안상 위험이 있을 수 있습니다. (테이블 정보나 민감한 데이터가 로그 파일에 남을 수 있어요)
그래서 운영 배포 시에는 해당 설정을 제거하거나 로그 레벨을 조정하는 것이 일반적입니다.
보내주신 내용에 더해, 개발하실 때 참고하시면 좋을 만한 설정을 몇 가지 더 정리해드렸는데 가볍게 보시고 궁금한 내용이 있으시면 키워드로 찾아보시면 좋을 것 같아요!
# ===============================
# [H2 연결 설정] (기본)
# ===============================
# JDBC URL (In-Memory 모드: 재시작 시 데이터 초기화)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# ===============================
# [H2 콘솔 설정] (개발 편의성)
# ===============================
# 웹 브라우저에서 DB 접속 허용 (localhost:8080/h2-console)
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# ===============================
# [커넥션 풀 설정] (HikariCP)
# ===============================
# 운영 환경(MySQL 등) 성능 튜닝의 핵심 설정입니다.
# 커넥션 풀의 최대 사이즈 (기본값: 10)
spring.datasource.hikari.maximum-pool-size=10
# 커넥션 확보 대기 시간 (ms) (기본값: 30000 -> 30초)
spring.datasource.hikari.connection-timeout=30000
# 풀의 이름 (로그 식별용)
spring.datasource.hikari.pool-name=H2-HikariPool
# ===============================
# [JPA 및 로그 설정] (디버깅용)
# ===============================
# 테이블 생성 전략 (create-drop: 시작 시 생성, 종료 시 삭제)
spring.jpa.hibernate.ddl-auto=create-drop
# 실행되는 SQL 쿼리 보기 (Hibernate 포맷)
spring.jpa.show-sql=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.
이렇게 많은 설정이 있다는 게 신기한 것 같습니다!! 요번에 잘 보고서 다음에 필요시에 찾아보고 적용해보겠습니다.
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.
👍👍
| @NotBlank(message = "이름은 필수 항목입니다.") | ||
| String name, | ||
|
|
||
| @NotBlank(message = "날짜는 필수 항목입니다.") | ||
| String date, | ||
| @NotNull(message = "날짜는 필수 항목입니다.") | ||
| @JsonFormat(pattern = "yyyy-MM-dd") | ||
| LocalDate date, | ||
|
|
||
| @NotBlank(message = "시간은 필수 항목입니다.") | ||
| String time | ||
| @NotNull(message = "시간은 필수 항목입니다.") | ||
| @JsonFormat(pattern = "HH:mm") | ||
| LocalTime time |
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.
@NotBlank,@NotNull두 어노테이션의 차이는 어떤게 있나요?- 예약 시
date,time을 분리했을 때의 이점은 어떤게 있을까요?
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.
1. @NotNull, @notempty, @notblank의 차이점
두 개의 차이점을 대해 알아보니 원래 3가지를 항상 같이 비교한다고 하여 같이 정리해보겠습니다.
집합 관계에서 @notblank>@notempty>@NotNull 인 것 같습니다.

예약 시 date, time을 분리했을 때의 이점은 어떤게 있을까요?
2. 관리의 유연성이라고 생각합니다.
2-1. DB접근 용이 : 만약 모든 데이터에 대해 10시를 가지고 있는 데이터를 조회하고 싶을때 date,time이 혼재되어 있는 자료형을 사용했다면 추가적인 가공이 필요하지만 따로 관리하면 바로 조회 할 수 있어 편리합니다.
2-2. 로직의 단순화 : 날짜 없이 '시간'만 검증해야 하는 로직(예: 영업시간 체크)에서 불필요한 날짜 파싱 비용을 줄일 수 있습니다.
2-3 테스트 용이성 : 특정 시간에 대한 테스트를 작성할 때 가짜 날짜 데이터를 만들 필요 없이 시간 객체에만 집중할 수 있습니다.
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.
controller 폴더에 있는건 따로 의도하신바가 있으실까요??
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.
그렇다면 적절한 위치는 어디가 좋을까요??
전역에서 발생하는 예외를 처리하는 공통 관심사이기 때문에, 컨트롤러 보다 좋은 위치가 있지 않을까 싶어요.
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.
아아 제가 컨트롤러 폴더의 유무의 필요성에 대해 리뷰 남겨 주신 내용으로 잘못 이해한 것 같습니다.
GlobalExceptionHandler의 경우엔 당연히 controller 폴더에 있으면 안된다고 생각합니다.
Advice폴더를 생성하여 위치 시켜보도록 하겠습니다!
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.
Advice 네이밍보다 좋은게 있을 것 같아요! 일반적인 케이스를 한번 찾아보면 더 도움이 될 것 같습니다~~
|
|
||
| private final ReservationService service; | ||
|
|
||
| @Autowired |
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.
ReservationService에 의존성을 주입하기 위해 @Autowired를 사용하셨는데, 이 어노테이션이 붙으면 스프링이 내부적으로 어떤 과정을 거쳐 객체를 넣어주는지 알고 계신가요?
단순히 기능을 사용하는 것보다 동작 원리를 이해하면 나중에 발생할 수 있는 순환 참조 같은 문제를 해결하는데 큰 도움이 됩니다!
시간 나실 때 아래 키워드로 한번 깊게 찾아보시는 걸 추천드려요!
- 리플렉션 (Reflection)
- 의존성 주입 (DI)
- 스프링 빈 (Spring Bean)
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.
- 스프링의 IoC 컨테이너(ApplicationContext)가 @component, @service, @repository, @controller 등이 붙은 클래스들을 찾아서 목록(스프링 빈) 을 만들게 됩니다.
- 스프링이 찾은 클래스들을 메모리에 생성 해놓습니다. 이때 빈 객체 상태로 되어있습니다.
- 의존성 주입 : 스프링이 객체들의 목록들을 보다가 @Autowired가 붙은 필드를 발견하게 되면 이때 리플렉션을 이용하여 private 필드여도 값을 넣어줍니다.
3-1 리플렉션이 어떻게 private인데도 다른 곳에서 값을 넣어줄 수 있는 거지
1. 클래스 정보
Class<?> clazz = service.getClass();
2. 필드 찾기 (이름이 'repository'인 변수를 찾음)
Field field = clazz.getDeclaredField("repository");
3. private 무시
field.setAccessible(true);
4. 의존성 주입 (service 객체의 저 필드에 myRepo를 넣어라)
field.set(service, myRepo);
와 같은 로직의 흐름으로 리플렉션이 흘러 갑니다.
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.
👍👍👍👍
멱등성에 대해 다시 한번 공부해보는 기회가 된 것 같습니다. 제가 멱등성에 대해 개념이 헷갈려서 이전과 같은 로직이였던 것 같습니다. |
gogo1414
left a comment
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.
@nonactress 리뷰 반영해주시느라 고생 많으셨습니다!
너무 잘 수정해주셨는데, 이번 수정을 진행하면서 코드 포맷이 조금 이상해진게 있어서 해당 부분에 코멘트 남겨드렸으니 확인 부탁드려요!
추가로, 이번에 테스트 코드를 수정하시면서 전체 테스트를 혹시 돌려보셨을까요?
우선 제가 실행했을 때는 아래 이미지와 같이 현재 테스트 코드 실행 시 일부 테스트가 주황불로 표시되는 것을 볼 수 있어요!
한번 현진님이 테스트 코드를 돌려보시고 로그를 확인하셔서 수정해주시면 좋을 것 같네요.
멱등성에 대해 수정하신 부분 잘 봤습니다👍
이에 대해 더 고민해보시면 좋을 내용들을 정리해봤어요. 시간 나실 때 찾아보시면 좋을 것 같아요!
동시성 이슈와 예외 처리
- 아주 짧은 시간에 동시에 요청이 들어오면 두 요청 모두 검증 로직을 통과할 수 있습니다. 현재 DB에 PK가 걸려있어 데이터 중복은 막히겠지만 DB 에러가 발생할텐데 어떻게 예외 처리를 할 지 (화면 상으로 짧은 시간에 동시에 요청이 들어오긴 어려워 보이긴 하네요..)
- 만약 멱등성 키는 같은데 요청 내용인 Body가 다를 경우 어떻게 처리할 지
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.
친절하게 설명해 주셔서 감사합니다! 😄
추가로 찾아보신 내용을 바로 적용해 주신 점이 인상 깊네요👍
다만, 쿼리나 파라미터를 로그로 남기는 설정은 개발 단계에서는 유용하지만 실제 운영 환경에서는 보안상 위험이 있을 수 있습니다. (테이블 정보나 민감한 데이터가 로그 파일에 남을 수 있어요)
그래서 운영 배포 시에는 해당 설정을 제거하거나 로그 레벨을 조정하는 것이 일반적입니다.
보내주신 내용에 더해, 개발하실 때 참고하시면 좋을 만한 설정을 몇 가지 더 정리해드렸는데 가볍게 보시고 궁금한 내용이 있으시면 키워드로 찾아보시면 좋을 것 같아요!
# ===============================
# [H2 연결 설정] (기본)
# ===============================
# JDBC URL (In-Memory 모드: 재시작 시 데이터 초기화)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# ===============================
# [H2 콘솔 설정] (개발 편의성)
# ===============================
# 웹 브라우저에서 DB 접속 허용 (localhost:8080/h2-console)
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# ===============================
# [커넥션 풀 설정] (HikariCP)
# ===============================
# 운영 환경(MySQL 등) 성능 튜닝의 핵심 설정입니다.
# 커넥션 풀의 최대 사이즈 (기본값: 10)
spring.datasource.hikari.maximum-pool-size=10
# 커넥션 확보 대기 시간 (ms) (기본값: 30000 -> 30초)
spring.datasource.hikari.connection-timeout=30000
# 풀의 이름 (로그 식별용)
spring.datasource.hikari.pool-name=H2-HikariPool
# ===============================
# [JPA 및 로그 설정] (디버깅용)
# ===============================
# 테이블 생성 전략 (create-drop: 시작 시 생성, 종료 시 삭제)
spring.jpa.hibernate.ddl-auto=create-drop
# 실행되는 SQL 쿼리 보기 (Hibernate 포맷)
spring.jpa.show-sql=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.
작성해 주신 테스트 코드를 보니 JdbcTemplate을 사용하여 DB에 데이터가 실제로 잘 저장되었는지 직접 검증해 주셨네요! 👍
이렇게 실제 DB 값을 확인하는 방식은 테스트의 신뢰도가 높다는 장점이 있습니다. 하지만 실제 DB를 조작하기 때문에, 만약 운영 환경 설정이 연결된 상태에서 이 테스트가 실행되면 실제 데이터가 수정되거나 삭제될 위험이 있습니다.
따라서, 이런 테스트를 작성할 때는 반드시 로컬이나 테스트 전용 DB 환경에서만 실행되도록 환경 분리에 신경 써야 한다는 점을 기억해 주시면 좋을 것 같습니다!
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.
그렇다면 적절한 위치는 어디가 좋을까요??
전역에서 발생하는 예외를 처리하는 공통 관심사이기 때문에, 컨트롤러 보다 좋은 위치가 있지 않을까 싶어요.
| return count != null && count > 0; | ||
| } | ||
|
|
||
| public Reservation get (String name,LocalDate date, LocalTime time) |
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.
소괄호, 중괄호 위치가 살짝 이상하네요! 한번 체크 부탁드려요
| public void deleteReservation(Long id) { | ||
| reservationRepository.deleteById(id); | ||
| } | ||
|
|
||
| public boolean exitsKey(String idempotencyKey) | ||
| { | ||
| return idempotencyRepository.exists(idempotencyKey); | ||
| } | ||
|
|
||
| public Reservation get(String name, LocalDate date, LocalTime time) | ||
| { | ||
| return reservationRepository.get(name, date, time); | ||
| } | ||
|
|
||
| public Reservation get(ReservationCreateRequest request) | ||
| { | ||
| return reservationRepository.get(request.name(), request.date(),request.time()); | ||
| } |
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.
이번 미션을 너무 길게 끌고갔네요.. 😅
현진님이 다음 미션을 진행하는데 어려움을 겪으실 것 같아요.
그래서 코드 리뷰는 여기까지 진행하기 위해 Approve를 드리겠습니다.
만약 더 궁금한 점이 있으시면 편하게 디스코드로 연락주시면 답변드리도록 하겠습니다!
그동안 고생 많으셨습니다 😁
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.
Advice 네이밍보다 좋은게 있을 것 같아요! 일반적인 케이스를 한번 찾아보면 더 도움이 될 것 같습니다~~
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.
좋네요! 저도 이전에 프로젝트 진행할 때 사용했던 방식입니다!
테스트 환경에서는 일반적으로 ddl-auto 설정으로 create-drop 을 주로 사용합니다. 참고해주시면 좋겠네요!
| } | ||
|
|
||
|
|
||
| } |
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.
🥲
안녕하세요 준수님!! 자바 미션 때 뵙고 또 뵙게 되어 좀 더욱 반갑게 느껴지는 것 같습니다.
스프링을 그리디 스터디 하며 처음 공부하게 되어 문법에 대한 이해나 로직에 대한 이해가 떨어지는 것 같습니다.
그래도 최대한 열심히 작성해보았습니다. 잘 부탁드립니다.
핵심 내용 설명
예약 생성 로직
클라이언트가 멱등성 키를 보내면 그대로 사용하고,
보내지 않은 경우에는 Controller에서 UUID를 생성하여 중복 요청을 방지하도록 했습니다.
이후 요청 내용을 DTO로 받고, 이 값을 기반으로 예약 엔티티를 만들어 저장하는 구조입니다.
중복 예약이나 시간·회원 관련 검증은 Service 레이어에서 수행하고 있습니다.
예약 조회 / 취소 로직
조회는 단순히 저장된 데이터를 조건에 맞게 가져오는 방식입니다.
취소는 ID로 예약을 찾은 뒤, 조건(이미 지난 예약인지 등)을 검사하고 상태 값을 변경하는 방식으로 처리했습니다.
멱등성 처리 흐름
동일한 요청이 여러 번 들어와도 한 번만 예약이 생성되도록 멱등성 키 기준으로 요청을 식별하게 했습니다.
저장 이전에 멱등성 키가 이미 존재하는지 확인하고, 존재한다면 새로 생성하지 않고 기존 예약을 반환하도록 했습니다.
DTO
Controller에서 DTO를 받아 필요한 값만 꺼내고,
그 값을 기반으로 Service에서 비즈니스 로직을 실행하는 구조입니다.
응답 역시 DTO로 감싸 간단한 정보만 반환하고 있습니다.
궁금한 점
DTO 변환 위치: 현재는 Controller에서 requestDto.toEntity()를 호출하여 Service에는 엔티티를 넘겨주고 있습니다. Service가 DTO를 모르게 하려는 의도였는데, Service가 DTO를 받아서 변환하는 방식과 현재 방식 중 어떤 것을 더 선호하시는지 궁금합니다.
멱등성 키 생성: 클라이언트가 키를 보내지 않았을 때 Controller에서 UUID(Universally Unique Identifier)로 생성해주고 있습니다. 이 처리가 적절한지, 혹은 더 나은 처리 방식이 있을지 조언 부탁드립니다.