/images/profile.png

더이상 기닀리지 μ•Šμ•„λ„ λ˜λŠ” 배치 무쀑단 배포

μ§€λ‚œ ν¬μŠ€νŒ…, κ·ΈλŸ¬λ‹ˆκΉŒ μš°μ•„ν•œ ν˜•μ œλ“€μ—μ„œ μ΄ˆλŒ€λ₯Ό λ°›μ•„ Spring batch 에 λŒ€ν•œ ν…Œν¬μ„Έλ―Έλ‚˜μ— λ‹€λ…€ μ™”λ‹€. κ·Έ 쀑 κ°€μž₯ μΈμƒκΉŠμ—ˆλ˜ 뢀뢄이 λ°”λ‘œ 무쀑단 배포. 차일피일 미루닀 ν•„μžκ°€ μ†ν•œ νŒ€μ—μ„œλ„ λ°°ν¬λ•Œλ§ˆλ‹€ κ°€μž₯ λΆˆνŽΈμ„ 느끼고 μžˆμ—ˆλ˜ λΆ€λΆ„μ΄μ—ˆκΈ°λ„ ν–ˆκ³ , κ·ΈλŸ°κ°€λ³΄λ‹€ ν•˜λ©° κ°œλ…λ§Œ μ•Œκ³  λ„˜μ–΄κ°€κΈ°μ—” 무언가 양심에 μ°”λ € 직접 무쀑단 배포λ₯Ό ν•  수 μžˆλ„λ‘ ꡬ성을 해보고 ν…ŒμŠ€νŠΈκΉŒμ§€ ν•΄λ³΄κ³ μž ν•œλ‹€. 상황 및 문제점 λ¦¬λˆ…μŠ€ μ„œλ²„μ— Jenkinsκ°€ μ„€μΉ˜λ˜μ–΄ 있고, Spring batch λͺ¨λ“ˆμ„ μ‹€ν–‰μ‹œν‚€κ³  μžˆλ‹€. μˆ˜λ™μœΌλ‘œ 싀행을 ν•˜κ±°λ‚˜, Jenkins RestApiλ₯Ό μ΄μš©ν•΄μ„œ 싀행을 ν•  수 μžˆμ§€λ§Œ 주둜 정해진 μ‹œκ°„ 즉, μŠ€μΌ€μ₯΄λ§μ— μ˜ν•΄ μ‹€ν–‰λ˜κ³€ ν•œλ‹€. μŠ€μΌ€μ₯΄λ§μ˜ κ°€μž₯ μž‘μ€ λ‹¨μœ„λŠ” 1λΆ„λ‹¨μœ„ λ°°μΉ˜λ„ 있기 λ•Œλ¬Έμ— 24μ‹œκ°„ λ©ˆμΆ”μ§€ μ•Šκ³  μ‹€ν–‰λ˜κ³  μžˆλ‹€κ³  λ¬΄λ°©ν•˜λ‹€. ν•˜μ§€λ§Œ 배치 λͺ¨λ“ˆμ΄ μˆ˜μ •λ˜κ³ , 배포λ₯Ό ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒκ³Ό 같은 μ‹œλ‚˜λ¦¬μ˜€λ‘œ 진행이 λœλ‹€. Jenkins μ„€μ •μ˜ 끄기전 μ€€λΉ„ λ₯Ό μ‹€ν–‰ν•˜μ—¬ 더이상 Jenkins에 μ˜ν•΄ Spring batch λͺ¨λ“ˆ(μ΄ν•˜ Job)이 μ‹€ν–‰λ˜μ§€ μ•Šλ„λ‘ ν•œλ‹€. μƒˆλ‘œμš΄ Job은 더이상 μ‹€ν–‰λ˜μ§€ μ•Šμ§€λ§Œ 이미 μ‹€ν–‰μ€‘μ΄μ˜€λ˜ Job 은 κ°•μ œλ‘œ 쀑단을 ν•˜κ±°λ‚˜ Job 이 λλ‚ λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦°λ‹€. 싀행쀑인 Job이 없을 경우 이제 배포λ₯Ό μ§„ν–‰ν•œλ‹€. 배포가 μ™„λ£Œλ˜λ©΄ Jenkins μ„€μ •μ˜ 끄기전 μ€€λΉ„λ₯Ό ν•΄μ œν•œλ‹€. 싀행쀑인 Job이 μ•ˆλλ‚˜λ©΄ 마λƒ₯ 기닀릴텐가? 좜처 : https://m.post.naver.com/viewer/postView.nhn?volumeNo=14100660&memberNo=2032633" 싀행쀑인 Job이 μ•ˆλλ‚˜λ©΄ 마λƒ₯ 기닀릴텐가? 좜처 : https://m.post.naver.com/viewer/postView.nhn?volumeNo=14100660&memberNo=2032633 μ‹€ν–‰λ˜λŠ” Job을 μ€‘λ‹¨ν•˜μ§€ λͺ»ν•˜λŠ” 상황 즉, 싀행쀑에 μ€‘λ‹¨ν•˜λ©΄ νŠΈλžœμž­μ…˜μ΄ κΉ¨μ Έ 무쑰건 κΈ°λ‹€λ €μ•Όλ§Œ ν•˜λŠ” 상황이라면 배포 λ˜ν•œ 계속 지연될 수 밖에 μ—†λŠ” 상황인 것이닀. Spring boot에 java config λ₯Ό ν™œμš©ν•˜κ³  λ”± jar 파일 ν•˜λ‚˜λ₯Ό μ‹€ν–‰ν•˜λŠ” 방식이라면 jarνŒŒμΌμ„ λ°”κΏ”μΉ˜κΈ° ν•˜λŠ” μ‹μœΌλ‘œ 고민을 ν•΄λ³Όμˆ˜λ„ μžˆμ„κ²ƒ κ°™λ‹€. ν•˜μ§€λ§Œ Legacy μ½”λ“œκ°€ 아직 μ‘΄μž¬ν•˜μ—¬ 일반 Spring 에 xml 둜 config ν•˜λŠ” λ°©μ‹μœΌλ‘œ μš΄μ˜μ€‘μ΄λΌ jar파일 ν•˜λ‚˜λ§Œ λ°”κΏ”μΉ˜κΈ° ν•˜κΈ°μ—” 무리가 μžˆλŠ” 상황. μ€μ΄μ•Œμ²˜λŸΌ μ–΄λ””μ—μ„œλ‚˜ μ‚¬μš©μ΄ κ°€λŠ₯ν•œ λ§Œλ³‘ν†΅μΉ˜μ•½ 같은 방법은 μ—†λ‹€. μ–Έμ œλ‚˜ κ·Έλž¬λ“― ν˜„μž¬ μ‹œμŠ€ν…œ(xml config 방식)에 κ°€μž₯ μ΅œμ ν™”λœ 방법, 그리고 java config λ°©μ‹μ—μ„œλ„ μ‚¬μš©μ΄ κ°€λŠ₯할것 같은 방법을 생각해 λ³΄μ•˜λ‹€. 무쀑단 배포λ₯Ό κ°€λŠ₯μΌ€ ν•˜λŠ” 3가지 핡심 1. 배포λ₯Ό 맀번 μƒˆλ‘œμš΄ κ²½λ‘œμ— λ°°ν¬ν•œλ‹€. 각 νšŒμ‚¬λ§ˆλ‹€, 그리고 μ„œλΉ„μŠ€λ§ˆλ‹€ 정말 λ‹€μ–‘ν•œ 배포 μ‹œμŠ€ν…œμ΄ μžˆλ‹€. κ·Έλ“€μ˜ 곡톡점은 μ›κ²©μ„œλ²„μ˜ νŠΉμ • κ²½λ‘œμ— λΉŒλ“œλœ νŒŒμΌλ“€μ„ λ°€μ–΄ λ„£μ–΄μ€€λ‹€λŠ” 것. μ‹œλ‚˜λ¦¬μ˜€λŠ” λ‹€μŒκ³Ό κ°™λ‹€. λ°°ν¬ν• λ•Œλ§ˆλ‹€ λ³„λ„μ˜ 디렉토리λ₯Ό μƒμ„±ν•œλ’€ 심볼릭 링크λ₯Ό μ—°κ²°ν•΄μ€€λ‹€. λ°°ν¬λŠ” 1μ—μ„œ μ—°κ²°ν•œ 심볼릭 링크에 λ°°ν¬λ˜λ„λ‘ μ„€μ •, κ²°κ΅­ 맀번 λ§Œλ“€μ–΄μ§€λŠ” 디렉토리에 배포가 되게 λœλ‹€. μ—¬κΈ°μ„œ μ€‘μš”ν•œμ μ€ “배포할 λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ 디렉토리에 배포가 λœλ‹€” 와 λ°°ν¬μ‹œμ—λŠ” 항상 심볼릭 λ§ν¬μ—λ§Œ 배포λ₯Ό ν•˜λ©΄ 되기 λ•Œλ¬Έμ— “λ°°ν¬μ‹œμŠ€ν…œμ΄ μƒˆλ‘œ λ§Œλ“€μ–΄μ§€λŠ” λ””λ ‰ν† λ¦¬μ˜ 경둜λ₯Ό λͺ°λΌλ„ λ¬΄λ°©ν•˜λ‹€"λŠ” 점이닀. #!/bin/sh cd /~~~/deploy/ # μž„μ‹œ 디렉토리 DIRECTORY_NAME=batch_$(/bin/date +%Y%m%d%H%M%S) mkdir $DIRECTORY_NAME μœ„ μ‰˜ 슀크립트λ₯Ό μ‹€ν–‰ν•˜λ©΄ batch_20191012205218 와 같은 디렉토리가 생성이 λœλ‹€. 심볼릭 링크 κ΄€λ ¨ν•΄μ„œλŠ” λ°”λ‘œ μ•„λž˜ μ΄μ–΄μ„œ μ„€λͺ…ν•˜κ² λ‹€. 2. 심볼릭 링크의 μ›λž˜ 링크λ₯Ό μ¦‰μ‹œ λ³€κ²½ 보톡 심볼릭 링크 (즉, λ°”λ‘œκ°€κΈ°) 의 경둜λ₯Ό λ³€κ²½ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ•„λž˜μ²˜λŸΌ 지웠닀가 μ‚­μ œν•˜λŠ” μ‹μœΌλ‘œ ν–ˆμ—ˆλŠ”λ° $ mkdir directory_a $ mkdir directory_b $ ln -s directory_a asdf $ ll asdf -> directory_a directory_a directory_b # directory_a μ—μ„œ directory_b 둜 λ°”κΎΈλŠ” 경우 (심볼릭 링크 자체λ₯Ό μ‚­μ œν•˜κ³  λ‹€μ‹œ 심볼릭 링크 생성) $ rm asdf $ ln -s directory_b asdf $ ll asdf -> directory_b directory_a directory_b μ΄λ ‡κ²Œ 되면 μ‚­μ œν•˜κ³  ~ λ‹€μ‹œ λ§Œλ“€μ–΄μ§€λŠ” 타이밍에 배포가 λ˜κ±°λ‚˜ 싀행이 λ˜λŠ” 즉, ν•΄λ‹Ή κ²½λ‘œμ— μ—‘μ„ΈμŠ€ ν•˜λŠ” 경우 μ΄μ „μ˜ 경둜λ₯Ό λ°”λΌλ³Έλ‹€κ±°λ‚˜ μ˜λ„ν–ˆλ˜ λ°©μ‹μœΌλ‘œ 싀행이 λ˜μ§€ μ•ŠλŠ” 상황이 λ°œμƒν•œλ‹€. (μ°°λ‚˜μ˜ 타이밍 μ΄μ§€λ§Œ ν•„μžλŠ” μ΄λŸ¬ν•œ 문제둜 μ΄μ „μ˜ 경둜λ₯Ό λ°”λΌλ³΄λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμ—ˆλ‹€.) κ·Έλž˜μ„œ ln 의 μ˜΅μ…˜μ€‘μΈ -Tfsμ˜΅μ…˜μœΌλ‘œ μ¦‰μ‹œ 변경을 해주도둝 ν•˜μž. (ln man μ°Έκ³ ) # λ§Œλ“  μž„μ‹œ λ””λ ‰ν† λ¦¬λ‘œ 배포될수 μžˆλ„λ‘ μ„€μ •ν•œλ‹€.

μš°μ•„ν•œ μŠ€ν”„λ§ 배치 ν…Œν¬μ„Έλ―Έλ‚˜ 정리 및 ν›„κΈ° (by μš°μ•„ν•œ ν˜•μ œλ“€)

μ§€λ‚œμ£Ό μš°μ•„ν•œ ν˜•μ œλ“€μ—μ„œ μ§„ν–‰ν•˜μ˜€λ˜ “9μ›” μš°μ•„ν•œ ν…Œν¬ μ„Έλ―Έλ‚˜ - μš°μ•„ν•œ μŠ€ν”„λ§ 배치” 에 λ‹€λ…€μ™”λ‹€. ν•„μžμ—κ²Œ 이번 9월은 정신이 어디에 μžˆλŠ”μ§€ λͺ¨λ₯Όλ§ŒνΌ λ°”μ˜κ³  νž˜λ“€μ—ˆμ§€λ§Œ μ˜ˆμ „λΆ€ν„° κΆκΈˆν•˜κΈ°λ„ ν–ˆκ³  μš”μ¦˜λ“€μ–΄ 관심을 κ°–λ˜ “배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜"을 μ–΄λ–»κ²Œ ν•˜λ©΄ “μš°μ•„ν•œ 방법"으둜 μ‚¬μš©ν•  수 μžˆμ„μ§€μ— λŒ€ν•΄ μ—¬λŸ¬ 생각듀이 μžˆμ—ˆκΈ°μ— 큰 κΈ°λŒ€λ₯Ό 가지고 지μ˜₯철을 견디며 μž μ‹€ κ·Όμ²˜μ— μžˆλŠ” μš°μ•„ν•œ ν˜•μ œλ“€ μž‘μ€μ§‘μœΌλ‘œ κ°€κ²Œ λ˜μ—ˆλ‹€. μ–΄λ–€ λ‚΄μš©μ„ λ°œν‘œν•˜μ˜€λŠ”μ§€μ— λŒ€ν•΄ κΈ°μ–΅μž˜ν•˜λŠ” λ˜‘λ˜‘ν•œ μ•΅λ¬΄μƒˆκ°€ λ˜μ–΄ μ •λ¦¬ν•˜κΈ° 보닀 μ£Όμš” ν¬μΈνŠΈμ— λŒ€ν•œ 생각과 ν•¨κ»˜ μ°Έμ—¬λ₯Ό λͺ»ν•œ λΆ„λ“€ μœ„ν•΄μ„œλΌκΈ° 보닀 λ‚΄ 슀슀둜 정리λ₯Ό ν•˜κΈ° μœ„ν•΄ ν¬μŠ€νŒ…μ„ μž‘μ„±ν•΄ 보고자 ν•œλ‹€. (μ΄λ²ˆμ—λ„ λΆˆλŸ¬μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€ ^=^) 인트둜 μ—°μ‚¬μž 뢄은 μ›Œλ‚™μ— 유λͺ…ν•˜μ‹  뢄이라 λ³„λ„μ˜ μ„€λͺ…이 ν•„μš” 없이 μš΄μ˜ν•˜μ‹œλŠ” λΈ”λ‘œκ·Έ μ£Όμ†Œλ‘œ λŒ€μ²΄λ₯Ό ν•΄λ³Έλ‹€. 이번 행사에 μ΄ˆλŒ€λ˜μ‹  뢄듀은 ν•œλ²ˆμ΄λΌλ„ μŠ€ν”„λ§ 배치λ₯Ό 써뢄 뢄듀을 λŒ€μƒμœΌλ‘œ μ§„ν–‰ν•˜κ²Œ λ˜μ—ˆλ‹€κ³  ν–ˆλŠ”λ° 마침 ν•„μžλ„ νŒ€ λ‚΄μ—μ„œ μš΄μ˜ν•˜κ³  μžˆλŠ” 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 보닀 효율적이고 μš°μ•„ν•˜κ²Œ λ°”κΏ”λ³΄κ³ μž ν•˜λŠ” λ‹ˆμ¦ˆκ°€ μžˆμ—ˆκΈ°μ— μ•„λ§ˆ μ΄ˆλŒ€λœκ²Œ μ•„λ‹κΉŒ μ‹Άλ‹€. μ•„κΈ°μžκΈ°ν•œ μš°μ•„ν•œ ν˜•μ œλ“€ 건물 λ‚΄λΆ€" μ•„κΈ°μžκΈ°ν•œ μš°μ•„ν•œ ν˜•μ œλ“€ 건물 λ‚΄λΆ€ λ”λΆˆμ–΄ λ°œν‘œμ „μ— κ°„λž΅νžˆ νšŒμ‚¬κ°€ μ›ν•˜λŠ” μΈμž¬μ— λŒ€ν•˜μ—¬ μ–ΈκΈ‰ν•΄μ£Όμ…¨λŠ”λ° 그게 μ–΄μ°Œλ‚˜ 곡감이 κ°€λ˜μ§€. μ—­μ‹œ 생각이 남닀λ₯Έ νšŒμ‚¬κ΅¬λ‚˜ ν•˜κ³  λ‹€μ‹œν•œλ²ˆ 생각을. μžκΈ°λ³΄λ‹€ κ²½ν—˜μ΄ “적은” μ‚¬λžŒμ—κ²Œ “섀득을 λ‹Ήν•  수” μžˆμ–΄μ•Ό ν•˜κ³ , μžκΈ°λ³΄λ‹€ κ²½ν—˜μ΄ “λ§Žμ€ μ‚¬λžŒμ„ 섀득” μ‹œν‚¬ 수 μžˆμ–΄μ•Ό ν•œλ‹€. 기본편 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄λž€ μ»΄ν“¨ν„°μ—μ„œ μ‚¬λžŒμ™€ μƒν˜Έμž‘μš©μ—†μ΄ μ΄μ–΄μ§€λŠ” ν”„λ‘œκ·Έλž¨(μž‘μ—…)λ“€μ˜ 싀행이라고 μœ„ν‚€ν”Όλ””μ•„μ— κ°„κ²°&λͺ…λ£Œν•˜κ²Œ μ •λ¦¬λ˜μ–΄ μžˆλ‹€. 그만큼 일반적인 μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜κ³Όμ˜ 차이가 μžˆλŠ”λ° μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ€ μ‹€μ‹œκ°„ μ²˜λ¦¬κ°€ 기본이고 μš”μ²­μ— λŒ€ν•œ 응닡을 μ œκ³΅ν•΄μ•Ό ν•˜λ‹ˆ μ•„λ¬΄λž˜λ„ 속도가 μƒλŒ€μ μ΄λ©° QAμ‹œ νŽΈν•œ 뢀뢄이 μžˆλ‹€. 그에 λ°˜ν•΄ 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ€ μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ§ν•˜λŠ” μš”μ²­μ΄λΌλŠ” κ°œλ…λ³΄λ‹€ ν›„μ†μ²˜λ¦¬μ— 가깝고, 속도 λ˜ν•œ μ ˆλŒ€μ μ΄λ©° QAκ°€ λ³΅μž‘ν•˜λ‹€λŠ”κ²Œ νŠΉμ§•μ΄λ‹€. λ”°λΌμ„œ ν…ŒμŠ€νŠΈμ½”λ“œλŠ” μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ 보닀 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 더 ν•„μš”ν•˜λ‹€κ³  λ³Ό 수 μžˆλ‹€. 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ ν•„μš”ν•œ 상황은 크게 λ‘κ°€μ§€λ‘œ λ‚˜λˆ  λ³Ό μˆ˜κ°€ μžˆλ‹€κ³  ν•œλ‹€. 일정 주기둜 μ‹€ν–‰ λ˜μ–΄μ•Ό ν•  λ•Œ μ‹€μ‹œκ°„ μ²˜λ¦¬κ°€ μ–΄λ €μš΄ λŒ€λŸ‰μ˜ 데이터λ₯Ό 처리 ν• λ•Œ ν‰μ†Œ 첫번째 μƒν™©λ§Œ μƒκ°ν•˜κ³  배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μž‘μ„±ν•˜κ³€ ν–ˆμ—ˆλŠ”λ° λ‘λ²ˆμž¬ 상황에 λŒ€ν•΄ 생각에 생각을 더 ν•΄λ³΄λ‹ˆ μŠ€ν”„λ§ 배치λ₯Ό κ°„λ‹¨ν•˜κ²Œλ§Œ (Tasklet) μ‚¬μš©ν•˜κ³  μžˆλŠ”κ±΄ μ•„λ‹Œκ°€ ν•˜λŠ” λ°˜μ„±μ„ 해보곀 ν–ˆλ‹€. (Reader, Processor, Writer λ“± λ‹€μ–‘ν•œ λ ˆμ΄μ–΄κ°€ μžˆλŠ”λ°λ„…) 특히 μŠ€ν”„λ§ λ°°μΉ˜μ—μ„œλŠ” 기본적으둜 λͺ¨λ“  데이터λ₯Ό λ©”λͺ¨λ¦¬μ— μŒ“μ§€ μ•ŠλŠ” μ‘°νšŒλ°©μ‹λΌκ³  ν•œλ‹€. (DBκΈ°μ€€) Paging ν˜Ήμ€ Cursor둜 pageSize만큼만 μ½μ–΄μ˜€κ³  chunkSize만큼만 commit ν•˜λŠ” ν˜•νƒœ. μ΄λŸ¬ν•œ 각 λ ˆμ΄μ–΄λ³„ sizeλ₯Ό 잘 μ‘°μ •ν•˜κΈ°λ§Œ 해도 적은 λ…Έλ ₯으둜 큰 μ„±λŠ₯을 얻을 수 μžˆλŠ” 뢀뢄이 ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λŠ” 이유 μ•„λ‹κΉŒ 라고 생각해본닀. λ˜ν•œ @JobScope λ‚˜ @StepScopeλŠ” Late Binding 즉 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹€ν–‰λ˜λŠ” μ‹œμ μ΄ μ•„λ‹ˆλΌ Job 이 μ‹€ν–‰λ λ•Œ 생성이 되기 λ•Œλ¬Έμ— 이λ₯Ό ν™œμš©ν•˜μ—¬ λ™μ μœΌλ‘œ reader / processor / wirter λ ˆμ΄μ–΄λ₯Ό λ§Œλ“€ 수 μžˆλ‹€κ³  ν•œλ‹€. ν™œμš©νŽΈ μŠ€ν”„λ§ 배치λ₯Ό μ΄μš©ν•œ 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 있고 이λ₯Ό μŠ€μΌ€μ₯΄λ§ λ“± 관리λ₯Ό ν•΄μ£ΌλŠ” 도ꡬ듀에 이야기λ₯Ό ν•΄μ£Όμ…¨λ‹€. Cron λ¦¬λˆ…μŠ€λ₯Ό μ–΄λŠμ •λ„ μ‚¬μš©ν•΄λ΄€λ‹€λ©΄ μ•Œλ§Œν•œ λ¦¬λˆ…μŠ€ κΈ°λ³Έ μŠ€μΌ€μ₯΄λ§ ν”„λ‘œκ·Έλž¨μΈ Cron. ν•„μžλ„ Cron 으둜 주기적으둜 μ‹€ν–‰ν•˜λ„λ‘ 섀정해보기도 ν•˜μ˜€μ§€λ§Œ 배치 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ νŠΉμ„±μƒ 둜그 및 μ‹€ν–‰/μ’…λ£Œ λ“± μ œν•œμ‚¬ν•­μ΄ λ§Žμ€ 건 사싀인것 κ°™λ‹€. Spring MVC + API Call μ£Όλ³€μ—μ„œ μ‚¬μš©ν•˜κ³  μžˆλ‹€κ³  ν•˜λ˜ 방식. 이 λ°©μ‹μ˜ μž₯점은 항상 λ– μžˆκΈ° λ•Œλ¬Έμ— μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ κ΅¬λ™μ‹œκ°„μ΄ λ³„λ„λ‘œ ν•„μš” μ—†λ‹€λŠ” μž₯점이 μžˆμ§€λ§Œ μ „λ°˜μ μΈ 관리가 μ–΄λ €μš΄ 단점이 μžˆλŠ”κ²ƒ κ°™λ‹€. λ¬Όλ‘  울며 겨자먹기 μ‹μœΌλ‘œ 단점을 극볡할 방법은 μ—¬λŸ¬κ°€μ§€κ°€ μžˆκ² μ§€λ§Œ λͺ¨λ“ κ±΄ 항상 Trade off Spring Batch Admin (Deprecated) μ˜ˆμ „ νŒ€λΆ„μ΄ μ•Œλ €μ£Όμ…”μ„œ 잠깐 봀던 뢀뢄이긴 ν•œλ° μ–΄λŠμ‚¬μ΄μ— Deprecated λ˜μ—ˆλ‹€κ³  ν•œλ‹€. Quertz + Admin http://www.quartz-scheduler.org/ μ•„μ£Ό μ˜€λž˜μ „μ— 써본 기얡이 μžˆμ§€λ§Œ 배보닀 배꼽이 더 큰 μƒν™©κ°™μ•˜λ˜ νž˜λ“€μ—ˆλ˜ κΈ°μ–΅λ“€λ§Œ λ‚¨μ•„μžˆλŠ” κ΅¬ν˜„λ°©λ²•μΈκ²ƒ κ°™λ‹€.

λ„€νŠΈμ›Œν¬ λͺ¨λ‹ˆν„°λ§μ΄ κΆκΈˆν• λ• ? Packetbeat !

λͺ¨λ‹ˆν„°λ§μ€ μ„œλΉ„μŠ€ 둜직 개발 만큼 ν•œλ²ˆμ”© 고민해보고 κ²½ν—˜ν•΄ 봀을 μ€‘μš”ν•œ μ˜μ—­μ΄λΌ ν•  수 μžˆλ‹€. 그쀑 μ›Ήμ„œλ²„μ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” μ—‘μ„ΈμŠ€ λ‘œκ·ΈλŠ” μš΄μ˜ν•˜κ³  μžˆλŠ” μ›Ήμ„œλΉ„μŠ€μ— λŒ€ν•΄ μ—¬λŸ¬κ°€μ§€ μΈ‘λ©΄μ—μ„œ 뢄석할 수 μžˆλŠ” κ°€μž₯ κ°•λ ₯ν•œ μ•„μ΄ν…œ 쀑에 ν•˜λ‚˜λΌκ³  μƒκ°ν•œλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μžλ“€μ΄ μ–΄λ–€ url을 많이 ν˜ΈμΆœν•˜κ³ , μ–΄λ–€ user-agentν˜•νƒœλ₯Ό μ‚¬μš©ν•˜λŠ”μ§€ μ•Œκ²Œ 되면 그에 따라 μ„œλΉ„μŠ€ μ „λž΅μ„ λ³€κ²½ν• μˆ˜λ„ 있고 μ•…μ˜μ μœΌλ‘œ 곡격적인 μš”μ²­μ— λŒ€ν•΄ μ›Ήμ„œλ²„λ‹¨μ—μ„œ 차단을 ν•  수 있기 λ•Œλ¬Έμ΄λ‹€. μ΄λ ‡κ²Œ inbound νŠΈλž˜ν”½(μ™ΈλΆ€μ—μ„œ λ“€μ–΄μ˜€λŠ” μš”μ²­)에 λŒ€ν•΄μ„œλŠ” μ—‘μ„ΈμŠ€ 둜그λ₯Ό 잘 λΆ„μ„ν•˜λ©΄ 기쑴의 μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜κ³ΌλŠ” μ „ν˜€ λ¬΄κ΄€ν•˜κ²Œ λͺ¨λ‹ˆν„°λ§μ΄ κ°€λŠ₯ν•˜μ§€λ§Œ λ°˜λŒ€λ‘œ outbund νŠΈλž˜ν”½(μ™ΈλΆ€λ‘œ λ‚˜κ°€λŠ” μš”μ²­)에 λŒ€ν•΄μ„œλŠ” μ–΄λ–€μ‹μœΌλ‘œ λͺ¨λ‹ˆν„°λ§μ„ ν•  수 μžˆμ„κΉŒ? 월급톡μž₯의 inbound νŠΈλž˜ν”½λ³΄λ‹€ outbound νŠΈλž˜ν”½μ΄ λ„ˆλ¬΄ λ§Žμ€ μš”μ¦˜…이미지 좜처 : https://www.app24moa.com/feedDetail/2/2002" 월급톡μž₯의 inbound νŠΈλž˜ν”½λ³΄λ‹€ outbound νŠΈλž˜ν”½μ΄ λ„ˆλ¬΄ λ§Žμ€ μš”μ¦˜… 이미지 좜처 : https://www.app24moa.com/feedDetail/2/2002 예컨데, 날씨 μ„œλΉ„μŠ€λ₯Ό ν•˜κΈ° μœ„ν•΄ μ™ΈλΆ€μ—μ„œ μ„œμšΈλ‚ μ”¨λΌλŠ” νŽ˜μ΄μ§€λ₯Ό μ‘°νšŒν–ˆμ„ 경우 기상청 APIμ—μ„œ λ„˜κ²¨λ°›μ€ 데이터λ₯Ό κ°€κ³΅ν•˜μ—¬ 보여쀀닀고 κ°€μ •ν•΄λ³΄μž. μ΄λ•Œ κΈ°μƒμ²­μ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” νŠΉμ • API쀑에 μ–΄λŠ ν•˜λ‚˜κ°€ 늦게 응닡이 μ˜¨λ‹€κ±°λ‚˜, νŠΉμ •μ‹œκ°„λŒ€μ— μ—λŸ¬μ‘λ‹΅μ„ λ°›μ„κ²½μš° κ³Όμ—° 이λ₯Ό μ–΄λ–€μ‹μœΌλ‘œ λͺ¨λ‹ˆν„°λ§ ν• μˆ˜ μžˆμ„κΉŒ? μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œμ— λͺ¨λ‹ˆν„°λ§μ„ μœ„ν•œ μ½”λ“œλ₯Ό μΆ”κ°€ν•  것인가? 혹 ν•˜λ‚˜μ˜ μ„œλ²„μ—μ„œ Aλͺ¨λ“ˆμ€ java둜, Bλͺ¨λ“ˆμ€ python으둜 κ°œλ°œλ˜μ—ˆμ„ 경우 각각 λͺ¨λ“ˆλ§ˆλ‹€ λͺ¨λ‹ˆν„°λ§μ„ μœ„ν•œ μ½”λ“œλ₯Ό μΆ”κ°€ν•˜λŠ” μ‹μœΌλ‘œ ν•˜λ‹€λ³΄λ©΄ λΉ„μ§€λ‹ˆμŠ€ λ‘œμ§μ„ λ°©ν•΄ν•˜κ±°λ‚˜ 였히렀 μΆ”κ°€ν•œ μ½”λ“œ λ˜ν•œ 관리해야 ν•˜λŠ” 배보닀 배꼽이 더 컀져버릴 상황도 μƒκΈΈμˆ˜ μžˆλ‹€. μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λΉ„μ§€λ‹ˆμŠ€ λ‘œμ§κ³ΌλŠ” λ¬΄κ΄€ν•˜κ²Œ μ„œλ²„ μžμ²΄μ—μ„œ μ™ΈλΆ€λ‘œ λ‚˜κ°€λŠ” λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½μ— λŒ€ν•΄ λͺ¨λ‹ˆν„°λ§μ„ ν•  수 μžˆλŠ” κ°€λ²Όμš°λ©΄μ„œλ„ μ‹¬ν”Œν•œ λͺ¨λ“ˆμ„ μ°Ύκ³  μ‹Άμ—ˆλ‹€. μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ κ°œλ°œμ–Έμ–΄κ°€ 무엇이든 상관없이 λ³„λ„μ˜ μ—μ΄μ „νŠΈ ν˜•μ‹μœΌλ‘œ λ„μ›Œλ‘κΈ°λ§Œ ν•˜λ©΄ λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½μ„ μˆ˜μ§‘ 및 뢄석, λ‚˜μ•„κ°€μ„œλŠ” λͺ¨λ‹ˆν„°λ§κΉŒμ§€ ν• μˆ˜μžˆλŠ”… κ·Έλž˜μ„œ μ°Ύλ‹€λ³΄λ‹ˆ μ—­μ‹œλ‚˜ μ΄λŸ¬ν•œ 고민을 λˆ„κ΅°κ°€λŠ” ν•˜κ³  μžˆμ—ˆκ³  μ˜€ν”ˆμ†ŒμŠ€κΉŒμ§€ λ˜μ–΄μžˆλŠ” Elastic Stack 의 Beat쀑 PacketbeatλΌλŠ” 데이터 μˆ˜μ§‘λͺ¨λ“ˆμ„ μ•Œκ²Œ λ˜μ—ˆλ‹€. μ—­μ‹œ λ‚΄κ°€ ν•˜κ³ μžˆλŠ” 고민은 이미 λˆ„κ΅°κ°€ ν–ˆλ˜ κ³ λ―Όλ“€… μ΄λŸ¬ν•œ 고민에 λŒ€ν•΄ ν•΄κ²°ν•˜λŠ” 방법을 보닀 빨리 μ°ΎλŠ”κ²Œ 경쟁λ ₯이 될텐데… 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” Packetbeat 에 λŒ€ν•΄ κ°„λ‹¨νžˆ μ•Œμ•„λ³΄κ³  이λ₯Ό ν™œμš©ν•˜μ—¬ outbound νŠΈλž˜ν”½μ— λŒ€ν•΄ λͺ¨λ‹ˆν„°λ§μ„ 해보며 μ–΄λ–€μ‹μœΌλ‘œ ν™œμš©ν•  수 μžˆλŠ”μ§€μ— λŒ€ν•΄ μ•Œμ•„λ³΄κ³ μž ν•œλ‹€. Packetbeat ? ElasticStack 쀑에 데이터 μˆ˜μ§‘κΈ° ν”Œλž«νΌμΈ Beats쀑 λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½ 데이터에 λŒ€ν•΄ μˆ˜μ§‘μ„ ν•  수 μžˆλŠ” 데이터 μˆ˜μ§‘κΈ°λ₯Ό μ œκ³΅ν•˜κ³  μžˆλ‹€. pcap라이브러리λ₯Ό μ΄μš©ν•˜μ—¬ μ„œλ²„μ˜ λ„€νŠΈμ›Œν¬ λ ˆλ²¨μ—μ„œ 데이터λ₯Ό μˆ˜μ§‘ 및 λΆ„μ„ν•œ ν›„ μ™ΈλΆ€λ‘œ(Elasticsearch, Logstash, Kafka λ“±) μ „μ†‘ν•΄μ£ΌλŠ” κ²½λŸ‰ λ„€νŠΈμ›Œν¬ νŒ¨ν‚· 뢄석기라고 곡식 ν™ˆνŽ˜μ΄μ§€μ— μ†Œκ°œλ˜κ³  μžˆλ‹€. λͺ‡λ²ˆ μ‚¬μš©ν•΄λ³΄λ©΄μ„œ λŠλ‚€ μž₯점듀은 λ‹€μŒκ³Ό κ°™λ‹€. μ„€μΉ˜ 및 싀행이 λ„ˆλ¬΄ κ°„λ‹¨ν•˜λ‹€. μ„€μ •κ°’ νŠœλ‹μ„ 톡해 κ°„λ‹¨ν•˜μ§€λ§Œ, κ·ΈλŸ¬ν•œ 간단함에 λΉ„ν•΄μ„œ λ„ˆλ¬΄ κ°•λ ₯ν•œ μˆ˜μ§‘μ΄ κ°€λŠ₯ν•˜λ‹€. μ•žμ„œ 이야기 ν–ˆλ˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œμ™€λŠ” μ „ν˜€ λ¬΄κ΄€ν•˜κ²Œ μž‘λ™ν•œλ‹€. 무엇을 해볼것인가?! (a.k.a. λͺ©ν‘œ) ν•„μžκ°€ μš΄μ˜ν•˜λŠ” Daily-DevBlog λΌλŠ” μ„œλΉ„μŠ€κ°€ μžˆλ‹€. (κ°‘λΆ„ μ„œλΉ„μŠ€ 홍보) μ—¬λŸ¬ μ‚¬λžŒλ“€μ˜ rssλ₯Ό μ‘°νšŒν•˜κ³  νŒŒμ‹±ν•΄μ„œ 메일을 λ³΄λ‚΄μ£ΌλŠ” μ„œλΉ„μŠ€ 인데, packetbeat μ‚¬μš© μ˜ˆμ‹œλ₯Ό λ“€κΈ°μœ„ν•΄ 쑰금 λ³€ν˜•ν•˜μ—¬ λͺ¨λ“  rssλ₯Ό μ ‘κ·Όν•˜κ³  κ°€μž₯ μ΅œμ‹ κΈ€μ˜ 제λͺ©μ„ 좜λ ₯ν•˜λŠ” μ•„μ£Ό κ°„λ‹¨ν•œ python 슀크립트둜 outbound νŠΈλž˜ν”½μ„ λ°œμƒμ‹œμΌœ 보고자 ν•œλ‹€. 그리고 packetbeat λ₯Ό μ΄μš©ν•˜μ—¬ μ™ΈλΆ€λ‘œ ν˜ΈμΆœλ˜λŠ” νŠΈλž˜ν”½μ„ μˆ˜μ§‘ν•˜κ³  Elasticsearch 둜 인덱싱 ν•˜μ—¬ μ΅œμ’…μ μœΌλ‘œλŠ” μ–΄λŠ rss의 속도가 κ°€μž₯ λŠλ¦°μ§€ μ‹€ν–‰λ˜λŠ” pythonμ½”λ“œμ™€λŠ” μ „ν˜€ 관련없이 λͺ¨λ‹ˆν„°λ§ ν•΄λ³΄κ³ μž ν•œλ‹€. python μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™λ‹€. 참고둜 ν•„μžλŠ” awesome-devblog의 μš΄μ˜μžλΆ„κ»˜ ν•΄λ‹Ή 데이터 μ‚¬μš©μ— λŒ€ν•΄ ν—ˆλ½μ„ 받은 μƒνƒœμ΄λ‹€. import requests, yaml, feedparser blog_info_list_yml_url = 'https://raw.githubusercontent.com/sarojaba/awesome-devblog/master/db.yml' blog_info_list_yml = requests.get(url=blog_info_list_yml_url).text blog_info_yaml_parse_list = yaml.load(blog_info_list_yml) for blog_info in blog_info_yaml_parse_list : if 'rss' not in blog_info.keys() or not blog_info['rss']: continue rss_url = blog_info['rss'] try : parse_feed = feedparser.parse(rss_url) except : continue parse_feed_data = parse_feed.entries[0] print(blog_info['name'], '|', parse_feed_data['title'], '|', parse_feed_data['link']) μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ μ•„λž˜μ²˜λŸΌ μ•„μ£Ό κ°„λ‹¨ν•˜κ²Œ λΈ”λ‘œκ·Έ 주인의 이름과 μ΅œμ‹ κΈ€ 제λͺ©, 링크가 좜λ ₯이 λœλ‹€.

μ•„νŒŒμΉ˜ λ‘œλ“œλ°ΈλŸ°μ‹±μœΌλ‘œ μ—¬λŸ¬ WAS μš΄μ˜ν•˜κΈ°

μ›Ήμ„œλ²„ ν•˜λ‚˜λ§Œ μ‚¬μš©ν•˜κ±°λ‚˜ WAS ν•˜λ‚˜λ§Œμ„ μ‚¬μš©ν•˜λ©° μ›Ήμ„œλΉ„μŠ€λ₯Ό μš΄μ˜ν•˜λŠ” κ²½μš°λŠ” 극히 λ“œλ¬Όλ‹€. μ›Ήμ„œλ²„μ˜ μž₯점과 WAS의 μž₯점 κ·Έ λ‘λ§ˆλ¦¬μ˜ 토끼λ₯Ό λ‹€ 작기 μœ„ν•΄ 보톡 μ•žλ‹¨μ— μ›Ήμ„œλ²„λ₯Ό 두고 κ·Έ 뒀에 WASλ₯Ό 두며 μ„œλΉ„μŠ€λ₯Ό μš΄μ˜ν•˜κ³€ ν•œλ‹€. ν—Œλ° μš΄μ˜ν•˜λŠ” μ„œλΉ„μŠ€κ°€ 인기가 λ§Žμ•„μ Έ(?) μ‚¬μš©λŸ‰μ΄ λ§Žμ•„μ§€λ‹€λ©΄ 그만큼 응닡이 느렀 (TPS λ“±) μ„œλ²„λ₯Ό λŠ˜λ €μ•Ό ν•˜λŠ” 상황이 생긴닀고 κ°€μ •ν•΄λ³΄μž.(λ¬Όλ‘  μ„œλ²„λ₯Ό λŠ˜λ¦¬λŠ” 것보닀 μΊμ‹œλ₯Ό μ μš©ν•˜κ±°λ‚˜ λ‘œμ§μ„ λ°”κΏ”λ³΄λŠ” λ…Έλ ₯이 μ„ ν–‰λ˜μ•Ό ν•˜κ² μ§€λ§Œ…) λ‹Ήμ—°νžˆ μ„œλ²„λΆ€ν„° κ΅¬λ§€ν•˜λ©° “Scale Out"을 ν•˜λ €κ³  할것이닀. λ§Œμ•½ μ›λž˜ μš΄μ˜ν•˜λ˜ μ„œλ²„κ°€ λ„ˆλ¬΄ μ’‹μ•„μ„œ CPUλ‚˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λ₯ μ΄ 거의 λ°”λ‹₯이여도 μ„œλ²„λ₯Ό ꡬ맀해야 ν• κΉŒ? μ„œλ²„λ₯Ό κ΅¬λ§€ν•˜κ²Œλ˜λ©΄ κ²°κ΅­ λ‘κ°œ μ΄μƒμ˜ μ„œλ²„κ°€ μš΄μ˜λ ν…λ° κ·Έ μ„œλ²„λ“€μ„ μ•žμ—μ„œ λ¬Άμ–΄μ£Όλ©° νŠΈλž˜ν”½μ„ λΆ„μ‚°μ‹œμΌœμ£ΌλŠ” 무언가가 ν•„μš”ν•˜λ‹€. κ·ΈλŸ¬ν•œ κΈ°μˆ μ„ λ°”λ‘œ λ‘œλ“œλ°ΈλŸ°μ‹± 이라고 ν•œλ‹€. 톡상 L4 μŠ€μœ„μΉ˜λ₯Ό ν™œμš©ν•˜μ—¬ μš”μ²­μ„ μ—¬λŸ¬ μ„œλ²„λ“€λ‘œ λΆ„μ‚°μ‹œν‚€λ©° μ‚°μˆ μ μœΌλ‘œλŠ” μ„œλ²„ λŒ€μˆ˜λ§ŒνΌ μ„±λŠ₯이 μ’‹μ•„μ§€λŠ” 효과λ₯Ό λ³Ό 수 μžˆλ‹€. ν•˜μ§€λ§Œ μ•žμ„œ λ§ν–ˆλ“― μ„œλ²„μ˜ μžμ› μ‚¬μš©λ₯ μ΄ λ°”λ‹₯일 μ •λ„λ‘œ 거의 μ‚¬μš©μ„ μ•ˆν• κ²½μš° μ„œλ²„λ₯Ό κ΅¬λ§€ν•˜λŠ”κ±΄ λ„ˆλ¬΄λ‚˜ λΉ„νš¨μœ¨μ μ΄λ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μ„œλ²„λ₯Ό λŠ˜λ¦¬μ§€ μ•ŠμœΌλ©΄μ„œ μ›Ήμ„œλ²„ 쀑 μ•„νŒŒμΉ˜λ₯Ό ν™œμš©ν•˜μ—¬ μ—¬λŸ¬ WASλ₯Ό μš΄μ˜ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄κ³ μž ν•œλ‹€. μ„œλ²„ λŠ˜λ €μ•Ό ν•˜λŠ” μƒν™©μ—μ„œ μ‚¬μš©ν•΄ λ³Ό 수 μžˆλŠ” λ‚˜λ§Œμ˜ 쒋은 무기(?)κ°€ μƒκΈ΄κ²Œ μ•„λ‹κΉŒ 생각이 λ“ λ‹€. μ•„νŒŒμΉ˜λŠ” EOL이 λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 2.4λ²„μ „μœΌλ‘œ μ„€μΉ˜ν•˜κ³ , WASλŠ” νŽΈμ˜μƒ ν†°μΌ“ μ΅œμ‹ λ²„μ „μœΌλ‘œ μ„€μΉ˜ν•΄μ„œ λ™μΌν•œ μ„œλ²„μ— μ•„νŒŒμΉ˜ ν•œλŒ€μ™€ ν†°μΌ“ 3λŒ€λ₯Ό μ—°λ™ν•˜λŠ”κ²ƒμ„ λͺ©μ μœΌλ‘œ ν•œλ‹€. λ‘œλ“œλ°ΈλŸ°μ‹±μ΄ μ–΄λ–€μ‹μœΌλ‘œ 이루어 지고 ν•˜μœ„μ— μ—°κ²°λœ 톰켓을 컨트둀 ν•˜λŠ” 방법 λ˜ν•œ μ•Œμ•„λ³Ό μ˜ˆμ •μ΄λ‹€. μ„œλ²„ ν™˜κ²½ 및 μ„€μΉ˜ν•˜κ²Œ 될 각 버전은 λ‹€μŒκ³Ό κ°™λ‹€. μ„œλ²„ : CentOS 7.4 64Bit apache : httpd-2.4.39 tomcat : apache-tomcat-8.5.43 tomcat-connectors(mod_jk) : 1.2.46 Apache 와 Tomcat μ„€μΉ˜ ν•„μžμ˜ ν¬μŠ€νŒ…μ—μ„œ μ’…μ’… λ‚˜μ˜€λŠ” 뢀뢄이기도 ν•˜κ³ , ꡬ글링 해보면 λ°”λ‘œ μ„€μΉ˜ 방법을 μ‰½κ²Œ 찾을 수 μžˆκ² μ§€λ§Œ κ·Έλ ‡λ‹€κ³  언급을 μ•ˆν•˜κ³  λ„˜μ–΄κ°€κΈ°μ—” λ„ˆλ¬΄ λΆˆμΉœμ ˆν•˜λ‹ˆ… μΉ˜νŠΈν‚€μ²˜λŸΌ(?) λΉ λ₯΄κ²Œ μ •λ¦¬ν•΄λ³΄μž. Apache $ wget http://apache.tt.co.kr//httpd/httpd-2.4.39.tar.gz $ tar -zxvf httpd-2.4.39.tar.gz $ ./configure --prefix=/home/~~~/apache $ make && make install $ cd /home/~~~/apache/bin $ sudo chown root:계정λͺ… httpd $ sudo chmod +s httpd $ vi /home/~~~/apache/conf/httpd.conf User 계정λͺ… Grop 계정λͺ… $ /home/~~~/apache/bin/apachectl start ← μ‹€ν–‰ μ΄λ ‡κ²Œ μ„€μΉ˜λ₯Ό ν•œλ’€ 싀행을 μ‹œν‚€κ³  μ„œλ²„μ˜ ipλ₯Ό 접속해보면 μ•„λž˜μ™€ 같은 화면을 λ³Ό 수 μžˆλ‹€. Tomcat $ wget http://mirror.apache-kr.org/tomcat/tomcat-8/v8.5.43/bin/apache-tomcat-8.5.43.tar.gz $ tar -zxvf apache-tomcat-8.5.43.tar.gz $ /home/apache-tomcat-8.5.43/bin/start.sh ← μ‹€ν–‰ ν†°μΌ“μ˜ κΈ°λ³Έ http 포트인 8080으둜 접속을 해보면 κ·€μ—¬μš΄ 고양이가 μžˆλŠ” ν†°μΌ“ 기본화면을 λ³Ό 수 μžˆλ‹€. μ•„νŒŒμΉ˜μ™€ ν†°μΌ“ μ—°λ™ν•˜κΈ° μ•„νŒŒμΉ˜μ™€ ν†°μΌ“μ˜ 연동은 mod_jk 와 mod_proxy λ“± λ‹€μ–‘ν•œ λͺ¨λ“ˆλ‘œ 연동을 ν•  수 μžˆλŠ”λ° 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” mod_jk λ₯Ό ν™œμš©ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄κ³ μž ν•œλ‹€. μš°μ„  mod_jk λ₯Ό μ„€μΉ˜ν•˜μž. κ°„λ‹¨νžˆ mod_jk λŠ” 컴파일, μ„€μ • λ“± λ³΅μž‘ν•˜μ§€λ§Œ ν†°μΌ“ μ „μš© λ°”μ΄λ„ˆλ¦¬ ν”„λ‘œν† μ½œμΈ AJPλ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— 높은 μ„±λŠ₯을 κΈ°λŒ€ν• μˆ˜κ°€ μžˆλ‹€. mod_proxy λŠ” 반면 기본으둜 μ•„νŒŒμΉ˜μ— νƒ‘μž¬λ˜μ–΄μžˆλŠ” λͺ¨λ“ˆμ΄κΈ° λ•Œλ¬Έμ— λ³„λ„μ˜ λͺ¨λ“ˆ μ„€μΉ˜κ°€ ν•„μš” μ—†κ³  섀정도 κ°„λ‹¨ν•˜λ‹€λŠ” μž₯점이 μžˆλ‹€. 각 μ—°λ™λ°©μ‹μ˜ μž₯단점이 있기 λ•Œλ¬Έμ— 본인이 μš΄μ˜ν•˜λŠ” μ„œλ²„ 상황에 λ§žμΆ”μ–΄ 적용 ν•  ν•„μš”κ°€ μžˆλ‹€. mod_jk μ„€μΉ˜ $ wget http://apache.tt.co.kr/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.46-src.tar.gz $ tar -zxvf tomcat-connectors-1.2.46-src.tar.gz $ cd tomcat-connectors-1.2.46-src/native $ ./configure --with-apxs=/home/~~~/apache/bin/apxs $ make && make install $ /home/~~~/apache/modules ν•˜μœ„μ— mod_jk.soκ°€ 생김 mod_jk λ₯Ό ν™œμš©ν•˜λ©΄ AJPλΌλŠ” ν†΅μ‹ μœΌλ‘œ μ•„νŒŒμΉ˜μ™€ 톰켓이 μ—°λ™λ˜λŠ”λ° ν†°μΌ“μ˜ κΈ°λ³Έ AJP ν¬νŠΈλŠ” 8009λ²ˆμž„μ„ μ•Œκ³  λ‹€μŒμ²˜λŸΌ 섀정을 ν•΄μ£Όμž. apache/conf/workers.properties worker.list=tomcat1 worker.tomcat1.port=8009 worker.tomcat1.host=localhost worker.tomcat1.type=ajp13 worker.tomcat1.lbfactor=1 apache/conf/httpd.conf LoadModule jk_module modules/mod_jk.so <IfModule jk_module> JkWorkersFile conf/workers.properties JkLogFile logs/mod_jk.log JkLogLevel info JkMount /* tomcat1 </IfModule> μ΄λ ‡κ²Œ ν•˜κ³ μ„œ μ•„νŒŒμΉ˜μ™€ 톰켓을 μž¬μ‹œμž‘ 후에 μ„œλ²„μ˜ ip둜 접속해보면 (λ³„λ„μ˜ port 없이) ν†°μΌ“ μ„€μ •νŽ˜μ΄μ§€λ‘œ λžœλ”©μ΄ λ˜λŠ”κ²ƒμ„ 확인할 수 μžˆλ‹€.

μŠ€ν”„λ§μ„ ν™œμš©ν•œ λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œ κ΅¬ν˜„

κ°œλ°œμ„ ν•˜λ‹€λ³΄λ©΄ μ‹€μ œλ‘œ 직접 κ΅¬ν˜„μ„ 해본적은 μ—†μ§€λ§Œ μ—¬κΈ°μ €κΈ°μ„œ λ“€μ–΄λ³Έ 지식과 κ·Έ λ™μ•ˆμ˜ 짬λ°₯(?)으둜 μΆ”μΈ‘ν•΄λ³Όμˆ˜ μžˆλŠ” 뢀뢄듀이 μžˆλ‹€. λ¬Όλ‘  λͺ¨λ“ μΌμ— 정닡은 μ—†κ² μ§€λ§Œ μš”μ¦˜ λŠλΌλŠ”κ±΄ μ±…μ—μ„œ κ³΅λΆ€λ§Œ 해본것과 λ‹€λ₯Έ λΈ”λ‘œκ·Έλ“€μ—μ„œ 눈으둜만 보고 λ„˜μ–΄κ°€λŠ”κ²ƒλ“€ 그리고 직접 손가락을 움직여가며 μ™œ μ—¬κΈ°μ„œλŠ” 이 방법을 μ‚¬μš©ν•˜μ§€ κ³ λ―Όν•˜λ©΄μ„œ κ΅¬ν˜„μ„ ν•΄λ³Έλ‹€λŠ”κ±΄ 정말 μ—„μ²­λ‚˜κ²Œ 큰 차이가 μžˆλŠ”κ²ƒ κ°™λ‹€. μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•˜λ‹€λ³΄λ©΄ ν•œλ²ˆ μ―€ λ§Œλ‚˜κ²Œ λ˜λŠ” 파일 μ—…λ‘œλ“œ κΈ°λŠ₯. ν•„μžλ„ λͺ‡λ²ˆ κ΅¬ν˜„μ€ ν•΄λ΄€μ§€λ§Œ κ·Έλƒ₯ λ‹¨μˆœνžˆ κ΅¬ν˜„λ§Œ ν•΄λ³Έ μƒνƒœμ˜€λ‹€κ°€ μ΅œκ·Όμ— κ·Έλƒ₯ 파일 μ—…λ‘œλ“œκ°€ μ•„λ‹Œ λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œμ—μ„œμ˜ λ¬Έμ œκ°€ λ°œμƒν•˜μ—¬ μ—¬κΈ°μ €κΈ° μ‚½μ§ˆμ„ ν•˜κ²Œ λ˜μ—ˆκ³  정리도 ν•΄λ³Όκ²Έ μŠ€ν”„λ§μ—μ„œμ˜ λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œμ‹œ ν•œλ²ˆμ―€ 고렀해봐야 ν•  뢀뢄에 λŒ€ν•΄ 정리λ₯Ό 해보렀고 ν•œλ‹€. λ¬Όλ‘  κ΅¬κΈ€μ—μ„œ 검색을 해보면 μ•„λ§ˆ ν•„μžκ°€ 쓴것 보닀 더 μžμ„Έν•˜κ³  쒋은 글듀이 μžˆκ² μ§€λ§Œ ν•„μžλŠ” 보닀 λŒ€μš©λŸ‰μ— μ§‘μ€‘μ—μ„œ μž‘μ„±ν•΄ 보고자 ν•œλ‹€. λͺ…μ‹¬ν•˜μž. “아무리 흐린 μž‰ν¬λΌλ„ 쒋은 κΈ°μ–΅λ ₯보닀 λ‚«λ‹€” λΌλŠ” 말이 μžˆλ“―μ΄ μŠ€ν”„λ§μ„ ν™œμš©ν•œ 파일 μ—…λ‘œλ“œ κ΅¬ν˜„ μš°μ„  μ™„μ „ μ΄ˆκΈ°μƒνƒœμ—μ„œ μ‹œμž‘ν•˜κΈ° μœ„ν•΄ μŠ€ν”„λ§ λΆ€νŠΈ ν”„λ‘œμ νŠΈλ₯Ό λ§Œλ“€κ³  κ°„λ‹¨ν•˜κ²Œ 파일 μ—…λ‘œλ“œλ₯Ό ν•  수 μžˆλŠ” form νŽ˜μ΄μ§€μ™€ μ—…λ‘œλ“œ λ²„νŠΌμ„ λˆŒλ €μ„λ•Œ μž‘λ™ν•˜κ²Œ λ˜λŠ” 컨트둀러λ₯Ό λ§Œλ“€μ–΄ 보자. import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import lombok.extern.slf4j.Slf4j; @Slf4j @Controller public class FileUploadController { // λ„ˆλ¬΄ 간단 ... @RequestMapping("/form") public String form() { return "form"; } @RequestMapping(value = "/upload", method = RequestMethod.POST) public String upload(@RequestParam("file") MultipartFile multipartFile) { log.info("### upload"); File targetFile = new File("/home1/irteam/" + multipartFile.getOriginalFilename()); try { InputStream fileStream = multipartFile.getInputStream(); FileUtils.copyInputStreamToFile(fileStream, targetFile); } catch (IOException e) { FileUtils.deleteQuietly(targetFile); e.printStackTrace(); } return "redirect:/form"; } } upload μš”μ²­μ΄ λ“€μ–΄μ˜€λ©΄ fileμ΄λΌλŠ” μ΄λ¦„μ˜ νŒŒλΌλ―Έν„°λ‘œ MultipartFile을 λ°›κ³  파일의 이름을 확인 ν›„ μŠ€νŠΈλ¦Όμ„ 읽어 νŠΉμ • κ²½λ‘œμ— 파일둜 μ €μž₯ν•˜λŠ” λ‘œμ§μ΄λ‹€. κ·Έλ‹€μŒ /form을 μ ‘μ†ν•˜κ²Œ 되면 λ‚˜μ˜€λŠ” 폼 화면을 λ§Œλ“€μž. 이것도 μ•„μ£Ό μ‹¬ν”Œν•˜κ²Œ! <h1>파일 μ—…λ‘œλ“œ</h1> <form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" value="파일 선택" name="file"/> <input type="submit" value="μ—…λ‘œλ“œ"/> </form> multipart/form-data λΌλŠ” Content-Type 을 λͺ…μ‹œν•΄μ£Όκ³  νŒŒμΌμ„ μ„ νƒν•˜λ©΄ /upload둜 POSTμš”μ²­μ„ ν•˜λ„λ‘ μ„€μ •ν•œλ‹€. μ΄λ ‡κ²Œ 되면 λ„ˆλ¬΄ κ°„λ‹¨ν•˜κ²Œ + 이상없이 파일이 μ—…λ‘œλ“œκ°€ 잘 λ˜λ‹ˆ 이게 이야기 ν•  꺼리인가(?) μ‹Άμ„μ •λ„λ‘œ μ‹¬ν”Œν•˜λ‹€. 그런데 파일 크기가 크닀면? μ„€λ§ˆ 파일 μ—…λ‘œλ“œ ν•˜λŠ” μš©λŸ‰μ΄ 크겠어?… 왠지 파일의 μš©λŸ‰μ΄ 크면 λ¬Έμ œμžˆμ„κ²ƒ 같은데… 좜처 : https://m.blog.naver.com/naibbo0407/30170815180" μ„€λ§ˆ 파일 μ—…λ‘œλ“œ ν•˜λŠ” μš©λŸ‰μ΄ 크겠어?… 왠지 파일의 μš©λŸ‰μ΄ 크면 λ¬Έμ œμžˆμ„κ²ƒ 같은데… 좜처 : https://m.blog.naver.com/naibbo0407/30170815180 κ°œλ°œμ„ ν•˜λ‹€λ³΄λ©΄ 항상 생각해야 ν•  뢀뢄쀑에 ν•˜λ‚˜κ°€ λ°”λ‘œ ν™•μž₯성인것 κ°™λ‹€. 이 λΆ€λΆ„μ—μ„œ μ—­μ‹œ λ¬Έμ œκ°€ λ˜μ—ˆλ˜ 것. ν‰μ†Œλ³΄λ‹€ μš©λŸ‰μ΄ 큰 파일이 μ—…λ‘œλ“œκ°€ λ˜λ©΄μ„œ (ν‰μ†Œ 3~400MB μ˜€λ‹€κ°€ 3~4GBμ •λ„μ˜ 파일이 μ—…λ‘œλ“œκ°€ λ˜λŠ” 맀직) μ—…λ‘œλ“œκ°€ μ•ˆλ˜λŠ” 상황이 λ°œμƒν•˜μ˜€λ‹€. λ‹Ήμ—°νžˆ λ¬Έμ œκ°€ λ°œμƒν•˜λ©΄ λˆ„κ΅°κ°€ λ§ν–ˆλ“― λ‘œκ·ΈλΆ€ν„° μ‚΄νŽ΄λ³΄μ•˜λŠ”λ° Apache - (AJP) - Tomcat 으둜 κ΅¬μ„±λœ ν™˜κ²½μ—μ„œ tomcat λ‘œκ·Έμ— ### uploadλΌλŠ” λ‘œκ·Έκ°€ μ—†κ³  μ•„νŒŒμΉ˜ λ‘œκ·Έμ—” 502 μ—λŸ¬κ°€ λ°œμƒν•œ κ²ƒμ΄μ—ˆλ‹€. μ™œ ν†°μΌ“ λ‘œκ·Έλ„ μ•ˆλ‚¨κ³  그전에 μ—λŸ¬κ°€ λ°œμƒν•˜μ˜€μ„κΉŒ? μ΄λ•ŒλΆ€ν„° (κ·Όκ±°μ—†λŠ” 좔츑을 ν•˜λ©°…) κ³ λ‚œκ³Ό μ—­κ²½μ˜ μ‚½μ§ˆμ„ ν•˜κΈ° μ‹œμž‘ν•˜κ²Œ λœλ‹€. ν†°μΌ“ 버전이 문제일까? λ‘œκ·Έκ°€ μ•ˆμ°ν˜”λ‹€λ©΄ λ‹€λ₯Έ ν•„ν„°λ‚˜ μΈν„°μ…‰ν„°μ—μ„œ 무언가λ₯Ό λ¨Ήκ³ (?)μžˆλŠ”κ±΄ μ•„λ‹κΉŒ? 잠깐, 근데 μ›λž˜ λŒ€μš©λŸ‰ μ—…λ‘œλ“œκ°€ 되긴 ν•΄? 파일 μ—…λ‘œλ“œ/λ‹€μš΄λ‘œλ“œ ν•˜λŠ” μ‚¬μ΄νŠΈ 보면 별도 ν”„λ‘œκ·Έλž¨μœΌλ‘œ ν•˜λ˜λ°… 꼬뢈꼬뢈 λ―Έλ‘œμ†μ„ ν—€λ©”λŠ”κ²ƒλ§Œ κ°™μ•˜λ˜ μ‚½μ§ˆμ˜ λ¬Έμ œλŠ” κ²°κ΅­ λ©”λͺ¨λ¦¬μ— μžˆμ—ˆλ‹€. νŒŒμΌμ„ μ—…λ‘œλ“œ ν•˜κ²Œ 되면 ν•΄λ‹Ή λ‚΄μš©μ„ μš°μ„  λ©”λͺ¨λ¦¬μ— λ‹΄κ²Œ 되고 λ‹€ 담은 ν›„ λ©”λͺ¨λ¦¬μ— μžˆλŠ” λ‚΄μš©μ„ was에 μ „λ‹¬ν•œ λ’€ HttpServletRequest 둜 λ„˜μ–΄μ˜€κ²Œ λœλ‹€.(Apache > Tomcat) 그런데 νŒŒμΌμ„ μ—…λ‘œλ“œ ν•˜λ©΄μ„œ λ©”λͺ¨λ¦¬μ— 파일이 써지닀가 λ©”λͺ¨λ¦¬ λΆ€μ‘±μœΌλ‘œ OOM이 λ°œμƒν•˜κ²Œ λ˜λ²„λ¦° κ²ƒμ΄μ—ˆλ‹€. λ˜ν•œ μŠ€ν”„λ§ 파일 μ΅œλŒ€ν¬κΈ°λ₯Ό λ³„λ„λ‘œ μ§€μ •ν•˜μ§€ μ•Šκ³  μžˆμ—ˆκΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬κ°€ μΆ©λΆ„ν–ˆλ‹€ ν•˜λ”λΌλ„ μ—λŸ¬κ°€ λ°œμƒν–ˆμ„ μƒν™©μ΄μ—ˆλ‹€.

2019 μƒλ°˜κΈ° 리뷰 (feat. κΈ€λ˜)

λˆ„κ΅¬λ‚˜ 어렸을 땐 빨리 μ–΄λ₯Έμ΄ 되고 μ‹Άμ–΄ ν•˜λŠ” 것 κ°™λ‹€. μ‹œκ°„μ΄ 빨리 μ§€λ‚˜κ°€κΈΈ 바라고, 빨리 μ–΄λ₯Έμ΄ 되고 μ‹Άλ‹€λŠ” κ°„μ ˆν•¨μ΄ μžˆμ§€λ§Œ μ΄μƒν•˜κ²Œλ„ 그땐 μ‹œκ°„μ΄ 천천히 κ°€λŠ” κ²ƒμ²˜λŸΌ λŠκ»΄μ‘Œλ‹€. 반면, μ‹œκ°„μ΄ 천천히 κ°”μœΌλ©΄ ν•˜λŠ” λ•Œκ°€ μžˆλ‹€. λ”± μ§€κΈˆ. 남듀은 μ›Œμ–΄μ–΄μ–΄μ–Όν™”μ•„μ•„μˆ˜μš°μš°λͺ¨μ˜₯κΈˆν‡Ό 이라고 λΆ€λ₯΄λ©° μ‹œκ°„μ΄ 느리게 κ°„λ‹€κ³  빨리 주말이 μ™”μœΌλ©΄ μ’‹κ² λ‹€κ³  ν•˜μ§€λ§Œ μš”μ¦˜μ˜ ν•„μžλŠ” μ • λ°˜λŒ€λ‹€. 방금 μΆœκ·Όν•œ 것 같은데 μ–΄λŠμƒŒκ°€ 퇴근인사λ₯Ό μ£Όκ³ λ°›κ³  μžˆλ‹€. 무언가에 홀린 것 κ°™λ‹€. 벌써 μ˜¬ν•΄λ„ 절반이 μ§€λ‚˜κ°€κ³  뜨거운 여름과 ν•¨κ»˜ ν›„λ°˜μ „μ΄ μ‹œμž‘λ˜μ—ˆλ‹€. κ·Έλž˜μ„œ 빨리 μ§€λ‚˜κ°”λ‚˜…좜처 : https://m.blog.naver.com/kong6482/220584667861" κ·Έλž˜μ„œ 빨리 μ§€λ‚˜κ°”λ‚˜… 좜처 : https://m.blog.naver.com/kong6482/220584667861 μ΄μ œκΉŒμ§€λŠ” 12μ›” 말 μ¦ˆμŒμ— ν•œ ν•΄λ₯Ό 바라보고 리뷰λ₯Ό ν–ˆμ—ˆλŠ”λ° κΈ€λ˜λΌλŠ” κΈ€μ“°κΈ° λͺ¨μž„에 κ°€μž…μ„ ν•˜κ²Œ λ˜μ–΄ μƒλ°˜κΈ° 리뷰λ₯Ό 해보렀 ν•œλ‹€. κΈ€λ˜ λͺ¨μž„μ˜ 첫 μˆ™μ œκ°€ μƒλ°˜κΈ° 리뷰 ν¬μŠ€νŒ…μ΄λ‹€. 사싀 리뷰λ₯Ό μƒλ°˜κΈ°μ— ν•˜λ˜ μ—° 말에 ν•œ ν•΄ κΈ°μ€€μœΌλ‘œ ν•˜λ˜ 정해진 건 μ—†μ§€λ§Œ λ‚˜λ₯Ό λ‹€μ‹œ 바라보고 λ‹€μž‘λŠ” μ‹œκ°„μ΄ λ§Žμ„μˆ˜λ‘ 보닀 더 μ•žμœΌλ‘œ κ°€λŠ”λ° 힘이 될 κ±°λΌλŠ” λ°μ—λŠ” 이견이 μ—†λ‹€. νšŒμ‚¬ μ†μ—μ„œμ˜ λ‚˜ νšŒμ‚¬μ—μ„œλŠ” νšŒμ‚¬μΌμ΄ μ΅œμš°μ„ !좜처 : https://m.blog.naver.com/hwee__/221191852972" νšŒμ‚¬μ—μ„œλŠ” νšŒμ‚¬μΌμ΄ μ΅œμš°μ„ ! 좜처 : https://m.blog.naver.com/hwee__/221191852972 μ΅œκ·Όμ— νŒ€μž₯λ‹˜κ³Ό λ©΄λ‹΄ 쀑에 λ‚˜μ˜¨ 이야기닀. μ‹ κΈ°ν•˜κ²Œλ„ κ΅° μ‹œμ ˆ μž₯κΈ°λ₯Ό 꿈꾸던 ν•„μžλ₯Ό μ–΄μ„œ μ „μ—­ν•˜λΌκ³  κΆŒμœ ν•˜μ‹œλ˜ λŒ€λŒ€μž₯λ‹˜κ»˜ 맀일같이 λ“€μ—ˆλ˜ 이야기와 λΉ„μŠ·ν•˜λ‹€. “μ΄μ œλŠ” λ‹¨μˆœ 개발만 ν•˜κ³  κΈ°λŠ₯κ΅¬ν˜„λ§Œ ν•˜λŠ” 것이 μ•„λ‹ˆλΌ κ·Έ 이상을 ν•΄μ•Ό ν•  μ‹œκΈ°κ°€ λ‹€κ°€μ˜¨λ‹€.” “μ‚¬λžŒλ“€ 관리가 될 μˆ˜λ„ 있고 μ–΄λŠ ν•œ 뢄야에 μ „λ¬Έκ°€κ°€ λ˜μ–΄μ•Ό ν•  μˆ˜λ„ 있고, 선택은 본인의 λͺ«” 사싀 κΈ°λŠ₯ κ΅¬ν˜„μ΄μ•Ό λˆ„κ΅¬λ‚˜ λ‹€ ν•  수 μžˆλ‹€. 단지 κ²½ν—˜μ— λ”°λ₯Έ κ΅¬ν˜„μ˜ μ†λ„λ‚˜ μ•ˆμ •μ„±μ˜ 차이가 μ•„λ‹κΉŒ 생각해본닀. κ·Έλ ‡λ‹€λ©΄ κ·Έ 이상은 μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒ? 정닡은 μ—†κ² μ§€λ§Œ ν•„μžλŠ” κ·Έ 이상을 해보렀 μš°μ„  νŒ€μ— 도움이 되기 μœ„ν•΄ μ—¬λŸ¬ 가지 μžλ™ν™” 툴 듀을 λ§Œλ“  것 κ°™λ‹€. 보닀 κΈ°λŠ₯ κ°œλ°œμ— μ§‘μ€‘ν•˜κ³  λ‹¨μˆœ 반볡적인 μ—…λ¬΄λŠ” μ‹œμŠ€ν…œμ΄ ν•  수 μžˆλ„λ‘. κ·Έλ ‡κ²Œ νˆ΄λ“€μ„ λ§Œλ“€μ–΄ κ°€λ©° μƒκ°ν•˜μ§€ λͺ»ν•œ 뢀뢄듀을 배우게 되고 λ‚˜μ€‘μ— κ·Έκ±Έ 또 μ‚¬μš©ν•˜κ²Œ λ˜λŠ”, 미래의 λ‚˜λ₯Ό μœ„ν•΄ κ°•μ œλ‘œ 배우고 μžˆλŠ”λ“―ν•œ λŠλ‚Œμ΄λž„κΉŒ. μ•„, λ¬Όλ‘  νšŒμ‚¬ λ³Έμ—°μ˜ 업무가 μ΅œμš°μ„ μ΄μ§€λ§Œ 말이닀. μ–΄μ¨Œλ“  μ‹œν‚¨ 일은 μš°μ„  차질 없이 잘 ν•˜κ³  μ‹œν‚€μ§€λ„ μ•Šμ€ 일을 μ°Ύμ•„μ„œ ν•˜λ €κ³  λ…Έλ ₯ν–ˆλ˜ 것 κ°™λ‹€. νŒ€μ„ μœ„ν•΄μ„œ, 곧 λ‚˜λ₯Ό μœ„ν•΄μ„œ. 적어도 νšŒμ‚¬μ—μ„œ μžˆλŠ” μ‹œκ°„ μ†μ—μ„œλŠ” λ‹€λ₯Έ 곳에 ν•œλˆˆ μ•ˆ νŒ”κ³  νšŒμ‚¬ 업무에 μ „λ…ν•˜λ €κ³  λ…Έλ ₯ν–ˆλ˜ 것 κ°™λ‹€. μ™ΈλΆ€ ν™œλ™ λΆ€μ‘±ν•œ μ‹œκ°„μ„ μͺΌκ°œλ©΄μ„œ λ°‹μ—…μ΄λ‚˜ μ„Έλ―Έλ‚˜μ— μ°Έμ—¬ν•˜κ³€ ν–ˆμ—ˆλ‹€. 그리고 마λƒ₯ λ“£κ³ λ§Œ μ˜€μ§„ μ•Šμ•˜κ³  “행사에 μ°Έμ—¬ν•˜λ©΄ 무쑰건 질문 ν•˜λ‚˜λŠ” ν•˜μž"λΌλŠ” λ‚˜μ™€μ˜ 약속을 지킀며 μ •λ¦¬ν•œ λ‚΄μš©μ„ λΈ”λ‘œκ·Έμ— ν¬μŠ€νŒ…ν•˜κΈ°λ„ ν•˜μ˜€λ‹€. μ˜¬ν•΄ 첫 λ°œν‘œ!" μ˜¬ν•΄ 첫 λ°œν‘œ! λ””μžμ΄λ„ˆμ™€ κ°œλ°œμžκ°€ ν•¨κ»˜ν•˜λŠ” νˆ¬κ²Œλ”ν†€μ„ μ§„ν–‰ν•˜κΈ°λ„ ν–ˆμ—ˆλ‹€. νˆ¬κ²Œλ”ν†€μ€ μ•½ ν•œ 달 λ™μ•ˆ μ§„ν–‰λ˜λŠ” ν•΄μ»€ν†€μœΌλ‘œ ν•˜λ£¨ λ˜λŠ” 무박 2일 λ™μ•ˆ ν•˜λŠ” κΈ°μ‘΄ 해컀톀과 λ‹€λ₯΄λ‹€. 이 κΈ°κ°„ λ™μ•ˆ νŒ€ λ‚΄μ—μ„œ 자유둭게 일정을 μ‘°μ •ν•  수 μžˆλ‹€. 우리 νŒ€μ€ μ•½ 7주에 걸쳐 “동넀 마트 할인 정보λ₯Ό μ•Œλ €μ£ΌλŠ” μ•±” 을 λ§Œλ“€κ²Œ λ˜μ—ˆλ‹€. ν•„μžλŠ” API μ „λ°˜μ— λŒ€ν•΄ 담당을 ν•˜μ˜€κ³  μž‘μ€ λΆ€λΆ„μ΄μ—ˆμ§€λ§Œ μ›Ήμ‚¬μ΄νŠΈλ„ κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€μ–΄ λ³΄μ•˜λ‹€. 아무것도 μ—†λŠ” λ°±μ§€μƒνƒœμ—μ„œ μ‹œμž‘ν•˜λ €λ‹ˆ λ§‰λ§‰ν–ˆμ§€λ§Œ ν›„κΈ°μ—μ„œλ„ μ μ—ˆλ“―μ΄ λ‹€μ‹œ 해보라고 ν•˜λ©΄ 머릿속에 전체 μ•„ν‚€ν…μ²˜κ°€ 그림으둜 그렀질 만큼 μžμ‹ κ°μ΄ 생겼닀. 특히 정말 쒋은 νŒ€μ›λ“€κ³Ό ν•¨κ»˜ ν˜‘μ—…ν•  수 μžˆμ–΄μ„œ λ„ˆλ¬΄ μ’‹μ•˜λ‹€. 내곡 μ—°λ§ˆ ν•œ 달에 2개 이상 λΈ”λ‘œκ·Έ 글을 μž‘μ„±ν•˜λŠ” λͺ©ν‘œκ°€ μžˆμ—ˆλ‹€. 그런데 μ§€λ‚œλ‹¬μ— 이사λ₯Ό ν•˜λ‹€ λ³΄λ‹ˆ (핑계…) λͺ©ν‘œλ₯Ό 달성 ν•  μˆ˜κ°€ μ—†μ—ˆλ‹€. ν•˜μ§€λ§Œ λ‚˜λ¦„ 퀄리티가 μžˆλŠ” 글을 μ“°λ €κ³  λ…Έλ ₯ν–ˆκ³  PV도 μž‘λ…„λ³΄λ‹€ μ‘°κΈˆμ”© 였λ₯΄κ³  μžˆλŠ” 것 κ°™μ•„ 내심 기뢄이 μ’‹λ‹€. 그리고 μž‘λ…„ 말뢀터 μ‹œμž‘ν•œ ν•„μžμ˜ 첫 ν† μ΄ν”„λ‘œμ νŠΈ 인 κΈ°μˆ λΈ”λ‘œκ·Έ κ΅¬λ…μ„œλΉ„μŠ€ 에 μ΄λŸ°μ €λŸ° κΈ°λŠ₯을 μΆ”κ°€ν•˜μ˜€λ‹€. μ„€λ§ˆ 1000λͺ…이 λ„˜κ²Œ ꡬ독 ν•˜κ² μ–΄?

Springμ—μ„œ Requestλ₯Ό μš°μ•„ν•˜κ²Œ λ‘œκΉ…ν•˜κΈ°

μŠ€ν”„λ§ 기반의 μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€λ‹€ 보면 μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ”λ° 맨 μ²˜μŒμ— μœ„μΉ˜ν•˜κ³  μžˆλŠ” Controller(μ΄ν•˜ 컨트둀러)λΌλŠ” λ ˆμ΄μ–΄λ₯Ό λ§Œλ“€κ²Œ λœλ‹€. κ·ΈλŸ΄λ•Œλ©΄ μ‚¬μš©μžκ°€ μ–΄λ–€ μš”μ²­(Request)을 ν•˜μ˜€λŠ”μ§€μ— λŒ€ν•΄ 확인이 ν•„μš”ν•  수 μžˆλ‹€. λ¬Όλ‘  확인을 μ•ˆν•΄λ„ λ¬΄λ°©ν•˜μ§€λ§Œ 가급적 λ‘œκΉ…μ€ μ‹œμŠ€ν…œ λ‘œμ§μ— 영ν–₯을 주지 μ•ŠλŠ” λ²”μœ„μ—μ„œ μ΅œλŒ€ν•œ λ‹€μ–‘ν•˜κ²Œ 미리 ν•΄λ‘λŠ”κ²Œ λ‚˜μ€‘μ— μœ μ§€λ³΄μˆ˜μ‹œ νŽΈν•  수 μžˆλ‹€. (μ˜ˆμ „ 쑰직μž₯λ‹˜κ»˜μ„œ λ§μ”€ν•˜μ‹ κ²Œ 아직도 머릿속에 꽉 자리작고 μžˆλ‹€…) μ•„~μ£Ό 일반적으둜, μ»¨νŠΈλ‘€λŸ¬μ—μ„œλŠ” λ‹€μŒκ³Ό 같이 λ©”μ†Œλ“œ λ‹¨μœ„λ‘œ νŒŒλΌλ―Έν„°λ₯Ό 직접 λ‘œκΉ…ν•˜κ²Œ λœλ‹€. @Slf4j @RestController public class SampleController { @GetMapping("/test1") public String test1(@RequestParam String id) { log.info("id : {}", id); return "length : " + id.length(); } } μ΄λ ‡κ²Œ 되면 μ‚¬μš©μžκ°€ GET /test1 μ΄λΌλŠ” μš”μ²­μ„ λ³΄λ‚Όλ•Œ μ–΄λ–€ νŒŒλΌλ―Έν„°λ‘œ ν˜ΈμΆœν•˜μ˜€λŠ”μ§€μ— λŒ€ν•΄ λ‘œκΉ…μ΄ λ‚¨κ²Œ λ˜λŠ”λ° 항상 log.info("id : {}", id); κ³Ό 같이 μˆ˜λ™μœΌλ‘œ λ‘œκΉ…μ„ 남겨야 ν•˜λŠ” λΆˆνŽΈν•¨μ΄ 생긴닀. λ¬Όλ‘  κΌΌκΌΌν•˜κ²Œ λ©”μ†Œλ“œλ§ˆλ‹€ λ‘œκΉ…μ„ 적어주면 μ „ν˜€ 문제될게 μ—†μ§€λ§Œ μ΄λŸ¬ν•œ 컨트둀러 ~ λ©”μ†Œλ“œκ°€ ν•œλ‘κ°œκ°€ μ•„λ‹Œ μˆ˜μ‹­ λ˜λŠ” 수백개일 κ²½μš°μ—” κ·Έλ•Œλ§ˆλ‹€ λ‘œκΉ…μ„ μ μ–΄μ€˜μ•Ό ν•˜λŠ” λΆˆνŽΈν•¨μ΄ μžˆμ„ 수 μžˆλ‹€. λ˜ν•œ 자칫 κΉœλ°•ν•˜κ³  λ‘œκΉ…μ„ λΉΌλ¨Ήκ³  배포λ₯Ό ν•˜κ²Œ 된 경우 λͺ¨λ‹ˆν„°λ§μ‹œ λ‘œκΉ…μ„ ν•˜μ§€ μ•Šμ•„μ„œ λ‹€μ‹œ λ‘œκΉ…ν•˜κ³  배포λ₯Ό ν•˜λŠ”, 별것도 μ•„λ‹Œλ°(?) “정말 λΆˆνŽΈν•œ” 상황이 μžˆμ„ 수 μžˆλ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μ‚¬μš©μžμ˜ μš”μ²­μ„ λͺ¨λ‹ˆν„°λ§ ν•˜κΈ° μœ„ν•΄ μ»¨νŠΈλ‘€λŸ¬λ§ˆλ‹€ μ½”λ“œλ₯Ό μž‘μ„±ν•΄κ°€λ©° λ‘œκΉ…μ„ ν•˜λŠ”κ²ƒμ΄ μ•„λ‹ˆλΌ HttpServletRequestWrapper λΌλŠ” 것과 Filter, AOPλ₯Ό μ΄μš©ν•˜μ—¬ Request의 정보λ₯Ό ν•œκ³³μ—μ„œ μš°μ•„ν•˜κ²Œ λ‘œκΉ…ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄κ³ μž ν•œλ‹€. μš”κ΅¬μ‚¬ν•­ 와 κ°œλ°œν•˜μžμ•„!좜처 : https://gfycat.com/ko/brightevilaoudad" 와 κ°œλ°œν•˜μžμ•„! 좜처 : https://gfycat.com/ko/brightevilaoudad νˆ¬μš°μ‚¬κ°€ ν”λ“œλŠ” λΉ¨κ°„ μ²œμ„ 보며 λŒμ§„ν•˜λŠ” ν™©μ†Œμ²˜λŸΌ (μ“°κ³ λ³΄λ‹ˆ λ„ˆλ¬΄ TMI κ°™λ‹€….) λ‹Ήμž₯ 코딩을 μ‹œμž‘ν•˜λ©° κ°œλ°œμ„ ν•  μˆ˜λ„ μžˆμ§€λ§Œ μ •μž‘ μ›ν•˜λŠ” κΈ°λŠ₯이 무엇인지 천천히 μ •λ¦¬ν•˜κ³  λ„˜μ–΄κ°ˆ ν•„μš”κ°€ μžˆλŠ” 것 κ°™λ‹€. (어쩔땐 였히렀 ν›„μžκ°€ 더 λΉ λ₯Έ κ°œλ°œμ„ ν•˜κ²Œ λ˜λŠ”κ²ƒ κ°™λ‹€.) GET, POST λ“± λ‹€μ–‘ν•œ http method 둜 κ΅¬ν˜„λœ λͺ¨λ“  컨트둀러의 νŒŒλΌλ―Έν„°μ™€ 기타 Request 정보가 λ‘œκΉ…μ΄ λ˜μ•Ό ν•œλ‹€. 컨트둀러, λ©”μ†Œλ“œκ°€ λŠ˜μ–΄λ‚ λ•Œλ§ˆλ‹€ λ³„λ„μ˜ μ½”λ“œ μΆ”κ°€ 없이 ν•œκ³³μ—μ„œ κ³΅ν†΅μ μœΌλ‘œ λ‘œκΉ…μ΄ λ˜μ•Ό ν•œλ‹€. URL 쀑 νŠΉμ • νŒ¨ν„΄μœΌλ‘œ λ“€μ–΄μ˜€λŠ” μš”μ²­μ€ λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ λ‘œκΉ…μ„ ν•˜κ±°λ‚˜, λ‘œκΉ…μ—μ„œ μ œμ™Έν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. μ•žμ„œ λ§ν–ˆλ“― λ‹€λ₯Έ λΉ„μ§€λ‹ˆμŠ€ λ‘œμ§μ— 영ν–₯을 주지 μ•Šμ•„μ•Ό ν•œλ‹€. κ΅¬ν˜„ν•˜κΈ° - Request 의 νŒŒλΌλ―Έν„° 정리 Request 의 λͺ¨λ“  λ‘œκΉ…μ„ ν•œκ³³μ—μ„œ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄μ„œ filter(ν•„ν„°)λ₯Ό ν™œμš©ν•˜μ˜€λ‹€. ν•„ν„°λŠ” Dispatcher servlet의 μ•žλ‹¨μ— μœ„μΉ˜ν•˜κ³  있기 λ•Œλ¬Έμ— λͺ¨λ“  정보λ₯Ό 확인할 수 μžˆλŠ”λ° μš©μ΄ν•˜λ‹€. λ¬Όλ‘  인터셉터λ₯Ό ν™œμš©ν•΄μ„œλ„ 방법이 μžˆκ² μ§€λ§Œ λ³Έ ν¬μŠ€νŒ… μ—μ„œλŠ” ν•„ν„°λ₯Ό ν™œμš©ν•΄μ„œ κ΅¬ν˜„ν•˜λŠ”κ²ƒμ„ λͺ©μ μœΌλ‘œ ν•œλ‹€. (사싀 μΈν„°μ…‰ν„°λ‘œ λͺ‡λ²ˆ μ‹œλ„ν•΄λ³΄λ‹€κ°€ μ‹€νŒ¨ν•΄μ„œ…유유 ) Spring MVC Request Life Cycle좜처 : https://justforchangesake.wordpress.com/2014/05/07/spring-mvc-request-life-cycle/" Spring MVC Request Life Cycle 좜처 : https://justforchangesake.wordpress.com/2014/05/07/spring-mvc-request-life-cycle/ Filterλ₯Ό λ§Œλ“€κΈ° 전에 Filterμ—μ„œ μ‚¬μš©ν•  μ£Όμš” 핡심(?) ν΄λž˜μŠ€κ°€ ν•„μš”ν•œλ° HttpServletRequest λ₯Ό Wrapping ν•΄μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ HttpServletRequestWrapperλ₯Ό μƒμ†λ°›λŠ” 클래슀λ₯Ό λ§Œλ“€μž. Request 에 λ‹΄κ²¨μžˆλŠ” param κ³Ό body둜 μš”μ²­μ΄ λ“€μ–΄μ˜¬ 경우 body에 μžˆλŠ” λ‚΄μš©μ„ param 에 λ‹΄λŠ” λ‘œμ§μ΄λ‹€. μ£Όμš” μ„€λͺ…은 μ½”λ“œ μ•ˆμ—μ„œ μ£Όμ„μœΌλ‘œ μ„€λͺ…ν•˜κ² λ‹€. public class ReadableRequestWrapper extends HttpServletRequestWrapper { // 상속 private final Charset encoding; private byte[] rawData; private Map<String, String[]> params = new HashMap<>(); public ReadableRequestWrapper(HttpServletRequest request) { super(request); this.params.putAll(request.getParameterMap()); // μ›λž˜μ˜ νŒŒλΌλ―Έν„°λ₯Ό μ €μž₯ String charEncoding = request.getCharacterEncoding(); // 인코딩 μ„€μ • this.encoding = StringUtils.isBlank(charEncoding) ? StandardCharsets.UTF_8 : Charset.forName(charEncoding); try { InputStream is = request.getInputStream(); this.rawData = IOUtils.toByteArray(is); // InputStream 을 λ³„λ„λ‘œ μ €μž₯ν•œ λ‹€μŒ getReader() μ—μ„œ μƒˆ 슀트림으둜 생성 // body νŒŒμ‹± String collect = this.getReader().lines().collect(Collectors.joining(System.lineSeparator())); if (StringUtils.isEmpty(collect)) { // body κ°€ μ—†μ„κ²½μš° λ‘œκΉ… μ œμ™Έ return; } if (request.getContentType() != null && request.

D.light νˆ¬κ²Œλ”ν†€ μ°Έκ°€ν›„κΈ°

νšŒμ‚¬μΌμ„ ν•˜λ‹€ 보면 μ‹œν‚€λŠ” λŒ€λ‘œ ν˜Ήμ€ νŒ€μ˜ λͺ©ν‘œμ— λΆ€ν•©ν•˜κΈ° μœ„ν•΄ μ–΄μ©” 수 없이 ν•΄μ•Ό ν•˜λŠ” 일을 ν•˜κ²Œ λœλ‹€. κ·ΈλŸ¬ν•œ 일이 재미있고 결과물에 λŒ€ν•œ λ§Œμ‘±λ„κ°€ 100% 라면 λ‹€ν–‰μ΄μ§€λ§Œ κ°„ν˜Ή μž¬λ―Έλ„ μ—†κ³  μ‹œμΌœμ„œ ν•˜λŠ” 일은 밀을 κΌ¬λ°• μƒˆ κ°€λ©΄μ„œ 완성을 해도 썩 κ·Έλ ‡κ²Œ λ§Œμ‘±μŠ€λŸ½μ§€ λͺ»ν•œ κ²½μš°κ°€ λŒ€λΆ€λΆ„μΈ 것 κ°™λ‹€.(λ¬Όλ‘  νšŒμ‚¬μΌμ—μ„œ μžμ‹ λ§Œμ˜ μΈμ‚¬μ΄νŠΈλ₯Ό μ°ΎλŠ”λ‹€λ©΄ κΈˆμƒμ²¨ν™”κ² μ§€λ§Œ… + 맀번 νšŒμ‚¬μΌμ΄ μž¬λ―Έμ—†κ³  ν•˜κΈ° 싫은건 μ•„λ‹˜) μ–Έμ œλΆ€ν„°μΈμ§€ ν•„μžλ„ μ΄λŸ¬ν•œ 뢀뢄에 κ°ˆμ¦μ„ 느끼며 νšŒμ‚¬μ™€λŠ” λ³„λ„λ‘œ 무언가λ₯Ό λ§Œλ“€μ–΄ 보고 싢은 마음이 무럭무럭 생겨날 즈음 facebook νƒ€μž„λΌμΈμ—μ„œ κ°œλ°œμžμ™€ λ””μžμ΄λ„ˆκ°€ μ•½ 7μ£Όκ°„ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λŠ” D.light νˆ¬κ²Œλ”ν†€ μ΄λΌλŠ” 행사가 μžˆλ‹€λŠ” 것을 λ°œκ²¬ν•˜κ³  λ‚˜λ¦„ μ •μ„±μŠ€λ ˆ μ§€μ›μ„œλ₯Ό μž‘μ„± ν›„ 합격 메일을 λ°›κ²Œ λœλ‹€. (GDG Facebook ν•΄λ‹Ή κ²Œμ‹œκΈ€) 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” ν•΄μ»€ν†€κ³ΌλŠ” 살짝 성격이 λ‹€λ₯Έ D.light νˆ¬κ²Œλ”ν†€μ„ μ§„ν–‰ν•˜λ©΄μ„œ 느꼈던 λΆ€λΆ„λ“€κ³Ό μ§„ν–‰ν•œ 결과물에 λŒ€ν•΄ κ°„λž΅νžˆ 리뷰λ₯Ό 해보며 정말 κΈ‰ν–‰μ²˜λŸΌ μ§€λ‚˜κ°„ μ•½ 7주간을 돌이켜 λ³΄λŠ” μ‹œκ°„μ„ κ°–κ³ μž ν•œλ‹€. νŒ€ λΉŒλ”© λˆˆλ„ λͺ»λ§ˆμ£ΌμΉ  μ •λ„λ‘œ μ–΄μƒ‰ν•œ 첫날Team. 그팽" λˆˆλ„ λͺ»λ§ˆμ£ΌμΉ  μ •λ„λ‘œ μ–΄μƒ‰ν•œ 첫날 Team. 그팽 총 6개 νŒ€ 쀑에 ν•„μžλŠ” μ—¬μž λ””μžμ΄λ„ˆ 두 λΆ„, λ‚¨μž μ•ˆλ“œλ‘œμ΄λ“œ 개발자 두 뢄을 ν¬ν•¨ν•œ νŒ€μ— μ†ν•˜κ²Œ λ˜μ—ˆλ‹€. 5λͺ… 쀑 해컀톀 μ°Έμ—¬ κ²½ν—˜μ΄ μžˆλ‹€λŠ” 이유만으둜 μ—¬μž λ””μžμ΄λ„ˆ λΆ„κ»˜μ„œ νŒ€μž₯이 λ˜μ‹œκ³ , 7μ£ΌλΌλŠ” μ‹œκ°„μ΄ 정말 κΈ‰ν•˜κ²Œ μ§€λ‚˜κ°ˆ 것 κ°™λ‹€λŠ” 얡지(?) 이유λ₯Ό λ“€λ¨Ήμ—¬ κ·ΈνŒ½μ΄λΌλŠ” νŒ€ 이름이 μ •ν•΄μ‘Œλ‹€. κ·Έλ ‡κ²Œ “μš°λ¦¬κ°€ 정말 무엇을 λ§Œλ“€ 수 μžˆμ„κΉŒ?” ν•˜λŠ” μ˜κ΅¬μ‹¬ 속에 ν”„λ‘œμ νŠΈκ°€ μ‹œμž‘μ΄ λ˜μ—ˆλ‹€. ν”„λ‘œμ νŠΈ 진행 μ „λ°˜ μ‹ κΈ°ν•˜κ²Œλ„ 우리 5λͺ…은 각각 μ‚¬λŠ” 지역이 μ „λΆ€ λ‹¬λžλ‹€. (심지어 ν•œ 뢄은 맀주 μ € 멀리 좩청남도 μ²œμ•ˆμ—μ„œ μ˜¬λΌμ˜€μ…”μ•Ό ν•˜λŠ” 수고λ₯Ό γ… γ… ) 맀 μ£Όλ§λ§ˆλ‹€ μ˜€ν”„λΌμΈμœΌλ‘œ λ§Œλ‚˜μ„œ 회의λ₯Ό μ§„ν–‰ν–ˆλ‹€. κ·Έλž˜μ•Ό κΈΈλ‹€λ©΄ κΈΈκ³  짧닀면 짧은 7μ£Ό μ•ˆμ— 완성도 높은 결과물을 λ§Œλ“€ 수 μžˆμ„ 것 κ°™μ•„μ„œμ˜€λ‹€. ν”„λ‘œμ νŠΈμ˜ 주제λ₯Ό μ •ν•˜λŠ” 아이디어 νšŒμ˜μ—μ„œ 정해진 우리의 λͺ©ν‘œλŠ” “동넀 마트 할인 정보λ₯Ό μ•Œλ €μ£ΌλŠ” μ•±"을 λ§Œλ“€κΈ°λ‘œ ν•˜μ˜€λ‹€. μ‹œκ°„κ°€λŠ”μ€„ λͺ°λžλ˜ μ•„μ΄λ°μ΄μ…˜ 회의" μ‹œκ°„κ°€λŠ”μ€„ λͺ°λžλ˜ μ•„μ΄λ°μ΄μ…˜ 회의 νŒ€μ›Œν¬κ°€ μ€‘μš”ν•œ νˆ¬κ²Œλ”ν†€ μž„μ—λ„ λΆˆκ΅¬ν•˜κ³  μ—¬λŠ 천재 λ””μžμ΄λ„ˆ, 천재 개발자처럼 일당백 μŠ€νƒ€μΌλ‘œ λšλ”± λ§Œλ“œλŠ” 그런 ν”„λ‘œμ νŠΈμ˜ 진행 방식은 ν”Όν•˜λ €κ³  우리 λͺ¨λ‘κ°€ λ…Έλ ₯ν•˜μ˜€λ‹€. λ˜λ„λ‘μ΄λ©΄ μ΄λ ‡κ²Œ λͺ¨μΈ λ‹€μ„― λͺ…이 ν•œλ§ˆμŒ ν•œλœ»μœΌλ‘œ κ°μžκ°€ μƒκ°ν•˜λŠ” 크기와 양은 λ‹€λ₯΄κ² μ§€λ§Œ 이 ν”„λ‘œμ νŠΈλ₯Ό 톡해 무엇이라도 배울 수 μžˆμ—ˆμœΌλ©΄ ν–ˆλ‹€. λ””μžμ΄λ„ˆ 뢄듀은 μ„œλ‘œ λ””μžμΈν•˜μ‹  μ‹œμ•ˆμ— λŒ€ν•΄ 곡유λ₯Ό ν•˜λ©΄μ„œ κ°œμ„ ν•΄ λ‚˜κ°€λŠ” λͺ¨μŠ΅κ³Ό, μ•ˆλ“œλ‘œμ΄λ“œ 개발자 두뢄은 (거의 맀일) λ°€λ§ˆλ‹€ μ„œλ‘œ μŠ¬λž™μ—μ„œ 개발 방법둠에 λŒ€ν•΄ μŠ€ν„°λ””λ₯Ό ν•˜λŠ” λͺ¨μŠ΅μ΄ 보기 λ„ˆλ¬΄ 보기 μ’‹μ•˜λ‹€. λ¬Όλ‘  ν•„μžλ„ 아무것도 μ—†λŠ” ν™˜κ²½μ—μ„œ λ°±μ—”λ“œ μ„œλ²„λ₯Ό κ΅¬μΆ•ν•˜κ³  APIλ₯Ό λ§Œλ“œλŠ” κ³Όμ • μ†μ—μ„œ 정말 λ§Žμ€κ²ƒμ„ 배울 수 μžˆμ—ˆλ‹€. κ·Έλ ‡κ²Œ μ‹œκ°„μ΄ 흘러 λ§ˆμ§€λ§‰ λ°œν‘œν•˜λŠ” μ „λ‚ μ—” νŒ€μ› λͺ‡ λΆ„κ³Ό ν•¨κ»˜ κΌ¬λ°• 밀을 μƒˆμš°λ©° ν”„λ‘œμ νŠΈ 결과물의 완성도λ₯Ό λ†’μ΄λŠ”λ° λ…Έλ ₯ν•˜μ˜€κ³  ν•„μž 개인적으둜 μ•„μ£Ό μ„±κ³΅μ μœΌλ‘œ ν”„λ‘œμ νŠΈλ₯Ό λ§ˆλ¬΄λ¦¬ν•  수 μžˆμ—ˆλ‹€. 개발 진행 μ•ˆλ“œλ‘œμ΄λ“œ κ°œλ°œμžλΆ„λ“€μ€ μ½”ν‹€λ¦° 기반으둜 κ°œλ°œμ„ ν•˜μ˜€λ‹€. μ—¬λŸ¬ λ””μžμΈ νŒ¨ν„΄κ³Ό λ‹€μ–‘ν•œ κΈ°μˆ λ“€μ„ μ‚¬μš©ν•˜μ˜€λ‹€κ³  λ“€μ—ˆλŠ”λ° ν•„μžλŠ” μ•„μ‰½κ²Œλ„ λ°±μ—”λ“œ κ°œλ°œμ„ ν•˜λ‹€ λ³΄λ‹ˆ μ „λΆ€λ₯Ό μ΄ν•΄ν•˜μ§€λŠ” λͺ»ν•˜μ˜€λ‹€. μ˜ˆμ „μ— 토이 ν”„λ‘œμ νŠΈλ₯Ό 파이썬 기반으둜 ν•΄λ³Έ κ²½ν—˜μ΄ μžˆμ–΄μ„œ Flask λ˜λŠ” Django 기반으둜 API μ„œλ²„λ₯Ό κ΅¬μΆ•ν•΄λ³ΌκΉŒ ν•˜κ³  κ³ λ―Όν•˜μ˜€λ‹€. ν•˜μ§€λ§Œ (Spring Boot κΈ°λ°˜μœΌλ‘œλ„ 해보고 μ‹Άμ—ˆκ³ ) νŒŒμ΄μ¬λ³΄λ‹€λŠ” μžλ°” 기반으둜 λ‹€μ–‘ν•œ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μš”κ΅¬ 사항을 κ°œλ°œν•˜λŠ”λ° 쑰금 더 λŠ₯μˆ™ν•  것 κ°™μ•„μ„œ Spring Boot 기반으둜 개발 ν™˜κ²½μ„ κ΅¬μ„±ν•˜μ˜€λ‹€. μ„œλ²„λŠ” AWS ν”„λ¦¬ν‹°μ–΄μ˜ EC2λ₯Ό λ°œκΈ‰λ°›κ³  DB λ˜ν•œ AWSμ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” RDS(mysql)을 λ°œκΈ‰λ°›μ•„ κ΅¬μ„±ν•˜μ˜€λ‹€. 그리고 DNSλŠ” μ˜ˆμ „μ— 무료 도메인을 μ°Ύλ‹€κ°€ μ•Œκ²Œ 된 http://mooo.com/ λΌλŠ” μ„œλΉ„μŠ€μ—μ„œ λ°œκΈ‰λ°›μ•„ μ—°κ²°ν•˜μ˜€κ³ , ν”„λ‘œμ νŠΈ κΈ°λŠ₯ 쀑에 μ„œλ²„μ—μ„œ μ•±μœΌλ‘œ ν‘Έμ‹œλ₯Ό ν•˜λŠ” κΈ°λŠ₯이 μžˆμ—ˆλŠ”λ° Firebaseλ₯Ό ν™œμš©ν•΄μ„œ ꡬ성할 수 μžˆμ—ˆλ‹€. μ‚¬μš©ν•œ κΈ°μˆ λ“€" μ‚¬μš©ν•œ κΈ°μˆ λ“€ Entity Relationship Diagram (ERD) λŠ” 무료둜 μΈν„°λ„·μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” 툴이 μžˆλŠ”μ§€ μ°Ύλ‹€λ³΄λ‹ˆ http://aquerytool.

μžλ°”, μ„±λŠ₯, λͺ¨λ‹ˆν„°λ§ ν…Œν¬μ„Έλ―Έλ‚˜ 정리 및 ν›„κΈ° (by μš°μ•„ν•œ ν˜•μ œλ“€)

μ‹€λ¬΄μ—μ„œ μžλ°” 기반으둜 κ°œλ°œμ„ ν•˜κ³  μ„œλΉ„μŠ€λ₯Ό μš΄μ˜μ„ ν•˜λ‹€λ³΄λ©΄ μ²˜μŒμ—” μ•„λ¬΄λŸ° λ¬Έμ œκ°€ μ—†λ‹€κ°€ μ‚¬μš©μžκ°€ λͺ°λ¦¬λŠ” λ“± μ΄λ²€νŠΈμ„±μœΌλ‘œ νŠΈλž˜ν”½μ΄ λ§Žμ•„μ§ˆ 경우 κΌ­ λ¬Έμ œκ°€ 생기기 λ§ˆλ ¨μ΄λ‹€. κ·ΈλŸ΄λ•Œλ©΄ λ’€λŠ¦κ²Œ λΆ€λž΄λΆ€λž΄ 원인을 μ°Ύκ³  κ°œμ„ ν•˜κΈ° λ°”λΉ μ§€κ²Œ λœλ‹€. (μ•„λ§ˆ μœ—λΆ„λ“€μ—κ²Œ ν˜Όλ‚˜λ©΄μ„œ?γ… γ… ) ν‰μ†Œμ— 이런 μ„±λŠ₯문제λ₯Ό κ°œμ„ ν•˜κ³  미리 λͺ¨λ‹ˆν„°λ§ ν• μˆ˜μžˆλŠ” 뢀뢄에 λŒ€ν•΄ 관심을 κ°–κ³  μžˆμ—ˆλ˜ μ°°λ‚˜, μš°μ•„ν•œ ν˜•μ œλ“€μ—μ„œ 5μ›” μš°μ•„ν•œ ν…Œν¬ μ„Έλ―Έλ‚˜λ₯Ό ν•œλ‹€κΈ°μ— λΆ€λž΄λΆ€λž΄ μž₯문의 κΈ€λ‘œ 신청을 ν•˜μ˜€κ³  운이 μ’‹μ•„ 당첨이 λ˜μ—ˆλ‹€. ν•œμ°½ νšŒμ‚¬μ—μ„œ μƒˆλ‘œμš΄ μ„œλΉ„μŠ€ μΆœμ‹œ, 그리고 μž μ„ 쀄여가며 λ³„λ„λ‘œ μ§„ν–‰ν•˜κ³  있던 ν† μ΄ν”„λ‘œμ νŠΈ λ“± μ—¬λŸ¬κ°€μ§€λ‘œ λ°”μœ μ‹œκΈ°μ˜€μ§€λ§Œ 특히 μ˜ˆμ „λΆ€ν„° λ΅™κ³ μ‹Άλ˜ μ΄μƒλ―Όλ‹˜κ»˜μ„œ 직접 κ°•μ˜λ₯Ό 해주신닀기에 ν”Όκ³€ν•œ 심신을 이끌고 μ„Έλ―Έλ‚˜μ— μ°Έμ„ν•˜μ˜€κ³  κ·Έ ν›„κΈ°λ₯Ό μ μ–΄λ³΄κ³ μž ν•œλ‹€. λ‘λ ˆμ΄λ‘œ λ§Œλ“œμ‹  λ°œν‘œμžλ£Œλ₯Ό κ³΅μœ ν•΄ μ£Όμ…¨μ§€λ§Œ μ €μž‘κΆŒ λ¬Έμ œλ„ 있고 ν•΄μ„œ ν•„μžκΈ°μ€€μ—μ„œ μ΄ν•΄ν•œ 뢀뢄에 λŒ€ν•΄μ„œλ§Œ κ³΅μœ ν•˜κ³ μž ν•œλ‹€. λ”λΆˆμ–΄ κ·Έλƒ₯ λ“£κ³  μ•΅λ¬΄μƒˆμ²˜λŸΌ λ°œν‘œλ‚΄μš© κ·ΈλŒ€λ‘œλ₯Ό κ³΅μœ ν•˜λŠ”κ±΄ μ˜λ―Έκ°€ μ—†λ‹€κ³  μƒκ°λ˜μ–΄… ν¬μŠ€ν„°λ§Œ 봐도 λ²Œμ¨λΆ€ν„° κ°€μŠ΄μ΄ λ›΄λ‹€(?)." ν¬μŠ€ν„°λ§Œ 봐도 λ²Œμ¨λΆ€ν„° κ°€μŠ΄μ΄ λ›΄λ‹€(?). μ„±λŠ₯ κ΅¬κΈ€μ—μ„œ μž‘μ„±ν•œ μ„±λŠ₯이 μ€‘μš”ν•œ 이유 λΌλŠ” 아티클을 κ³΅μœ ν•΄ μ£Όμ…¨λ‹€. (μ‹œκ°„μ΄ λœλ‹€λ©΄ ν•œλ²ˆ 읽어보길 κ°•μΆ”, 무렀 ν•œκΈ€!) μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ„±λŠ₯은 μ‚¬μš©μžμ˜ 증가, μ΄νƒˆμœ¨, 응닡속도에 영ν–₯이 있고 μ΄λŠ” κ²°κ΅­ μΆ”κ΅¬ν•˜λŠ” κ°€μΉ˜(이λ₯Ό ν…Œλ©΄ 수읡)에 μ§λ©΄ν•œλ‹€κ³  ν•œλ‹€. μ‚¬μš©μžλŠ” μ–΄λŠ κ΄€μ μ—μ„œ λ°”λΌλ³΄λŠ”κ°€μ— 따라 달라지고 각 관점에 따라 μ„±λŠ₯을 챙겨야 ν•˜λŠ” 뢀뢄이 달라진닀. μˆ˜κ°•μ‹ μ²­μ„ ν•˜λŠ” μ‹œμ μ—μ„œμ˜ μ‚¬μš©μžμ™€ λ‰΄μŠ€ νŽ˜μ΄μ§€λ₯Ό μ½λŠ” μ‹œμ μ—μ„œμ˜ μ‚¬μš©μžλŠ” 각 성격이 μ—„μ—°νžˆ λ‹€λ₯Έκ²ƒμ²˜λŸΌ. μ‹œμŠ€ν…œ κ΄€λ¦¬μž λ“±λ‘λœ / λ“±λ‘λ˜μ§€ μ•Šμ€ μ‚¬μš©μž μ„œλ²„ 관점 둜그인된 / 둜그인 ν•˜μ§€ μ•Šμ€ μ‚¬μš©μž μ„±λŠ₯ ν…ŒμŠ€ν„° 관점 Active User μ„œλ²„μ— λΆ€ν•˜λ₯Ό μ£ΌλŠ” μ‚¬μš©μž λ©”λ‰΄λ‚˜ 링크λ₯Ό λˆ„λ₯΄κ³  κ²°κ³Όκ°€ λ‚˜μ˜€κΈ°λ₯Ό κΈ°λ‹€λ¦¬λŠ” μ‚¬μš©μž μ„±λŠ₯ν…ŒμŠ€νŠΈμ‹œ Vuser와 거의 동일 ( Vuser : κ°€μƒμ‚¬μš©μž(virtual user) ) Concurrent user μ„œλ²„μ— λΆ€ν•˜λ₯Ό μ£Όκ³  μžˆκ±°λ‚˜, 쀄 κ°€λŠ₯성이 λ§€μš°λ†’μ€ μ„œλΉ„μŠ€μ— 접속쀑인 μ‚¬μš©μž μ›Ή νŽ˜μ΄μ§€λ₯Ό λ„μ›Œλ†“μ€ μ‚¬μš©μž TPS(Transaction Per Seconds)λŠ” μ΄ˆλ‹Ή μ–Όλ§ˆλ‚˜ λ§Žμ€ μš”μ²­μ„ μ²˜λ¦¬ν• μˆ˜ μžˆλŠ”μ§€μ— λŒ€ν•œ μ‹œμŠ€ν…œμ˜ μ ˆλŒ€μ μΈ 수치둜 λ³Όμˆ˜μžˆλ‹€. (κ°œλ°œμžλŠ” μ–΄λŠμƒν™©μ—μ„œλ“ μ§€ λŒ€μΆ© 감으둜 이야기 ν•˜μ§€λ§κ³  μ •ν™•ν•œ 수치둜 이야기 ν•΄μ•Όν•œλ‹€λŠ” 뼈λ₯Ό λ•Œλ¦¬λŠ” μ‘°μ–Έκ³Ό ν•¨κ»˜…) TPSλŠ” Scale out/up을 톡해 μ¦κ°€μ‹œν‚¬μˆ˜ μžˆμ§€λ§Œ Response Time 은 λΆˆκ°€λŠ₯ν•˜λ‹€. λ¬Όλ‘  μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ νŠœλ‹ν•˜λ©΄ 두 수치 λͺ¨λ‘ κ°œμ„ μ΄ κ°€λŠ₯ν•˜λ‹€. μ΄λŸ¬ν•œ TPS와 Response Time의 μ΅œλŒ€μΉ˜λŠ” μΆœμ‹œμ „μ— λ°˜λ“œμ‹œ ν…ŒμŠ€νŠΈλ₯Ό 톡해 μ•Œκ³  μžˆμ–΄μ•Ό μ΄μŠˆλ°œμƒμ‹œ λŒ€μ‘ν•˜λŠ”λ° μœ μš©ν•˜λ‹€. Bottleneck 즉 병λͺ©μ€ μž₯λΉ„, μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜, μ €μž₯μ†Œ, μ„€μ • λ“± λ‹€μ–‘ν•œ μƒν™©μ—μ„œ λ°œμƒν• μˆ˜ μžˆλ‹€. 그쀑에 “μ•„μ£Ό 일반적"으둜 κ°€μž₯ 병λͺ©μ΄ 많이 λ°œμƒν•˜λŠ” ꡬ간은 DB이고 κ·Έ λ‹€μŒμœΌλ‘œ ν΄λΌμ΄μ–ΈνŠΈ(Web page, App), Network이 μžˆμ„ 수 μžˆλ‹€. 결둠은 Performance engineering is “Composite Art” of IT λΌλŠ” ν•˜λ‚˜μ˜ λ¬Έμž₯으둜 정리λ₯Ό ν•΄μ£Όμ…¨λ‹€. 아무리 이쁜 λ””μžμΈκ³Ό μ–΄λ ΅κ³  λ³΅μž‘ν•œ κΈ°λŠ₯이 μžˆμ„μ§€λΌλ„ μ„±λŠ₯이 λ’·λ°›μΉ¨ μ•ˆλœλ‹€λ©΄ λŒ€μš©λŸ‰ νŠΈλž˜ν”½ μƒν™©μ—μ„œλŠ” λ¬΄μ˜λ―Έν•΄μ§€κΈ° λ•Œλ¬Έμ΄λΌκ³  μƒκ°ν•œλ‹€. μžλ°” μžλ°”μ˜ 역사에 λŒ€ν•΄ μ„€λͺ…ν•΄ μ£Όμ…¨λ‹€. ( 역사에 λŒ€ν•œ 보닀 μžμ„Έν•œ μ„€λͺ…은 https://www.whatap.io/blog/12/ μ°Έκ³  ) μ–Έμ œλΆ€ν„°μΈκ°€ JDK λΌμ΄μ„ΌμŠ€ μ΄μŠˆκ°€ λ§Žμ•˜μ—ˆλŠ”λ° μ‹€λ¬΄μ—μ„œ κ°œλ°œν•˜λŠ” μž…μž₯μ—μ„œλŠ” java 8 μ—μ„œλŠ” λ¬Έμ œκ°€ μ•ˆλ˜κ³  java 11λΆ€ν„° λΌμ΄μ„ΌμŠ€ λ¬Έμ œκ°€ λ³΅μž‘ν•˜κ²Œ μƒκΈΈμˆ˜ μžˆλ‹€κ³  ν•œλ‹€. 이뢀뢄은 κ³΅μ‹λ¬Έμ„œ(?)λ₯Ό μ°Ύμ•„λ³΄λŠ”κ²Œ 쒋을듯 ν•˜λ‹€. (개인 λ˜λŠ” νšŒμ‚¬μ—μ„œ μ‚¬μš©ν•  경우 상황에 따라 법적 μ΄μŠˆκ°€ μƒκΈΈμˆ˜λ„, μ•ˆμƒκΈΈμˆ˜λ„ μžˆλŠ” λ³΅μž‘ν•œ λ¬Έμ œκ°€ μžˆμ–΄λ³΄μ—¬μ„œ… ν•„μžλ„ μ œλŒ€λ‘œ μ΄ν•΄ν•˜μ§€λŠ” λͺ»ν–ˆλ‹€γ… ) 그리고 각 μžλ°” λ²„μ „μ—μ„œ λ°œν‘œν•œ μƒˆλ‘œμš΄ κΈ°λŠ₯에 λŒ€ν•΄ μ„€λͺ…ν•΄μ£Όμ…¨λ‹€. Java 8 lambda, stream, default method, LocalDate / LocalTime μΆ”κ°€ stream κ³Ό foreach 의 μ„±λŠ₯은 거의 차이 μ—†μŒ (였히렀 가독성이 λ‚˜λΉ μ§ˆμˆ˜λ„ μžˆλ‹€.) ParallelStream 은 ν•΄λ‹Ή μž₯λΉ„μ˜ cpu 개수만큼 μŠ€λ ˆλ“œ 풀을 λ§Œλ“€μ–΄ μ‚¬μš© (였히렀 독이 될수 μžˆμœΌλ‹ˆ 잘 μ•Œμ•„λ³΄κ³  μ‚¬μš©ν• κ²ƒ) Java 9 Compact Strings : char[] > byte[] G1 default GC : https://www.

spring-bootμ—μ„œ mybatis둜 mysql μ—°λ™ν•˜κΈ°

μ‹€λ¬΄μ—μ„œ κ°œλ°œμ„ ν•˜λ‹€λ³΄λ©΄ κ³Όκ±° λˆ„κ΅°κ°€ 잘 ꡬ성해 놓은 λ°₯상(legacy)에 μˆŸκ°€λ½λ§Œ μ–ΉλŠ” λŠλ‚ŒμœΌλ‘œ 둜직 κ΅¬ν˜„λ§Œ ν• λ•Œκ°€ μžˆλ‹€. κ·ΈλŸ¬λ‹€λ³΄λ©΄ 각쒅 λ ˆμ΄μ–΄κ°€ μ–΄λ–»κ²Œ ꡬ성(μ„€μ •)λ˜μ–΄μžˆλŠ”μ§€λ„ λͺ¨λ₯΄κ³  κ°„ν˜Ή μ„€μ •μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•˜λ©΄ “μ•„ λ‚΄κ°€ 이것도 λͺ¨λ₯΄κ³  μ΄μ œκΉŒμ§€ κ°œλ°œμ„ ν•΄μ™”λ‚˜” ν•˜λŠ” 자괴감이 λ“€λ©° λͺ‡μ‹œκ°„을 μ‚½μ§ˆν•˜λŠ” κ²½μš°κ°€ μžˆλ‹€. 그게 μ§€κΈˆμ˜ ν•„μžμΈκ²ƒ κ°™λ‹€. (λˆ™λ¬Ό…) 좜처 : http://blog.naver.com/PostView.nhn?blogId=ondo_h&logNo=221437452142" 좜처 : http://blog.naver.com/PostView.nhn?blogId=ondo_h&logNo=221437452142 μ‚¬μ΄λ“œ ν”„λ‘œμ νŠΈ μ΄ˆκΈ°μ…‹νŒ…μ„ ν•˜λ©° 호기둭게 spring boot μ΅œμ‹ λ²„μ „μ—μ„œ dbλ₯Ό μ—°λ™ν•˜λ € ν–ˆλŠ”λ° 막상 μ™„μ „ λ°”λ‹₯λΆ€ν„° ν•΄λ³Έ κ²½ν—˜μ΄ μ λ‹€λ³΄λ‹ˆ (spring boot 2 λ²„μ „μ—μ„œλŠ” λ”μš±λ”…) μ–΄λ””μ„œλΆ€ν„° 뭘 섀정을 해야할지… 그리고 μ΄λŸ΄λ•Œ λ³΄λŠ” λ„νλ¨ΌνŠΈλ₯Ό 봐도 잘 이해가 μ•ˆλ˜μ–΄ μ‚½μ§ˆμ„ ν•΄κ°€λ©° λ‹Ήν™©ν•˜κΈ° μΌμ‘€μ˜€λ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μ•„λž˜μ™€ 같은 ꡬ성을 ν•˜λŠ”λ° λͺ©ν‘œλ₯Ό λ‘κ³ μž ν•œλ‹€. Spring Boot 2 ν”„λ‘œμ νŠΈλ₯Ό 처음 λ§Œλ“€κ³  mybatis λ₯Ό μ‚¬μš©ν•΄μ„œ mysql 을 μ—°λ™ν•˜λŠ”κ²ƒ (AWS 의 RDSλ₯Ό μ‚¬μš©, μΆ”ν›„ RDSμ‚¬μš©λ²•μ— λŒ€ν•΄ λΈ”λ‘œκΉ… μ˜ˆμ •) μœ„μ™€ 같은 상황을 처음 μ ‘ν•˜λŠ” λΆ„λ“€κ»˜ 도움이 λ˜μ—ˆμœΌλ©΄ ν•˜λŠ” λ°”λž¨μœΌλ‘œ μ§§κ²Œλ‚˜λ§ˆ ν•„μžμ˜ μ‚½μ§ˆκΈ°λ₯Ό μ—¬ν–‰ν•΄λ³΄μž. Spring boot 2 ν”„λ‘œμ νŠΈ λ§Œλ“€κΈ° ν•„μžλŠ” IntelliJλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ–΄μ„œ μƒˆλ‘œ ν”„λ‘œμ νŠΈλ₯Ό λ§Œλ“€λ €κ³  ν• λ•Œ 클릭 λͺ‡λ²ˆλ§ŒμœΌλ‘œ dependency μ„€μ •κΉŒμ§€ λ‹€ ν•΄μ£ΌκΈ° λ•Œλ¬Έμ— νŽΈν•˜κ³  μ’‹μ•˜λ‹€. 혹 μ΄ν΄λ¦½μŠ€λ‚˜ λ‹€λ₯Έ IDEλ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€λ©΄ https://start.spring.io/ 을 μ°Έκ³ ν•˜λ©΄ 도움이 될것같닀. μ—¬κΈ°μ„œλ„ 클릭 λͺ‡λ²ˆμœΌλ‘œ IntelliJ μ—μ„œ ν•΄μ£ΌλŠ” κ²ƒμ²˜λŸΌ λ‚΄κ°€ μ‚¬μš©ν•  λͺ¨λ“ˆμ„ μ„ νƒν•˜κ³  generate λ₯Ό λˆ„λ₯΄λ©΄ ν”„λ‘œμ νŠΈκ°€ μƒμ„±λ˜μ–΄ λ‹€μš΄λ‘œλ“œ 받아진닀. (μ°Έ 쒋은 세상…) μš°μ„  File β†’ New β†’ Project λ₯Ό λˆŒλŸ¬μ„œ μ•„λž˜ 창을 μ—΄μ–΄λ³΄μž. 그리고 λ­”κ°€ λ‹€ 해쀄것 같은 (κ°œλ°œλ„ ν•΄μ£Όλ©΄ μ•ˆλ˜λ‚˜…) Spring Initializr을 선택후 μ•„λž˜μ™€ 같은 섀정을 적어쀀 λ’€ λ‹€μŒμ„ λˆŒλŸ¬μ€€λ‹€. μ‚¬μš©ν•  λͺ¨λ“ˆμ„ μ„ νƒν•΄μ£Όμž. ν•„μžλŠ” 이것저것(?)을 λ„μ™€μ£ΌλŠ” lombokκ³Ό Mybatis, MySQL을 μ„ νƒν•˜κ³  ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•˜μ˜€λ‹€. 그러면 이쁜(?) pom.xml κ³Ό ν•¨κ»˜ λ‹Ήμž₯ κ°œλ°œμ„ μ‹œμž‘ν•  수 μžˆλŠ” ν™˜κ²½μ΄ μ œκ³΅λœλ‹€. <dependencies> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> μš°μ„  μ—¬κΈ°κΉŒμ§€ 잘 λ˜μ—ˆλŠ”μ œ 확인해보기 μœ„ν•΄ Controller 에 ν˜„μž¬μ‹œκ°„μ„ 좜λ ₯ν•˜λŠ”κ±Έ λ§Œλ“€μ–΄ 보고 @RestController public class ApiController { @GetMapping(path = "/helloWorld") public String helloWorld() { return LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } } 톰켓을 싀행해보면 μ •μƒμ μœΌλ‘œ 접속과 좜λ ₯이 λ˜λŠ”κ²ƒμ„ 확인할 수 μžˆλ‹€. MySQL μ—°λ™ν•˜κΈ° ν•„μžκ°€ ν—ˆλ‘₯지λ‘₯ ν–ˆλ˜μ  쀑 ν•˜λ‚˜λŠ” MyBatis와 MySQL을 λ™μ‹œμ— μ—°λ™ν•˜λ €κ³  ν•˜λ‹€λ³΄λ‹ˆ λ¬Έμ œκ°€ λ°œμƒν•΄λ„ μ–΄λ””μ„œμ˜ λ¬Έμ œμΈμ§€λ₯Ό μ œλŒ€λ‘œ νŒŒμ•…ν•˜μ§€ λͺ»ν•˜κ³  μ‚½μ§ˆν–ˆλ‹€λŠ” 점이닀. μ—¬κΈ°μ„œ μ •ν™•νžˆ 짚고 λ„˜μ–΄κ°€λ©΄ μš°μ„  데이터λ₯Ό μ—°κ²°ν•΄μ£ΌλŠ” ORM인 MyBatisλ₯Ό μ…‹νŒ…ν•΄μ€€ λ‹€μŒ MySQL을 μ—°λ™ν•΄μ£ΌλŠ” μ‹μœΌλ‘œ λΆ„λ¦¬ν•΄μ„œ 섀정을 ν•˜λ©΄ ν–‡κ°ˆλ¦¬μ§€ μ•Šκ³  (λŒμ•„κ°€μ§€ μ•Šκ³ ) 보닀 λΉ λ₯΄κ²Œ 섀정이 κ°€λŠ₯할것 κ°™λ‹€. (μ—¬κΈ°μ„œ μˆœμ„œλŠ” μ€‘μš”ν•˜μ§€ μ•Šκ³  λ³„λ„λ‘œ μ„€μ •ν•΄μ•Ό ν•œλ‹€λŠ” 관점이 μ€‘μš”ν•œκ²ƒ κ°™λ‹€.) μš°μ„  src/main/resources폴더에 μžˆλŠ” application.properties 에 λ‹€μŒμ²˜λŸΌ μž‘μ„±ν•΄μ£Όμž. spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.hikari.jdbc-url=jdbc:mysql://{url}:{port}/{db} spring.datasource.hikari.username={id} spring.datasource.hikari.password={password} μœ„μ˜ jdbc-url ν•­λͺ©μ—μ„œ AWSμ—μ„œ μ œκ³΅ν•˜λŠ” RDSλ₯Ό μ‚¬μš©ν•˜λŠ” 경우 RDSμ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” μ—”λ“œν¬μΈνŠΈμ™€ 포트λ₯Ό 적어주면 λœλ‹€. (μΆ”ν›„ AWS - RDS에 λŒ€ν•΄ λΈ”λ‘œκΉ… μ˜ˆμ •μ΄λ‹€.) Spring Boot 2.0 이후뢀터 기본적으둜 μ‚¬μš©λ˜λŠ” 컀λ„₯μ…˜ 풀이 HikariCP둜 λ³€κ²½λ˜μ—ˆλ‹€κ³  ν•œλ‹€. (링크) 컀λ„₯μ…˜ ν’€ μ’…λ₯˜μ€‘ μ„±λŠ₯이 μ’‹λ‹€κ³  ν•˜λŠ”λ° 링크λ₯Ό 가보면 λ‹€λ₯Έ 컀λ„₯μ…˜ ν’€ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ μ„±λŠ₯을 λΉ„κ΅ν•œ 벀치마크 κ²°κ³Όλ₯Ό 확인할 수 μžˆλ‹€. μœ„μ²˜λŸΌ spring.datasource.hikari κ°€ prefix둜 λΆ™κ³  각쒅 정보듀을 적어주어 config μ—μ„œ μΈμ‹λ μˆ˜ μžˆλ„λ‘ ν•΄μ£Όμž. κ·Έ λ‹€μŒ DataSource 섀정을 ν•΄μ€€λ‹€. @Slf4j @Configuration @PropertySource("classpath:/application.properties") public class DatabaseConfiguration { @Bean @ConfigurationProperties(prefix = "spring.datasource.hikari") public HikariConfig hikariConfig() { return new HikariConfig(); } @Bean public DataSource dataSource() { DataSource dataSource = new HikariDataSource(hikariConfig()); log.info("datasource : {}", dataSource); return dataSource; } } μœ„ λ‚΄μš©μ€ DataSource λ₯Ό hikariConfigμ—μ„œ μ„€μ •ν•œ μ •λ³΄λ‘œ λ§Œλ“€μ–΄ μ€€λ‹€λŠ” μ˜λ―Έμ΄λ‹€. μ΄λ ‡κ²Œλ§Œ ν•˜κ³  ν”„λ‘œμ νŠΈλ₯Ό λ‹€μ‹œ μ‹€ν–‰μ‹œμΌœλ³΄λ©΄ logger 에 μ˜ν•΄ datasource 의 정보λ₯Ό λ³Όμˆ˜κ°€ μžˆλ‹€. 2019-04-22 00:27:35.048 INFO 23040 --- [ main] com.