[ SJCE ์คํฐ๋ / 4์ฃผ์ฐจ ] Docker, Redis, Nodejs(Async/Await), Coroutines
24.09.28(ํ )
[ ๐พ Server Part. ]
1. ์๋ฒ ์์ํ๊ธฐ(2) - pm2 ์ค์น
[ SJCE ์คํฐ๋ / 1์ฃผ์ฐจ ] 3-Tier Architecture ๊ธฐ๋ฐ ํด๋ผ์ด์ธํธ, ์๋ฒ ๊ฐ๋ฐ ์์ํ๊ธฐ
2024.08.24(ํ )์คํฐ๋ ๋ค์ผ๋ฉด์ ๋ ธ์ ์ ๋์ถฉ ์ ๋ฆฌํด ๋๊ณ ๋ค์ ์ ๋ฆฌํ๋ฉด์ ๋ธ๋ก๊ทธ๋ก ์ฎ๊ฒจ์ผ์ง ~ ํ๊ณ ์ด์ ์๊ฐ๋์ ์ ๋ฆฌ์ค .. ์ด๋ฒ ์คํฐ๋๋ ํด๋ผ์ด์ธํธ๋ถํฐ ์๋ฒ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊น์ง 3๊ณ์ธต ์ํคํ
record-coding53.tistory.com
1์ฃผ์ฐจ์์ Node์ Express๋ฅผ ์ค์นํ๋ค. ๋ณธ๊ฒฉ์ ์ผ๋ก ์๋ฒ ๊ฐ๋ฐ์ ์์ํ๊ธฐ ์ํ ์ธํ ์ ์งํํด ์ฃผ์๋ค.
1. pm2 ์ค์น
: pm2๋ Node.js ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ด๋ฆฌํ๊ณ ์ ์งํ๊ธฐ ์ํ ํ๋ก์ธ์ค ๊ด๋ฆฌ์๋ก, Node.js ์๋ฒ๋ฅผ ์ฝ๊ฒ ์คํํ๊ณ ์ฃฝ์ง ์๊ฒ ์ ์งํ๊ณ ์๋ ์ฌ์์ํ๊ณ ๋ก๊ทธ๋ ๋ณด๊ธฐ ํธํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ชจ๋์ด๋ค.
: node index.js ๋ช ๋ น์ด๋ก ์คํ ์ ๋ฐฑ๊ทธ๋ผ์ด๋๊ฐ ์๋๋ผ ํฌ๊ทธ๋ผ์ด๋(ํฐ๋ฏธ๋๊ณผ ์ง์ ์ฐ๊ฒฐ๋ ์ฑ๋ก ์คํ)๋ก ์คํํ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์์ ์ ํ ์ ์๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋(ํฐ๋ฏธ๋๊ณผ ๋ณ๊ฐ๋ก ๋ฐ๋ก ์คํ → ํฐ๋ฏธ๋์์ ๋ค๋ฅธ ์์ ๊ฐ๋ฅ) ์คํ๊น์ง ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๊ฒ์ด pm2์ด๋ค.
npm install -g pm2
์๋จ ๋ช ๋ น์ด๋ฅผ ํตํด ์ค์นํ๋ค
๐ pm2 ์ฌ์ฉ๋ฒ
1. watching ๋ชจ๋ ์ต์
: ์คํ๋ pm2 ์์ค์ฝ๋, ํ๋ก์ ํธ์ ๋ณ๊ฒฝ์ฌํญ์ด ์์ผ๋ฉด ์๋ ๋ฐ์ํ๊ณ ์ฌ์์
pm2 start index.js --name game-server --watch
pm2 start | PM2๋ก ์๋ก์ด ์ฑ(ํ๋ก์ธ์ค)์ ์คํํ๊ฒ ๋ค๋ ๋ช ๋ น์ด |
index.js | ์คํํ Node.js ํ์ผ (๋น์ ์ ์๋ฒ ์ง์ ์ ํ์ผ) |
--name game-server | ์คํํ๋ ์ฑ์ "game-server" ๋ผ๋ ์ด๋ฆ์ ๋ถ์ด๊ฒ ๋ค๋ ๋ป |
--watch | ํ์ผ ๋ณ๊ฒฝ์ฌํญ์ ์๋ ๊ฐ์งํด์ ์๋ฒ๋ฅผ ์๋์ผ๋ก ์ฌ์์ํ๊ฒ ๋ค๋ ์ต์ |
2. ์ฑ ์คํ
pm2 start index.js | ๊ธฐ๋ณธ ์คํ (index.js ์คํ) |
pm2 start index.js --name my-app | ์ด๋ฆ ์ง์ ํด์ ์คํ |
pm2 start index.js --watch | ์ฝ๋ ์์ ๊ฐ์งํด์ ์๋ ์ฌ์์ |
pm2 start ecosystem.config.js | ์ค์ ํ์ผ(ecosystem) ๊ธฐ๋ฐ ์ฌ๋ฌ ์ฑ ์คํ |
3. ์ฑ ์ค์ง / ์ฌ์์ / ์ญ์
pm2 stop all | ๋ชจ๋ ์ฑ ์ ์ง |
pm2 stop 0 | ID 0๋ฒ ์ฑ๋ง ์ ์ง |
pm2 stop app-name | ์ด๋ฆ์ด app-name์ธ ์ฑ ์ ์ง |
pm2 restart 0 | ID 0๋ฒ ์ฑ ์ฌ์์ |
pm2 restart app-name | ์ด๋ฆ์ด app-name์ธ ์ฑ ์ฌ์์ |
pm2 restart 0 --watch | ID 0๋ฒ ์ฑ ์ฌ์์ + ๋ณ๊ฒฝ ๊ฐ์ ์์ |
pm2 delete 0 | ID 0๋ฒ ์ฑ ์ญ์ |
pm2 delete app-name | ์ด๋ฆ์ด app-name์ธ ์ฑ ์ญ์ |
pm2 delete all | ๋ชจ๋ ์ฑ ์ญ์ |
4. ์ฑ ์ํ / ๋ก๊ทธ ๋ณด๊ธฐ
โญ๏ธ pm2 list | ํ์ฌ ์คํ ์ค์ธ ๋ชจ๋ ์ฑ ๋ชฉ๋ก ํ์ธ |
pm2 show 0 | ID 0๋ฒ ์ฑ์ ์์ธ์ ๋ณด ๋ณด๊ธฐ |
pm2 show app-name | ์ด๋ฆ์ด app-name์ธ ์ฑ ์์ธ์ ๋ณด ๋ณด๊ธฐ |
pm2 monit | ์ค์๊ฐ ๋ชจ๋ํฐ๋ง ๋์๋ณด๋ |
โญ๏ธ pm2 logs | ์ ์ฒด ๋ก๊ทธ ๋ณด๊ธฐ (์ค์๊ฐ) |
pm2 logs app-name | ํน์ ์ฑ ๋ก๊ทธ๋ง ๋ณด๊ธฐ |
pm2 flush | ์ ์ฅ๋ ๋ก๊ทธ ์ด๊ธฐํ (๋น์ฐ๊ธฐ) |
5. ์๋ฒ ์ฌ๋ถํ ๋๋น ์๋ ์ฌ์์ ์ค์
pm2 startup | ๋ถํ ์ PM2 ์๋ ์คํ ์คํฌ๋ฆฝํธ ์์ฑ |
pm2 save | ํ์ฌ ์คํ ์ค์ธ ์ฑ ์ํ ์ ์ฅ (startup ํ ํ์) |
pm2 resurrect | ๋ง์ง๋ง ์ ์ฅ๋ ์ํ๋ก ๋ณต๊ตฌ |
pm2 reset app-name | ์ฑ์ ์ํ (์ฌ์์ ํ์ ๋ฑ) ์ด๊ธฐํ |
+ index.js ์์ port๋ฅผ 80์ผ๋ก ๋ฐ๊พธ๋ฉด uptime์ด 5์ด์ ๋๋ก ์กํ(๊ทธ ์ฌ์ด์ restart๋ ๊ฒ). ์ดํ 80ํฌํธ ๊ฒฝ๋ก๋ก ์ ์ํ๋ฉด ์ ๋๋ค. ๋ฆฌ๋ ์ค ๊ณ์ด์ ์๋ฒ๋ 1000๋ฒ ์ดํ์ ํฌํธ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๋ฉด ๊ด๋ฆฌ์ ๊ถํ์ ํ์๋ก ํ๊ธฐ ๋๋ฌธ์ ๊ถํ์ ๋ฌผ์ด๋ณผ ์ ์๋ค.
2. ์๋ฒ ์์ํ๊ธฐ(2) - Docker, Redis ์์ํ๊ธฐ
OS์ ๊ตฌ์กฐ ์ฐจ์ด(Mac,Linux vs Windows)์ ๋ฐ๋ฅธ ์ค์น ํ์ผ์ ์ฐจ์ด๊ฐ ์กด์ฌํ๋ค. OS๋ง๋ค ๋ค ๋ฐ๋ก ์ค์นํ๊ธฐ ๋ฒ๊ฑฐ๋กญ๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ Docker๋ฅผ ์ฌ์ฉํ๋ค.
๐ 1. Client Device์ ๋น๋ ๋ค์์ฑ
Client device๋ ์ฌ์ฉ์์ ๋ฌผ๋ฆฌ์ ์ธ ํ๋์จ์ด/OS๋ฅผ ์๋ฏธํ๋ค.
Device OS ์์
PC | Windows, macOS |
๋ชจ๋ฐ์ผ | iOS (iPhone, iPad), Android (AOS, Android OS) |
โก ๊ฐ๊ฐ ์ด์์ฒด์ ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์,
๊ฐ ๋๋ฐ์ด์ค์ ๋ง๊ฒ ๋ฐ๋ก ๋น๋(์ปดํ์ผ)ํด์ ๋ฐฐํฌํด์ผ ํ๋ค.
- Windows์ฉ ์ฑ → .exe
- macOS์ฉ ์ฑ → .app
- iOS ์ฑ → .ipa
- Android ์ฑ → .apk
์ฆ, ํ๋์ ์์ค ์ฝ๋๋ผ๋ ๊ธฐ๊ธฐ๋ณ๋ก "ํฌ๋งท"๊ณผ "ํ๊ฒฝ"์ ๋ค๋ฅด๊ฒ ๋ง์ถฐ์ผ ํ๋ค๋ ์๋ฏธ์ด๋ค.
๐ ๏ธ 2. Docker๋?
Docker๋ ๋ค์ํ ์ด์์ฒด์ (OS) ํ๊ฒฝ์ ๊ด๊ณ์์ด, ์ปจํ ์ด๋๋ผ๋ ๊ฐ๋ฒผ์ด ๊ฐ์ํ๊ฒฝ ์์์ ํ๋ก๊ทธ๋จ์ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ํ๋ซํผ์ ๋๋ค.
โ ์ฝ๊ฒ ๋งํ๋ฉด:
- "์ด์์ฒด์ ์ข
๋ฅ๊ฐ ๋ญ๋ ์๊ด์์ด,
Docker๋ง ๊น๋ ค ์์ผ๋ฉด ์๋ฒ ์ธํ ์ ๋๊ฐ์ด ํ ์ ์๋ค!"
Linux (Ubuntu, RedHat, Rocky, CentOS) | ๊ฐ๋ฅ โ |
Windows Server | ๊ฐ๋ฅ โ |
macOS (๊ฐ๋ฐ์ฉ) | ๊ฐ๋ฅ โ |
โก ์ฆ, ์๋ฒ๋ง๋ค ๋ค๋ฅด๊ฒ ์ง์ ์ธํ ํ ํ์ ์์ด, Docker ์ปจํ ์ด๋ ์์ ๋ชจ๋ ์ธํ ์ ํต์ผํ ์ ์๋ค.
๐ณ 3. Docker์์ ์ค์นํ ์ ์๋ ๊ฒ๋ค
- Node.js
- MongoDB
- Redis
- Nginx
- MySQL
- PostgreSQL
โก ์ด๋ฐ ํ๋ก๊ทธ๋จ๋ค๋ Docker ์ด๋ฏธ์ง๋ฅผ ํตํด ์ฝ๊ฒ ์ค์น/์คํํ ์ ์๋ค.
docker pull redis
docker pull mongo
docker pull node
docker pull nginx
(๊ณต์ ์ธ์ฆ ๋งํฌ ์๋ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์์ ํ๋ค)
๐ฆ 4. Containers, Port, Files, Exec
โ Containers ์ฐฝ
- ํ์ฌ ์คํ ์ค์ธ Docker ์ปจํ ์ด๋๋ค์ ๊ด๋ฆฌํ๋ ๊ณณ
- ๊ฐ ์ปจํ ์ด๋๋ณ๋ก Port ์ค์ , ํ์ผ ์์คํ , ์คํ ์ํ ๋ฑ์ ํ์ธ ๊ฐ๋ฅ
โ Port
- ํธ์คํธ(์๋ฒ)์ ์ปจํ ์ด๋ ๊ฐ ํต์ ์ ์ฐ๊ฒฐํ๋ ๋ฌธ.
- ์: localhost:6379 → redis ์ฐ๊ฒฐ
โ Files
- ์ปจํ ์ด๋ ์์ ํ์ผ ์์คํ ํ์ธ ๊ฐ๋ฅ.
- Linux๋ macOS์ ํด๋ ๊ตฌ์กฐ์ ๊ฑฐ์ ๋น์ทํจ (ex. /etc, /var, /usr ๋ฑ)
โ Exec
- ์ปจํ ์ด๋ ์์ผ๋ก "๋ค์ด๊ฐ์" ๋ฆฌ๋ ์ค ๋ช ๋ น์ด๋ฅผ ์ง์ ์น ์ ์๋ ๊ธฐ๋ฅ.
docker exec -it container_name bash
- ์ด๊ฑธ๋ก ์ค์ ๋ฆฌ๋ ์ค ์๋ฒ์ฒ๋ผ ๋ช ๋ น์ด ์ ๋ ฅ ๊ฐ๋ฅ.
๐ 5. Bind Mounts vs Volume
๊ตฌ๋ถ ํน์งBind Mounts | ์๋ฒ์ ํน์ ํด๋์ ์ปจํ ์ด๋์ ํด๋๋ฅผ ์ง์ ์ฐ๊ฒฐ→ ์๋ฒ ํ์ผ์ ์์ ํ๋ฉด ์ปจํ ์ด๋์๋ ๋ฐ๋ก ๋ฐ์ |
Volumes | Docker๊ฐ ์์ฒด์ ์ผ๋ก ๊ด๋ฆฌํ๋ ์ ์ฅ๊ณต๊ฐ→ ์ปจํ ์ด๋ ์ญ์ ํด๋ ๋ฐ์ดํฐ ์ ์ง ๊ฐ๋ฅ (๋ฐฑ์ , ์ด๊ด ์ฉ์ด) |
โก ๊ฐ๋ฐ ์ด๋ฐ์๋ Bind Mounts ์ฌ์ฉํด์ ๋น ๋ฅด๊ฒ ์์ ํ๊ณ ,
์ด์(์ด์ ์๋ฒ)์์๋ ์์ ์ฑ๊ณผ ๋ฐฑ์
์ ์ํด Volume์ ๋ง์ด ์๋๋ค.
๐ 6. CommonJS vs ES6 ๋ชจ๋ ์์คํ
โ CommonJS (cjs)
- 2016๋ ์ด์ Node.js ํ์ค
- ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ/๋ด๋ณด๋ด๊ธฐ ๋ฐฉ์:
// ๋ถ๋ฌ์ค๊ธฐ
const express = require('express');
// ๋ด๋ณด๋ด๊ธฐ
module.exports = someFunction;
โก ์๋ฒ ์ฌ์ด๋(Node.js)์์ ์ฃผ๋ก ์ฌ์ฉ๋์.
โ ES6 Modules (esm)
- ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ค (ECMAScript 2015)
- ๋ธ๋ผ์ฐ์ /Node.js ๋ ๋ค ์ฌ์ฉํ ์ ์์
// ๋ถ๋ฌ์ค๊ธฐ
import express from 'express';
// ๋ด๋ณด๋ด๊ธฐ
export default someFunction;
โก ํ๋ก ํธ์๋(Vue, React ๋ฑ)์์๋ ์ฃผ๋ก ES6 ๋ชจ๋์ ์ฌ์ฉ.
๐ฅ cjs vs es6 ์ ๋ฆฌ
๊ตฌ๋ถ CommonJS (cjs) ES6 Modules (esm)์ฌ์ฉ๋ฒ | require / module.exports | import / export |
๊ธฐ๋ณธ ์ ์ฉ | ์์ Node.js | ์ต์ Node.js, ๋ธ๋ผ์ฐ์ |
ํน์ง | ๋๊ธฐ ๋ก๋ฉ | ๋น๋๊ธฐ ๋ก๋ฉ ์ง์ |
ํ์ผ ํ์ฅ์ | .js (๊ธฐ๋ณธ) | .mjs ๋๋ package.json ์ค์ ํ์ |
์ด๋ค ๋ชจ๋์ ์ฌ์ฉํ๋์ง์ ๋ฐ๋ผ (๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ๋ผ) cjs ๋ฐฉ์์ด๋ esm ๋ฐฉ์ ์ค ํ๋๋ฅผ ๋ง์ถฐ์ผ ํฉ๋๋ค!
์ฐ์ ๋์ปค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ค์นํด ์ค๋ค.
์ฐธ๊ณ ๋ก, ๋์ปค์ ๊ด๋ จ๋ ์๋น์ค๋ค์ ๋ชจ๋ Linux ๊ธฐ๋ฐ์ผ๋ก ์ค์น๋๋ค. (containers ์ฐฝ์ port > files๋ฅผ ์ด๋ํด๋ณด๋ฉด Linux๋ mac์ ๊ตฌ์กฐ์ ํ์ผ ๊ตฌ์กฐ๊ฐ ๊ฑฐ์ ๋์ผํจ์ ์ ์ ์๋ค)
Step 1. Docker Desktop Install
- mac : https://docs.docker.com/desktop/install/mac-install/
- windows : https://docs.docker.com/desktop/install/windows-install/
์๋จ ๋งํฌ์์ Docker.dmg๋ฅผ ๋ค์ด๋ฐ๊ณ ๋๋๊ทธ์ค ๋๋กญํ๋ GUI ๋ฐฉ์์ผ๋ก ์ค์น๋ฅผ ์งํํ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ๊ฐ ๊ฝค ์๋ค..
ํ๋จ ๋ช ๋ น์ด๋ฅผ ํตํด, CLI ๋ฐฉ์์ผ๋ก ์ค์น๋ฅผ ์งํํ์.
sudo hdiutil attach Docker.dmg sudo /Volumes/Docker/Docker.app/Contents/MacOS/install sudo hdiutil detach /Volumes/Dockerโ
์ฐธ๊ณ โก๏ธ https://docs.docker.com/desktop/setup/install/mac-install/
Step 2. Redis, Mongo ์ด๋ฏธ์ง ์ค์น
: ์ธ์ฆ ํ์๋ฅผ ์ ํ์ธํด์ ์ค์นํ ๊ฒ
์ฐ์ ์ค์น๊น์ง๋ง ํด๋๊ณ optional settings ์ค์ ๊ณผ ๋์ฐ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ ํ์คํ๊ฒ ๋ค.
3. ๋๊ธฐ / ๋น๋๊ธฐ
๋๊ธฐ : ํ๋์ ์์ ์ด ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ค์ ์์ ์ ์คํ
๋น๋๊ธฐ : ์ ํ ์์ ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ณ๋ ฌ์ ์ผ๋ก ์์ ์ฒ๋ฆฌ
Await : ๊ธฐ๋ค๋ ค๋ผ! <- ๋๊ธฐ ๋ฐฉ์
Async/Await : ๋น๋๊ธฐ ์์ ์ ๋๊ธฐ ์ฒ๋ฆฌ ๋ฐฉ์
cf) ๋น๋๊ธฐ ์ฒ๋ฆฌ ํจํด Promise
์ฌ์ฉํ๋ ์ด์ ?
Redis์ ๊ฐ์ DB์ ์ฐ๊ฒฐ(connect)์ด ์๋ฃ๋ ์ดํ์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํด์ผ ํ๋ค๋ฉด, ๋น๋๊ธฐ ์์ ์ ์์๋ฅผ ๋ณด์ฅํ ํ์๊ฐ ์๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์กฐํ ์์ ์ DB ์ฐ๊ฒฐ์ด ๋์ง ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค. ์ด๋ฐ ๊ฒฝ์ฐ await๋ฅผ ์ฌ์ฉํ๋ฉด DB ์ฐ๊ฒฐ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ ๊ทธ ๋ค์ ์์ ์ ์ฒ๋ฆฌํ ์ ์์ด ์์๋ฅผ ๋ณด์ฅํ ์ ์๋ค.
- await ๊ตฌ๋ฌธ์ ๋ง์ง๋ง๊น์ง ๋ค ์ํํ๊ณ ๋ ๋ค ๋ค์ ์ฝ๋ ์ํ
- ๋น๋๊ธฐ๋ ํ๋ก์ธ์ค๊ฐ ๋ถ๋ฆฌ๊ฐ ๋จ
์๊ฐ ์ง์ฐ ํจ์ setTimeout์ผ๋ก delay ํจ์ ๊ตฌํ
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function fetchUserInfo() {
await delay(1000); // 1์ด ๋๊ธฐ
console.log("์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ต๋๋ค.");
}
Node express์ get ์์ฒญ๊ณผ Redis Client์ set์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ ๋ณด ๋๊ฒจ์ฃผ๊ธฐ
app.get("/user", async (req, res) => {
await redisClient.set("user", JSON.stringify({ name: "ํฌ" }));
const user = await redisClient.get("user");
res.send(user);
});
[ ๐ฅ๏ธClient Part. ]
1. ์ฝ๋ฃจํด(Coroutines) ๋ฐ ํด๋ผ์ด์ธํธ-์๋ฒ ์ฐ๊ฒฐ
๐ก ์ฝ๋ฃจํด์ด๋?
: ์ฝ๋ฃจํด์ ์ ๋ํฐ์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ(ํน์ ์๊ฐ ๊ฐ๊ฒฉ ์ฒ๋ฆฌ)๋ฅผ ํ ์ ์๋๋ก ๋์์ฃผ๋ ํน์ํ ํจ์์ด๋ค. ์ผ๋ฐ ํจ์์๋ ๋ฌ๋ฆฌ ์ค๊ฐ์ ๋ฉ์ท๋ค๊ฐ(yield) ๋์ค์ ๋ค์ ์ด์ด์ ์คํํ ์ ์๋ค.
IEnumerator MyCoroutine() {
for (int i = 0; i < 10; i++) {
Debug.Log($"๋ก๊ทธ ์ถ๋ ฅ {i + 1}");
yield return new WaitForSeconds(1f); // 1์ด ๋๊ธฐ
}
}
- IEnumerator: ์ฝ๋ฃจํด ํจ์๋ ๋ฐ๋์ ์ด ๋ฐํ ํ์ ์ ์ฌ์ฉํด์ผ ํจ
- yield return: ์ค๊ฐ์ ์ ์ ๋ฉ์ท๋ค๊ฐ ๋ค์ ์ด์ด์ ์คํํ ์ ์๋๋ก ํ๋ ํค์๋
- StartCoroutine(MyCoroutine()): ์ฝ๋ฃจํด์ ์์ํ ๋ ์ฌ์ฉ
๐ ํด๋ผ์ด์ธํธ-์๋ฒ ์ฐ๊ฒฐ ์ค์ต
์ ๋ํฐ์์ ์ธ๋ถ ์๋ฒ(Redis ๋ฑ)์ ์ฐ๋ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ธฐ๋ณธ ํ๋ฆ์ด๋ค.
- ๋ก๊ณ ์ฌ์ ๋ฒํผ ์์ฑ
- ์๋ฒ ์ฐ๊ฒฐ ํ ์คํธ๋ฅผ ์ํ UI ๋ฒํผ์ ์์ฑํฉ๋๋ค.
- UI → Button ์ ํ ํ ์ ์ ํ ์์น์ ๋ฐฐ์น.
- ๋คํธ์ํฌ ๋งค๋์ ์ค๋ธ์ ํธ ์์ฑ
- ๋น GameObject๋ฅผ ์์ฑํ๊ณ ์ด๋ฆ์ NetworkManager๋ก ์ง์ ํฉ๋๋ค.
- ๋คํธ์ํฌ ๋งค๋์ ์คํฌ๋ฆฝํธ ์์ฑ
- NetworkManager.cs๋ผ๋ ์ด๋ฆ์ผ๋ก C# ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๊ณ , ๋ค์๊ณผ ๊ฐ์ ์ฝ๋ ์์ฑ
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class NetworkManager : MonoBehaviour {
public void OnConnectButtonClicked() {
StartCoroutine(GetDataFromServer());
}
IEnumerator GetDataFromServer() {
string url = "http://<์๋ฒ์ฃผ์>/api/test"; // ์ค์ ์๋ฒ ์ฃผ์๋ก ๋ณ๊ฒฝ
UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success) {
Debug.Log("์๋ฒ ์๋ต: " + request.downloadHandler.text);
} else {
Debug.LogError("์๋ฒ ์ฐ๊ฒฐ ์คํจ: " + request.error);
}
}
}
4. ๋ฒํผ๊ณผ ์คํฌ๋ฆฝํธ ์ฐ๊ฒฐ
- ๋ฒํผ์ OnClick() ์ด๋ฒคํธ์ NetworkManager ์ค๋ธ์ ํธ๋ฅผ ๋ฑ๋กํ ๋ค, OnConnectButtonClicked ํจ์๋ฅผ ์ฐ๊ฒฐ
5. ํ ์คํธ ๋ฐ์ดํฐ ํ์ธ
- ์๋ฒ๊ฐ ๋์์ ธ ์๋ ์ํ์์ ๋ฒํผ ํด๋ฆญ ์ Redis์ ์ ์ฅ๋ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋์ง ํ์ธ
๊ทธ๋ฆฌ๊ณ ์ง๋ ์ฃผ ๊ณผ์ ์๋ ์บ๋ฆญํฐ์ ๋ชฌ์คํฐ๊ฐ ์ถฉ๋ ์ ์ผ์ ํ์ ๊ณต๊ฒฉ ์ดํ ๋ค์ ์ง๋๊ฐ๊ฒ๋ ๊ตฌํ๋ ๋ง๋ฌด๋ฆฌํ๋ค โ๐ป