[๐ ์ฌ์ดํด2 - ๋ฏธ์ (์์ฝ ๋ณ๊ฒฝ/์ทจ์์ ์๋ฌ ์ฒ๋ฆฌ)] ์๊ธฐ(๊น๊ธฐ์) ๋ฏธ์ ์ ์ถํฉ๋๋ค.#430
[๐ ์ฌ์ดํด2 - ๋ฏธ์
(์์ฝ ๋ณ๊ฒฝ/์ทจ์์ ์๋ฌ ์ฒ๋ฆฌ)] ์๊ธฐ(๊น๊ธฐ์) ๋ฏธ์
์ ์ถํฉ๋๋ค.#430Giyoul wants to merge 13 commits into
Conversation
ํ์ฅ์ฑ์ ์ํด List๋ฅผ ์ง์ ๋ฐํํ๋ ๋ชจ๋ ์๋ํฌ์ธํธ๋ฅผ ๋ํผ ๊ฐ์ฒด๋ก ๊ฐ์ธ๋๋ก ์์ - AdminReservationsResponse, ReservationsResponse - ReservationTimesResponse, ThemesResponse - AvailableReservationTimesResponse
- reservation ํ ์ด๋ธ์ created_at ์ปฌ๋ผ ์ถ๊ฐ - Reservation.create()๋ก ์ ๊ท ์์ฑ ์ ๊ณผ๊ฑฐ ๋ ์ง ๊ฒ์ฆ - Reservation.restore()๋ก DB ๋ณต์ ์ ๊ฒ์ฆ ์์ด ์ฌ๊ตฌ์ฑ - ReservationDao.save()๊ฐ Reservation์ ๋ฐ์ ID ํฌํจ Reservation ๋ฐํ - ์๋น์ค์์ ๊ฒ์ฆ์ฉ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก ์์ฑํ๋ ๊ตฌ๋ฌธ ์ ๊ฑฐ
- DAO ํ ์คํธ๋ฅผ EmbeddedDatabaseBuilder๋ก ์ ํ โ Spring Boot ์ปจํ ์คํธ ์ ๊ฑฐ - DaoTest ์ถ์ ํด๋์ค ์ญ์ - Tautological test ์ ๊ฑฐ (Mock ์ถ๋ ฅ์ ๊ทธ๋๋ก ๊ฒ์ฆํ๋ ์๋น์ค ํ ์คํธ) - data.sql ํ๋์ฝ๋ฉ ์์กด ํ ์คํธ ๊ฐ์ (isNotEmpty, before-1 ํจํด) - ThemeControllerTest ์๋ชป๋ ์๋ํฌ์ธํธ ์์ (/themes โ /themes/popular)
- ๋ ์ง+์๊ฐ ๊ธฐ์ค ๊ณผ๊ฑฐ ์์ฝ ๋ถ๊ฐ (LocalDateTime ๋น๊ต๋ก ๋ณ๊ฒฝ) - created_at ์ปฌ๋ผ DATE โ TIMESTAMP๋ก ๋ณ๊ฒฝ - ์ด๋ฏธ ์ง๋ ์์ฝ ์ทจ์ ๋ถ๊ฐ - @Valid ์ ์ฉ โ ReservationRequest, ReservationTimeRequest, ThemeRequest - ReservationDao.findById() ์ถ๊ฐ
- ErrorResponse(code, message) DTO ์ถ๊ฐ - GlobalExceptionHandler ๋ณด๊ฐ - MethodArgumentNotValidException โ 400 INVALID_INPUT - HttpMessageNotReadableException โ 400 INVALID_FORMAT - NoResourceFoundException โ 404 NOT_FOUND - Exception fallback โ 500 SERVER_ERROR
- ReservationUpdateRequest(date, timeId) DTO ์ถ๊ฐ - ReservationDao.update() ์ถ๊ฐ - ReservationService.update() โ ์กด์ฌ ์ฌ๋ถ, ๊ณผ๊ฑฐ ๋ ์ง, ์ค๋ณต ์์ฝ ๊ฒ์ฆ
- PastReservationException โ 422 (๊ณผ๊ฑฐ ๋ ์ง ์์ฝ/์ทจ์/๋ณ๊ฒฝ) - ReservationConflictException โ 409 (์ค๋ณต ์์ฝ) - GlobalExceptionHandler์ 422, 409 ํธ๋ค๋ฌ ์ถ๊ฐ
- ์์ฝ ๋ชฉ๋ก์ ๋ณ๊ฒฝ ๋ฒํผ ์ถ๊ฐ
- ๋ ์งยท์๊ฐ ์ ํ ๋ชจ๋ฌ ๊ตฌํ
- PATCH /reservations/{id} ํธ์ถ
- code ๊ธฐ๋ฐ ์ฌ์ฉ์ ์นํ์ ์๋ฌ ๋ฉ์์ง ์ฒ๋ฆฌ
- ์ญ์ ์๋ฌ๋ code ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์
donghoony
left a comment
There was a problem hiding this comment.
์๊ธฐ ์๋ ํ์ธ์~ ์ด๋ฒ ์ฌ์ดํด ๋น ๋ฅด๊ฒ ์งํํด์ฃผ์ ๋๋ถ์ ์ฌ๋ฏธ์๋ ์ด์ผ๊ธฐ๋ฅผ ๋ง์ด ๋๋ ๋ณผ ์ ์์ ๊ฒ ๊ฐ๋ค์ ๐ ๊ฐ๋ฐ์๋ง๋ค ์ฑํฅ์ด ๋ค๋ฅด๊ฒ ์ง๋ง, ์ ๋ ๊ฐ์ฒด์งํฅ์ผ๋ก๋ถํฐ ๋ป์ด๋๊ฐ๋ ์ค๊ณ๋ฅผ ์ข์ํ๋ ํธ์ด๋ผ ๋ช ๊ฐ์ง ์ฝ๋ฉํธ๋ฅผ ๋จ๊ฒจ๋ณด์์ด์. ๋ค์ํ ๊ด์ ์ ์ดํด๋ณด๊ณ ์ด์ผ๊ธฐํ๋ ์๊ฐ์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
์๊ตฌ์ฌํญ์ ์ ์ฒด์ ์ผ๋ก ์ ๋ง์กฑํ๊ณ ์๊ณ , ๋ช ๊ฐ์ง ๋ณด์ํ ๋ถ๋ถ์ ๋ํด์ ๋ฆฌ๋ทฐ๋ฅผ ๋จ๊ฒจ๋์์ผ๋ ์ฝ๋ฉํธ ํ์ธํด์ฃผ์ธ์~
| import java.util.List; | ||
|
|
||
| public record AdminReservationsResponse(List<AdminReservationResponse> reservations) { | ||
| } No newline at end of file |
There was a problem hiding this comment.
POSIXํ์ค์ด๊ณ , cat ๊ฐ์ ๋ช
๋ น์ด ์ณค์๋์ ํ์ผ์ด ๋ถ์ด๋ฒ๋ฆฌ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด ๋ถ๋ถ์ ์ ๋ฆฌ๋ทฐ์ด ๋ถ๋คํํ
๋ ๊ณตํต์ ์ผ๋ก ์ง์ ๋ฐ์๋ ๋ถ๋ถ์ด๊ณ , ๊ทธ๋์ EOF์ ์ํฐ ์ฝ์
intellij ์๋๊ธฐ๋ฅ๋ ์ค์ ํด๋์๋๋ฐ, ๋ญ๊ฐ ์ถฉ๋์ด ์๋์ง ์๊พธ ์ง์์ง๋ค์ใ
ใ
ํผ์ ๋ ๋ฆฌ๊ธฐ ์ ์๋ ๋ง์ง๋ง์ผ๋ก ๋ชจ๋ ํ์ผ ๋ค์ด๊ฐ์ option + command + L๋ก ํ์ผ ํฌ๋ฉง ์ ๋ฆฌ๋ ํ๊ณ EOF์ ์ํฐ ์์ณ์ ธ์์ผ๋ฉด ์๋์ผ๋ก ํ๋ํ๋ ์ถ๊ฐํ๋๋ฐ, ์ด๊น์์ด ์ง์์ ธ ์๋ค์...
์ผ๋จ ํ์ผ ๋ค ํ์ธํ๊ณ ์๋์ผ๋ก ์ํฐ ๋ค์ ์ถ๊ฐํ๋๋ก ์์ ํด๋ณด๊ฒ ์ต๋๋ค...
| @@ -0,0 +1,7 @@ | |||
| package roomescape.exception; | |||
|
|
|||
| public class PastReservationException extends RuntimeException { | |||
There was a problem hiding this comment.
์ด ์์ธ๋ ์ด๋์์ ๋ฐ์ํ๋์? Dao์์๋, Controller์์ ๋ฐ์ํด๋ ์ด์ํ์ง ์์ ํจํค์ง ์์น๋ก ๋ณด์ฌ์. ๋ฐ์ํ๋ ๊ณณ์์ ์์ธ๋ฅผ ์ ์ํ๋ฉด ์ด๋จ๊น์?
There was a problem hiding this comment.
๋งค๋ฒ ํจํค์ง์ด ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค์..
PastReservationException์ Reservation ๋๋ฉ์ธ ๊ฐ์ฒด์์, ReservationConflictException์ ReservationService์์ ๋ฐ์ํฉ๋๋ค.
๋ง์๋๋ก ๊ฐ๊ฐ domain๊ณผ service ํจํค์ง๋ก ์ด๋ํ๋ฉด ์์ธ๊ฐ ๋ฐ์ ๋งฅ๋ฝ๊ณผ ๊ฐ๊น์์ง๊ณ ๋ณ๋์ exception ํจํค์ง๋ ์ ๊ฑฐํ ์ ์๊ฒ ๋ค์.
์์ ํ๊ฒ ์ต๋๋ค.
|
|
||
| @Transactional | ||
| public Reservation update(long id, LocalDate date, long timeId) { | ||
| Reservation reservation = reservationDao.findById(id) |
There was a problem hiding this comment.
์ฌ๊ธฐ์๋ final์ด ๋ถ์ง ์์๋ค์? ์ด์ ๊ฐ ์์๋์? ๋ฉ์๋ ๋ด์์ ๋ณ์๋ฅผ ์ฌํ ๋นํ์ง ์๋๋ค๋ ์ปจ๋ฒค์
์ ๋ชจ๋๊ฐ ๊ณต์ ํ๊ณ ์๋ค๋ฉด ์ ๊ฑฐํ๋ ๋ฐฉํฅ์ผ๋ก ํต์ผํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ ์ค ํ๋๋ผ๊ณ ์๊ฐํด์~
There was a problem hiding this comment.
์... ์ด๊ฑด ๊ทธ์ '๋ด ์ฝ๋ ๊ตฌ๋ ค ๋ณ'์ด ๋์ ธ์ ์๊ธด ๋ฌธ์ ์ธ ๋ฏ ํฉ๋๋ค..
ํ๋๋ final ์ ์ง, ๋ก์ปฌ ๋ณ์๋ ์ ๊ฑฐ๋ก ๊ตฌ๋ถํ๊ฒ ์ต๋๋ค.
| if (LocalDateTime.of(date, newTime.getStartAt()).isBefore(LocalDateTime.now())) { | ||
| throw new PastReservationException("๊ณผ๊ฑฐ ๋ ์ง๋ก๋ ์์ฝํ ์ ์์ต๋๋ค."); | ||
| } |
There was a problem hiding this comment.
ํ์ฌ Controller-Service-Dao์ ๊ณ์ธต์ผ๋ก ๋๋ ์ฃผ์
์, ๋๋ฉ์ธ์ด๋ผ๋ ๊ฐ๋
์ด ์กฐ๊ธ ์์์ง ์ ์์ต๋๋ค. ๋๋ฉ์ธ ์ง์๊ณผ ๊ณ์ธต ๊ตฌ์กฐ๋ ์๋ก ์๋ฐ๋๋ ๊ฒ์ด ์๋๋ผ์ ํจ๊ป ์ด์ฐ๋ฌ์ง ์ ์๋๋ฐ์.
๊ณผ๊ฑฐ ๋ ์ง๋ก ์์ฝํ ์ ์๋ค๋์์ฝ์๊ฒ ์์ด์ ์ ๋์ ์ธ ๋ถ๋ณ์์ ํด๋นํ์ง ์์๊น์?- ๋ง์ฝ ๊ทธ๋ ๋ค๋ฉด, ํ์ฌ ์๊ฐ์ด ์์ฝ์ ์กด์ฌํ์ง ์์ผ๋
Service์์ ์งํํ๋ ๊ฒ์ ์์ฐ์ค๋ฌ์ ๋ณด์ ๋๋ค. - ๋ค๋ง, ์์ฝ์๊ฒ๋
์์ฝ ์๊ฐ๋ฟ๋ง ์๋๋ผ,์์ฝ์ ์งํํ ์๊ฐ๋ ์ค์ํ ์ ๋ณด ์๋๊น์?
๊ฒ์ฆ์ ์๋น์ค๊ฐ ์๋ ๋๋ฉ์ธ๋จ์ผ๋ก ์ด๋ํ๋ฉด ์ด๋ค ์ ์ด ์ด์ ์ผ๋ก ๋ค๊ฐ์ฌ์ง ๊ณ ๋ฏผํด๋ณด์ ๋ ์ข๊ฒ ์ต๋๋ค. (์์ฝ ์๊ฐ, ์์ฝ์ ๋ํ ๊ฒ์ฆ์ ๊ฒฝ์ฐ์๋ ๋๋ฉ์ธ ํผ์์๋ ํด๊ฒฐํ ์ ์์ผ๋ฏ๋ก Service ๊ณ์ธต์ ๋์์ ๋ฐ์์ผ ํ๊ฒ ์ต๋๋ค)
There was a problem hiding this comment.
save()์์๋ Reservation.create()๊ฐ ๊ณผ๊ฑฐ ๋ ์ง๋ฅผ ๊ฒ์ฆํ๊ณ ์์ด์ ๋๋ฉ์ธ์ด ์ ์ญํ ์ ํ๊ณ ์๋๋ฐ, update()์ delete()์์๋ ๋์ผํ ๋ถ๋ณ์์ ์๋น์ค๊ฐ ์ง์ ์ฒดํฌํ๊ณ ์์์ต๋๋ค.
์ด๊ฑฐ๋ฅผ ๋๋ฉ์ธ ์ฑ
์์ด ์ผ๊ด๋์ง ์๊ฒ ์๋น์ค๋ก ์์ด๋๊ฐ๊ฑฐ๋ก ๋ณผ ์ ์๊ฒ ๋ค์
๊ทธ๋ฌ๋ฉด Reservation์ withUpdated(date, newTime, now)์ validateCancellable(now) ๊ฐ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ ๊ณผ๊ฑฐ ๋ ์ง ๊ฒ์ฆ์ ๋๋ฉ์ธ์ผ๋ก ์ด๋ํ๊ฒ ์ต๋๋ค.
์ถฉ๋ ์ฒดํฌ๋ DB ์กฐํ๊ฐ ํ์ํ๋ ์๋น์ค์ ์ ์งํ๊ณ , ๋๋จธ์ง ์๋น์ค๋ ์์ ์ค์ผ์คํธ๋ ์ด์
๋ง ๋ด๋นํ๋ ๋ฐฉํฅ์ผ๋ก ์์ ํ๊ฒ ์ต๋๋ค.
์ฝ๊ฐ ๊ตณ์ด ํ ๊ณ์ธต ๋ ๋ค์ด๊ฐ๋ ๋๋์ด๋ผ ์ด๋ ๊ฒ ํ์ง ์์์๋๋ฐ, ์ฑ ์ ๋ถ๋ฆฌ์ ์ค๋ณต ์ฝ๋ ์ ๊ฑฐ์ ๊ด์ ์์ ์๊ฐํด๋ณด๋ ์ด๊ฒ ๋ ์ข๊ฒ ๋๊ปด์ง๋ ๊ฒ ๊ฐ๋ค์
| if (reservationDao.existsByDateAndTimeIdAndThemeId(date, timeId, reservation.getTheme().getId())) { | ||
| throw new ReservationConflictException("์ด๋ฏธ ์์ฝ๋ ์๊ฐ์ ๋๋ค."); | ||
| } |
There was a problem hiding this comment.
(์ด์ ์ฝ๋ฉํธ์ ๋ฐ๋ก ์ ์ฝ๋ฉํธ๋ก๋ถํฐ ์ด์ด์ง๋๋ค!)
- ๋ง์ฝ ์ด๋ฒ ๋ฏธ์ ์ด ๋ธ๋์ญ๊ณผ ๊ฐ์ ์ฝ์ ๊ธฐ๋ฐ์ ๊ฐ์ฒด์งํฅ ๋ฏธ์ ์ด์๋ค๋ฉด, ๊ทธ๋ฆฌ๊ณ DB ์ฐ๊ฒฐ ๋ํ ์์๋๋ผ๋ฉด ๊ฐ์ฒด ์ค๊ณ๋ฅผ ์ด๋ป๊ฒ ์งํํ์ จ์ ๊ฒ ๊ฐ๋์?
- ์๋ฅผ ๋ค์ด๋ณด์๋ฉด, ์ค๋ณต ์์ฝ์ ๋ํ ๊ฒ์ฆ์ ์ํด ํ ๋ง์ ํ๋ฃจ ์์ฝ์ ๊ด๋ฆฌํ๋ ์ผ๊ธ ์ปฌ๋ ์ ์ด ๋ฑ์ฅํ ์ ์์ต๋๋ค.
Dao์ ์ํธ์์ฉ์ DB๋ผ๋ ์ ์์ค์ ์ข ์๋๋ ๋๋์ด ๋ญ๋๋ค. ํ ์ด๋ธ์ ์ธ์ด๋ก ์ํธ์์ฉํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ฃ . ์๊ธฐ๊ฐRepository์Dao๋ฅผ ๊ตฌ๋ถํด์ฃผ์ ๋งํผRepository์์๋ ํด๋น ๋๋ฉ์ธ์ ์์ํํ๋ ๊ณผ์ ์ด ๋ด๊ธธ ์ ์์ด์. ๊ทธ๋ ๋ค๋ฉด ์๋น์ค์์๋ ํด๋น ์ผ๊ธ ์ปฌ๋ ์ ์ผ๋ก ์ํตํ๊ณ , ์ ์ฅํ๋ ์ผ๋ จ์ ๊ณผ์ ์ ๋ง๋ค์ด๋ผ ์๋ ์์ต๋๋ค. ์ด๋ฅผ ์ ์ฅํ๊ธฐ ์ํด์ DB ์ปฌ๋ผ์ ์ผ์น์ํฌ ์๋ ์์ง๋ง, ์ฑ๋ฅ์ ์ด๋ฅผ ํฌ๊ธฐํ๋ ๊ฒฝ์ฐ๋ ์๊ณ ์. (์ด ๊ฒฝ์ฐ ๋งคํ์ ์ฑ ์์ ๊ณ ๋ฏผํด๋ณด๋ ๊ฒ๋ ์ข์ ๊ณต๋ถ๊ฐ ๋ฉ๋๋ค)
๋ฌผ๋ก ๊ตฌํํด์ฃผ์ ๋ฐฉํฅ๋ ์๊ตฌ์ฌํญ์ ์ถฉ๋ถํ ๋ง์กฑํ์ง๋ง, ๋๋ฉ์ธ์ ํ๊ตฌํ๊ณ ๊ฐ์ฒด์ ์ฑ ์์ ๋์ถํด๋ด๋ ๊ณผ์ ์ผ๋ก๋ถํฐ ์ค๊ณ๊ฐ ์งํ๋๋ค๋ฉด ๋ ๋จ๋จํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค๊ณ ์๊ฐํด์! ๋ฐ์ํ์์ง ์์๋ ๋๊ณ ํ๋์ ๊ด์ ์ผ๋ก ๋ฐ๋ผ๋ด์ฃผ์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค ๐
There was a problem hiding this comment.
"๋๋ฉ์ธ์ ๋จผ์ ํ๊ตฌํ๊ณ ๊ฐ์ฒด์ ์ฑ
์์ ๋์ถํ ๋ค ์ค๊ณ"๋ผ๋ ๋ง์์ด ์๊ฐ์ ์ฌ์ง๋ฅผ ๋ง์ด ๋์ ธ์ฃผ๋ ๊ฒ ๊ฐ์ต๋๋ค...!
์๊ฐํด๋ณด๋ DB ๊ตฌ์กฐ๊ฐ ๋๋ฉ์ธ ์ค๊ณ๋ฅผ ์ฃผ๋ํ๊ณ ์์๋ ๊ฒ ๊ฐ์ต๋๋ค.
DB ์์ด ์ค๊ณํ๋ค๋ฉด ThemeDaySchedule ๊ฐ์ ์ผ๊ธ ์ปฌ๋ ์
์ด ์ค๋ณต ์์ฝ ๊ฒ์ฆ์ ์ฑ
์์ ๊ฐ์ ธ๊ฐ ์ ์๊ฒ ๋ค์.
ํ์ฌ๋ DB ์กฐํ(existsByDateAndTimeIdAndThemeId)๊ฐ ๊ทธ ์ญํ ์ ๋์ ํ๋ค ๋ณด๋ ๋๋ฉ์ธ์ด ์์์ง ์ํฉ์ด์์ต๋๋ค.
Repository๊ฐ ๋๋ฉ์ธ ๊ฐ์ฒด์ DB ์ปฌ๋ผ ์ฌ์ด์ ๋งคํ์ ๋ด๋นํ๊ณ , Service๋ ์ผ๊ธ ์ปฌ๋ ์ ๊ณผ ๋๋ฉ์ธ ์ธ์ด๋ก ์ํตํ๋ ๊ตฌ์กฐ๊ฐ ๋ ๋จ๋จํ ์ค๊ณ์์ ์ดํดํ์ต๋๋ค!
| @RestControllerAdvice | ||
| public class GlobalExceptionHandler { | ||
|
|
||
| @ExceptionHandler(IllegalArgumentException.class) |
There was a problem hiding this comment.
IllegalArgumentException์ 400์ผ๋ก ์ฒ๋ฆฌํ๊ณ , e.getMessage()๋ฅผ ๋
ธ์ถํด๋ ๊ด์ฐฎ์๊น์? IllegalArgumentException์ด ์๋์น ์์ ๋ค๋ฅธ ๊ณณ์์ ๋ฐ์ํ ์ํ์ ์์๊น์?
There was a problem hiding this comment.
IllegalArgumentException์ ๊ด๋ฒ์ํ๊ฒ ์ก์ผ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ๋ ์์ํฌ ๋ด๋ถ์์ ๋ฐ์ํ ์์ธ๊น์ง 400์ผ๋ก ์ฒ๋ฆฌ๋๊ณ ๋ด๋ถ ๋ฉ์์ง๊ฐ ๋
ธ์ถ๋ ์ํ์ด ์๊ฒ ๋ค์.
๋๋ฉ์ธ ์ ์ฉ ์ปค์คํ
์์ธ(InvalidInputException ๋ฑ)๋ฅผ ๋ง๋ค์ด์ ์ฐ๋ฆฌ ์ฝ๋์์ ์๋์ ์ผ๋ก ๋์ง๋ ๊ฒฝ์ฐ๋ง ์ก๋๋ก ๋ถ๋ฆฌํ๊ฒ ์ต๋๋ค!
There was a problem hiding this comment.
dto ํด๋์ค๊ฐ ๋ง์์ง๋ฉด์ ๋ด๊ณ ์๋ ๋ด์ฉ์ด ์ปค์ง๊ณ ์๋ค์. ํจํค์ง๋ฅผ ์ ์ ํ๊ฒ ๋๋ ๋ณด๋ฉด ์ด๋จ๊น์?
There was a problem hiding this comment.
ํ์ฌ controller.dto ํ๋์ Reservation, Theme, ReservationTime ๊ด๋ จ DTO๊ฐ 15๊ฐ ๋ชจ์ฌ์๋ ์ํฉ์ด๋ผ ๋๋ฉ์ธ๋ณ ์๋ธ ํจํค์ง๋ก ๋ถ๋ฆฌํ๋ ๋ฐฉํฅ์ด ์ ํฉํ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
controller/dto/reservation/, controller/dto/time/, controller/dto/theme/ ํํ๋ก ๋๋๋ฉด ๊ฐ ๋๋ฉ์ธ๋ณ๋ก Request/Response๋ฅผ ํ ๋์ ๋ณผ ์ ์๊ณ , ๊ธฐ์กด domain/ ํจํค์ง ๊ตฌ๋ถ ๊ธฐ์ค๊ณผ๋ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
ํน์ ์๊ฐํ์ ๋ค๋ฅธ ๊ธฐ์ค์ด ์์ผ์๋ฉด ๋ง์ํด ์ฃผ์๋ฉด ๋ฐ์ํ๊ฒ ์ต๋๋ค.
There was a problem hiding this comment.
ํ ๊ฐ์ง ๊ฑธ๋ฆฌ๋ ์ ์, ํ์ฌ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด:
roomescape/
controller/ โ ๊ณ์ธต
dao/ โ ๊ณ์ธต
domain/ โ ๊ณ์ธต
exception/ โ ๊ณ์ธต
service/ โ ๊ณ์ธต์ ์ฒด๊ฐ ๊ณ์ธต ๊ธฐ๋ฐ(horizontal slicing) ์ผ๋ก ๋๋์ด ์์ต๋๋ค.
์ฌ๊ธฐ์ dto/ ์์์๋ง ๋๋ฉ์ธ ๊ธฐ์ค์ ์์ผ๋ฉด ์ผ๊ด์ฑ์ด ๊นจ์ง๋๋ค.
dao/๋ service/๋ ๋๋ฉ์ธ sub-package ์์ด flatํ๋ฐ dto/๋ง domain-based๊ฐ ๋ฉ๋๋ค.
๊ทธ๋์, ํ์ฌ์ ์ฒ ํ์ ๋ฐ๋ฅด๋ ค๋ฉด Request / Response ๋ถ๋ฆฌํ๋๊ฒ ๋ง์ ๋ณด์ด๋๋ฐ,
controller/dto/
request/ โ ์
๋ ฅ
response/ โ ์ถ๋ ฅ์๋ฃจ๋ dto/ ์ด ์๋์ ๋๋ฉ์ธ๋ณ๋ก ํจํค์ง๋ฅผ ๋๋๋ ๊ฒ๊ณผ, ์์์ ๋งํ ๊ฒ ์ค์ ์ด๋๊ฒ ๋ ๊ด์ฐฎ์ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ๋ณด์๋์?
| id BIGINT NOT NULL AUTO_INCREMENT, | ||
| start_at TIME NOT NULL UNIQUE, | ||
| PRIMARY KEY (id) |
There was a problem hiding this comment.
์ฌ๋ฌ start_time์ด DB์์ผ๋ก ์กด์ฌํ ์ ์์ ๊ฒ ๊ฐ๋ค์.
There was a problem hiding this comment.
๋ฐฉ์ด ํ๋์ธ ๋ฐฉํ์ถ ์นดํ ๋งฅ๋ฝ์ด๋ผ๋ฉด UNIQUE (date, time_id)๋ก ๋ณ๊ฒฝํด์ผ ์๊ฐ๋น ํ ํ๋ง ์์ฝ์ด ๊ฐ๋ฅํด์ง ๊ฒ ๊ฐ์ต๋๋ค.
์๋น์ค์ ์ค๋ณต ์ฒดํฌ ๋ก์ง๋ ํจ๊ป ์์ ํ๊ฒ ์ต๋๋ค
| ### ์๋ฌ ์๋ต ํ์ | ||
|
|
||
| ```json | ||
| { "code": "RESERVATION_CONFLICT", "message": "์ด๋ฏธ ์์ฝ๋ ์๊ฐ์ ๋๋ค." } |
There was a problem hiding this comment.
code๊ฐ ํ์ํ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์? ์ค์ ๋ก ํ๋ก ํธ์์ ํด๋น code๋ฅผ ๋ณด๊ณ ๋ถ๊ธฐ๊ฐ ์ด๋ค์ง๋์? ์๋ฒ์์ ๋ถํ์ํ ์ ๋ณด๋ฅผ ๋ด๋ ค์ฃผ๊ณ ์๋ ๊ฒ์ ์๋๊น์?
There was a problem hiding this comment.
user.html์์ code ํ๋๋ฅผ ์ค์ ๋ก ๋ถ๊ธฐ์ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
์ทจ์ยท๋ณ๊ฒฝ API ์๋ต์์ PAST_RESERVATION๊ณผ RESERVATION_CONFLICT๋ฅผ ๊ตฌ๋ถํด ๊ฐ๊ฐ ๋ค๋ฅธ ์๋ด ๋ฉ์์ง๋ฅผ ํ์ํ๋ ์ฉ๋์
๋๋ค.
๋ค๋ง ํ๋ก ํธ๊ฐ code์ ์์กดํ๋ ๋์ HTTP ์ํ ์ฝ๋(422, 409)๋ง์ผ๋ก ๋ถ๊ธฐํ ์ ์๋๋ก ๋ฆฌํฉํ ๋งํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๊ณ , ๊ทธ๋ ๋ค๋ฉด code ํ๋๋ ์ ๊ฑฐํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
ํ์ฌ ๊ตฌ์กฐ๋ฅผ ์ ์งํ ์ง ์๊ฒฌ ์ฃผ์๋ฉด ๋ฐ์ํ๊ฒ ์ต๋๋ค!
| Reservation reservation = reservationDao.findById(id) | ||
| .orElseThrow(() -> new IllegalArgumentException("์กด์ฌํ์ง ์๋ ์์ฝ์ ๋๋ค.")); | ||
| if (LocalDateTime.of(reservation.getDate(), reservation.getTime().getStartAt()).isBefore(LocalDateTime.now())) { | ||
| throw new PastReservationException("์ด๋ฏธ ์ง๋ ์์ฝ์ ์ทจ์ํ ์ ์์ต๋๋ค."); |
There was a problem hiding this comment.
์ด๋ค ๊ฒฝ์ฐ์ ๊ธฐ๋ณธ ์์ธ๋ฅผ ์ฌ์ฉํ๊ณ , ์ด๋ค ๊ฒฝ์ฐ์๋ ๋ง๋ค์ด์ฃผ์ ์ปค์คํ ์์ธ๋ฅผ ์ฌ์ฉํ์ จ๋์?
There was a problem hiding this comment.
๋์๋ณด๋ ๋ช
ํํ ๊ธฐ์ค ์์ด, HTTP ์ํ ์ฝ๋๊ฐ 400์ด ์๋ ๋๋ง ์ปค์คํ
์์ธ๋ฅผ ๋ง๋๋ ํจํด์ด์์ต๋๋ค.
์๋ํ ์ค๊ณ๊ฐ ์๋์์ต๋๋ค.
๋ ๋์ ๊ธฐ์ค์ "๋๋ฉ์ธ ๊ท์น ์๋ฐ์ ๋ชจ๋ ์ปค์คํ
์์ธ, IllegalArgumentException์ ํ๋ก๊ทธ๋๋ฐ ์ค๋ฅ์๋ง"์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
"์กด์ฌํ์ง ์๋ ์์ฝ์
๋๋ค" ๊ฐ์ ์ผ์ด์ค๋ ReservationNotFoundException ๊ฐ์ ๋๋ฉ์ธ ์์ธ๋ก ํํํ๋ ๊ฒ ๋ง๊ณ , IllegalArgumentException์ ์์์น ๋ชปํ ์ํฉ์๋ง ๋จ๊ฒจ๋๋ ๋ฐฉํฅ์ผ๋ก ์ ๋ฆฌํ๊ฒ ์ต๋๋ค.

์ธ์ฌ๋ง
์๋ฃจ ์๋ ํ์ธ์!
๋น ๋ฅด๊ฒ ์ฝ๋๋ฅผ ๊ฐ์ง๊ณ ๋์์์ต๋๋ค!
cycle1 ๋ง์ง๋ง์ ์ฃผ์ ํผ๋๋ฐฑ ๋ด์ฉ๊ณผ ์ ๊ฐ ๋ค์ ์ฌ์ดํด๋ก ๋ฏธ๋ฃจ๊ฒ ๋ค๊ณ ๋ง์๋๋ ธ๋ ๋ฆฌํฉํ ๋ง ์ฌํญ๋ค ๋ํ ์ ๋ถ ์ ์ฉํด์ ๊ฐ์ ธ์์ผ๋, ํ์ธํด์ฃผ์๋ฉด ๊ฐ์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค!
์ ๋ถํ๋๋ฆฝ๋๋ค :)
์ฒดํฌ ๋ฆฌ์คํธ
test๋ฅผ ์คํํ์ ๋, ๋ชจ๋ ํ ์คํธ๊ฐ ์ ์์ ์ผ๋ก ํต๊ณผํ๋์?๋ฒ ์ด์ค ์ฝ๋ ์ ํ ์ฒดํฌ
์ด๋ค ๋ถ๋ถ์ ์ง์คํ์ฌ ๋ฆฌ๋ทฐํด์ผ ํ ๊น์?
๋ํผ DTO ์ค๊ณ ๋ฐฉ์์ ๋ํ ๊ณ ๋ฏผ ์ง๋ฌธ
ํ์ฌ ๊ฐ ์๋ต๋ง๋ค ๋ณ๋ ํด๋์ค๋ฅผ ๋๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋๋ฐ, ๋ค๋ฅธ ๋ฐฉ์๊ณผ ๋น๊ตํด ์ด๋ค ๋ฐฉํฅ์ด ๋ ์ ์ ํ์ง ์ฌ์ญค๋ณด๊ณ ์ถ์ต๋๋ค.
๋ฐฉ์ 1. ๋ณ๋ ํด๋์ค (ํ์ฌ)
๋ฐฉ์ 2. ์ ๋ค๋ฆญ ๊ณตํต ํด๋์ค
๋ฐฉ์ 3. Inner class๋ก ๋ฌถ๊ธฐ
๋ฐฉ์ 1์ JSON ํ๋๋ช ์ด ๋ช ํํ๊ณ ์๋ต๋ณ ํ์ฅ์ด ์์ ๋กญ์ง๋ง ํ์ผ์ด ๋ง์์ง๊ณ , ๋ฐฉ์ 2๋ ์ฝ๋๊ฐ ์ค์ง๋ง ํ๋๋ช ํํ๋ ฅ์ด ๋จ์ด์ง๋ฉฐ, ๋ฐฉ์ 3์ ํ์ผ ์๋ฅผ ์ค์ด๋ฉด์ ํ๋๋ช ์ ์ ์งํ ์ ์์ง๋ง ํ์ ๋ช ์ด ๊ธธ์ด์ง๋ ํธ๋ ์ด๋์คํ๊ฐ ์์ต๋๋ค.
์ด๋ฒ ๋ฏธ์ ์์ ์ ๋ 1๋ฒ ๋ฐฉ์์ ์ ํํ๊ณ , ํ์์ ํ๋ก์ ํธ๋ฅผ ํ ๋๋ 3๋ฒ ๋ฐฉ์์ ์ ํธํ๋ ํธ์ ๋๋ค.
์ด ๋ถ๋ถ์ ํญ์ ๊ณ ๋ฏผ์ ํ์ง๋ง, ์ ๋ต์ด ์๋ค๊ณ ๋๊ปด์ ธ์ ์ด๋ ค์ด ๊ฒ ๊ฐ์ต๋๋ค.
๋ฌผ๋ก ์ด ๋ถ๋ถ์ด ํ ๋ด ์ปจ๋ฒค์ ์ผ ๊ฒ ๊ฐ๊ธด ํ๋ฐ, ์๋ฃจ๋ ๊ฐ์ธ ๊ฐ๋ฐํ์ค๋ ์ด๋ ๋ฐฉํฅ์ ์ ํธํ์๋์ง ๊ถ๊ธํด์ง๋ ๊ฒ ๊ฐ์ต๋๋ค!