25-03-09
๐ Daily Reportโ
๐ ํ๋ก์ ํธ ์ํฉโ
์ฌ์ ํ ๊ตฌํํ ๊ฒ์ด ์ฐ๋๋ฏธ์ด๊ณ , ์ฝ๋ ๋ฆฌ๋ทฐ๊ฐ ๋ค์ด์์ ๊ฒํ ํ ๋ฆฌํฉํ ๋งํด์ผ ํ๊ณ , Kibana ์ธ์ฝ๋ฉ ๋ฌธ์ ๋ ํด๊ฒฐ ๋ชปํ๋ค.
ใ ใ ใ ใ ใ ใ ใ ใ ใ
๋๋๊ฒ๋ ์ค๋ ํ๊ณ ์ถ์ ๋งํผ ์ ์ด๋์ ๊ฒ์ด๊ณ , ์ค์ ๋ก๋ ํ ์ผ ๋ ๋ง์.
API Gateway์ https ์ค์ ์ ๋งํ์ ๋ง๋ฌด๋ฆฌํ๋ฉด์ ํ๋ ค ํ๋๋ฐ... ๋ชฉ์์ผ๋ถํฐ ์ฑ๋ฅ ํ ์คํธ ๋ณด๊ณ ์ ์์ฑํ๋ ค๋ฉด ์ฝ๋ ๋ฆฌ๋ทฐ ๊ฒํ ๊น์ง๋ง ํ๊ณ ๋ฆฌํฉํ ๋ง์ ํ์์๋ก ๋ฐ์ด์ผ ํ ๋ฏ ์ถ๋ค.๐
๐ JS ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ค์ฝํโ
๊ทธ๋์ ์ async
-await
๋ถ์ฌ๋ ๋ ๋๊ฐ ์๊ณ ์๋ ๋๊ฐ ์๋์ง ์๋ฌธ์ธ ์ ์ด ๋ช ๋ฒ ์์๋๋ฐ,
์ด ๋ ํผ๋ฐ์ค์์ ์ค์ํ ๋ช ์ธ์ ํ๋ ๋จ๊ฒจ๋์ ๊ฒ ๊ฐ๋ค.
"์๋ฐ์คํฌ๋ฆฝํธ์์ async/await ์ฌ์ฉ ์ ๋์ผํ ์ค์ฝํ์์ awaitํ์ง ์์ผ๋ฉด ์์ ์คํํ async๋ฅผ ๊ธฐ๋ค๋ ค์ฃผ์ง ์๋๋ค."
๊ทธ๋ฌํ๋ค. ์ค์ฝํ...
์ ์๋ฌด๋ ์ค์ฝํ์ ๋ํด์ ์๊ธฐ๋ฅผ ์ํ๋๊ฑฐ์ง? ์ด ์ธ ๊ธ์๋ก ์ดํด๊ฐ ๋ฐ๋ก ๋๋๋ฐ.
๐ ERD 4์ฐจ ์์ ์ ๋ฐ๋ฅธ ์ฌ์ด๋ ์ดํํธโ
์ฌ๊ฑด์ ๋ฐ๋จ์ ์ด๋ฌํ๋ค.
- ํ์ ์คํ ์ด ์์ธ ํ์ด์ง์ ์ด์ ์์ ์๊ฐ๊ณผ ์ข ๋ฃ ์๊ฐ์ด ๋ค์ด๊ฐ ํ์๊ฐ ์์์ ๋๋
- ์ด ๊ทผ๋ฐ ํ์ ์คํ ์ด ํ ์ด๋ธ์ ๊ด๋ จ ์นผ๋ผ์ด ์๋ค? ์ถ๊ฐํด์ผ์ง
- ์ด๋ฏธ ์ด์ ์์์ผ์
storeStart
, ์ข ๋ฃ์ผ์storeEnd
๋ค์ด๋ฐ์ผ๋ก ๋๊ณ ์์ - ์ด์ ์๊ฐ์ ์ถ๊ฐํ๊ธฐ ์ํด ์ด์ ์ผ์ ์นผ๋ผ๋ช
์
Date
๋ฅผ ๋ถ์ด๊ณ , ์ด์ ์๊ฐ์ ๋ค์Time
์ ๋ถ์ด๊ธฐ๋ก ํจ Store
์ํฐํฐ ์์
data.sql
ํ์ผ ์๊ฐ ์ ์ผ ํฐ ๋ฌธ์ ์ธ๋ฐ, ์ด๋ ๊ฒ ์นผ๋ผ ๋ณ๊ฒฝ ๋ฑ์ผ๋ก ํ
์ด๋ธ ์คํ์ด ๋ฐ๋์ด์ ํ์ผ ๋ด์ INSERT๊ฐ ์ ๋๋ก ๋์ํ์ง ์์๋, ์๋ฌด๋ฐ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ์ง ์๋๋ค.
๊ทธ๋์ ๋๊น ๋ง์ผ๋ฉด์ ์๊ฒ ๋๋ ๋ถ๋ถ์ธ๋ฐ ์ด๋ฏธ ์ ์ ๋ง์๋ด์, ๋คํํ ๊ธ๋ฐฉ ๋์น์ฑ๊ธด ํ๋ค.
mock data ์ฟผ๋ฆฌ๊ฐ ์๋ ๋ผ๊ฐ๋๊น ES ์ธ๋ฑ์ฑ์ด ์๋์๊ฐ๊ณ -> ์ธ๋ฑ์ฑ์ด ์๋๋๊น ๋ฉ์ธํ๋ฉด์์ ๋ชฉ๋ก ์กฐํ๊ฐ ์๋๋๋ผ.
INSERT ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๋ ํ ์ด๋ธ ์คํ์ ๋ง์ถฐ ์์ ํ๋ ๋ค์ ์ธ๋ฑ์ฑ์ ๋์๊ฐ๋๋ฐ, ๋น์ฐํ ES Document ์คํ๋ ๊ฐ์ด ์์ ํ์ด์ผ ํ๋ค. ์ด๋ฒ์ ์ถ๊ฐ๋ ์นผ๋ผ์ด ์ธ๋ฑ์ฑ ๋์์ ์๋์์ง๋ง, ์ธ๋ฑ์ฑํ๋ ์ด์ ์ผ์ ์นผ๋ผ๋ช ์ด ๋ฐ๋์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ ๊ฒ ์์ ํด์ ์๋ฒ๋ฅผ ์คํํ๋๋ฐ, ํ์๋ฆฌํ๊ฐ ํฐ์ง๋๋ผ. ์ต์ด ๋ ๋๋ง๋ง ํ ํ๋ฆฟ ์์ง์ผ๋ก ํ๊ณ ์ดํ์ ๋ ๋๋ง ๋ณํ๋ axios ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ ค ํ๋๋ฐ ์ด ๋ฐฉ์์ด... ๋ณ๋ก์ธ๊ฐ?
์๋ฌดํผ ์นผ๋ผ๋ช ๋ณ๊ฒฝ์ผ๋ก flatpickr ์ค์ ๊น์ง ํฐ์ ธ์ view๋จ๊น์ง ์น ๊ณ ์ณ์ค์ผ ํ์ใ
๐ @DynamicInsert
๋ฅผ ๋๋์ด ์ดํดํจโ
@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReservationEntry {
// ...
@Column(nullable = false)
@ColumnDefault("0")
private Integer reservedCount; // ์์ฝ์ ์
// ...
}
public class StoreService {
// ...
// 5. ReservationEntry ์์ฑ
List<ReservationEntry> reList = new ArrayList<>();
LocalDate endDate = dto.getStoreEndDate();
LocalTime endTime = dto.getStoreEndTime();
int reserveGap = dto.getReserveGap();
int capacity = dto.getCapacity();
for (LocalDate curDate = dto.getStoreStartDate(); !curDate.isAfter(endDate); curDate = curDate.plusDays(1)) {
for (LocalTime curTime = dto.getStoreStartTime(); curTime.isBefore(endTime); curTime = curTime.plusMinutes(reserveGap)) {
reList.add(ReservationEntry.builder()
.store(store)
.entryDate(curDate)
.entryTime(curTime)
.capacity(capacity)
.entryStatus(ReservationEntry.EntryStatus.OPEN)
.build()
);
}
}
reRepo.saveAll(reList);
// ...
}
20:14:26.751[http-nio-9093-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Failed to complete request: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.ssginc.commonservice.reserve.model.ReservationEntry.reservedCount
์ @ColumnDefault("0")
๊ฐ ์๋จนํ๊ณ ์๋ฌ๊ฐ ๋จ๋์ง ์๋ฌธ์ด์๋๋ฐ, ์ด ๊ธ์ ์ฐธ๊ณ ํด๋ณด๋ฉด @DynamicInsert
๋ฅผ ์ํฐํฐ์ ๋ช
์ํ์ง ์์๊ธฐ์
INSERT ์ฟผ๋ฆฌ์์ reserveCount
๋ฅผ null๋ก ๋ฃ์ผ๋ ค ํ ๊ฒ ๊ฐ๋ค.
ํ์ง๋ง ํ๋ก์ ํธ์ ๊ฒฝ์ฐ MySQL์์ ๋ํดํธ ๊ฐ 0์ ์ง์ ํ๊ธฐ ๋๋ฌธ์ @DynamicInsert
๋ฅผ ์ถ๊ฐํด์ ์์ INSERT ์ฟผ๋ฆฌ์์ reserveCount
์นผ๋ผ์ด ์ ์ธ๋์ด์ผ ํ๋ ๊ฒ์ด ๋ง๋ค.
...๊ทธ๋ฐ๋ฐ @DynamicInsert
๋ฃ์ด๋ ๋๊ฐ์ด ์ค๋ฅ ๋ฐ์ํด์ ์ผ๋จ ๋๋นต ์ฒ๋ฆฌํด๋๊ณ ๋์ค์ ๋ค์ ๋๋ฒ๊น
ํด๋ด์ผ ํ ๊ฒ ๊ฐ๋ค.
๐ ํ์ ์คํ ์ด ๋ฑ๋ก API ๊ตฌํ ์๋ฃโ
Store
StoreImage
StoreCategory
ReservationEntry
์๋ค ์ฒ๋ฆฌ ์์๊ฐ ์ฒ์์ ๋ชจํธํ๋ค.
์๋ฐฉํฅ ๋งคํ๊ด๊ณ๋๋ฌธ์ Store๋ฅผ ์ ์ฅํ๋ ค๋ฉด StoreImage์ StoreCategory๋ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋๋ฐ
StoreImage์ StoreCategory ์ญ์ Store๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ...
๋๊ตฌ๋ฅผ ๋จผ์ , ์ด๋ป๊ฒ ์์ฑํด์ผ ํ๋๊ฐ? ๋ผ๋ ์๋ฌธ์ด ๋ค์๋ค.
๊ทธ๋ฐ๋ฐ ์ฝ๋ ์์ฑํ๋ค๋ณด๋, Elasticsearch์์ Store๋ฅผ ์ธ๋ฑ์ฑํด์ผํ๊ณ
์ธ๋ฑ์ฑํ ๋ StoreImage๋ ์ํํด์ MAIN_THUMBNAIL์ ๊ฐ์ ธ๊ฐ๊ณ
StoreCategory๋ CategoryNoDescDto๋ก ์ฌ๊ฐ๊ณตํด์ ๊ฐ์ ธ๊ฐ๋๊น,
์ธ๋ฑ์ฑํ๊ธฐ ์ ์๋ ์๋ค๊ฐ ๋ฉ๋ชจ๋ฆฌ ์์ ํ ๋น์ด ๋์ด์์ด์ผ ํ๋ ๊ฒ์.
์ ๋ฆฌํ์๋ฉด ์ด๋ ๋ค.
- StoreImage, StoreCategory๋ง ํ ๋น ์๋ Store ์์ฑ -> ๋ฉ๋ชจ๋ฆฌ ์์ ์กด์ฌ
- EntityManager๋ก Store๋ฅผ persist -> INSERT ์ฟผ๋ฆฌ ๋ ๋ผ๊ฐ (์ด ์์ ๋ถํฐ auto increment๋ id ๊ฐ ์ ๊ทผ ๊ฐ๋ฅ)
- Store์ id ๊ฐ์ผ๋ก StoreImage์ StoreCategory ์์ฑ -> ๋ฉ๋ชจ๋ฆฌ ์์ ์กด์ฌ
- Store์ StoreImage, StoreCategory setํ๊ธฐ -> ๋ฉ๋ชจ๋ฆฌ ์์ ๊ฐ์ฒด์ ํ ๋น
- StoreImage ์ ์ฅ (๋น์ฐํ StoreCategory๋ ์ ์ฅ ์ํจ.) -> INSERT ์ฟผ๋ฆฌ ๋ ๋ผ๊ฐ
- ReservationEntry ์์ฑ ๋ฐ ์ ์ฅ -> INSERT ์ฟผ๋ฆฌ ๋ ๋ผ๊ฐ
- Elasticsearch ์ธ๋ฑ์ฑ -> ๋ฉ๋ชจ๋ฆฌ ์์ Store ๊ฐ์ฒด๋ก ์ฒ๋ฆฌํจ
@Transactional
์ ์ํด COMMIT
๊ฒฐ๊ตญ์, ๋ฉ๋ชจ๋ฆฌ ์์ ๊ฐ์ฒด๊น์ง๋ง ํ์ํ ๋ถ๋ถ์ด ์ด๋ ์ง์ ์ธ์ง,
๊ทธ๋ฆฌ๊ณ DB์ ์ฟผ๋ฆฌ๊ฐ ๋ ๋ผ๊ฐ์ผ ํ๋ ์ง์ ์ด ์ด๋ ์ง์ ์ธ์ง๋ฅผ ๋ช ํํ ์๊ณ ์์ด์ผ ํ๋ค.
Store๋ ๋๋ถ๋ถ์ด @OneToMany
๋ก ์์์ด ๋งคํ๋ ๋ถ๋ชจ ์ํฐํฐ์ด๊ณ , ์์ ์ ๋ณด๊ฐ DB์ INSERT ๋ ๋ฆด ๋๋ ๋ฑํ ํ์ ์์ผ๋๊น, Store๋ฅผ persistํด์ INSERT ์ฟผ๋ฆฌ๋ฅผ ๋จผ์ ๋ ๋ฆฌ๋ ๊ฒ์ด ์ณ์ ์์์๋ ๊ฒ์ด๋ค.
JPA์์ ๋ถ๋ชจ-์์ ์ํฐํฐ ํ๋ฒ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์๋ค๊ณ ๋ ํ๋๋ฐ ์ด๋ ๋์ค์ ๋ฆฌํฉํ ๋งํด๋ณด๊ธฐ๋ก ํ๊ณ
๋ฌด์ํ๊ฒ ์๊ฐํ์๋ฉด ์๋จ์ ์ ์์๊ฐ ์ง๊ด์ ์ด๋ค.
โจ ๊ตฌํ ๊ฒฐ๊ณผโ
๊ณ ์ํ๋ค. ๊ทผ๋ฐ resizing ์ต์ ์ ์๋ชป ์ค์ ํ๋ฏ ใ ใ ใ ใ
๋ฒ๊ทธ ๋ฆฌํฌํธ... ์ถ๊ฐ์...