์จ๋ผ์ธ 3D ๋ฐฉํ์ถ ๊ฒ์ ์๋น์ค ๐ด
โzzzโ ๋ ๊ฟ์ ๊พธ๋ ์ํ๋ฅผ ํํํ ๋จ์ด์ด์, ๊ฒ์ ํ๋ก์ ํธ์ ์ด๋ฆ์ ๋๋ค
โ๊ฟโ ์ด๋ผ๋ ๋งค์ฒด๋ฅผ ์ด์ฉํ์ฌ ์์ํ๊ณ ๋ฌธ์ ๋ฅผ ํ๋ฉด์ ํด๊ฒฐํ์ฌ ๋ฐฉํ์ถ์ ํ๋ ๊ฒ์ด ๋ณธ ๊ฒ์์ ์ด์ด๋๊ฐ ์ ์๋ ๋ฐฉ๋ฒ์ ๋๋ค
๋น์ ์ ๊ฟ ์์์ ์ผ๋ง๋งํผ์ ์ญ๋์ ๋ฐํํ ์ ์๋์ง ๊ถ๊ธํ์ง ์์ผ์ ๊ฐ์?
- 2022.2.25 ~ 2022.4.9
- 1์ฐจ ๋ฐฐํฌ : 2022.3.30
๐ 5์ผ ๋์ 550์ฌ๋ช ์ ์ ์ ๋ค์ด 550์ฌ๊ฐ์ ๋ฐฉ์ ๋ง๋ค๊ณ , 375ํ์ด ๊ฒ์์ ์์ํ์์ผ๋ฉฐ, 9ํ์ด ํ์ถ์ ์ฑ๊ณตํ์์ต๋๋ค!!
- ์๋น์ค ๋ฐ๋ก๊ฐ๊ธฐ
- GitHub ๋ฉ์ธํ์ด์ง
- ํ๋ก ํธ์๋ GitHub
- ๋ฐฑ์๋ GitHub(NodeJS)
- ์์ฐ์์
๐ ๋ฐฑ์๋์ ๊ณ ๋ฏผ๊ณผ ๊ณต๋ถ ๊ธฐ๋ก์ โ https://github.com/HangHae99Zzz/RoomEscape_BE/wiki
ํ
๋ฐฉํ์ถ ๊ฒ์์ ์ํ ๋ฐฉ์ ๋ง๋ค๊ณ , ๋ญํน์กฐํ ๋ฐ ๊ฒ์ ์ค๋ช ์ ํ์ธํ ์ ์์ต๋๋ค.๋๊ธฐ
ํ์ฌ ๋๊ธฐ์ค์ธ ์ธ์์ ์ฒดํฌํ๊ณ ๊ฒ์์ ์์ํ ์ ์์ต๋๋ค. ๋งํฌ๋ก ์น๊ตฌ๋ฅผ ์ด๋ํ๊ณ , ๋ณด์ด์ค ์ฑํ ๋ ๊ฐ๋ฅํด์!๊ฒ์
ํ์๋ค๊ณผ ๋ณด์ด์ค์ฑํ ์ ๋๋๋ฉฐ ๋ฐฉ์ ๋ฐฐ์น๋ 3D ๋ฌผ์ฒด๋ฅผ ํด๋ฆญํด ์ฃผ์ด์ง ๋ฌธ์ ๋ฅผ ํ๊ณ ํ์ถํ ์ ์์ต๋๋ค. ์ ํ์๊ฐ ์์ ๋ฐฉ์ ํ์ถํด๋ณด์ธ์.
๊น๊ฐ์ | ์ต๊ท์ | ๋ฐ์์ฌ |
---|---|---|
@Kim gaeun | @Choi kyuwon | @Ban wonjae |
- Java 1.8.0
- Springboot 2.6.4
- Gradle 7.4
- MySQL 8.0.23
- Node.js 16.14.0
- Express 4.17.1
- Socket.io 2.3.0
- Nginx 1.14.0
- Mockito 4.4.0
Coding Convention
ยท Commit Convention
Coding Convention
- ํด๋๋ช ์ ์๋ฌธ์, Class๋ช ์ ์ฒซ ๊ธ์ ๋๋ฌธ์
- Method๋ lowerCamelCase์ ์ฌ์ฉํ๊ณ , ๋์ฌ๋ ์ ์น์ฌ๋ก ์์ํ๋ค. ex) get/set, init, is/has/can, create, find, to, A-By-B โฆ
- JUnit Test Method : Method๋ช _ํ ์คํธ์ํ_๊ธฐ๋ํ์ ex) isAdult_AgeLessThan18_False
Commit Convention
โ
์ ๋ค์ํฐ ์ปค๋ฐ ๋ฉ์์ง ์คํ์ผ ๊ฐ์ด๋ : ์ฐธ๊ณ
โ
๋ณธ๋ฌธ์๋ ๋ณ๊ฒฝํ class ์ด๋ฆ๊ณผ ์ด๋ป๊ฒ, ๋ฌด์์, ์ ๋ณ๊ฒฝํ๋์ง ์์ธํ ์ ๊ธฐ
์ปค๋ฐ ํ์
: ์ ๋ชฉ
//๋์ด์ฐ๊ธฐ
๋ณธ๋ฌธ
//๋์ด์ฐ๊ธฐ
(๊ผฌ๋ฆฌ๋ง ํ์
: #์ด์ ๋ฒํธ)
๐จ ์ปค๋ฐ ํ์
Docs: ๋ฌธ์ ์์
Feat: ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ
Fix: ๋ฒ๊ทธ๋ฅผ ๊ณ ์น ๊ฒฝ์ฐ
Refactor: ๋ฆฌํฉํ ๋ง
Comment: ์ฃผ์ ์ถ๊ฐ ๋ฐ ๋ณ๊ฒฝ
Rename: ํ์ผ ํน์ ํด๋๋ช
์์ , ๊ฒฝ๋ก ๋ณ๊ฒฝ
Remove: ํ์ผ ํน์ ๊ธฐ๋ฅ ์ญ์
Test: ํ
์คํธ ๊ด๋ จ ์์
Resolve conflicts: ์ถฉ๋ ๋ฐ์ commit์์ ์ฌ์ฉ(๋ณธ๋ฌธ, ๊ผฌ๋ฆฌ๋ง ์๋ต)
๐จ ๊ผฌ๋ฆฌ๋ง ํ์
Fixes: ์ด์ ์์ ์ค(์์ง ํด๊ฒฐ๋์ง ์์ ๊ฒฝ์ฐ)
Resolves: ์ด์ ํด๊ฒฐํ์ ๋
Ref: ์ฐธ๊ณ ํ ์ด์๊ฐ ์์ ๋
Error ๊ด๋ฆฌ
โ ๋ชจ๋ ์๋ฌ๋ Error Code๋ก ๊ด๋ฆฌ
- Error Code๋ง๋ค httpStatus / errorCode / errorMessage ์์ฑ
- ErrorCode๋ httpStatus๋ง๋ค ์ผ๋ จ๋ฒํธ๋ฅผ ๋ถ์ธ๋ค("httpStatus_number") ex) "400_3", "404_4"
๋ธ๋ ์น ๊ด๋ฆฌ
โ ๊ฐ์ธ๋ณ ๋ธ๋ ์น(gaeun, kyuwon, wonjae)์์ ์์
- push ์ ์ ํ ์คํธ์ฝ๋๋ฅผ ํต๊ณผํ๋์ง ํ์ธํ๊ธฐ
- ํ์์๊ฒ ๋ณ๊ฒฝ๋ ์ฌํญ ๊ณต์ ํ main์ PR
- ๊ฐ์ธ๋ณ ๋ธ๋ ์น๋ main์ pullํ์ฌ ๋ณ๊ฒฝ๋ ์ต์ ์ฌํญ ์ ๋ฐ์ดํธ
โ NodeJS๋ ๋ณ๋์ Repository์์ ๊ด๋ฆฌํ๋ฉฐ, main์ ๋ฐ๋ก push/pull
โ ๊ธฐ๋ฅ ๊ฐ๋ฐ์ ์ํด ๋ณ๋๋ก ํ ์คํธํ๋ ๊ฒฝ์ฐ์๋ ์๋ก์ด ๋ธ๋ ์น์์ ์์ : ์ดํ ๋ฐ์ ์ main์ผ๋ก PR ํ Close
- springRTC ๋ธ๋์น๋ spring์ ๊ธฐ๋ฐ์ผ๋ก webRTC๋ฅผ ๊ตฌํํจ.
- ๋ค๋ง 1๋1 P2P์ฐ๊ฒฐ์ ์ฑ๊ณตํ์์ผ๋ N:N ์ฐ๊ฒฐ์ด ๋์ง ์๋๋ค๋ ํ๊ณ๊ฐ ์กด์ฌํจ.
- ์ดํ์ Spring์ด ์๋ Node.js์ socket.io๋ฅผ ํ์ฉํ๊ฒ ๋๋ ๊ณ๊ธฐ๊ฐ ๋จ.
- redis ๋ธ๋์น๋ redis๋ฅผ ๋ถ๋ถ์ ์ผ๋ก ์ ์ฉํด๋ณด๋ ๋ธ๋์น์.
- ํ ํ๋ก์ ํธ ๊ธฐ๊ฐ ์ ํ ๋๋ฌธ์ ์ ๋๋ก ์ ์ฉํ์ง ๋ชปํ์์ผ๋ spring์ผ๋ก redis์ Clue๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ค๋ ๊ฒ์ ์ฑ๊ณตํจ.
์ด์ ๊ด๋ฆฌ
โ ์๋ก์ด Issue๊ฐ ์๊ธฐ๋ฉด ๋จผ์ GitHub Issues์ ์์ฑ
- bug, feature ์ค ํด๋น๋๋ Issue template ์ฌ์ฉ
- issue ์์ฑ ๋ด์ฉ ์ค ๋ณ๊ฒฝ์ฌํญ์ด ์๋ ๊ฒฝ์ฐ์๋ ํด๋น ๊ธ์ comment๋ ๋ณ๋ ์ด์๋ก ์์ฑํ์ฌ ์ ๋ฐ์ดํธ
โ ์๋ฃ๋ ์ด์๋ commit Resolves ์ฌ์ฉํด์ Close
โ ๊ด๋ จ๋ ์ด์๊ฐ ๋ง์ ๊ฒฝ์ฐ์๋ Milestones๋ฅผ ์ฌ์ฉํด์ ๊ด๋ฆฌ
API ๋ช ์ธ์
๐จ API ์ค๊ณ๊ท์น
Rest API URI ์ค๊ณ๊ท์น์ ๋ฐ๋ฅธ๋ค.
1. ํํ /๋ URI์ ํฌํจํ์ง ์๋๋ค.
2. ๊ณ์ธต๊ด๊ณ๋ฅผ ๋ํ๋ผ ๋ ์ฌ๋์ ๊ตฌ๋ถ์๋ฅผ ์ฌ์ฉํ๋ค. ex) /rooms/{roomId}/quizzes/{quizType}
3. ๊ธด path๋ฅผ ํํํ๋ ๊ฒฝ์ฐ์๋ ๊ฐ๋
์ฑ์ ๋์ด๊ธฐ ์ํด ํ์ดํ(-)์ ์ฌ์ฉํ๋ค.
4. ์ธ๋๋ฐ(_)๋ URI์ ์ฌ์ฉํ์ง ์๋๋ค.
5. URI๋ ๋ชจ๋ ์๋ฌธ์๋ก ์์ฑํ๋ค.
6. ํ์ผํ์ฅ์๋ URI์ ํฌํจํ์ง ์๋๋ค.
7. ๋ชจ๋ resource๋ ๋ณต์ํ์ ์ฌ์ฉํ๋ค.
๋ฉ์ธํ์ด์ง ์๋ฒ ๋ถํ ๋ฌธ์
๋ฉ์ธํ์ด์ง์์ ๋ณ๊ฒฝ๋ ๋ฐฉ ์ ๋ณด๋ฅผ ์ ๋ฐ์ดํธํ๊ธฐ ์ํด 1์ด ๊ฐ๊ฒฉ์ผ๋ก Room ๋ฆฌ์คํธ ์กฐํํ๊ธฐ api๋ฅผ ์์ฒญ(Polling)
๋ฉ์ธํ์ด์ง์ ์ ์์๊ฐ ์ง์ค๋๋ฉด ์๋ฒ ๋ถํ ์ฆ๊ฐ โ ๋ฐฐํฌ ์ดํ ๋ฉ์ธํ์ด์ง 40๋ช ์ ๋ ์ ์ํ๋ฉด์ CPU 90%๋ก ๊ธ์ฆ
๐ ์๋ฒ๋ฅผ t3.micro์ผ๋ก ๋ณ๊ฒฝ(CPU 1 โ 2)ํ์ฌ ์ฐ์ ์กฐ์น(๋ฉ๋ชจ๋ฆฌ๋ Swap์ผ๋ก ๋๋ ค๋์ 3G๋ก ์ถฉ๋ถํ๋ค๊ณ ํ๋จ)
๋ฉ์ธํ์ด์ง ์ ์์ ์์ ๋ฐ๋ฅธ ์๋ฒ ๋ถํ๋ฅผ ํ์ธํ๊ธฐ ์ํด ํ ์คํธ ์งํ
Client์ ๋ฉ์ธํ์ด์ง ์ ์์ ์๋ฅผ 10 ๋จ์๋ก ์ฆ๊ฐ์ํค๋ฉด์ CPU ์ฌ์ฉ๋์ ์ค์๊ฐ ๊ด์ฐฐ
โ CPU ์ฌ์ฉ๋์ด ๊ธ์ฆ โก ์ ์ฒด 200 ์ค 180%๊น์ง ์ฌ๋ผ๊ฐ๋ ์ง์ ์ ํ๊ณ๋ก ๋ด
- api ์์ฒญ ๊ฐ๊ฒฉ 1์ด(ํ์ฌ ์ํ) : 70๋ช
- api ์์ฒญ ๊ฐ๊ฒฉ 1.5์ด : 80๋ช
- api ์์ฒญ ๊ฐ๊ฒฉ 2์ด : 100๋ช
ํ์ฌ ์๋น์ค ์์ค์์ 70๋ช ์ด์์ด ๋ฉ์ธํ์ด์ง์ ์ ์ํ ๊ฐ๋ฅ์ฑ์ ๋ฎ๊ณ ,
์ ๋ฐ์ดํธ ๊ฐ๊ฒฉ์ 2์ด๋ก ๋๋ฆฌ๋ฉด ์คํ๋ ค ์ ์ ๊ฒฝํ์ด ์์ข์ ์ง๊ฑฐ๋ผ๊ณ ํ๋จ
์๋น์ค๊ฐ ์ฑ์ฅํ๋ค๋ฉด, Polling์ด ์๋๋ผ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์ ํด๊ฒฐ์ ์๋ํ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ!
WebRTC ์๋ฒ ๊ตฌ์ถ ๋ฌธ์
โ 4๋ช ๊น์ง ๋ณด์ด์ค ์ฑํ ์ด ๊ฐ๋ฅํ ํ๊ฒฝ์ ๋ง๋ค๊ธฐ ์ํด ์ด๋ค ์๋ฒ๋ฅผ ์ฌ์ฉํด์ผ ํ๋๊ฐ?
๐ ์ค๋์ค๋ง ์ฌ์ฉํ๊ณ , 4๋ช ๊น์ง๋ง ์ฐ๊ฒฐํ๊ธฐ ๋๋ฌธ์ signalling server๋ก๋ client ๋ถ๋ด์ด ํฌ์ง ์์ ๊ฑฐ๋ผ๊ณ ์๊ฐํ๊ณ , MCU, SFU๋ ํ๋ก์ ํธ ๊ธฐํ ๋ด์ ๊ตฌํํ๊ธฐ ์ด๋ ค์ธ ๊ฒ์ผ๋ก ํ๋จํ๋ค.
๐ Springboot๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋์ ์๋ฒ๋ง ๊ด๋ฆฌํ๋ฉด ๋๊ณ , ํ์๋ค ๋ชจ๋๊ฐ ์ต์ํ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๊ทธ๋ฌ๋ ์ฐธ๊ณ ์๋ฃ๊ฐ ๋ง์ง ์๋ค.
๐ NodeJS๋ฅผ ์ฌ์ฉํ๋ฉด Socket.io ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ๋น๊ต์ ์ฝ๊ฒ ๊ตฌํ์ด ๊ฐ๋ฅํ๋,
์๋ฒ๋ฅผ 2๊ฐ ๊ด๋ฆฌํด์ผ ๋๊ธฐ ๋๋ฌธ์ ์ ์ง๊ด๋ฆฌ์ ๋น์ฉ์ด ๋ ์๋ชจ๋๊ณ , ์ต์ํ์ง ์์ ์ธ์ด์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๐ Springboot๋ก signalling server๋ฅผ ๊ตฌ์ถํ๋ฉด ์๊ฐ์ด ๋ ์ค๋ ๊ฑธ๋ฆด ๊ฒ์ผ๋ก ์์ํ๊ณ ,
์ ํ๋ ์๊ฐ ์์ ์๋น์ค์ ์์ฑ๋๋ฅผ ๋์ด๊ธฐ ์ํด์๋ NodeJS์ Socket.io๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ํฉํ๋ค๊ณ ํ๋จ!
์ ์ disconnect ์ฒ๋ฆฌ ๋ฌธ์
๐ ์ ์ ๊ฐ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ข ๋ฃํ๋ฉด socket.io์ disconnect ์ด๋ฒคํธ๊ฐ ๋ฐ์
๐ Client๋ ๋ฐฉ์ฅ์ด ๋๊ฐ๋ฉด ์๋ก์ด ๋ฐฉ์ฅ์ ์์์ผํ๋ค(๋ฐฉ์ฅ๋ง ๊ฒ์ ์์ ๊ฐ๋ฅ!)
๐ DB์์๋ disconnect๋ ์ ์ ์ ๋ณด๋ฅผ ์ญ์ ํ๊ณ , ๋ฐฉ์ฅ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ ์ ๋ฐ์ดํธ ํ์
๐ nodeJS์์ disconnect์ event๋ฅผ ํตํด disconnect๋ ์ ์ ์ socket.id๋ฅผ Client๋ก ๋ณด๋
๐ Client๋ Spring์ผ๋ก HTTP ํต์ ์ ํตํด socket.id๋ฅผ ๋๊ฒจ์ฃผ๊ณ , ๋ฐฉ์ฅ์ด ๋ฐ๋ ๊ฒฝ์ฐ return ๊ฐ์ ๋ฐ์
๐ ์ ์ ๊ฐ 1๋ช ๋จ์๋๋ฐ disconnect๊ฐ ๋๋ฉด Client๊ฐ ์์ผ๋ฏ๋ก nodeJS์์ DB๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋
๐ disconnect์ DB์ ํ์ํ ์ ๋ฐ์ดํธ/์ญ์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๊ณ , ๋ฐฉ์ฅ์ด ๋ณ๊ฒฝ๋๋ฉด event๋ก ํด๋น ๋ฐฉ Client์๊ฒ ์๋ ค์ค
๊ฒ์ ํ๋ ์ด ์ค ๋์์ฑ ์ ์ด ๋ฌธ์
๐ ๊ฒ์ ์ค ๋ง์ถ ๋ฌธ์ ์(์ค์ฝ์ด), ์ฐฌ์ค๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ ํด๋น ๋ฐฉ Client ๋ชจ๋์๊ฒ ํด๋น ์ ๋ณด๋ฅผ ์ ๋ฐ์ดํธํด์ฃผ์ด์ผ ํจ
โ Socket.io์ ์ด๋ฒคํธ๋ฅผ ํ์ฉํด์ ์ค์ฝ์ด๋ ์ฐฌ์ค ๋ณ๊ฒฝ ์ด๋ฒคํธ ๋ฐ์ ์ ํด๋น ๋ฐฉ์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์ฌ์ค ์๋ ค์ฃผ์!
๐ HTTP ํต์ ์์๋ Client ์์ฒญ ์์ด Server๊ฐ Response ํ ์ ์์ผ๋ฏ๋ก socket ํต์ ์ ์ด์ฉํ๋ฉด ํด๊ฒฐํ ์ ์์!
๐ ํด์ฆ๋ฅผ ๋์์ ๋ณด๊ณ ์์ ๋๋ ํ ๋ช ์ด ๋ฌธ์ ๋ฅผ ํ๋ฉด ์ด๋ฒคํธ๋ฅผ ํ์ฉํด ์ด๋ฏธ ํผ ๋ฌธ์ ๋ก ๋ณ๊ฒฝ
CI/CD ์ ์ฉ
๐ ํ๋ก ํธ์ ๋ฐฑ์๋๋ฅผ ํฉ์น ์ดํ ์๊ธฐ์น ๋ชปํ๋ ๋ง์ ์๋ฌ๊ฐ ๋ฐ์ํจ
๐ ์ฆ์ ์๋ฌ์์ ์ผ๋ก ์ธํ ์๋ ๋ฐฐํฌ์ ๋๋ ์๊ฐ ์๋ชจ๊ฐ ์ ์ ๋ง์์ ธ ์๊ฐ ์ ์ฝ์ ์ํ์ฌ ๋ฐฐํฌ ์๋ํ ํ์
๐ Travis๋ฅผ ๋ ๋ง์ด ์ฐ๊ณ ๋ธ๋ก๊ทธ ์๋ฃ๋ ๋ง์์ง๋ง ๋ฐ๋ก ์๋ฒ ์ค์น๋ฅผ ํด์ผํจ
๐ Github Actions๋ ๋ณ๋์ ์๋ฒ ์ค์น์์ด Github์ ํตํด ๋ฐ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํจ
๐ ๊ธฐ๊ฐ์ด ํ์ ๋์ด ์์ด์ ๋ฐฐํฌ ์๋ํ ๊ตฌ์ถ์ ๋ง์ ์๊ฐ์ ์์ ์๊ฐ ์๋ค
๐ Travis๋ฅผ ์ฌ์ฉํ ๋งํผ ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ํฌ์ง ์๊ณ ์๋ฒ ์ค์น์ ๋ํ ์๊ฐ์ ์ฝ, ๊ทธ๋ฆฌ๊ณ Github์ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํด๋ณด๊ณ ์ถ์๋ ๋ง์์ด ์์ด์ Github Actions๋ฅผ ์ด์ฉํ์ฌ ๋ฐฐํฌ ์๋ํ๋ฅผ ๊ตฌ์ถํ๊ธฐ๋ก ๊ฒฐ์
ํ ์คํธ ์ฝ๋ ์ ์ฉ
๐ ๋ฐฐํฌ ์๋ํ๋ฅผ ๋์ ํ๊ธฐ ๋๋ฌธ์ ๊ฒ์ฆ๋์ง ์์ ์ฝ๋๋ค์ด ์๋์ผ๋ก ๋ฐฐํฌ๋ ์ ์์ด ์ฐจํ์ ๋ฌธ์ ํ์ ์ด๋ ค์์ด ์กด์ฌ.
---> ํ ์คํธ์ฝ๋๋ฅผ ํตํด ์ฌ์ ๊ฒ์ฆ์ ํ์์ฑ ์กด์ฌ.
ํ ์คํธ ์ฝ๋๋ฅผ ํตํด์ ์ฝ๋ ์์ฑ์์ ๊ณ ๋ คํ์ง ๋ชปํ๋ case์ ๋ํ ํ์ธ๊ณผ ๊ฐ์ ์ด ๊ฐ๋ฅ.
๋ฆฌํฉํ ๋ง์์ ๋น ๋ฅด๊ฒ ์ฝ๋๋ฅผ ๊ฒ์ฆ ๊ฐ๋ฅ.
๐ ๋จ์ ํ ์คํธ(QuizServiceTimeTest)์์ ClueRepository์ QuizRepository๋ฅผ @Mock์ผ๋ก ์ฒ๋ฆฌํ์ง ๋ชปํ๋ ๋ฌธ์ ๋ฐ์.
๐ ํตํฉ ํ ์คํธ์์ DI ๋ฐฉ๋ฒ์ผ๋ก @RequiredArgsConstructor๋ฅผ ํตํ ์์ฑ์ ์ฃผ์ ๋ฐฉ์์ด ์ ์ฉ ์๋๋ ๋ฌธ์ ๋ฐ์.
๐ ๋จ์ ํ ์คํธ์์ ์ค์ Quizservice์ ์กด์ฌํ๋ quizRepository.save(roomId)๊ณผ clueRepository.findAllByRoomId(room.getId())๋๋ฌธ.
@Mock์ผ๋ก ๋ง๋ค๋ ค๋ฉด when().thenReturn()๊ฐ์ ๋ฉ์๋๋ฅผ ๋ฐ๋์ ๋ช ์ํด์ค์ผํ๋๋ฐ ํ ์คํธ์ ์ ํํ RoomId๋ฅผ ์์๋ด๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅ.
---> when().thenReturn() ๋ฉ์๋ ์๋ ์ํจ.
๐ ํตํฉ ํ ์คํธ์์ DI ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ์ ์ฃผ์ ๋ฐฉ์(@RequiredArgsConstructor)์๋๋ ์ด์ ๋ difference in autowire handling between Spring and Spring integration with JUnit๋๋ฌธ.
์ฆ, JUNIT5๊ฐ DI๋ฅผ ์ค์ค๋ก ์ง์ํ๊ธฐ ๋๋ฌธ์ ์์ฑ์๋ lombok ๋ฐฉ์์ผ๋ก DI๊ฐ ๋์ง ์์.
๐ ๋จ์ํ ์คํธ์์ ๋ฐ๋ผ์ @Spy๋ฅผ ํตํด์ Stubbing ํ์ง ์์ ์ค์ ๊ฐ์ฒด๋ค์ @InjectMocks๋ฅผ ํตํด์ quizService์ ์ฃผ์ ์ํค๋ ๋ฐฉ์์ผ๋ก ํด๊ฒฐ.
--->๋จ์ ํ ์คํธ์ ๋ชฉ์ ์ด ํด์ฆ ์์ฑ ์๊ฐ ์ธก์ ์ ์์๊ธฐ ๋๋ฌธ์ Mock์ด ์๋ ์ค์ ๊ฐ์ฒด๋ค๋ก ์ฃผ์ ํ๋ ๊ฒ์ด ์คํ๋ ค ๋ ๋ซ๋ค ํ๋จ(์ค์ ๋ก ๊ฑธ๋ฆฌ๋ ์๊ฐ ์ธก์ ๊ฐ๋ฅ).
๐ ํตํฉํ ์คํธ์์ DI ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ์ ์ฃผ์ ๋ฐฉ์๋ง๊ณ @Autowired ๋ฐฉ์ ์ ํ.
Quiz ๋๋ค ๋ฌธ์
๐ ๊ฒ์์ฑ์ ์ํด ๋์ผํ Quiz๋ผ๋ Quiz์ ๋ต์ด ๋๋ค์ผ๋ก ์ ํด์ง๊ฒ ํ์!
๐ ๊ทธ๋ ์ง๋ง ํด๋น ๋ฐฉ ์์์๋ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ณด์ฌ์ผ ํจ
๐ ๋ฐฉ๋ง๋ค ๋ค๋ฅธ ๊ฐ์ผ๋ก Quiz๊ฐ ๊ตฌ์ฑ๋๋๋ก ํด์ฆ ์์ฑ ์๊ณ ๋ฆฌ์ฆ์ Random์ ํฌํจํ๋ฉด์, Quiz ์กฐํ API๊ฐ ์์ฒญ๋ ๋๋ง๋ค Quiz๋ฅผ ์๋ก ์์ฑ โ Quiz ํด๋ฆญ ์ ๋งค๋ฒ Quiz๊ฐ ๋ฌ๋ผ์ง๋ ๋ฌธ์ ๋ฐ์
๐ ๋ฐฉ ์์์๋ง ๋์ผํ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋ฐฉ ๋ง๋ค ์์ฑ๋ Quiz๋ฅผ DB์ ์ ์ฅ
๐ Quiz๋ฅผ ์์ฑํ๋ API๊ฐ ํธ์ถ๋๋ ์์ ์ ๋ฐฉ ๊ฐ์ค์ด ์๋ ๊ฒ์ ์์ ์ดํ๊ฐ ์ ์ ํ๋ค๊ณ ํ๋จ
: ๋ฐฉ ๊ฐ์ค ๋ Quiz ์์ฑํ๋ฉด ๋ฐฉ๋ง ๋ง๋ค๊ณ ๊ฒ์์ ์์ํ์ง ์์์ ๊ฒฝ์ฐ ์ถ๊ฐ ์ฒ๋ฆฌ ํ์
๐ ๋ฐฉ์ ์ ์ ์ค ํ ๋ช ์ด Quiz ์ค๋ธ์ ํธ๋ฅผ ํด๋ฆญํ์ ๋ DB์ ํด๋น Quiz๊ฐ ์์ผ๋ฉด ์์ฑ, ์์ผ๋ฉด ์กฐํํ๋๋ก ๊ตฌํ
: ์ด๋ฏธ ๊ฒ์ ์์ ๋ API๊ฐ ์ฌ๋ฌ ๊ฐ ํธ์ถ๋๊ณ ์์ด์ ์์ฒญ์ ๋ถ์ฐ์ํค๊ธฐ ์ํจ
ํ๋ก์ ํธ๋ฅผ ๋ง๋ฌด๋ฆฌํ๋ฉด์ ์์ฌ์์ด ๋จ์๋ ๋ถ๋ถ๋ค์ ๊ธฐ๋กํ๋ค. ํ๊ณ ๋ฅผ ํตํด ๋ค์ ํ๋ก์ ํธ์์๋ ๋ ์ํ์!
redis
โ๏ธ DB์ ์ ์ฅ๋๋ ๋ฐ์ดํฐ ์ค ๊ฒ์ ์ข
๋ฃ ํ ์ญ์ ๋๋ ๋ฐ์ดํฐ๋ ์ธ๋ฉ๋ชจ๋ฆฌ DB๋ฅผ ์ฌ์ฉํด๋ ์ข์์ ๊ฒ ๊ฐ๋ค.
๋, redis ๋ธ๋ ์น๋ฅผ ํตํด ์ผ๋ถ ๋ฐ์ดํฐ๋ก ํ
์คํธํด๋ณธ ๊ฒฐ๊ณผ ์กฐํ ์ฑ๋ฅ ๊ฐ์ ๊ฐ๋ฅ์ฑ์ ํ์ธํ ์ ์์๋ค.
ํ๋ก์ ํธ ์ด๊ธฐ์ ์ฐ๋ฆฌ ๋ฐ์ดํฐ์ ํน์ฑ์ ๊ณ ๋ คํ์ฌ redis๋ฅผ ๋์
ํ๋ค๋ฉด ๋ ์ฑ๋ฅ ๊ฐ์ ์ ํ ์ ์์์ ๊ฒ ๊ฐ๋ค๋ ์์ฌ์์ด ๋จ๋๋ค.
๋ก๊ทธ ๊ด๋ฆฌ
โ๏ธ ํ๋ก์ ํธ ๋ง๋ฌด๋ฆฌ ๋จ๊ณ์์ ๋ก๊ทธ ๊ด๋ฆฌ๋ฅผ ์ํด logback์ ์ค์ ํ์๋ค.
์ด์ ์๋ console์ ๋จ๋ ๋ก๊ทธ๋ ํ์ธํ์ง๋ง ํ์ผ๋ก ์ ์ฅํ๋ฉด ๋์ค์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ํ์ธํ ์ ์๊ณ ,
์ฝ๋๋ฅผ ์ง๋ฉด์ ์ค๊ฐ ์ค๊ฐ์ ํ์ํ ๋ก๊ทธ๋ฅผ ๋จ๊ฒจ ํ์ธํ๋ฉด ํจ์ฌ ๋ ์ข์์ ๊ฒ ๊ฐ๋ค.
๋ค์์ ํ๋ก์ ํธ๋ฅผ ํ๋ค๋ฉด ์ผ๋จ ์ค์ ์ ํด๋๊ณ ์์ํ ๊ฒ ๊ฐ๋ค!
ํ ์คํธ์ฝ๋
โ๏ธ ํ
์คํธ์ฝ๋ ์ญ์ ํ๋ก์ ํธ ๋ง๋ฌด๋ฆฌ ๋จ๊ณ์ ๋์
ํ๋ค.
๋์
์ดํ ๋ฆฌํฉํ ๋ง ํ๋ฉด์ ๋ฐ๋ก๋ฐ๋ก ํ
์คํธ์ฝ๋๋ก ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ์๋ํ๋์ง ํ์ธํ ์ ์์ด์ ์ข์๋ค.
ํ๋ก์ ํธ ์ด๊ธฐ์ ํ
์คํธ์ฝ๋ ์ ๋ต์ ๊ตฌ์ํด์ ๋จ์ํ
์คํธ ํน์ ํตํฉํ
์คํธ๋ฅผ ๊ฐ๋ฐ ์ผ์ ์ ๋ฐ๋ผ ๋์
ํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
์ค๋ฅ์ ๋ณด ์ฌ๋ก
โ ๏ธ ๊ฒ์ ํ๋ ์ด ์ค ๋ง์ถ ๋ฌธ์ ์๋ ๋จ์ ์ฐฌ์ค ์๊ฐ ์ ์์ ์ผ๋ก ๋ณ๊ฒฝ๋์ง ์๋ ๋ฌธ์ ์ ๋ณด
NodeJS์ undefined ์๋ฌ๋ก ์ธํด ์๋ฒ๊ฐ ์ฌ์์๋๋ฉด์ ๊ฐ ๋ธ๋ผ์ฐ์ ์ roomID ์ด๊ธฐํ
socket.io์ ๋ฐฉ ๊ตฌ๋ถ ๊ธฐ๋ฅ์ด ์ ์์ ์ผ๋ก ์๋ํ์ง ์์
๐ NodeJS์ ์๋ฌ๋ฅผ ํด๊ฒฐํ์ฌ ์๋ฒ๊ฐ ์ฌ์์๋์ง ์๋๋ก ์กฐ์น
๊ฐ์ ์ฌํญ ์ฌ๋ก
โ๏ธ "๋ง์ดํฌ๋ฅผ ์ฐจ๋จํ์ ๋ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์ ํ ์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค."
๋ธ๋ผ์ฐ์ ์ ๋ง์ดํฌ ์ฌ์ฉ ๊ถํ์ ์ ํํ๋ฉด ๊ฒ์ ํ๋ ์ด ๋ถ๊ฐ
๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ๊ถํ ํ์ฉ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ ์ฐฝ์ ๋์ ๋ค์ ์๋น์ค ์ด์ฉํ ์ ์๋๋ก ์๋ด
ban wonjae
๐ ์ฒ์์ node.js๋ ๋ณด์ด์ค ์ฑํ
๋ง ๋ค๋ฃจ๊ณ ๋๋จธ์ง ์ญํ ์ spring์์ ๋ด๋นํ๊ธฐ๋ก ํ์์
-> ์คํ๋ง์์ ํ ๋ฐฉ์ ์ธ์๋ค์ด ์ ๋ถ ๋ก๋ฉ์ด ๋ค ๋์๋์ง ์ฒดํฌ.
๐ ํด๋ผ์ด์ธํธ๋ค์ด ๊ฐ์ ๊ฒ์ ๋ก๋ฉ์ด ๋ค ์๋ฃ๋๋ฉด spring์ request๋ฅผ ๋ณด๋
->spring์์๋ request๊ฐ ์ฌ๋๋ง๋ค count๋ฅผ ์ธ์ count๊ฐ ํ์ฌ ํ ๋ฐฉ์ ์ธ์๋ค์ ์ซ์์ ๊ฐ์์ง๋ฉด ๊ฒ์์ ์์.
๐ ์ฌ๊ธฐ์ ๋ก๋ฉ์ค์ ๋๊ตฐ๊ฐ๊ฐ ๋๊ฐ๋ฉด ๋ฌดํ๋๊ธฐํ์์ด ๋ฐ์ํ ์ ์๋ค๊ณ ์๊ฐ.
์๋ํ๋ฉด ๋๊ฐ ์ฌ๋์ ์์ํ spring์ ๋ก๋ฉ์ด ๋ค ๋์๋ค๋ request๋ฅผ ๋ณด๋ด์ง ์๊ธฐ ๋๋ฌธ.
๐ ๊ตฌ์ฒด์ ์ผ๋ก ๋น์ ๋
ธ๋ socket์์ ์ ์ disconnect๊ฐ ๋ฐ์
-> ์คํ๋ง์์ 1. ๋ฐฉ์ฅ์ด ๋๊ฐ ๊ฒฝ์ฐ: ์๋ก์ด ๋ฐฉ์ฅ userId response. 2. ์ผ๋ฐ์ธ์ด ๋๊ฐ ๊ฒฝ์ฐ: null response.
-> ๊ทธ๋ฆฌ๊ณ ๋๊ฐ ์ ์ ์ ์ ๋ณด DB์์ ์ญ์ ํ๋ ๋ก์ง ์คํ.
๐ spring์์ ๊ฒ์ ๋ก๋ฉ ์ฒดํฌ
-> 1. false response 2. ๋ง์ง๋ง ์ธ์ํํ
๋ true response.
๐ ๋ฌธ์ ๋ ์์ ๋ก์ง๋ค์ด ๋์์ ๋ฐ์ํ๋ ๊ฒฝ์ฐ
-> ๊ฒ์ ๋ก๋ฉ์ค์ ๋ฐฉ์ฅ์ด disconnect๊ฐ ๋๋ค๋ฉด ์ต์
์ ๊ฒฝ์ฐ ์๋ก์ด ๋ฐฉ์ฅ userId,
๊ฒ์ ๋ฌดํ ๋๊ธฐ ํ์์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ง์ง๋ง ์ธ์๊น์ง ๋ก๋ฉ์ด ์๋ฃ๋์๋ค๋ true๊ฐ๋ ๋ณด๋ด์ค์ผํจ.
๐ ๋ฐ๋ผ์ disconnect์ responsedto์ ๊ฒ์ ๋ก๋ฉ์ฒดํฌ responsedto๋ ๊ฐ์์ผํจ.
์ฆ, ๋๊ตฐ๊ฐ๊ฐ ๋๊ฐ๋ค๋ฉด userID๋ง ๋๊ฒจ์ฃผ๋ ๊ฒ์ด ์๋๋ผ userId์ true, false๊ฐ์ ๊ฐ์ด ๋ณด๋ด์ค,
๋ฐ๋๋ก ๊ฒ์ ๋ก๋ฉ์ค์๋ true, false๋ฟ๋ง ์๋๋ผ userId๊น์ง ๋ณด๋ด์ค.
๐ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ํ๋ก ํธ์ชฝ์์ true ๋๋ false๊ฐ๋ ๋ฐ๋๊ฒ ๊ฐ๋ฅ
-> ๋ฌดํ๋๊ธฐํ์์ ํด๊ฒฐํ ์ ์๋ค ์๊ฐํจ.
๐ ์ฆ, ์ํฉ์ ๋ฐ๋ผ 1. ๊ฒ์๋ก๋ฉ X, ๋๊ตฐ๊ฐ๊ฐ ๋๊ฐ -> 1. ๋ฐฉ์ฅ์ด ๋๊ฐ๊ฒฝ์ฐ: {"userId" : "์๋ก์ด ID", "check": null}
2. ์ผ๋ฐ์ธ์ด ๋๊ฐ๊ฒฝ์ฐ: {"userId": null, "check": null}
๐ 2. ๊ฒ์๋ก๋ฉ O, ๋๊ตฐ๊ฐ๊ฐ ๋๊ฐ -> 1. ๋ฐฉ์ฅ์ด ๋๊ฐ๊ณ ๋๋จธ์ง ์ธ์ ์ ๋ถ ๋ก๋ฉ ์๋ฃ:{"userId": "์๋ก์ดID", "check": "true"},
2. ๋ฐฉ์ฅ์ด ๋๊ฐ์ง๋ง ๋๋จธ์ง ์ธ์์ด ์ ๋ถ ๋ก๋ฉ X: {"userId": "์๋ก์ดID", "check":null},
3. ์ผ๋ฐ์ธ์ด ๋๊ฐ๋๋ฐ ๋๋จธ์ง ์ ๋ถ ๋ก๋ฉ: {"userId" : null, "check": "true"},
4. ์ผ๋ฐ์ธ์ด ๋๊ฐ๋๋ฐ ๋๋จธ์ง ์ ๋ถ ๋ก๋ฉX: {"userId" : null, "check": "null"}
๐ 3. ์ผ๋ฐ์ ์ธ ๊ฒ์ ๋ก๋ฉ
--> 1. {"userId": null, "check": null} ... 2. ์ ์ผ ๋ง์ง๋ง ์ธ์ ๋ก๋ฉ: {"userId": null, "check":"true"}๋ก ์๋ตํ๋ ๊ฒ์ผ๋ก ํด๊ฒฐํ๊ณ ์ ํจ.
๐ ํ์ง๋ง disconnect๊ฐ ๋ฐ์ -> ๋ฐฉ ์ ์ฒด ์ธ์๋ค์ด Spring์ผ๋ก request๋ฅผ ๋ณด๋
-> disconnect ์ ์ ๋ฅผ ์ญ์ ํ๊ณ ์๋ก์ด ๋ฐฉ์ฅ์ ๋ง๋๋ ๋ก์ง์ด ์ฌ๋ฌ๋ฒ ๋ฐ์ํ๋ ๋ฌธ์ ์กด์ฌ.
๐ ๊ฒฐ๋ก ์ ์ผ๋ก node์์ socket disconnect์์ DB์์ ์ ์ ํ๋ฒ๋ง ์ญ์ ํ๊ณ ๋ฐฉ์ฅ ๋ณ๊ฒฝ๊น์ง ์ฒ๋ฆฌ.
๊ฒ์ ๋ก๋ฉ๋ node์์ ์งํ.