Skip to content

Project Tech Log

bohyeon edited this page Dec 21, 2019 · 2 revisions

Project Tech Log

λͺ©μ°¨

1μ£Όμ°¨ - μ„œλΉ„μŠ€ 기획 + 개발 μ„ΈνŒ… + 브랜치 μ „λž΅

기획, μ–΄λ–€ μ•„μ΄ν…œμœΌλ‘œ μ •ν•  것인가?

  • μ›Ή κ²Œμž„ (OX ν€΄μ¦ˆ)
    • websocket으둜 μ‹€μ‹œκ°„ 톡신 κ΅¬ν˜„ (μ‹€μ‹œκ°„ ν˜‘μ—… 툴의 μž‘λ™μ›λ¦¬μΈ μ†ŒμΌ“ 톡신 κ²½ν—˜)
    • MVC νŒ¨ν„΄ μ‹€μŠ΅μ΄ κ°€λŠ₯
    • κ²Œμž„ 둜직으둜 μΈν•œ λ³΅μž‘μ„± 관리λ₯Ό κ²½ν—˜
    • νŒ€μ΄ κ°œλ°œν•˜λ©΄μ„œ 재미λ₯Ό λŠλ‚„ 수 μžˆλŠ” 기획

개발 μ„ΈνŒ… (개발 도ꡬ, 개발 ν™˜κ²½, μ½”λ”© μ»¨λ²€μ…˜)

  • 개발 도ꡬ : VSCode
  • 개발 ν™˜κ²½ : Client, Server λ‘˜ λ‹€ ES6+, ES Module λ°©μ‹μœΌλ‘œ κ΅¬ν˜„
  • μ½”λ”© μ»¨λ²€μ…˜ : ESLintλ₯Ό μ‚¬μš©ν•΄ μ»¨λ²€μ…˜μ„ 톡일. airbnbλ₯Ό λ”°λ₯΄κ³ , μΆ”κ°€μ μœΌλ‘œ νŒ€μ˜ κΈ°ν˜Έμ— 맞좰 세뢀사항을 쑰율
    • else μ•ˆ μ“°κ³  if와 return을 μ΄μš©ν•΄μ„œλ§Œ λΆ„κΈ°
    • space 2μΉΈ & ν•œ 쀄 100자 μ œν•œμœΌλ‘œ λ“€μ—¬μ“°κΈ°λ₯Ό 쀄이고 ν•œ 쀄에 λ§Žμ€ λ‚΄μš©μ΄ λ“€μ–΄κ°ˆ 수 있게 ν–ˆλ‹€.
    • Class의 private λ©”μ„œλ“œλ₯Ό ν‘œν˜„ν•˜κΈ° μœ„ν•΄ underscoreλ₯Ό μ‚¬μš©
    • ES5 trailing commaλ₯Ό μ‚¬μš© λ“±

브랜치 μ „λž΅

  • git-flowλ₯Ό μ°Έκ³ ν•˜κ³  ν”„λ‘œμ νŠΈ 규λͺ¨μ— 맞게 κ°„λž΅ν™”

이슈 관리 도ꡬ, CI 도ꡬ

  • GitHub ν”„λ‘œμ νŠΈ, GitHub issues
    • ν•™μŠ΅ κΈ°κ°„ λ™μ•ˆ κΎΈμ€€νžˆ μ‚¬μš©ν–ˆλ˜ 도ꡬ듀이고, githubκ³Ό 연동이 쉽고 잘 λ˜μ–΄μžˆλ‹€.
  • travis
    • jenkins와 비ꡐ. jenkins와 λ‹€λ₯΄κ²Œ μ„œλ²„κ°€ λ”°λ‘œ ν•„μš” μ—†λŠ” λ“± κ°„λ‹¨ν•˜κ³  ν•„μš”ν•œ κΈ°λŠ₯(docker ν™˜κ²½ 이용)듀이 λͺ¨λ‘ 지원됐기 λ•Œλ¬Έμ— μ±„νƒν–ˆλ‹€.
    • 정리 링크

2μ£Όμ°¨ - 인프라 + κ°œλ°œν™˜κ²½ μ„€μ •(husky + ESLint)

인프라 ꡬ성 λ°©ν–₯

  • ν”„λ‘œμ νŠΈ ꡬ성은 Minimize + Dockerize

    • μ‚¬μš©ν•  μ„œλΉ„μŠ€λ„ μ΅œμ†Œν™”ν•œλ‹€.
    • React 파일 μ œκ³΅ν•˜λŠ” μ„œλ²„ 없이, production build react νŒŒμΌμ„ 정적 파일 배포 κΈ°λŠ₯이 μžˆλŠ” NGINXμ—μ„œ λ°°ν¬ν•˜κΈ°λ‘œ κ²°μ •ν–ˆλ‹€.
    • 이에 따라 μ‚¬μš©ν•  μ„œλΉ„μŠ€λŠ” NGINX, Node.js app, MySQL 3κ°€μ§€λ‘œ μ •ν–ˆλ‹€.
    • λ˜ν•œ 3가지 μ„œλΉ„μŠ€λŠ” NCP의 단일 μ„œλ²„λ₯Ό μ‚¬μš©ν•΄ docker-compose둜 μ‹€ν–‰ν•˜κΈ°λ‘œ ν–ˆλ‹€.
  • Docker

    • Docker ν•™μŠ΅ λͺ©μ  (Docker의 ν™•μž₯ μš©μ΄μ„± λ“±)

Dockerize 이슈

  • Production build React νŒŒμΌμ„ 가진 NGINX docker 이미지
    • 처음 μƒκ°ν–ˆλ˜ 방식은 React νŒŒμΌλ“€μ΄ μžˆλŠ” client ν΄λ”λ‘œ μ΄λ™ν•œ λ’€, npm run buildλ₯Ό 톡해 production buildλ₯Ό λ§Œλ“€κ³ , λ§Œλ“€μ–΄μ§„ νŒŒμΌμ„ NGINX μ„€μ • 파일이 μžˆλŠ” ν΄λ”λ‘œ μ΄λ™ν•˜κ³ μž ν–ˆλ‹€.
    • ν•˜μ§€λ§Œ, dockerfile에선 폴더λ₯Ό λ‹€λ₯Έ 폴더λ₯Ό μ΄λ™ν•˜λŠ” λͺ…λ Ήμ–΄λŠ” λΆˆκ°€λŠ₯ν–ˆκΈ°μ— client 폴더에 NGINX μ„€μ • νŒŒμΌμ„ λ„£κ³ , docker 이미지λ₯Ό client ν΄λ”μ—μ„œ λΉŒλ“œ ν•˜κΈ°λ‘œ ν–ˆλ‹€.
    • λ˜ν•œ λΉŒλ“œ ν•˜λŠ” κ³Όμ •μ—μ„œ 2가지 이미지λ₯Ό μ‚¬μš©ν•˜λŠ”λ°, 두 이미지 λΉŒλ“œ κ³Όμ •μ—μ„œ 파일이 κ³΅μœ λ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ μžˆμ—ˆλ‹€. 이λ₯Ό COPY의 --from μ˜΅μ…˜μ„ 톡해 ν•΄κ²°ν•  수 μžˆμ—ˆλ‹€.

Travis CI 이슈

μ΅œμ‹ μ˜ develop 브랜치 μ½”λ“œ μ μš©ν•˜κΈ°

  • Travis CI 처음 μ μš©ν–ˆμ„ λ•Œ, μ–΄λ–€ λΈŒλžœμΉ˜λ“  Pull Request μ‹œ λͺ¨λ‘ 개발 μ„œλ²„μ— μžλ™ 배포될 수 μžˆλ„λ‘ μ„€μ •ν–ˆμ—ˆλ‹€. κ·Έ μ΄μœ λŠ” ν˜„μž¬ μž‘μ—… κ²°κ³Όκ°€ NCP의 개발 μ„œλ²„μ—μ„œλ„ 잘 μž‘λ™ν•˜λŠ”μ§€ λ°”λ‘œ ν™•μΈν•˜κ³ μž ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.
  • κ·ΈλŸ¬λ‚˜ 반영된 결과물이 develop λΈŒλžœμΉ˜μ— μžˆλŠ” μ½”λ“œλŠ” ν¬ν•¨λ˜μ§€ μ•Šμ•˜μ—ˆλ‹€. κ·Έ μ΄μœ λŠ” PR μ‹œ μ΅œμ‹ μ˜ develop λΈŒλžœμΉ˜κ°€ μžλ™μœΌλ‘œ 반영된 λ’€ docker 이미지 λΉŒλ“œ ν•˜λŠ” 것이 μ•„λ‹ˆκ³ , PRλ₯Ό ν•œ λΈŒλžœμΉ˜μ— μžˆλŠ” μ½”λ“œλ‘œλ§Œ docker 이미지λ₯Ό λΉŒλ“œ ν•˜κΈ° λ•Œλ¬Έμ΄μ—ˆλ‹€.
  • 이λ₯Ό 2가지 λ°©λ²•μœΌλ‘œ ν•΄κ²°ν•˜μ˜€λŠ”λ°, λ¨Όμ € Pull Request μ‹œ develop을 ν•΄λ‹Ή κΈ°λŠ₯ κ΅¬ν˜„ λΈŒλžœμΉ˜μ— pull λ°›κ³  PR λ³΄λ‚΄λŠ” 것, 그리고 PRλŠ” test만 ν•˜κ²Œ ν•˜κ³ , μžλ™ λ°°ν¬λŠ” develop, master λΈŒλžœμΉ˜μ— merge(push) 될 λ•Œλ§Œ μ‹€ν–‰λ˜λ„λ‘ μ„€μ •ν–ˆλ‹€.

배포 방식에 λ”°λ₯Έ μ„€μ •

  • master와 develop λΈŒλžœμΉ˜μ— merge 될 λ•Œλ§Œ λ°°ν¬ν•˜κ³  μ‹Άμ—ˆλ‹€. 그런데 merge κ΄€λ ¨ 섀정이 μ‘΄μž¬ν•˜μ§€ μ•Šμ•˜λ‹€.
    • masterλ‚˜ develop λΈŒλžœμΉ˜μ— mergeκ°€ 되면 pushκ°€ μΌμ–΄λ‚œλ‹€.
    • master와 develop λΈŒλžœμΉ˜μ— push ν•  λ•Œλ§Œ λ°°ν¬ν•˜λ„λ‘ μ„€μ •ν–ˆλ‹€.

husky + ESLint

  • ν”„λ‘œμ νŠΈ setting을 ν•˜λ©° ESLint rule을 μ •ν•˜κ³  VScode 섀정을 ν–ˆλ‹€. λ˜ν•œ huskyλΌλŠ” commit lintλ₯Ό λ°œκ²¬ν•˜μ˜€κ³  commit style도 톡일성을 μ£Όκ³  μ‹Άμ—ˆλ‹€. ν•˜μ§€λ§Œ husky rule μ„€μ • λ³€κ²½μ—μ„œ 쑰금 μ–΄λ €μš΄ 뢀뢄이 μžˆμ—ˆλ‹€. μš°λ¦¬κ°€ μ‚¬μš©ν•  type으둜 husky 섀정을 λ°”κΏ”μ•Ό ν•˜λŠ”λ° λ¦¬μ„œμΉ˜ν•΄λ„ 잘 λ‚˜μ˜€μ§€ μ•Šμ•˜λ‹€. -> package.jsonμ—μ„œ commitlint 섀정에 rule을 μ μš©ν•  수 μžˆμ—ˆλ‹€.

3μ£Όμ°¨ - 캐릭터 μ• λ‹ˆλ©”μ΄μ…˜ + μ‹€μ‹œκ°„ μ›€μ§μž„ ν‘œμ‹œ

canvas

  • λ§Žμ€ μ›€μ§μž„μ΄ μ‹€μ‹œκ°„μœΌλ‘œ ν‘œν˜„λ˜μ–΄μ•Ό ν•œλ‹€. DOM의 직접적인 μ‘°μž‘λ³΄λ‹€ μ„±λŠ₯이 훨씬 λΉ λ₯Έ canvasλ₯Ό μ‚¬μš©ν–ˆλ‹€.

sprite

  • κ±·λŠ” λͺ¨μ–‘을 보여주기 μœ„ν•΄ 일정 ν”„λ ˆμž„λ§ˆλ‹€ 이미지λ₯Ό λ°”κΏ”μ€˜μ•Ό ν–ˆλŠ”λ°, μ΄λ―Έμ§€μ˜ 경둜λ₯Ό λ³€κ²½(img.src = "...") ν•˜κ±°λ‚˜ 이미지 객체λ₯Ό μž¬μƒμ„±(new Image()) ν•˜λŠ” 것보닀 κ·Έλ €λ‚΄λŠ” μ˜μ—­λ§Œ λ°”κΏ”μ£ΌλŠ” 것(drawImage(...))이 λΉ„μš©μ΄ 더 적기 λ•Œλ¬Έμ— sprite 이미지λ₯Ό μ‚¬μš©ν–ˆλ‹€.

캐릭터:μΊ”λ²„μŠ€ = 1:1

  • 캐릭터가 움직인 ν›„μ—λŠ” κ·Έμ „ μœ„μΉ˜μ˜ 캐릭터 μ΄λ―Έμ§€λŠ” μ§€μ›Œμ€„ ν•„μš”κ°€ μžˆλ‹€. 그런데 κ·Έλ ‡κ²Œ 되면 κ²ΉμΉ˜λŠ” μ˜μ—­μ— 있던 λ‹€λ₯Έ 캐릭터가 μ§€μ›Œμ§€λŠ” μ΄μŠˆκ°€ μžˆμ—ˆκΈ° λ•Œλ¬Έμ— 캐릭터가 생성될 λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ canvasλ₯Ό μƒμ„±ν•΄μ„œ 각각 canvasλ₯Ό κ°€μ§€κ²Œ ν–ˆλ‹€.
  • ν•˜λ‚˜μ˜ canvasμ—μ„œ 맀번 λͺ¨λ“  캐릭터λ₯Ό 지웠닀가 λ‹€μ‹œ 그릴 μˆ˜λ„ μžˆμ—ˆμ§€λ§Œ, μ—¬λŸ¬ μΊλ¦­ν„°μ˜ μ›€μ§μž„μ΄ λΉˆλ²ˆν•˜κ²Œ μΌμ–΄λ‚˜λŠ” μ„œλΉ„μŠ€μ—μ„œ 맀 μ›€μ§μž„λ§ˆλ‹€ λͺ¨λ“  캐릭터λ₯Ό μ§€μš°κ³  λ‹€μ‹œ κ·Έλ €μ£ΌλŠ” κ²ƒλ³΄λ‹€λŠ” 각각의 canvasμ—μ„œ 일이 μˆ˜ν–‰λ˜κ²Œ ν•˜λŠ” 게 더 효율적이라고 νŒλ‹¨ν–ˆλ‹€.

requestAnimationFrame

  • μ›€μ§μ΄λŠ” μ• λ‹ˆλ©”μ΄μ…˜μ„ μœ„ν•΄, 캐릭터 이미지λ₯Ό λͺ¨μ…˜μ— 맞게 λ°”κΎΈκ³  μœ„μΉ˜λ₯Ό μ΄λ™μ‹œν‚€λŠ” λ‘œμ§μ„ 일정 ν”„λ ˆμž„λ§ˆλ‹€ 반볡적으둜 μˆ˜ν–‰ν•΄μ•Ό ν–ˆλ‹€. 이λ₯Ό μœ„ν•΄ setTimeout이 μ•„λ‹ˆλΌ requestAnimationFrame ν•¨μˆ˜λ₯Ό μž¬κ·€μ μœΌλ‘œ ν˜ΈμΆœν•˜λŠ” 방식을 μ„ νƒν–ˆλ‹€. 이 ν•¨μˆ˜λŠ” λΈŒλΌμš°μ €κ°€ μ‹€μ œ 화면을 κ·Έλ¦¬λŠ” 주기에 따라 μ§€μ •λœ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κΈ° λ•Œλ¬Έμ—, μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μž‘μ„±λœ 둜직이 ν”„λ ˆμž„ μ‹œμž‘ μ‹œμ— ν˜ΈμΆœλ˜λ„λ‘ 보μž₯ν•œλ‹€. 이런 λ°©μ‹μœΌλ‘œ ν•˜λ©΄ ν”„λ ˆμž„μ΄ λˆ„λ½λ  일도 μ—†κ³ , 일정 κ°„κ²©μœΌλ‘œ λ‘œμ§μ„ μˆ˜ν–‰ν•˜λŠ” 것이 보μž₯되기 λ•Œλ¬Έμ— λ§€λ„λŸ¬μš΄ μ• λ‹ˆλ©”μ΄μ…˜μ„ ν‘œν˜„ν•˜κΈ° μœ„ν•΄ μ μ ˆν•˜λ‹€κ³  νŒλ‹¨ν–ˆλ‹€.

캐릭터 μ›€μ§μž„ μ‹€μ‹œκ°„ ν‘œμ‹œ

  • λͺ¨λ“  μΊλ¦­ν„°μ˜ μ›€μ§μž„μ΄ λͺ¨λ“  μ‚¬μš©μžλ“€μ—κ²Œ λ™μΌν•˜κ²Œ 보여야 ν–ˆλ‹€. 이λ₯Ό μœ„ν•΄μ„œ μ„œλ²„μ—μ„œ μ—¬λŸ¬ μœ μ €λ“€μ˜ ν‚€λ³΄λ“œ μž…λ ₯을 λ°›μ•„ 움직일 수 μžˆλŠ” μœ„μΉ˜μΈμ§€ 계산 ν›„, λͺ¨λ“  μœ μ €λ“€μ—κ²Œ ν•΄λ‹Ή μΊλ¦­ν„°μ˜ μ›€μ§μž„μ„ μ•Œλ €μ£Όκ²Œ ν–ˆλ‹€.

좩돌 검사

  • λ‹€μ΄λ‚΄λ―Ήν•œ κ²Œμž„ μš”μ†Œλ₯Ό μœ„ν•΄, μ—¬λŸ¬ μΊλ¦­ν„°μ˜ μ›€μ§μž„μ„ μ‹€μ‹œκ°„μœΌλ‘œ 보여쀄 뿐만 μ•„λ‹ˆλΌ λ‹€λ₯Έ 캐릭터가 μžˆλŠ” μœ„μΉ˜μ—λŠ” μ΄λ™ν•˜μ§€ λͺ»ν•˜κ²Œ ν•΄μ„œ μ„œλ‘œ 길을 막을 수 있게 ν•˜λ €κ³  ν–ˆλ‹€. 캐릭터 κ°„ μΆ©λŒμ„ κ²€μ‚¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” 각 이미지 κ°„μ˜ 거리 값을 κ³„μ‚°ν•˜κ±°λ‚˜ 겹쳐져 μžˆλŠ” ν”½μ…€μ˜ 투λͺ…도 값을 검사해야 ν–ˆλŠ”λ°, κ²Œμž„ 엔진 없이 λͺ¨λ“  ν”½μ…€ 값을 λΉ λ₯΄κ²Œ κ³„μ‚°ν•˜κΈ°μ—λŠ” 무리가 μžˆλ‹€κ³  νŒλ‹¨ν–ˆλ‹€. κ·Έλž˜μ„œ μΊλ¦­ν„°λ§ˆλ‹€ μœ„μΉ˜ν•  수 μžˆλŠ” 칸을 λ§Œλ“€κ³ , 각 μΉΈμ—λŠ” ν•˜λ‚˜μ˜ μΊλ¦­ν„°λ§Œ λ“€μ–΄κ°ˆ 수 있게 ν•΄μ„œ 좩돌과 λΉ„μŠ·ν•œ μΈν„°λž™μ…˜μ„ κ΅¬ν˜„ν–ˆλ‹€.

4μ£Όμ°¨ - κ²Œμž„ μ˜ˆμ™Έμƒν™© + socket test + μ†ŒμΌ“ μž¬μ—°κ²° 이슈

κ²Œμž„ μ˜ˆμ™Έ 상황

  • μ›Ήκ²Œμž„μ΄λΌλŠ” νŠΉμ„±μƒ, κ²Œμž„ 쀑에 λ°© λ‚˜κ°€κΈ° λ²„νŠΌμ„ 막아놓아도 λ’€λ‘œκ°€κΈ°λ‚˜ νƒ­ λ‹«κΈ°λ₯Ό 톡해 μ–Έμ œλ“ μ§€ κ²Œμž„μ„ 쉽고 λΉ λ₯΄κ²Œ λ‚˜κ°ˆ 수 μžˆμ—ˆλ‹€. λ•Œλ¬Έμ— μ˜ˆμƒλ³΄λ‹€ λ„ˆλ¬΄ μž¦μ€ μœ μ €λ“€μ˜ μ΄νƒˆλ‘œ 인해 κ²Œμž„ μ§„ν–‰μƒμ˜ μ˜ˆμ™Έ 상황이 λ§Žμ•˜λ‹€.
  • κ²Œμž„μ΄ μ§„ν–‰λ˜μ§€ μ•ŠλŠ” μƒνƒœμ—μ„  μœ μ €μ˜ μž¦μ€ μœ μž…/μ΄νƒˆμ΄ μ˜ˆμ™Έ 상황을 λ°œμƒμ‹œν‚€μ§„ μ•Šμ•˜μ§€λ§Œ, κ²Œμž„ 진행 μ€‘μ—μ„œ μœ μ €κ°€ λ‚˜κ°€κ²Œ λœλ‹€λ©΄, κ²Œμž„ 둜직이 μ‰½κ²Œ λ’€μ—‰μΌœ μ‚΄μ•„μžˆλŠ” μœ μ €κ°€ μ—†λŠ”λ°λ„ κ²Œμž„μ΄ 계속 μ§„ν–‰λ˜λŠ” λ“±μ˜ 버그 및 μ˜ˆμ™Έ 상황을 λ§ˆμ£Όν•˜μ˜€λ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄, κ²Œμž„ μ‹œμž‘ ν›„ 맀 λΌμš΄λ“œμ˜ μ‹œμž‘ 및 μ’…λ£Œ μ‹œμ μ— 인원 및 ν˜„μž¬ λΌμš΄λ“œλ₯Ό ν™•μΈν•˜μ—¬ κ²Œμž„ μ§„ν–‰μ—μ„œμ˜ μ˜ˆμ™Έ 사황을 μ œκ±°ν•  수 μžˆμ—ˆλ‹€.

socket μž¬μ—°κ²° 이슈

  • ν•œλ²ˆ μ—°κ²°λ˜λ©΄ 계속 ν•΄λ‹Ή socket으둜 μœ μ €λ₯Ό κ΅¬λΆ„ν•΄μ„œ μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•˜κ²Œ ν•˜κ³  μ‹Άμ—ˆλ‹€. 그런데 μ„œλΉ„μŠ€μ— μ†ŒμΌ“ 연결을 ν•΄μ„œ 접속 후에, 일정 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ 연결이 끊기고 λ‹€μ‹œ μž¬μ—°κ²°λ˜λŠ” μ΄μŠˆκ°€ μžˆμ—ˆλ‹€. socket.ioλ₯Ό μ΄μš©ν•œ μ—°κ²°μ˜ κΈ°λ³Έ μ˜΅μ…˜μ΄ polling 방식이기 λ•Œλ¬Έμ΄μ—ˆλŠ”λ°, μ˜΅μ…˜μœΌλ‘œ websocket을 μ€˜μ„œ ν•΄λ‹Ή 이슈λ₯Ό ν•΄κ²°ν•  수 μžˆμ—ˆλ‹€.
  • polling 방식은 μ£ΌκΈ°λ§ˆλ‹€ μš”μ²­μ„ 보내고 응닡을 λ°›μœΌλ©΄μ„œ 연결을 μœ μ§€ν•˜λŠ” 방식이기 λ•Œλ¬Έμ— 연결이 주기적으둜 끊기고 μ˜€λ²„ν—€λ“œλ„ λ°œμƒν•œλ‹€. websocket 방식은 connection을 계속 μœ μ§€ν•˜κΈ° λ•Œλ¬Έμ— μ˜€λ²„ν—€λ“œλ„ 적고 연결이 주기적으둜 λŠκΈ°μ§€λ„ μ•ŠλŠ”λ‹€.

socket test

  • socket test에 λŒ€ν•œ μžλ£Œκ°€ λ§Žμ§€ μ•Šμ•„μ„œ 어렀움을 κ²ͺμ—ˆμ§€λ§Œ socket-ioλ₯Ό ν™œμš©ν•˜λ©΄ mock clientλ₯Ό 생성할 수 있고, μ„œλ²„λŠ” λ²ˆλ“€λ§λœ app.jsλ₯Ό μ΄μš©ν•΄μ„œ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ μ„œλ²„λ‘œ 생성해 쀄 수 μžˆμ—ˆλ‹€. mock client와 μƒμ„±ν•œ μ„œλ²„λ₯Ό μ΄μš©ν•΄μ„œ socket testλ₯Ό μž‘μ„±ν–ˆλ‹€.
  • μœ„ λ°©λ²•μœΌλ‘œ νŠΉμ • socket eventμ—μ„œ μ œλŒ€λ‘œ 된 응닡과 데이터가 μ˜€λŠ”μ§€ 확인할 수 μžˆμ—ˆκ³ , eventλ“€κ°„μ˜ 흐름도 ν…ŒμŠ€νŠΈν•  수 μžˆμ—ˆλ‹€.

5μ£Όμ°¨ - 캐릭터 μ›€μ§μž„ 버그 + OAuth 둜그인

캐릭터 μ›€μ§μž„ 버그

  • μ‹€μ œ μ„œλ²„μ—μ„œ μ €μž₯ν•˜κ³  μžˆλŠ” μΊλ¦­ν„°λ“€μ˜ μœ„μΉ˜μ™€, μ‹€μ œλ‘œ ν΄λΌμ΄μ–ΈνŠΈκ°€ ν‘œμ‹œν•˜λŠ” ν™”λ©΄μ—μ„œ λ³΄μ΄λŠ” μœ„μΉ˜κ°€ λ‹€λ₯Έ μ΄μŠˆκ°€ λ°œκ²¬λ˜μ—ˆλ‹€. λ”λΆˆμ–΄ μ—¬λŸ¬ μ‚¬μš©μžκ°„μ—λ„ μ„œλ‘œκ°€ μœ„μΉ˜κ°€ λ‹€λ₯΄κ²Œ λ³΄μ˜€λ‹€.
  • 원인1: μ†ŒμΌ“
    • μ†ŒμΌ“ 톡신은 연결지ν–₯이기 λ•Œλ¬Έμ—, λ¬΄μ°¨λ³„μ μœΌλ‘œ λ“€μ–΄μ˜€λŠ” μ‚¬μš©μžλ“€μ˜ μž…λ ₯에 λŒ€ν•΄ μ œμ–΄ν•˜κΈ°κ°€ νž˜λ“€μ—ˆλ‹€. 거의 λ™μ‹œλ‹€λ°œμ μœΌλ‘œ λ“€μ–΄μ˜€λŠ” μ›€μ§μž„ μ΄λ²€νŠΈλ“€μ€ λͺ¨λ‘ λΉ„λ™κΈ°λ‘œ λ³‘λ ¬μ μœΌλ‘œ μ‹€ν–‰λœλ‹€. 그리고 λŒ€λΆ€λΆ„ 같은 μžμ›μ„ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—, 동일 μžμ›μ„ λ™μ‹œμ— 읽고 μ“°λ©΄μ„œ μžμ›μ΄ μ›ν•˜μ§€ μ•Šκ²Œ λ³€κ²½λ˜μ–΄ μœ„μΉ˜κ°€ κΌ¬μ΄λŠ” 버그가 λ°œμƒν–ˆλ‹€.
  • 원인2: requestAnimationFrame
    • λ§€λ„λŸ¬μš΄ μ• λ‹ˆλ©”μ΄μ…˜μ„ μœ„ν•΄ requestAnimationFrame ν•¨μˆ˜λ₯Ό μ‚¬μš©ν–ˆλŠ”λ°, 이 ν•¨μˆ˜λŠ” μ„±λŠ₯κ³Ό μ΅œμ ν™”λ₯Ό μœ„ν•΄ 화면이 보이고 μžˆμ§€ μ•Šμ„ λ•ŒλŠ” (λ‹€λ₯Έ 탭에 κ°€μžˆκ±°λ‚˜ 탭이 λ‚΄λ €κ°€ μžˆμ„ λ•Œ) μ• λ‹ˆλ©”μ΄μ…˜μ„ μˆ˜ν–‰ν•˜μ§€ μ•Šλ‹€κ°€ λ‹€μ‹œ 화면이 보일 λ•Œ μˆ˜ν–‰ν•œλ‹€. 그런데 μ†ŒμΌ“ μ΄λ²€νŠΈλŠ” μ •μƒμ μœΌλ‘œ μˆ˜ν–‰λ˜κΈ° λ•Œλ¬Έμ—, λ‹€λ₯Έ 탭에 κ°€μžˆλŠ” λ™μ•ˆμ˜ λ‹€λ₯Έ 캐릭터 μ›€μ§μž„μ€ ν‘œν˜„λ˜μ§€ μ•Šλ‹€κ°€ 화면을 λ‹€μ‹œ λ³΄λŠ” μˆœκ°„ ν•˜λ‚˜μ˜ μ›€μ§μž„λ§Œ 보여주기 λ•Œλ¬Έμ— μœ„μΉ˜κ°€ λ‹€λ₯΄κ²Œ ν‘œμ‹œλ˜λŠ” μ΄μŠˆκ°€ λ°œμƒν–ˆλ‹€.
  • ν•΄κ²°: μ›€μ§μž„ 이벀트 처리 큐(Queue) κ΅¬ν˜„
    • μ„œλ²„μ—μ„œ ν•˜λ‚˜μ˜ μ›€μ§μ΄λŠ” 둜직이 끝날 λ•ŒκΉŒμ§€λŠ”, μƒˆλ‘œ λ“€μ–΄μ˜¨ μ›€μ§μž„ 이벀트λ₯Ό 큐에 μ €μž₯해놓고 이전 둜직이 λλ‚œ 후에 μˆ˜ν–‰λ  수 μžˆλ„λ‘ ν•΄μ„œ 이벀트λ₯Ό 순차적으둜 μ œμ–΄ν–ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈμ—μ„œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ, λ™μΌν•œ μΊλ¦­ν„°μ˜ μ›€μ§μž„ μ΄λ²€νŠΈμ— λŒ€ν•΄ 큐둜 μ œμ–΄ν•΄μ„œ 순차적으둜 μ‹€ν–‰λ˜κ²Œ ν–ˆλ‹€. 화면이 보이지 μ•ŠλŠ” λ™μ•ˆμ—λ„ 큐에 μŒ“μ•„λ†¨λ‹€κ°€ 화면을 λ‹€μ‹œ λ³Ό λ•Œ 순차적으둜 큐에 μžˆλŠ” λ‘œμ§μ„ μˆ˜ν–‰ν•˜λŠ” λ°©λ²•μœΌλ‘œ 이슈λ₯Ό ν•΄κ²°ν–ˆλ‹€.

OAuth 둜그인

  • JWT
    • ν˜„μž¬ μ‚¬μš©μžκ°€ λ‘œκ·ΈμΈν•œ μ‚¬μš©μžμΈμ§€ νŒλ³„ν•˜κΈ° μœ„ν•΄ cookie에 μ‚¬μš©μžμ˜ github idλ₯Ό 가지고 μžˆλŠ” JWTλ₯Ό μ €μž₯ν•˜μ˜€λ‹€. JWT의 νŠΉμ„±μƒ cookieλ₯Ό λ³€κ²½ν•˜λ©΄ λ³΅ν˜Έν™”κ°€ μ œλŒ€λ‘œ λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μˆ˜μ •λ˜μ§€ μ•Šμ€ μ‚¬μš©μžμ˜ μ •λ³΄λ§Œ μ •μƒμ μœΌλ‘œ λ³΅ν˜Έν™”ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.
    • μ‚¬μš©μžμ˜ github idλŠ” λ―Όκ°ν•œ μ •λ³΄λŠ” μ•„λ‹ˆμ§€λ§Œ μ‘°μž‘ν•˜λ©΄ μ•ˆλ˜λŠ” 정보이기 λ•Œλ¬Έμ— JWTκ°€ μ ν•©ν•˜λ‹€κ³  νŒλ‹¨ν–ˆλ‹€.
  • GitHub OAuth app을 2개 μƒμ„±ν•œ 이유
    • github oauth app을 생성할 λ•Œ Homepage URLκ³Ό Authorization callback URL이 ν•„μš”ν•˜λ‹€. 그런데 developmentμ—μ„œμ˜ urlκ³Ό prodcuction mode일 λ•Œμ˜ url이 λ‹€λ₯΄κΈ°λ•Œλ¬Έμ— github oauth app을 2개 μƒμ„±ν•˜μ—¬ ν•˜λ‚˜λŠ” development mode일 λ•Œ μ‚¬μš©ν•˜κ³  ν•˜λ‚˜λŠ” production modeμ—μ„œ μ‚¬μš©ν•˜μ˜€λ‹€.

6μ£Όμ°¨ - μ‚¬μš΄λ“œ + 도메인 + μ—„κ²©ν•œ μ±„νŒ… 길이 검사 + μ• λ‹ˆλ©”μ΄μ…˜ μΆ”κ°€

λΌμš΄λ“œκ°€ 끝날 λ•Œλ§ˆλ‹€ λ“±μž₯ν•˜λŠ” μ• λ‹ˆλ©”μ΄μ…˜

  • ν•œ λΌμš΄λ“œκ°€ 끝날 λ•Œλ§ˆλ‹€ νƒ€λ…ΈμŠ€ 이미지λ₯Ό canvas requestAnimationFrame을 μ΄μš©ν•΄ λ‚˜νƒ€λ‚˜κ²Œν–ˆλ‹€. 그런데 λ¬Έμ œλŠ” requestAnimationFrame은 탭을 보지 μ•ŠλŠ” μƒνƒœμ—μ„œλŠ” μ‹€ν–‰μ‹œν‚€μ§€μ•Šκ³  λ‹€μ‹œ 탭을 λ³Ό λ•Œ μ‹€ν–‰μ‹œν‚€κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ 탭을 보닀가 λŒμ•„μ˜€λ©΄ ν•œλ²ˆμ— νƒ€λ…ΈμŠ€κ°€ μ—¬λŸ¬λ²ˆ λ“±μž₯ν–ˆλ‹€. μ‚¬μš©μžκ°€ ν˜„μž¬ 탭을 보고 μžˆλŠ”μ§€ μ•ŒκΈ° μœ„ν•΄μ„œ Page Visibility APIλ₯Ό μ‚¬μš©ν–ˆλ‹€. κ·Έλž˜μ„œ μ‚¬μš©μžκ°€ 보고 μžˆμ§€ μ•Šλ‹€λ©΄ μ• λ‹ˆλ©”μ΄μ…˜μ„ μ‹€ν–‰μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.

μ‚¬μš΄λ“œ

  • μ›Ή κ²Œμž„μ΄κΈ° λ•Œλ¬Έμ— λ„ˆλ¬΄ λ§Žμ€ μ‚¬μš΄λ“œ μš”μ†Œλ³΄λ‹€λŠ”, κ°€λ³κ²Œ λ°°κ²½ μŒμ•…κ³Ό κ²Œμž„ μ‹œμž‘/끝 μ‚¬μš΄λ“œ 효과만 λ„£κΈ°λ‘œ ν–ˆλ‹€.
  • μ‚¬μš΄λ“œ μž¬μƒμ΄λ‚˜ λ³Όλ₯¨ 등을 μ‹œκ°μ μœΌλ‘œ 보여쀄 ν•„μš”κ°€ μ—†μ—ˆκΈ° λ•Œλ¬Έμ—, μ‚¬μš΄λ“œλ₯Ό μœ„ν•΄ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§Œλ“€μ–΄ μ“°κ±°λ‚˜ λ³„λ„μ˜ λͺ¨λ“ˆμ„ μ„€μΉ˜ν•΄ μ‚¬μš©ν•˜κΈ°λ³΄λ‹€ html5 audio λ₯Ό μ‚¬μš©ν–ˆλ‹€.
  • audioλ₯Ό 일반 λ³€μˆ˜μ— μ €μž₯ν•˜λ©΄, μ»΄ν¬λ„ŒνŠΈκ°€ λ¦¬λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ 가끔씩 쀑볡 생성 및 μž¬μƒλ˜λŠ” μ΄μŠˆκ°€ μžˆμ–΄μ„œ ν•˜λ‚˜λ‘œ μœ μ§€ν•˜κΈ° μœ„ν•΄ audio 객체λ₯Ό λ¦¬μ•‘νŠΈ state둜 λ§Œλ“€μ—ˆλ‹€. μ΄λ ‡κ²Œ λ§Œλ“  stateλ₯Ό 가지고 μ»€μŠ€ν…€ 훅을 λ§Œλ“€ μˆ˜λ„ μžˆμ—ˆλŠ”λ°, ν•˜λ‚˜μ˜ μ»΄ν¬λ„ŒνŠΈμ—μ„œλ§Œ μ‚¬μš©ν•΄μ„œ μž¬μ‚¬μš©μ„±μ΄ 거의 μ—†μ—ˆκΈ° λ•Œλ¬Έμ— μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€ state둜만 μ‚¬μš©ν–ˆλ‹€.

도메인 + SSL μ„€μ •

  • 도메인은 Google Domainsμ—μ„œ κ΅¬μž…ν–ˆλ‹€. κ΅¬μž…ν•œ 경둜λ₯Ό μ μš©ν•˜κΈ° μœ„ν•΄μ„  SSL μΈμ¦μ„œλ₯Ό λ°œκΈ‰ λ°›μ•„μ•Ό ν–ˆλŠ”λ°, μ΄λŠ” Let's Encrypt의 Certbotλ₯Ό μ΄μš©ν–ˆλ‹€.
  • μ²˜μŒμ—λŠ” docker-composeλ₯Ό 톡해 싀행쀑인 NGINX의 섀정을 λ³€κ²½ν•˜μ—¬ SSL μΈμ¦μ„œλ₯Ό νŠΉμ • 폴더에 μ €μž₯ν•˜κ³ μž ν–ˆμœΌλ‚˜, μ œλŒ€λ‘œ μž‘λ™λ˜μ§€ μ•Šμ•˜λ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄, μ‹€ν–‰ 쀑인 docker μ»¨ν…Œμ΄λ„ˆλ₯Ό λͺ¨λ‘ λ©ˆμΆ”κ³ , μƒˆλ‘œμš΄ NGINX 이미지λ₯Ό dockerλ₯Ό 톡해 μ‹€ν–‰ν•΄ μΈμ¦μ„œλ₯Ό 받을 수 μžˆμ—ˆλ‹€. λ˜ν•œ 받은 μΈμ¦μ„œλ₯Ό docker volume을 μ΄μš©ν•΄ μΈμ¦μ„œκ°€ μ €μž₯된 폴더λ₯Ό μ§€μ •ν•΄μ„œ SSL μΈμ¦μ„œ μ μš©μ‹œν‚¬ 수 μžˆμ—ˆλ‹€.

μ±„νŒ… 검사

  • μ±„νŒ…μ„ ν•  λ•Œλ§ˆλ‹€ 캐릭터 μœ„μ— 말풍선이 κ·Έλ €μ§€κ²Œ μ μš©ν–ˆκΈ° λ•Œλ¬Έμ—, κΈ€μžμˆ˜λ‘œλ§Œ μ±„νŒ…μ„ κ²€μ‚¬ν•˜λŠ” 것이 μ•„λ‹ˆλΌ 말풍선 μ•ˆμ— κΈ€μžλ“€μ΄ λͺ¨λ‘ λ“€μ–΄κ°€λŠ”μ§€ 확인해야 ν–ˆλ‹€.
    • μ±„νŒ…μ°½ λ„λ°°μ™€λŠ” λ‹€λ₯΄κ²Œ 말풍선을 μ΄μš©ν•œ λ„λ°°λŠ” 캐릭터λ₯Ό κ°€λ¦¬λŠ” λ“± μœ μ € κ²½ν—˜μ„ 크게 망칠 수 μžˆλ‹€.
    • UTF-8μ—μ„œ κ°€μž₯ 길이가 κΈ΄ κΈ€μžλŠ” μœ„μ™€κ°™μ€ 문제 λ•Œλ¬Έμ— 적은 수의 κΈ€μžλ§Œ 타이핑할 수 있게 ν•΄μ•Όν–ˆλ‹€.
  • canvas context의 길이츑정 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄ μ‚¬μš©μ€‘μΈ 폰트, 폰트 크기에 맞좰 canvas에 κ·Έλ €μ§€λŠ” μ‹€μ œ ν…μŠ€νŠΈμ˜ 길이λ₯Ό μΈ‘μ •ν–ˆλ‹€.
  • νŒ€μ—μ„œ μ •ν•œ 말풍선 높이에 λ§žμΆ°μ„œ κΈ€μžλ₯Ό μž˜λΌμ€¬λ‹€.

7μ£Όμ°¨ - λ¦¬νŒ©ν† λ§

  • λ§€μ§λ„˜λ²„ μƒμˆ˜ν™”
  • ν•¨μˆ˜ μž‘μ€ λ‹¨μœ„λ‘œ μͺΌκ°œκΈ°
  • μ€‘λ³΅μ½”λ“œ μ—†μ• κΈ° (ν•¨μˆ˜ λ§Œλ“€κΈ°)
  • 톡일성을 μœ„ν•΄ 빠진 주석 μΆ”κ°€ 및 보완
  • λ³€μˆ˜, ν•¨μˆ˜λͺ… 고민해보기
Clone this wiki locally