λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

ν”„λ‘œμ νŠΈ/Airbnb Clone

(13)
[둜그인 및 νšŒμ›κ°€μž…] μ‚¬μš©μž νŽΈμ˜μ„±μ„ κ³ λ €ν•œ 이메일 인증 기반 둜그인/νšŒμ›κ°€μž… μ†Œκ°œ μš”κ΅¬μ‚¬ν•­ μ†Œκ°œAirbnb μ‚¬μ΄νŠΈμ—μ„œ λ‘œκ·ΈμΈν•˜κΈ° μœ„ν•΄ 이메일을 μž…λ ₯ν–ˆμ„ λ•Œμ΄λ©”μΌμ΄ μ‘΄μž¬ν•œλ‹€λ©΄ λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜λŠ” 창을 λ„μ›Œμ£Όκ³ ,이메일이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ν•΄λ‹Ή 이메일을 가지고 νšŒμ›κ°€μž…μ„ ν•˜λ„λ‘ μ§„ν–‰μ‹œν‚΅λ‹ˆλ‹€.κ³ λ―Ό 포인트1. Aμ‚¬μš©μžμ™€ Bμ‚¬μš©μžκ°€ λ™μ‹œμ— 같은 μ΄λ©”μΌλ‘œ νšŒμ›κ°€μž…μ„ ν•  λ•Œ, λˆ„κ΅¬μ˜ 이메일을 μœ νš¨ν•˜κ²Œ λ³Ό 것인가? μ²˜μŒμ—λŠ” λ‘œκ·ΈμΈν•˜κΈ° μœ„ν•΄ 이메일을 λ¨Όμ € μž…λ ₯ν•œ μ‚¬μš©μžλ§Œ μ²˜λ¦¬λ˜μ•Ό ν•œλ‹€ μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.κ·Έλž˜μ„œ λ™μ‹œμ— 이메일을 μž…λ ₯ν–ˆμ„ λ•Œμ˜ μΌ€μ΄μŠ€λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ μ‹±κΈ€ μŠ€λ ˆλ“œμΈ Redis 에 λ¨Όμ € λ“€μ–΄μ˜¨ 이메일을 μ €μž₯ ν•  순 μžˆμ§€λ§Œ, 이후에 μš”μ²­ν•œ μ‚¬μš©μž μž…μž₯μ—μ„œλŠ” νšŒμ›κ°€μž… ν•˜μ§€λ„ μ•Šμ•˜λŠ”λ° λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜λŠ” 창을 λ„μ›Œμ£ΌλŠ” 것은 μ‚¬μš©μžλ‘œ ν•˜μ—¬κΈˆ λΆˆνŽΈν•˜λ‹€κ³  νŒλ‹¨ν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜, 메일 μ„œλ²„μ˜ APIλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄..
[νŠΈλŸ¬λΈ” μŠˆνŒ…] jakarta.mail.internet.addressexception: local address contains control or whitespace ꡬ글링 해도 λ‚˜μ˜€μ§€ μ•Šλ˜ μ—λŸ¬λ₯Ό ν•΄κ²°ν•˜λŠ” 과정을 μ†Œκ°œν•˜λ©°, μ™œ λ°œμƒν•˜κ³  μ–΄λ–»κ²Œ ν•΄κ²°ν–ˆλŠ”μ§€ μ†Œκ°œν•˜λŠ” κΈ€μž…λ‹ˆλ‹€.SMTP κΈ°λŠ₯에 λŒ€ν•΄ μ„€λͺ…ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.μ„œλ‘ μ—μ–΄λΉ„μ•€λΉ„μ— νšŒμ›κ°€μž…ν•  λ•Œ, νšŒμ›μ΄ μž…λ ₯ν•œ 이메일이 정상 이메일인지 ν™•μΈν•˜κ³ μž 인증번호λ₯Ό λ³΄λ‚΄κ³ μž ν–ˆμŠ΅λ‹ˆλ‹€.κ·Έλž˜μ„œ, μ•„λž˜μ™€ 같은 μ½”λ“œλ‘œ 넀이버 μ„œλ²„μ— 메일을 λ³΄λƒˆμœΌλ‚˜, `jakarta.mail.internet.addressexception: local address contains control or whitespace` μ—λŸ¬κ°€ javaMailSender.send(message) μ—μ„œ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.public void sendVerificationEmail(String memberEmail) { try { SimpleMai..
[νŠΈλŸ¬λΈ” μŠˆνŒ…] 20만 더미 데이터 μ‚½μž…μ„ csvνŒŒμΌμ„ μ΄μš©ν•΄μ„œ DB connection timeout → 7초둜 쀄이기 β­μ„œλ‘ μ½”λ“œμŠ€μΏΌλ“œ 에어비앀비 클둠 μ½”λ”© ν”„λ‘œμ νŠΈ 쀑 μ„±λŠ₯ ν…ŒμŠ€νŠΈλ₯Ό ν•˜κ³  μ‹Άμ—ˆκ³ ,이λ₯Ό μœ„ν•΄ λ‹€λŸ‰μ˜ μˆ™μ†Œ, μ˜ˆμ•½, νšŒμ›μ˜ 더미 데이터λ₯Ό λ§Œλ“€κ³ μž ν•˜μ˜€μŠ΅λ‹ˆλ‹€. λ”λ―Έ 데이터λ₯Ό μˆ™μ†Œ 20만개, μ˜ˆμ•½ 100만개, νšŒμ› 1만λͺ…을 λ§Œλ“€κ³ μž ν•˜μ˜€μŠ΅λ‹ˆλ‹€.이 쀑, μˆ™μ†Œ 20만개λ₯Ό λ§Œλ“œλŠ” κ³Όμ •μ—μ„œ 생긴 일을 μ†Œκ°œν•©λ‹ˆλ‹€. 20만개 μˆ™μ†Œ 데이터λ₯Ό Java μ½”λ“œλ‘œ μˆ™μ†Œ 1κ°œλ§ˆλ‹€ INSERT INTO 쿼리λ₯Ό DB에 λ‚ λ Έλ”λ‹ˆ DB connection timeout 문제λ₯Ό λ§ˆμ£Όν–ˆμŠ΅λ‹ˆλ‹€. - κ³ λ €ν•œ λ°©μ•ˆMySQL의 λ ˆμ½”λ“œλŠ” ν…Œμ΄λΈ” λ‹¨μœ„μ˜ 파일둜 μ €μž₯λœλ‹€λŠ” 점에 μ°©μ•ˆν•œ csv파일 μ‚¬μš©λŒ€λŸ‰ μ‚½μž…μ— νŠΉν™”λœ 기술인 Spring Batch - 2가지 이유둜 csvνŒŒμΌμ„ μ΄μš©ν•˜κΈΈ μ„ νƒν–ˆμŠ΅λ‹ˆλ‹€.ν”„λ‘œμ νŠΈ 남은 1μ£Ό λ™μ•ˆ μ„±λŠ₯ ν…ŒμŠ€νŠΈλ₯Ό ν•΄μ•Όλœλ‹€λŠ” 점더미 ..
[λ™μ‹œμ„± μ œμ–΄] μœ λ‹ˆν¬ μ œμ•½μ‘°κ±΄μ„ ν™œμš©ν•΄ 1 건의 μ˜ˆμ•½λ§Œ μ €μž₯ β­μš”κ΅¬μ‚¬ν•­μ½”λ“œμŠ€μΏΌλ“œμ˜ Airbnb ν”„λ‘œμ νŠΈ 쀑같은 μˆ™μ†Œμ— μ‚¬λžŒ A 와 μ‚¬λžŒ B κ°€ λ™μ‹œμ— μ˜ˆμ•½μ„ μš”μ²­ν•  경우, ν•œ 건의 μ˜ˆμ•½λ§Œ 성곡해야 ν•©λ‹ˆλ‹€.(같은 μˆ™μ†Œλ₯Ό μ‚¬λžŒ A와 μ‚¬λžŒ Bκ°€ λ™μ‹œμ— μ‚¬μš©ν•˜λ©΄ μ•ˆλ˜λ‹ˆκΉŒ!)β­κ³ λ―Όκ·Έλž˜μ„œ, λ™μ‹œμ— μ˜ˆμ•½ μš”μ²­μ„ 막기 μœ„ν•΄λΉ„κ΄€μ  락낙관적 락DB의 μœ λ‹ˆν¬ μ œμ•½μ‘°κ±΄μ„ κ³ λ―Όν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.⭐해결 κ³Όμ •μ˜ˆμ•½μ΄ μ €μž₯λ˜λŠ” μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.@Transactionalpublic BookingResponse create(BookingSaveRequest request) { // μš”μ²­ν•œ μ˜ˆμ•½μ΄ κΈ°μ‘΄ μ˜ˆμ•½μ˜ 일정과 μ€‘λ³΅λ˜λŠ”μ§€ ν™•μΈν•˜λŠ” 둜직 Long bookedStayCount = bookingRepository.countBookedStay(request.getStayId(), re..
[Querydsl] Expressions.dateTemplate, timeTemplate μ‚¬μš©κΈ° Querydsl 의 κΈ°λ³Έ μ‚¬μš©λ²•μ€ μ†Œκ°œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Querydsl 을 ν•™μŠ΅ 쀑에 μž‘μ„±ν•œ 글이기 λ•Œλ¬Έμ— μ†Œκ°œν•œ 방법이 졜고의 방법이 아닐 수 μžˆμŒμ„ μ•Œλ €λ“œλ¦½λ‹ˆλ‹€πŸ™‡‍β™‚οΈκ°œλ°œν™˜κ²½JDK 17, Querydsl 5.0.0, Spring boot 3.xβ­μ„œλ‘ μ½”λ“œμŠ€μΏΌλ“œ 에어비앀비 클둠 ν”„λ‘œμ νŠΈ 쀑, μ‚¬μš©μž 쑰건에 따라 μˆ™μ†Œκ°€ κ²€μƒ‰λ˜λŠ” κΈ°λŠ₯을 κ΅¬ν˜„ν•˜κ³ μž ν–ˆμŠ΅λ‹ˆλ‹€.μ‚¬μš©μžκ°€ 6/19 ~ 6/20 λ₯Ό μˆ™μ†Œ 검색 쑰건으둜 λ“±λ‘ν•˜λ©΄,μ„œλ²„μ—μ„œλŠ” 6/19 ~ 6/20 κΉŒμ§€ 이용 κ°€λŠ₯ ν•œ μˆ™μ†Œ ID(μ˜ˆμ•½ λ˜μ–΄μžˆμ§€ μ•Šμ€ μˆ™μ†Œ ID) λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€. μ˜ˆλ₯Ό λ“€μ–΄,μˆ™μ†Œ IDκ°€ 1인 μˆ™μ†Œμ— `6/19 PM15:00 ~ 6/20 AM11:00` 인 μ˜ˆμ•½μ΄ μžˆλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€.λ§Œμ•½, μ‚¬μš©μžκ°€ 6/20 ~ 6/21 에 μ΄μš©κ°€λŠ₯ν•œ μˆ™μ†Œλ₯Ό μ°ΎλŠ”λ‹€λ©΄..