์ฌ์ฉ์ API(์ด ์ ์ฅ์)์ ํธ์คํธ ๊ด๋ฆฌ์ ์ฑ(honeyRest_host)์ ํ๋์ MySQL ์คํค๋ง๋ฅผ ๊ณต์ ํ๋ฉด์๋ JPA ์ํฐํฐ๋ฅผ ๊ฐ์ ๋ณต์ฌํด ์จ ์๋ค. ์ฌ๋ณธ์ ์๊ฐ์ด ์ง๋๋ฉฐ ์กฐ๊ธ์ฉ ๋ฌ๋ผ์ก๋ค(ํ๋๋ช , ์ ๋ฐ๋, ๋๋ฉ์ธ ๋ฉ์๋, ์ธ๋ฑ์ค ์ ์ธ). ์ด ๋ฌธ์๋ ๋ ์ฌ๋ณธ์ ํ๋์ ๋ชจ๋๋ก ํฉ์น๋ฉด์ ์ํฐํฐ๋ง๋ค ๋ฌด์์ด ๋ฌ๋๊ณ ์ด๋ป๊ฒ ์ ํ๋์ง๋ฅผ ๊ธฐ๋กํ๋ค.
- ๊ธฐ์ค(truth): Flyway
V1~V11(src/main/resources/db/migration) + DB_SCHEMA.md. ์ปฌ๋ผ์ ๋ฐ๊พธ์ง ์์๋ค(์ ๋ง์ด๊ทธ๋ ์ด์ ์์). - ์์น
- ์คํค๋ง์ ์๋ ์ปฌ๋ผ์ด๋ฉด ์ด๋ ํ์ชฝ์๋ง ๋งคํ๋ผ ์์ด๋ ๊ณต์ ์ํฐํฐ์ ๋ฃ๋๋ค.
- ํ์ชฝ์๋ง ์๋ ๋๋ฉ์ธ ๋ฉ์๋๋ ๋ชจ๋ ๊ณต์ ํด๋์ค์ ๋จ๊ธด๋ค(์ญ์ ํ์ง ์์).
- ์ด๋ฆ์ด ๋ค๋ฅด๋ฉด ์ปฌ๋ผ๋ช ๊ณผ ๋ง๋ ์ด๋ฆ์ ๊ณ ๋ฅด๊ณ ๋ ์ฑ์ ์ฌ์ฉ์ฒ๋ฅผ ๊ณ ์น๋ค.
- ํ ์ฑ๋ง ์ฐ๊ณ ์๋ฌด ์ํฐํฐ๋ ์ฐธ์กฐํ์ง ์๋ ์ํฐํฐ๋ ๊ทธ ์ฑ์ ๋จ๊ธด๋ค(
ErrorLogโ ํธ์คํธ).
honeyRest_user/ (๋ฃจํธ ํ๋ก์ ํธ = ์ฌ์ฉ์ API. ๊ธฐ์กด ์์น ๊ทธ๋๋ก)
โโโ settings.gradle include 'honeyrest-domain'
โโโ build.gradle implementation project(':honeyrest-domain')
โโโ honeyrest-domain/
โ โโโ build.gradle java-library, group com.honeyrest
โ โโโ src/main/java/com/honeyrest/domain/
โ โโโ entity/ ์ํฐํฐ 30๊ฐ + BaseEntity + ReservationChanges(์ธํฐํ์ด์ค)
โ โโโ type/ ReservationStatus, BannerPosition
โโโ src/main/resources/db/migration/ Flyway V1~V12 (API ๋ชจ๋์ ๋จ์)
honeyRest_host/
โโโ .gitmodules libs/honeyrest-user โ Seongwonp/honeyRest_user (branch main)
โโโ settings.gradle includeBuild('libs/honeyrest-user') + substitute com.honeyrest:honeyrest-domain
โโโ build.gradle implementation 'com.honeyrest:honeyrest-domain'
โโโ src/main/java/com/honeyrest/honeyrest_host/entity/ErrorLog.java (ํธ์คํธ ์ ์ฉ ์ํฐํฐ๋ง ๋จ์)
- ๋ ์ด์์ ์ ํ: ์ฌ์ฉ์ API๋ฅผ
honeyrest-api/๋ก ์ฎ๊ธฐ์ง ์๊ณ ๋ฃจํธ์ ๋ ์ฑhoneyrest-domain/์๋ธํ๋ก์ ํธ๋ง ์ถ๊ฐํ๋ค. ์์คยท๋ฆฌ์์คยทCIยทREADME ๋งํฌยทIDE ์ค์ ๊ฒฝ๋ก๊ฐ ๋ชจ๋ ๊ทธ๋๋ก๋ผ ๋ณ๊ฒฝ์ด ๊ฐ์ฅ ์๊ณ , ํธ์คํธ๋ composite build ์project(':honeyrest-domain')์นํ์ผ๋ก ์ด ๋ชจ๋๋ง ๊น๋ํ๊ฒ ๊ฐ์ ธ๊ฐ ์ ์๋ค(๋ฃจํธ ์ฑ ํ๋ก์ ํธ๋ ๊ตฌ์ฑ๋ง ๋๊ณ ๋น๋๋์ง ์๋๋ค). - ์์กด์ฑ:
jakarta.persistence-api(api), Lombok,hibernate-core(compileOnly โ@CreationTimestamp/@UpdateTimestamp),querydsl-apt/querydsl-core(compileOnly โ ์ฌ์ฉ์ API ์ QueryDSL ๋ฆฌํฌ์งํ ๋ฆฌ๊ฐ ์ฐ๋QReservation๋ฑ Q ํ์ ์ ์ํฐํฐ์ ๊ฐ์ ํจํค์ง์ ์์ฑ). Spring ์์กด์ฑ, ์๋น์ค/๋ฆฌํฌ์งํ ๋ฆฌ๋ ์๋ค. - ์ค์บ: ๋ ์ฑ ๋ชจ๋
@EntityScan์ ๋ช ์ํ๋ค. ์ฌ์ฉ์ API@EntityScan("com.honeyrest.domain"), ํธ์คํธ@EntityScan({"com.honeyrest.domain", "com.honeyrest.honeyrest_host.entity"})(ErrorLog ํฌํจ). - ํ
์คํธ:
honeyrest-domain/src/test์ DBยทSpring ์๋ ๋จ์ ํ ์คํธ 6๊ฐ(ReservationStatus, Reservation ๋๋ฉ์ธ ๋ฉ์๋).
"๋์ผ"์ ๋ ์ฌ๋ณธ์ ๋งคํยท๋ฉ์๋๊ฐ ๊ฐ์ ํจํค์ง๋ง ์ฎ๊ธด ๊ฒฝ์ฐ๋ค. ์ธ๋ฑ์ค(@Index)๋ ์ฌ์ฉ์ ์ฌ๋ณธ์๋ง ์ ์ธ๋ผ ์์๊ณ ๊ณต์ ์ํฐํฐ์ ๊ทธ๋๋ก ๋์๋ค
(์ด์์ Flyway ๊ฐ ์คํค๋ง๋ฅผ ๋ง๋ค๊ณ validate ๋ ์ธ๋ฑ์ค๋ฅผ ๊ฒ์ฌํ์ง ์์ผ๋ฏ๋ก, H2 create-drop ํ
์คํธ ์คํค๋ง์๋ง ์ํฅ).
| # | ์ํฐํฐ (ํ ์ด๋ธ) | ์ฌ์ฉ์ ์ฌ๋ณธ | ํธ์คํธ ์ฌ๋ณธ | ๊ณต์ ์ํฐํฐ ๊ฒฐ์ |
|---|---|---|---|---|
| 1 | Accommodation (accommodation) |
updateRating() ๋ณด์ |
๋ฉ์๋ ์์ | ๋งคํ ๋์ผ. updateRating() ์ ์ง. ๋ฏธ์ฌ์ฉ java.sql.Time import ์ ๊ฑฐ |
| 2 | AccommodationCategory |
โ | โ | ๋์ผ |
| 3 | AccommodationImage |
โ | โ | ๋์ผ |
| 4 | AccommodationRequestMap |
ํ๋ RequestMapId(๋๋ฌธ์) |
๋์ผ | ํ๋๋ช
requestMapId ๋ก ์ ์ . getter(getRequestMapId)๋ ๊ทธ๋๋ก, ๋น๋ ๋ฉ์๋๋ง .requestMapId() (์ฌ์ฉ์ฒ ์์) |
| 5 | AccommodationTag |
iconName |
icon (๋ ๋ค ์ปฌ๋ผ icon_name) |
iconName ์ฑํ(์ปฌ๋ผ๋ช
๊ณผ ์ผ์น). ํธ์คํธ ์ฝ๋ยทํ
ํ๋ฆฟ์ icon ์ฌ์ฉ์ฒ ์์ |
| 6 | AccommodationTagMap |
โ | โ | ๋์ผ |
| 7 | Banner |
entity.BannerPosition |
entity.enums.BannerPosition |
๋งคํ ๋์ผ. BannerPosition ์ Banner ๊ฐ ์ฐธ์กฐํ๋ฏ๋ก com.honeyrest.domain.type ์ผ๋ก ์ด๋ |
| 8 | BaseEntity (MappedSuperclass) |
Spring AuditingEntityListener (@CreatedDate/@LastModifiedDate), ์ปฌ๋ผ๋ช
์๋ฌต |
๊ฐ์ ๋ฆฌ์ค๋ + @PrePersist/@PreUpdate ํด๋ฐฑ, ์ปฌ๋ผ๋ช
๋ช
์ |
Hibernate @CreationTimestamp/@UpdateTimestamp + ์ปฌ๋ผ๋ช
๋ช
์(created_at, updated_at). ๊ณต์ ๋ชจ๋์ Spring ๋ฌด์์กด์ผ๋ก ๋๊ธฐ ์ํจ. INSERT ์ ๋ ๋ค, UPDATE ์ updated_at ๊ฐฑ์ ์ผ๋ก ๊ฒฐ๊ณผ ๋์ผ |
| 9 | CancellationPolicy |
detail = TEXT |
detail = JSON |
TEXT (V6 ์คํค๋ง ๊ธฐ์ค) |
| 10 | Company |
โ | โ | ๋์ผ |
| 11 | Coupon |
maxOrderAmount |
maxDiscountAmount (์ปฌ๋ผ max_discount_amount) |
maxDiscountAmount ์ฑํ. ์ฌ์ฉ์ PaymentOrchestrationService, CouponService ํธ์ถ๋ถ ์์ . ํ๋ก ํธ ๊ณ์ฝ์ธ AvailableCouponDTO.maxOrderAmount ํ๋๋ช
์ ์ ์ง |
| 12 | CouponUsage |
โ | @ManyToOne ์ ์๋ชป ๋ถ์ @Enumerated(STRING) |
์๋ชป๋ @Enumerated ์ ๊ฑฐ, ๋๋จธ์ง ๋์ผ |
| 13 | EmailVerificationToken |
pending_email(V8) ๋งคํ, ์ธ๋ฑ์ค, @PrePersist ์์ ๋ง๋ฃ +24h |
pending_email ์์, @PrePersist ์์ isVerified=false |
pendingEmail ํฌํจ. @PrePersist ๋ createdAtยท๋ง๋ฃ(+24h) + isVerified ๊ฐ null ์ผ ๋๋ง false |
| 14 | Event |
โ | โ | ๋์ผ |
| 15 | Inquiry |
์ธ๋ฑ์ค 3๊ฐ | changeTitle/Content/Category/Reply/User/Accommodation() |
์ธ๋ฑ์ค + ํธ์คํธ ๋ณ๊ฒฝ ๋ฉ์๋ ๋ชจ๋ ์ ์ง (changeReply ๋ isReplied ๋๊ธฐํ) |
| 16 | Notification |
isRead = false (๋น๋ ๊ธฐ๋ณธ๊ฐ ๊ฒฝ๊ณ ) |
@Builder.Default |
@Builder.Default ์ฑํ |
| 17 | PasswordResetToken |
์ ์ ํฉํ ๋ฆฌ create() |
@PrePersist(createdAt, isUsed=false) |
๋ ๋ค ์ ์ง. @PrePersist ๋ ๊ฐ์ด ๋น์ด ์์ ๋๋ง ์ฑ์(create() ๊ฐ ๋ณด์กด) |
| 18 | Payment |
์ธ๋ฑ์ค, @OneToOne(mappedBy) paymentDetail(cascade ALL, orphanRemoval), isCompleted/isCancelled/isTossPayment() |
์์ | ๋ชจ๋ ์ ์ง. ์ปฌ๋ผ ์ถ๊ฐ ์์(์ญ๋ฐฉํฅ ์ฐ๊ด). ํธ์คํธ์๋ Payment ์ญ์ ๊ฒฝ๋ก๊ฐ ์์ด cascade ์ํฅ ์์ |
| 19 | PaymentDetail |
isCardPayment/isVirtualAccountPayment/isInstalledPayment() |
์์ | ์ ์ง |
| 20 | PointHistory |
์ธ๋ฑ์ค 2๊ฐ | โ | ์ธ๋ฑ์ค ์ ์ง, ๋งคํ ๋์ผ |
| 21 | PriceCalendar |
โ | โ | ๋์ผ |
| 22 | RefreshToken |
์ธ๋ฑ์ค | โ | ์ธ๋ฑ์ค ์ ์ง, ๋งคํ ๋์ผ |
| 23 | Region |
โ | โ | ๋์ผ |
| 24 | Reservation |
์ธ๋ฑ์ค 4๊ฐ, status/cancelReason @Setter, price ์ ๋ฐ๋ ๋๋ฝ |
public Long reservationId, price precision=10,scale=2, validateNew()/update(ReservationDTO,โฆ)/cancel() |
PK ํ๋๋ช
์ ์์ชฝ ๋ชจ๋ reservationId ๋ผ ์ ์งํ๋ private ๋ก(ํธ์คํธ ์ง์ ํ๋ ์ ๊ทผ ์์, JPQL r.reservationId ๊ทธ๋๋ก). price ๋ DECIMAL(10,2). @Setter + ํธ์คํธ ๋ฉ์๋ ๋ชจ๋ ์ ์ง. update() ๋ ํธ์คํธ DTO ์์กด์ ๋๊ธฐ ์ํด ReservationChanges ์ธํฐํ์ด์ค๋ฅผ ๋ฐ๊ฒ ๋ฐ๊พธ๊ณ ํธ์คํธ ReservationDTO ๊ฐ ๊ตฌํ |
| 25 | Review |
rating precision=3,scale=2, updateContent(), likeCount @Setter, ์ธ๋ฑ์ค |
rating scale=1 |
scale=2 (V1 DECIMAL(3,2)). ์ฌ์ฉ์ ๋ฉ์๋/์ธํฐ ์ ์ง |
| 26 | ReviewImage |
์ธ๋ฑ์ค | โ | ์ธ๋ฑ์ค ์ ์ง, ๋งคํ ๋์ผ |
| 27 | Room |
โ | โ | ๋์ผ |
| 28 | RoomImage |
โ | โ | ๋์ผ |
| 29 | User |
tokenValidAfter(V9), revokeExistingTokens(), verify/updateEmail/updateProfileโฆ/deleteAccount() |
isVerified @Builder.Default |
๋ชจ๋ ์ ์ง + @Builder.Default(๋น๋ ๊ธฐ๋ณธ๊ฐ์ด null โ false, is_verified NOT NULL) |
| 30 | UserCoupon |
use(), ์ธ๋ฑ์ค |
โ | ์ ์ง |
| 31 | WishList |
์ธ๋ฑ์ค(user_id, accommodation_id UNIQUE ํฌํจ) |
โ | ์ธ๋ฑ์ค ์ ์ง, ๋งคํ ๋์ผ |
| 32 | ErrorLog (error_log, V11) |
์์ | ํธ์คํธ ์ ์ฉ | ํธ์คํธ์ ๋จ๊น (com.honeyrest.honeyrest_host.entity). ๋ค๋ฅธ ์ํฐํฐ๊ฐ ์ฐธ์กฐํ์ง ์์ |
| ํ์ | ๊ฒฐ์ |
|---|---|
ReservationStatus |
์์ยทOCCUPYING ์ ์์ชฝ ๋์ผ. ํธ์คํธ์ ALL, isOccupying(), normalize() ๋ฅผ ํฉ์ณ com.honeyrest.domain.type ์ผ๋ก ์ด๋ |
BannerPosition |
๊ฐ ๋์ผ(MAIN_TOP, MAIN_MIDDLE, CATEGORY_TOP). com.honeyrest.domain.type ์ผ๋ก ์ด๋ |
ReservationChanges (์ ๊ท) |
Reservation.update() ๋ถ๋ถ ๋ณ๊ฒฝ ๊ฐ ์ธํฐํ์ด์ค. null = ๋ณ๊ฒฝ ์์ |
- ๊ฐ์ฌ(auditing) ๋ฐฉ์ ๋ณ๊ฒฝ:
AuditingEntityListenerโ Hibernate ํ์์คํฌํ.@CreationTimestamp๋ INSERT ๋ ํญ์ ํ์ฌ ์๊ฐ์ผ๋ก ๋ฎ์ด์ด๋ค (ํธ์คํธ ํด๋ฐฑ์ ๋ฏธ๋ฆฌ ์ฑ์ด createdAt ์ ๋ณด์กดํ๋ค). ๋ ์ฑ ๋ชจ๋ createdAt ์ ์ง์ ์ฑ์ ์ ์ฅํ๋ ์ฝ๋๊ฐ ์์ด ๋์ ์ฐจ์ด๋ ์๋ค.@EnableJpaAuditing์ ๋ ์ฑ์ ๋จ์ ์์ง๋ง ๋ฌดํดํ๋ค. EmailVerificationToken๋ง๋ฃ: ์ฌ์ฉ์ ์ฌ๋ณธ๋๋ก@PrePersist์์ ํญ์ +24h ๋ก ์ ํ๋ค. ํธ์คํธ๋ ์ด ํ ํฐ์ ๋ง๋ค์ง ์๋๋ค.AvailableCouponDTO.maxOrderAmount: ์ํฐํฐ ํ๋๋ช ๋ง ๋ฐ๊พธ๊ณ API ์๋ต ํ๋๋ช ์ ํ๋ก ํธ์๋ ๊ณ์ฝ์ด๋ผ ๊ทธ๋๋ก ๋์๋ค.- QueryDSL Q ํ์
: ์ํฐํฐ๊ฐ ๋ชจ๋๋ก ์ฎ๊ฒจ๊ฐ Q ํ์
๋
honeyrest-domain์์ ์์ฑ๋๋ค(com.honeyrest.domain.entity.QReservation). ์ ์ฅ์์ ์ปค๋ฐ๋ผ ์๋ ์ ํจํค์ง์ Q ํ์ ์ค๋ ์ท(src/main/generated/โฆ, ๋น๋์ ์ฐ์ด์ง ์์)์ ์ญ์ ํ๋ค. - ํธ์คํธ
entity/ํด๋์ ๋ ๊ฑฐ์ SQL(accommodation.sql,insert.sql)์ ์ด๋ฒ ๋ฒ์ ๋ฐ์ด๋ผErrorLog.java์์ ๊ทธ๋๋ก ๋์๋ค.
- ์ํฐํฐ๋ฅผ ๋ฐ๊ฟ ๋๋ ์ด ์ ์ฅ์์์
honeyrest-domain์ํฐํฐ์ Flyway ๋ง์ด๊ทธ๋ ์ด์ ์ ๊ฐ์ ์ปค๋ฐ์ผ๋ก ๋ฐ๊พผ๋ค. ./gradlew test(๋ฃจํธ +:honeyrest-domain) โ ๊ฐ๋ฅํ๋ฉด./gradlew integrationTest(Docker).- ํธ์คํธ ์ ์ฅ์์์ ์๋ธ๋ชจ๋์ ๊ทธ ์ปค๋ฐ์ผ๋ก ์ฌ๊ณ ์ ํ๋ค.
cd honeyRest_host git submodule update --remote libs/honeyrest-user # ๋๋: git -C libs/honeyrest-user checkout <์ปค๋ฐ> ./gradlew test git add libs/honeyrest-user && git commit -m "honeyrest-user ์๋ธ๋ชจ๋ ์ฌ๊ณ ์ "
- ์ปค๋ฐ ์ ๋ณ๊ฒฝ์ ํธ์คํธ์์ ๋ฐ๋ก ํ์ธํ๋ ค๋ฉด ๋ ์ ์ฅ์๋ฅผ ๋๋ํ ๋๊ณ
./gradlew test -PhoneyrestUserDir=../honeyRest_user.