개발자 HOON
πŸ› HOON DEVLog
개발자 HOON
전체 방문자
였늘
μ–΄μ œ
  • 😎 전체 μΉ΄ν…Œκ³ λ¦¬ (137)
    • πŸ“ μ‹ μž… 인터뷰 μ€€λΉ„ (7)
    • πŸ¦” μ·¨μ—…μ€€λΉ„ 기둝 (7)
    • β˜• μžλ°” : JAVA (5)
    • 🐍 μ½”λ”©ν…ŒμŠ€νŠΈ λŒ€λΉ„ : PS (80)
    • 🌱 λ°±μ—”λ“œ : Backend (13)
    • πŸ§ͺ 컴퓨터과학 : CS (11)
    • πŸ—‚ λ°μ΄ν„°λ² μ΄μŠ€ : DB (1)
    • πŸƒ‍♂️ DEVLOG (8)
    • βš™οΈ Trouble Shooting (5)

λΈ”λ‘œκ·Έ 메뉴

  • ν™ˆ
  • GitHub
  • Resume

곡지사항

인기 κΈ€

졜근 κΈ€

ν‹°μŠ€ν† λ¦¬

hELLO Β· Designed By μ •μƒμš°.
개발자 HOON

πŸ› HOON DEVLog

[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (1) λ³€μˆ˜ μž‘λͺ…, Optional, Enum ν™œμš©
πŸƒ‍♂️ DEVLOG

[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (1) λ³€μˆ˜ μž‘λͺ…, Optional, Enum ν™œμš©

2022. 12. 15. 23:57

🏝 0. μ„œλ‘ 

 

μ‘Έμ—…μž‘ν’ˆμœΌλ‘œ νƒˆλͺ¨ 진단 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μΈ '제발λͺ¨λ°œ'을 κ°œλ°œν•˜κ³ , 'ν•΄λ‹Ή ν”Œλž«νΌμ„ μžμ‹ μ˜ νšŒμ‚¬μ— 이전해 μ‚¬μš©ν•˜κ³  μ‹Άλ‹€'λΌλŠ” μ–΄λŠ κ΅μˆ˜λ‹˜μ„ λ§Œλ‚˜ AWS μƒνƒœκ³„μ—μ„œ 사내 μ„œλ²„ μ»΄ν“¨ν„°λ‘œ 이전을 μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

 

이전을 μ§„ν–‰ν•˜λ©΄μ„œ 이미지 μ €μž₯ λ“±μ˜ κΈ°λŠ₯은 AWS μƒνƒœκ³„μ— μ˜μ‘΄ν–ˆμ—ˆκΈ° λ•Œλ¬Έμ— ν•΄λ‹Ή μ˜μ‘΄μ„ λŠμ–΄λ‚΄κΈ° μœ„ν•΄μ„œ 이미지 μ—…λ‘œλ“œ 및 λ‹€μš΄λ‘œλ“œ APIλ₯Ό λ§Œλ“€ 일이 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ©΄μ„œ λ°±μ—”λ“œ λ ˆκ±°μ‹œ μ½”λ“œλ₯Ό ν™•μΈν–ˆλŠ”λ°, 생각보닀 λ¬Έμ œκ°€ λ§Žμ•„ λ¦¬νŒ©ν† λ§ & κ°œμ„ μ„ ν•˜κΈ°λ‘œ λ§ˆμŒλ¨Ήμ—ˆμŠ΅λ‹ˆλ‹€. 

 

ν€„λ¦¬ν‹°μ™€λŠ” 관계 없이 ν•΄λ‹Ή λ°±μ—”λ“œ μ„œλ²„λ₯Ό μ΄μ „ν•˜κ³  μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ œκ³΅ν•˜λŠ” 것이 κ³„μ•½μ˜ μ „λΆ€μ§€λ§Œ, ν•œ 번 λ³Έ 이상 κ·Έλƒ₯ μ§€λ‚˜μΉ  μˆ˜λŠ” μ—†μ—ˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μ•žμœΌλ‘œ μ—¬λŸ¬λͺ¨λ‘œ λ¬Έμ œκ°€ λ§Žμ€ μ½”λ“œλ₯Ό, μ•Œμ•„λ³΄κΈ° μ‰¬μš΄ μ½”λ“œ / μž¬μ‚¬μš©μ„±μ΄ 쒋은 μ½”λ“œ / μœ μ—°ν•œ μ½”λ“œ / μ‹€μˆ˜λ₯Ό 쀄일 수 μžˆλŠ” μ½”λ“œλ‘œ λ³€κ²½ν•˜λŠ” 과정을 ν•˜λ‚˜μ”© 기둝해보렀고 ν•©λ‹ˆλ‹€.

 

μ‘Έμ—…μž‘ν’ˆ 개발 λ‹Ήμ‹œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ „λ‹΄μœΌλ‘œ λ§‘μ•˜κ³ , 각자 맑은 역할에 μ§‘μ€‘ν•˜κ³  λ°λ“œλΌμΈ μ§€ν‚€κΈ°λ₯Ό μš°μ„ μˆœμœ„λ₯Ό λ†’κ²Œ λ‘μ—ˆμŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ λ°±μ—”λ“œ 파트의 μ½”λ“œλ¦¬λ·°λ₯Ό 자주 ν•˜μ§€ μ•Šκ³  주된 ν”Όλ“œλ°± 없이, κΈ°λŠ₯에 λŒ€ν•œ 검증이 μ–΄λŠμ •λ„ 되면 무심코 λ„˜κ²¨λ²„λ Έλ˜κ²Œ 큰 산이 λ˜μ–΄ λŒμ•„μ™”λ„€μš”. λ‹€μ‹œκΈˆ ν•œ 번 μ½”λ“œλ¦¬λ·°μ˜ μ€‘μš”μ„±μ„ κΉ¨λ‹«μŠ΅λ‹ˆλ‹€.

 

μš°μ„ μ μœΌλ‘œ 손 λ³Ό 곳은 '진단' νŒŒνŠΈμž…λ‹ˆλ‹€. 기쑴에 μ„€λ¬Έ + AI M자 νƒˆλͺ¨ 이미지λ₯Ό μ œμΆœν•˜λŠ” 진단 κΈ°λŠ₯만 μžˆμ—ˆμœΌλ‚˜, 열화상 μ΄λ―Έμ§€λ‘œ μ§„λ‹¨ν•˜λŠ” κΈ°λŠ₯이 좔가될 κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. 이에 기쑴의 ꡬ쑰 ν˜Ήμ€ λƒ„μƒˆλ‚˜λŠ” μ½”λ“œλ₯Ό μ œκ±°ν•˜κ³ , μƒˆλ‘­κ²Œ κ°œνŽΈμ„ ν•˜λ €κ³  ν•©λ‹ˆλ‹€.

 

 


 

🧐 1. κΈ°μ‘΄ API μ‚΄νŽ΄λ³΄κΈ°

 

AS-IS

 

ν•΄λ‹Ή 뢀뢄은 μ„œλΉ„μŠ€ λ ˆμ΄μ–΄μ— μžˆλŠ” 진단 μ‹œμž‘ μ‹œ μ΄ˆκΈ°ν™” μž‘μ—…μ„ ν•˜λŠ” μ½”λ“œμž…λ‹ˆλ‹€.

진단 도쀑 κ°•μ œμ μœΌλ‘œ μ’…λ£Œν•œ κ²½μš°μ—λŠ”, 진단 μ™„λ£Œλœ κ²½μš°κ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— ν•΄λ‹Ή 기둝을 νκΈ°ν•˜λ €λŠ” λͺ©μ μœΌλ‘œ DB에도 activeλΌλŠ” attribute둜 κ΄€λ¦¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

 

λ”°λΌμ„œ ν•΄λ‹Ή active 여뢀에 따라 기둝 폐기 μ§„ν–‰ + μƒˆλ‘œμš΄ 진단 기둝을 μƒμ„±ν•˜κ³  진단 번호λ₯Ό μ–»μ–΄μ˜€λŠ” 것이 이 μ΄ˆκΈ°ν™” μž‘μ—…μ„ ν•˜λŠ” λΆ€λΆ„μž…λ‹ˆλ‹€.

 

μ–Έλœ» 봐도 λ¬Έμ œκ°€ ꡉμž₯히 λ§Žμ•„λ³΄μž…λ‹ˆλ‹€.

1. λ©”μ†Œλ“œ λͺ©μ μ„ μ •ν™•ν•˜κ²Œ νŒŒμ•…ν•˜κΈ° μ–΄λ €μš΄ 이름
2. findByIdλ₯Ό 톡해 얻은 값은 Optional μ΄μ§€λ§Œ, Optional을 μ‚¬μš©ν•œ μ˜λ―Έκ°€ ν‡΄μƒ‰λ˜λŠ” μ½”λ“œ
3. 기둝 μ‚­μ œ 3κ°€μ§€λ₯Ό μ „λΆ€ ν•œ νŠΈλžœμž­μ…˜μ— λ„£μ§€ μ•ŠμŒ.
4. "createLog" λΌλŠ” λ©”μ†Œλ“œκ°€ λΉŒλ” νŒ¨ν„΄ 내뢀에 인라인으둜 λ“€μ–΄κ°€ ν•΄λ‹Ή μ„œλΉ„μŠ€μ—μ„œ μƒˆλ‘œμš΄ 기둝을 μƒμ„±ν•˜λŠ”μ§€ μ•Œμ•„λ³΄κΈ° 어렀움. λ“±λ“±.

 

λ˜ν•œ 좔가적인 κ°œμ„  사항은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

1. 더 λ§Žμ€ 정보λ₯Ό 담은 response + ResponseEntityλ₯Ό ν™œμš©ν•œ 응닡.
2. μš”μ²­ λ‚΄λΆ€μ˜ 값이 μœ νš¨ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ”, Bad Requestλ₯Ό 보내야 함.
3. κΈ°μ‘΄μ—λŠ” activeλ₯Ό κΈ°μ€€μœΌλ‘œ 둜그λ₯Ό 'μ‚­μ œ' ν–ˆμœΌλ‚˜, 이 activeλ₯Ό state둜 λ°”κΏ” 7κ°€μ§€μ˜ μƒνƒœλ‘œ ν‘œν˜„. μ‚­μ œκ°€ μ•„λ‹Œ 'SHUTDOWN'으둜 λ³€κ²½
4. 각 μ„œλΉ„μŠ€λ§ˆλ‹€ νŠΉμ • μš”κ±΄μ— λ”°λ₯Έ responseλ₯Ό λ¦¬ν„΄ν•˜κ²Œ λ˜λŠ”λ°, 응닡에 λŒ€ν•΄ μœ μ—°ν•œ μ‚¬μš© + μž¬μ‚¬μš©μ„±μ΄ 높은 ꡬ쑰 λ§Œλ“€κΈ°

 


 

🧐 2. λ©”μ„œλ“œ / λ³€μˆ˜ 이름 λ³€κ²½

 

disabledServiceλŠ”, μ„œλΉ„μŠ€ μžμ²΄μ— μž₯μ• κ°€ μžˆλ‹€λŠ” 것인지, μž₯μ• κ°€ μžˆλŠ” 무언가λ₯Ό μ²˜λ¦¬ν•˜λŠ” μž‘μ—…μΈμ§€ λͺ…ν™•ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ˜ν•œ ν•΄λ‹Ή λ©”μ„œλ“œλŠ” non-activeν•œ μš”μ†Œλ₯Ό μ œκ±°ν•˜λŠ” 것이 핡심 λͺ©ν‘œκ°€ μ•„λ‹ˆλΌ, "진단 생성"ν•˜λŠ” 것이 μ΅œμš°μ„  μž‘μ—…μ΄λ©° 이 두 κ°€μ§€λ₯Ό λ¬Άμ–΄μ„œ 진단 μ΄ˆκΈ°ν™”λΌκ³  ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

λ”°λΌμ„œ 쑰금 더 λͺ…μ‹œμ μΈ μ΄λ¦„μœΌλ‘œ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.

disabledService → forInitDiagnosis

 

사싀, λ©”μ†Œλ“œ λͺ…은 λŒ€λΆ€λΆ„ '동사'의 ν˜•νƒœλ‘œ κΈ°μˆ ν•˜λŠ” 것이 μΌλ°˜μ μž…λ‹ˆλ‹€.

λ‹€λ§Œ, μ»¨νŠΈλ‘€λŸ¬μ™€ λ°”λ‘œ λ§žλ‹Ώμ•„ μžˆλŠ” μ„œλΉ„μŠ€μ˜ λ©”μ†Œλ“œμ— λŒ€ν•΄μ„œλ§Œ μ•žμ— 'for'을 뢙인 넀이밍을 μ§„ν–‰ν•˜λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

κ·Έ 이후, λ©”μ†Œλ“œ λͺ…λ§Œ 보고 이 ν•¨μˆ˜κ°€ μ–΄λŠ λ ˆμ΄μ–΄μ— μœ„μΉ˜ν•œ λ©”μ†Œλ“œμΈμ§€ ν•œ λ²ˆμ— 확인할 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

 

return diagnosisService.disabledService(request) 
→ return diagnosisService.forInitDiagnosis(requestForInitDiagnosis);

 

이 외에도 기타 λ³€μˆ˜μ— λŒ€ν•΄μ„œ ν•΄λ‹Ή μ½”λ“œλ₯Ό 처음 λ³΄λŠ” κ°œλ°œμžλ„ μ‰½κ²Œ 이해할 수 μžˆλ„λ‘ ν’€μ–΄μ„œ μž‘μ„±ν•˜κ³ , μΉ΄λ©œμΌ€μ΄μŠ€λ₯Ό μ΄μš©ν•΄ μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€.

 


 

πŸ€” 3. Optional을 μ‚¬μš©ν•˜λŠ” λͺ©μ μ€ NPE λ°©μ–΄

 

λ‹€μ‹œλ³΄λŠ” λƒ„μƒˆ μ½”λ“œ

 

기쑴의 μ½”λ“œλ₯Ό 보면,

userNum = memberRepository.findById(disabled.getId()).get().getUserNum();

이 λΆ€λΆ„μ—λŠ” λ§Žμ€ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 

 

1) disabled.getId()μ—μ„œ NPE λ°œμƒ κ°€λŠ₯μ„± 쑴재
2) findByIdλ₯Ό 톡해 μ–»μ–΄μ˜¨ 값은, Optional<T>인데, get() λ©”μ†Œλ“œλ₯Ό ν†΅ν•΄μ„œ μ–»μ–΄μ˜€κ²Œ 되면 λ‚΄λΆ€κ°€ λΉ„μ–΄μžˆλŠ” 경우 λ˜‘κ°™μ΄ NPEκ°€ λ°œμƒν•¨. Optional을 μ‚¬μš©ν•œ μ΄μœ κ°€ μ—†μŒ.
3) μ΅œμ’… getUserNumμ—μ„œλ„ NPEκ°€ λ°œμƒν•  κ°€λŠ₯성이 μ‘΄μž¬ν•¨.

λ¬Όλ‘  try-catch 문으둜 λ§‰μ•„μ„œ ν”„λ‘œκ·Έλž¨μ΄ 쀑단될 상황은 λͺ¨λ©΄ν•˜κ² μ§€λ§Œ, 이 쀑 ν•˜λ‚˜λΌλ„ NPEκ°€ 뜰 κ²½μš°μ˜€λ‹€λ©΄, μ‚¬μš©μžμ˜ μš”μ²­μ΄ λΆ€μ‹€ν•œ κ²½μš°μ΄λ―€λ‘œ bad requestλ₯Ό λ³΄λ‚΄λŠ” 것이 λ§žλ‹€κ³  νŒλ‹¨ν–ˆμŠ΅λ‹ˆλ‹€.

 

기쑴의 μ½”λ“œλ₯Ό μˆ˜μ •ν•œ κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

 

 /* λΆˆλ³€ κ°’ μ •μ˜ */
final String REQUEST_HAVE_NULL = "REQUEST_HAVE_NULL";
final int NO_REQUEST_USER_IN_DB = -1;

/* requestBody μ—μ„œ userID κ²€μΆœ */
String userIDFromRequest = Optional.ofNullable(requestForInitDiagnosis)
	.map(JBMBRequestObject::getRequestBody)
	.map(DiagnosisDTO.RequestForInitDiagnosis::getUserID)
	.orElse(REQUEST_HAVE_NULL);

/* BAD REQUEST => Null 값을 ν¬ν•¨ν•œ REQUEST */
if (userIDFromRequest.equals(REQUEST_HAVE_NULL)) {
	return 응닡 μƒλž΅;
}

/* READ => userID 기반으둜, 멀버 식별 번호 검색 */
int userNumFromRequest = memberRepository.findById(userIDFromRequest)
	.map(Member::getUserNum)
	.orElse(NO_REQUEST_USER_IN_DB);

/* INTERNAL ERROR => DB에 ν•΄λ‹Ή μœ μ €κ°€ μ—†μŒ. ν—ˆμš©λ˜μ§€ μ•Šμ€ μ ‘κ·Ό 처리 */
if (userNumFromRequest == NO_REQUEST_USER_IN_DB) {
	return 응닡 μƒλž΅;
}

 

λ¬Έμ œκ°€ λ§Žμ€ ν•œ μ€„μ΄μ—ˆλ˜ μ½”λ“œκ°€, κ½€ λŠ˜μ–΄λ‚¬μŠ΅λ‹ˆλ‹€.

 

Optional은 λ‚΄λΆ€μ˜ 값이 λΉ„μ–΄μžˆλŠ” μƒνƒœλΌλ©΄, "orElse" ꡬ문 μ‹œλ¦¬μ¦ˆλ‘œ ν•΄λ‹Ή λΉ„μ–΄μžˆλŠ” 값을 NPEλ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•Šκ³  λŒ€μ²΄ν•©λ‹ˆλ‹€.

public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

orElse와 orElseGet은 Optional 객체의 값이 Optional.empty()의 값인 경우 other의 값을 λŒ€μ²΄ν•΄μ„œ 보낼 수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ Optional 객체의 값이 λΉ„μ–΄μžˆμ§€ μ•Šλ‹€λ©΄, Optional<> 껍질이 벗겨지고 λ‚΄λΆ€μ˜ κ°’ κ·ΈλŒ€λ‘œλ₯Ό κ°€μ§€κ²Œ λ©λ‹ˆλ‹€.

 

orElse와 orElseGet의 λ‹€λ₯Έ 점은 크게 두 κ°€μ§€μž…λ‹ˆλ‹€. 

1. orElse의 μΈμžκ°’μ€ T이기 λ•Œλ¬Έμ—, ν•΄λ‹Ή 였브젝트λ₯Ό κ·Έλƒ₯ λ„£μ–΄μ£Όλ©΄ λ©λ‹ˆλ‹€. (ν˜Ήμ€ ν•΄λ‹Ή 였브젝트λ₯Ό λ¦¬ν„΄ν•˜λŠ” ν•¨μˆ˜)
orElseGet의 μΈμžκ°’μ€ Supplierμž…λ‹ˆλ‹€. λžŒλ‹€μ‹μ„ μ΄μš©ν•΄μ„œ 값을 λ„£μ–΄μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

2. 또 λ‹€λ₯Έ 점 ν•˜λ‚˜λŠ”, orElseλŠ” Optional λ‚΄λΆ€κ°€ λΉ„μ–΄μžˆλ˜ μ•„λ‹ˆλ˜, 일단 μ‹€ν–‰λ˜κ³  λ‚˜μ€‘μ— 값이 κ²°μ •λ©λ‹ˆλ‹€.
orElseGet은 Optional λ‚΄λΆ€κ°€ λΉ„μ–΄μžˆλ‹€λ©΄, λ‚΄λΆ€μ˜ 값이 μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
λ§Œμ•½ orElse의 μΈμžμ— Tλ₯Ό λ¦¬ν„΄ν•˜λŠ” λ©”μ†Œλ“œμ§€λ§Œ, λ‚΄λΆ€μ—μ„œ DB μ‘°μž‘λ“±μ˜ κΈ°λŠ₯이 λŒμ•„κ°„λ‹€λ©΄ μ˜λ„μ™€λŠ” λ‹€λ₯΄κ²Œ 인자 λ‚΄λΆ€κ°€ μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ— 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. 이런 κ²½μš°μ—λŠ” orElseGet을 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

 

orElseThrowλŠ” λ§ˆμ°¬κ°€μ§€λ‘œ Optional.empty()인 경우 λ‚΄κ°€ 직접 Exception을 μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μ»€μŠ€ν…€ν•œ Exception ν˜Ήμ€ μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 직접 μž‘μ„±ν•  수 μžˆλ‹€λŠ” μ μ—μ„œ μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

 

Optional 객체에 λŒ€ν•΄ .get() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄, λ‚΄λΆ€μ˜ 값이 λΉ„μ–΄μžˆλ‹€λ©΄ NPEλ₯Ό λ°œμƒμ‹œν‚€λ―€λ‘œ Optional을 μ“΄ μ˜λ―Έκ°€ μ—†μŠ΅λ‹ˆλ‹€.

μœ„μ™€ 같은 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 ꢌμž₯λ˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

 

 

μ΄λŸ¬ν•œ Optional 객체에 λŒ€ν•΄ map λ©”μ„œλ“œλ‘œ λ‚΄λΆ€μ˜ 값에 νŠΉμ • λ©”μ†Œλ“œλ₯Ό μ μš©μ‹œν‚¬ λ•Œ λ§ˆλ‹€ μžλ™μœΌλ‘œ Optional이 μ”Œμ›Œμ§€κ²Œ λ©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같은 ν΄λž˜μŠ€κ°€ μžˆλ‹€κ³  ν•΄λ΄…μ‹œλ‹€.

@AllArgsConstructor
@Getter
class Example{
	private String test;
}
Example example = new Example("hi");

Optional.ofNullable(example)
	.map(Example::getTest) // μ΄λ•Œ, Optional<String>이 됨.
    ... μƒλž΅

Example의 getter인 getTestλŠ” String νƒ€μž…μ„ λ¦¬ν„΄ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ map을 톡해 호좜이 되면, μžλ™μœΌλ‘œ Optional이 μ”Œμ›Œμ§€κ²Œ λœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. 이 점을 μ΄μš©ν•΄ 연속적인 NPE μœ„ν—˜μ—μ„œλ„ λ²—μ–΄λ‚  수 μžˆμŠ΅λ‹ˆλ‹€.

 

Nμ€‘μœΌλ‘œ if 문을 μ‚¬μš©ν•΄ null 체크λ₯Ό ν•΄μ•Ό ν•˜λ˜ 것이 μ—†μ–΄μ§€κ³  map을 μ‚¬μš©ν•¨μœΌλ‘œμ¨ 가독성을 높이고 μ—°μ‚° μˆœμ„œλ₯Ό λ”μš± μ§κ΄€μ μœΌλ‘œ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

 

기쑴에 try-catch 문에 λͺ¨λ“  둜직이 λ‹€ λ“€μ–΄μžˆμ—ˆμ§€λ§Œ, try-catchλ₯Ό μ œκ±°ν•˜κ³  λΆˆλ³€ 값을 μ •μ˜ν•΄ ν•΄λ‹Ή κ°’κ³Ό 비ꡐ해 응닡을 λ³΄λ‚΄λŠ” 둜직으둜 λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.

 

try-catch λ¬Έ λ‚΄λΆ€μ—μ„œ μ„ μ–Έν•œ μ§€μ—­λ³€μˆ˜λŠ” λ°–μ—μ„œ μ‚¬μš©ν•  수 μ—†μ–΄ 미리 μ„ μ–Έν•œ ν›„ 값을 λ³€κ²½ν•΄μ•Ό ν•œλ‹€λŠ” 점을 ν”Όν•  수 있으며, μ–΄λŠ λΆ€λΆ„μ—μ„œ return이 λ°œμƒν•˜κ²Œ λ˜λŠ”μ§€ κ°œλ°œμžκ°€ λ”μš± μ§κ΄€μ μœΌλ‘œ 확인할 수 μžˆλ‹€κ³  νŒλ‹¨ν–ˆμŠ΅λ‹ˆλ‹€. 미리 Exception νƒ€μž…μ„ λͺ¨λ‘ μ˜ˆμΈ‘ν•΄ catch문을 μ—¬λŸ¬κ°œ μž‡λŠ” 것 보닀 말이죠.

 


 

πŸ€” 4. Enum을 ν™œμš©ν•΄λ³΄μž.

 

Enum을 ν™œμš©ν•΄λ³΄μžλŠ” λ§ˆμŒμ„ 먹은 λ°μ—λŠ” μ—¬λŸ¬ μ΄μœ κ°€ μžˆμŠ΅λ‹ˆλ‹€.

1) resultCode에 int 값을 λ„£κ³  μžˆλŠ”λ°, λ°±μ—”λ“œ / ν”„λ‘ νŠΈμ—”λ“œ λͺ¨λ‘ μ–΄λ–€ 결과값인지 μ •ν™•ν•˜κ²Œ νŒŒμ•…ν•˜κΈ° μ–΄λ ΅λ‹€.
2) active(0 ν˜Ήμ€ 1)μ—μ„œ → state(OPEN, SURVEY, IMAGE_UPLOAD, DIAGNOSE, DONE, ERROR, SHUTDOWN)의 μ—¬λŸ¬ μƒνƒœλ‘œ λ‚˜λˆ μ•Ό ν•˜λŠ”λ°, 이λ₯Ό 숫자(λΆ„κ°„ν•˜κΈ° 어렀움) ν˜Ήμ€ 문자(개발자의 μ‹€μˆ˜ μ—¬μ§€κ°€ 많음)둜 ν‘œν˜„ν•˜λŠ”λ°μ—λŠ” ν•œκ³„κ°€ 있음.
3) μ–΄λŠ κ³³μ—μ„œλŠ” 0κ³Ό 1둜 ν‘œν˜„, μ–΄λŠ κ³³μ—μ„œλŠ” ν•΄λ‹Ή 0κ³Ό 1이 λ‚˜νƒ€λ‚΄λŠ” 문자 μ½”λ“œ 값을 같이 λ¬Άκ³  μ‹ΆμŒ λ“±.

 

javaμ—μ„œμ˜ Enum은 class이기 λ•Œλ¬Έμ— λ”μš± λ§Žμ€ ν™œμš©μ΄ κ°€λŠ₯ν•˜λ‹€κΈΈλž˜, 적극적으둜 ν”„λ‘œμ νŠΈ κ°œμ„ μ„ ν•˜λ©΄μ„œ ν™œμš©ν•΄λ³΄κ³ μž 곡뢀λ₯Ό ν–ˆμŠ΅λ‹ˆλ‹€.

 

λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•œ Enum의 μ˜ˆμ‹œ 쀑, 진단 νƒ€μž…μ„ κΈ°λ³Έν˜• / μ—΄ν™”μƒν˜•μ„ μ •μ˜ν•˜λŠ” μ½”λ“œμž…λ‹ˆλ‹€.

@Getter
@AllArgsConstructor
public enum JBMBDiagnosisTypeIdentifier {

    DEFAULT(false),
    THERMAL(true);

    private boolean isThermal;

    public static JBMBDiagnosisTypeIdentifier getJBMBDiagnosisTypeWhetherIsThermal(Boolean isThermal){
          return Optional.ofNullable(isThermal)
                .filter(bl -> bl)
                .map(bl -> JBMBDiagnosisTypeIdentifier.THERMAL)
                .orElse(JBMBDiagnosisTypeIdentifier.DEFAULT);
    }
}


/* requestBody 의 'isThermal' 을 μ‚¬μš©ν•΄ diagnosisType κ²€μΆœ */
/* 'request' 에 isThermal 값을 보내지 μ•ŠμœΌλ©΄, κΈ°λ³Έ μ§„λ‹¨μœΌλ‘œ μ„€μ •. */
JBMBDiagnosisTypeIdentifier diagnosisTypeFromRequest = Optional.of(requestForInitDiagnosis)
	.map(JBMBRequestObject::getRequestBody)
	.map(DiagnosisDTO.RequestForInitDiagnosis::getIsThermal)
	.map(JBMBDiagnosisTypeIdentifier::getJBMBDiagnosisTypeWhetherIsThermal)
	.orElse(JBMBDiagnosisTypeIdentifier.DEFAULT);

 

'진단 μœ ν˜• μ‹λ³„μž'λΌλŠ” 이름을 κ°€μ§„ Enum을 μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€.

JBMBDiagnosisTypeIdentifier.DEFAULT와 JBMBDiagnosisTypeIdentifier.THERMAL 두 κ°€μ§€ μœ ν˜•μ΄ μžˆμŠ΅λ‹ˆλ‹€.

java의 enum은 클래슀이기 λ•Œλ¬Έμ— 내뢀에 ν•„λ“œμ™€ λ©”μ„œλ“œλ₯Ό κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

 

DEFAULT μΈμŠ€ν„΄μŠ€λŠ” false κ°’μœΌλ‘œ, THERMAL μΈμŠ€ν„΄μŠ€λŠ” true 값을 μƒμ„±μžλ₯Ό 톡해 μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ λ©”μ„œλ“œλ‘œλŠ” 정적 νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό 생성해, 쑰건에 λ§žλŠ” Enum μΈμŠ€ν„΄μŠ€λ₯Ό boolean νƒ€μž…μ˜ μΈμžκ°’μ„ λ°›μ•„ 얻을 수 μžˆλ„λ‘ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

 

μ„œλΉ„μŠ€μ—μ„œλŠ” μœ„μ˜ μ½”λ“œ μ˜ˆμ‹œμ²˜λŸΌ 'diagnosisTypeFromRequest'λ₯Ό λ°›μ•„μ˜¨λ‹€λ©΄, .name()을 ν†΅ν•΄μ„œ 'THERMAL' ν˜Ήμ€ 'DEFAULT' 값을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. 

 

/* ShutDown λŒ€μƒμ„ ν‘œν˜„ν•œ Enum */
public enum ShutDownTarget {
	EXIST, NOT_EXIST, ERROR;

	public static ShutDownTarget getShutDownTargetByCount(long countOfShutDown) {
		return countOfShutDown > 0L ? ShutDownTarget.EXIST : (countOfShutDown == 0L ? ShutDownTarget.NOT_EXIST : ShutDownTarget.ERROR);
	}
}

@Getter
@AllArgsConstructor
public enum JBMBDiagnosisStateIdentifier {

    OPEN(1, "진단 μ‹œμž‘", true),
    SURVEY(2, "섀문쑰사 μ§„ν–‰", true),
    UPLOAD(3, "이미지 μ—…λ‘œλ“œ", true),
    DIAGNOSE(4, "진단 쀑", true),
    DONE(5, "진단 μ™„λ£Œ",false),
    ERROR(6, "μ—λŸ¬ λ°œμƒ", false),
    SHUTDOWN(7, "진단 쀑단", false);

    private int stateCode;
    private String stateDescription;
    private boolean interruptible;

    public static boolean isShutDownAble(JBMBDiagnosisStateIdentifier nowState) {
        return nowState.isInterruptible();
    }

}
    

/* CommonDiagnosisService.java */
@Transactional
public long updateStateToShutDown(String requestUserID, int requestUserNum) {
	// UPDATE => SHUTDOWN 으둜 μƒνƒœ λ³€κ²½ 및, λ³€κ²½ λŒ€μƒ 수 리턴
	try {
	Stream<String> shutDownedDiagnosisInfoIDList = diagnosisInfoRepository.findAllByUserNum(requestUserNum)
		.stream()
		/* SHUTDOWN 으둜 μƒνƒœλ₯Ό λ³€κ²½ν•΄μ•Ό ν•  λŒ€μƒλ§Œ 필터링 */
		.filter(diagnosisInfo -> JBMBDiagnosisStateIdentifier.isShutDownAble(diagnosisInfo.getDiagnosisState()))
		/* state SHUTDOWN 으둜 λ³€κ²½ ν›„ μ €μž₯ */
		.map(JBMBDiagnosisInfoEntity::setDiagnosisStateToShutDown)
		.map(diagnosisInfoRepository::save)
		/* λ³€κ²½ λŒ€μƒ 진단 아이디 λͺ©λ‘μœΌλ‘œ λ³€κ²½ */
		.map(JBMBDiagnosisInfoEntity::getDiagnosisID)
		.map(Object::toString);

	log.info("=> Member [{}]'s diagnosis log is shut down, count : {} / changed ID : [{}]",
		requestUserID,
		shutDownedDiagnosisInfoIDList.count(),
		shutDownedDiagnosisInfoIDList.collect(Collectors.joining(", ")));

	return shutDownedDiagnosisInfoIDList.count();
	} catch (Exception e) {
		log.error(e.getMessage());
		return -1L;
	}
}

/* UPDATE => SHUTDOWN 으둜 μƒνƒœ λ³€κ²½ 및, λ³€κ²½ λŒ€μƒ 수 리턴 */
/* SHUTDOWN λ³€κ²½κ³Ό 같은 경우, μ‹€νŒ¨ν•΄λ„ 크게 타격이 μ—†μŒ. λ‹€μŒμ— λ‹€μ‹œ μ‹œλ„ν•΄λ„ 됨. */
ShutDownTarget shutDownTarget = ShutDownTarget.getShutDownTargetByCount(
	commonDiagnosisService.updateStateToShutDown(userIDFromRequest, userNumFromRequest));

 

 

7κ°€μ§€μ˜ 진단 μƒνƒœλ₯Ό Enum으둜 ν‘œν˜„ν•œ 것과, SHUTDOWN λŒ€μƒ 쑴재 μ—¬λΆ€λ₯Ό Enum으둜 ν‘œν˜„ν•œ κ²ƒμ˜ μ˜ˆμ‹œμž…λ‹ˆλ‹€.

Enum을 μ‚¬μš©ν•¨μœΌλ‘œμ¨ 이점은 λ§Žμ•˜μŠ΅λ‹ˆλ‹€.

1) λ™μ‹œμ— μ—¬λŸ¬ 값을 포함할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 이해할 수 μ—†λ˜ μˆ«μžμ½”λ“œλ§Œ 덜렁 있던 μ΄μ „κ³ΌλŠ” λ‹€λ₯΄κ²Œ, ν•΄λ‹Ή μˆ«μžμ½”λ“œκ°€ λ‚˜νƒ€λ‚΄λŠ” λ©”μ‹œμ§€, 이름, 등등을 같이 ν•œ 객체 내에 ν‘œν˜„ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

2) λ‹¨μˆœν•œ 숫자, 문자의 ν‘œν˜„μ΄ μ•„λ‹Œ Enum νƒ€μž…μ˜ 객체λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— 개발자의 이해가 더 쉽고, μ§κ΄€μ μž…λ‹ˆλ‹€. λ˜ν•œ String 문자λ₯Ό 잘 λͺ» μž…λ ₯ν•˜λŠ” 사고λ₯Ό ν”Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3) μƒˆλ‘œμš΄ 진단 μƒνƒœκ°€ μƒκΈ΄λ‹€ν•˜λ”λΌλ„, Enum의 μƒμ„±μž λΆ€λΆ„λ§Œ λ§Œμ§„λ‹€λ©΄ λ‹€λ₯Έ 둜직의 μˆ˜μ • 없이 μœ μ—°ν•œ ν™•μž₯이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

 

λ‹€μŒ μΌμ§€μ—μ„œλŠ” DTO와 κ΄€λ ¨λœ λ‚΄μš©κ³Ό, 곡톡 응닡에 λŒ€ν•œ 처리, μž¬ν™œμš©μ„±μ΄ 높은 ResponseCreatorλ₯Ό λ§Œλ“  λ‚΄μš©μ— λŒ€ν•΄ μ„œμˆ ν•˜λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (2) κ³΅ν†΅ν•„λ“œκ°€ λ§Žμ€ DTO λ§Œλ“€κΈ°

🏝 0. μ§€λ‚œ κΈ€ [DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (1) λ³€μˆ˜ μž‘λͺ…, Optional, Enum ν™œμš© 🏝 0. μ„œλ‘  μ‘Έμ—…μž‘ν’ˆμœΌλ‘œ νƒˆλͺ¨ 진단 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μΈ '제발λͺ¨λ°œ'을 κ°œλ°œν•˜κ³ , 'ν•΄λ‹Ή ν”Œ

hoons-dev.tistory.com

 

μ €μž‘μžν‘œμ‹œ λΉ„μ˜λ¦¬ 동일쑰건 (μƒˆμ°½μ—΄λ¦Ό)

'πŸƒβ€β™‚οΈ DEVLOG' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[DEVLOG] if(kakao) dev 2022 개발자 컨퍼런슀 ν›„κΈ° - 1. ISFP의 μ½”λ“œ 가독성 κ°œμ„  κ²½ν—˜  (1) 2023.01.01
[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (4) createdAtκ³Ό updatedAt, JPA AttributeConverter  (1) 2022.12.27
[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (3) DTO에 λ”°λ₯Έ 응닡 생성 클래슀 λ§Œλ“€κΈ°  (0) 2022.12.16
[DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (2) κ³΅ν†΅ν•„λ“œκ°€ λ§Žμ€ DTO λ§Œλ“€κΈ°  (0) 2022.12.16
[DEVLOG] if(kakao) 개발자 컨퍼런슀 - (0) μ»¨νΌλŸ°μŠ€μ— λŒ€ν•œ κΈ°λŒ€  (1) 2022.12.07
    'πŸƒ‍♂️ DEVLOG' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
    • [DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (4) createdAtκ³Ό updatedAt, JPA AttributeConverter
    • [DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (3) DTO에 λ”°λ₯Έ 응닡 생성 클래슀 λ§Œλ“€κΈ°
    • [DEVLOG] μš°λ‹Ήνƒ•νƒ• 제발λͺ¨λ°œ v2 개발기 - νƒˆλͺ¨ 진단 API μˆ˜μ •ν•˜κΈ° (2) κ³΅ν†΅ν•„λ“œκ°€ λ§Žμ€ DTO λ§Œλ“€κΈ°
    • [DEVLOG] if(kakao) 개발자 컨퍼런슀 - (0) μ»¨νΌλŸ°μŠ€μ— λŒ€ν•œ κΈ°λŒ€
    개발자 HOON
    개발자 HOON
    쒋은 λ°±μ—”λ“œ μ—”μ§€λ‹ˆμ–΄κ°€ 되기 μœ„ν•œ 기둝을 λͺ¨μ•˜μŠ΅λ‹ˆλ‹€. # μ£Όλ‹ˆμ–΄ # λ°±μ—”λ“œ # 개발자

    ν‹°μŠ€ν† λ¦¬νˆ΄λ°”