chat gpt์ ๋์์ ๋ฐ์ผ๋ฉฐ ์ผ๋จ ๋ฐฐํฌ ๋จผ์ ํด๋ณด์!๋ผ๋ ์๊ฐ์ผ๋ก ํ๋์ฉ ํด๋ณด๊ณ ์๋ค.
๋ชฉํ: Node.js + MongoDB ํ๋ก์ ํธ๋ฅผ GitHub Actions + DockerHub + Docker Compose + AWS EC2๋ฅผ ํ์ฉํด ์์ ์๋ํ + ์ค์ ๋ฐฐํฌ๊น์ง ํด๋ณด๊ธฐ
github ๋ ํฌ์งํ ๋ฆฌ 2๊ฐ์ push ๋์ด์๋ค.
devops-node-todo-api / compose-todo-api
devops-node-todo-api
compose-todo-api
์ฝ๋๋ฅผ ๊นํ๋ธ์ ์ฌ๋ ค๋์ผ๋ ์ฐธ๊ณ ํด์ ๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
mongoose.connect('mongodb://mongo:27017/todos')
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
์ดํ
docker build -t devops-node-todo-api
๋ฅผ ์ด์ฉํด ๋์ปค ์ด๋ฏธ์ง๋ฅผ ๋น๋ํด์ฃผ๊ณ
docker run -p 3000:3000 devops-node-todo-api
๋ฅผ ์จ์ ๋์ปค ์ปจํ
์ด๋๋ฅผ ์คํํด์ค๋ค.
-p 3000:3000 -> ๋ด ์ปดํจํฐ์ 3000๋ฒ ํฌํธ๋ฅผ ์ปจํ
์ด๋ ์์ 3000๋ฒ ํฌํธ์ ์ฐ๊ฒฐ
services:
backend:
build: ./backend
ports:
- "3000:3000"
depends_on:
- mongo
mongo:
image: mongo
ports:
- "27017:27017"
mongoose.connect('mongodb://mongo:27017/todos', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
useNewUrlParser๋ useUnifiedTopology๋ MongoDB ์ต์ ๋ฒ์ ์์๋ ํ์์๋ ์ต์
.
๊ทธ๋ฌ๋ mongoose.connect() ์์ฒด๋ ํ์๋ค. Node.js ์๋ฒ๊ฐ MongoDB์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ/์ฝ๊ธฐ ํ๋ ค๋ฉด Mongoose๊ฐ MongoDB ์๋ฒ์ "์ฐ๊ฒฐ"๋์ด ์์ด์ผํ๊ธฐ ๋๋ฌธ.
์์ ์ฝ๋
// MongoDB ์ฐ๊ฒฐ
mongoose.connect('mongodb://mongo:27017/todos')
.then(() => console.log('โ
MongoDB ์ฐ๊ฒฐ ์ฑ๊ณต!'))
.catch(err => console.error('โ MongoDB ์ฐ๊ฒฐ ์คํจ:', err));
์ดํ docker-compose up --build๋ฅผ ๋ค์ ํ๊ณ localhost:3000/todos์ ์ ์ํ๋ [] ์ด ๋ด๋ค(์ ์์ถ๋ ฅ)
๊ทธ๋ค์ VS Code REST Client ํ์ฅ์ผ๋ก POST /todos ์์ฒญ๋ ๋ณด๋ด๋ดค๋ค.
์ฌ๊ธฐ์์์ ๋ฌธ์ ๋
PUT๊ณผ DELETE๊ฐ ๋์ง ์์
ํ๋์ .http ํ์ผ์ GET, POST, PUT , DELETE๋ฑ ์ฌ๋ฌ ์์ฒญ์ ์ฐ์ต์ฉ์ผ๋ก ๋ค ๋ฃ์ ์ ์๋ค.
1. index.js์ PUT๊ณผ DELETE์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ฝ๋๋ฅผ ๋ฃ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ index.js์ PUT, DELETE ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.
// โ
ํ ์ผ ์์ (PUT)
app.put('/todos/:id', async (req, res) => {
const { id } = req.params;
const updated = await Todo.findByIdAndUpdate(id, { text: req.body.text }, { new: true });
if (updated) {
res.json(updated);
} else {
res.status(404).json({ error: "ํ ์ผ์ ์ฐพ์ ์ ์์ด์!" });
}
});
// โ
ํ ์ผ ์ญ์ (DELETE)
app.delete('/todos/:id', async (req, res) => {
const { id } = req.params;
const deleted = await Todo.findByIdAndDelete(id);
if (deleted) {
res.json({ message: "์ญ์ ์๋ฃ!" });
} else {
res.status(404).json({ error: "์ญ์ ํ ํญ๋ชฉ์ ์ฐพ์ ์ ์์ด์!" });
}
});
์์ ํ ์ ์ฒด .http ์ฝ๋
### ์ ์ฒด ํ ์ผ ๋ชฉ๋ก ์กฐํ
GET http://localhost:3000/todos
Accept: application/json
###
### ์๋ก์ด ํ ์ผ ์ถ๊ฐ (POST ์์ฒญ)
POST http://localhost:3000/todos
Content-Type: application/json
{
"text": "Docker Compose ์ค์ต ์ต๊ณ !"
}
###
### ํ ์ผ ์์ (PUT ์์ฒญ)
PUT http://localhost:3000/todos/์ฌ๊ธฐ์_์ค์ _ID_์
๋ ฅ
Content-Type: application/json
{
"text": "์์ ๋ ๋ด์ฉ์
๋๋ค!"
}
###
### ํ ์ผ ์ญ์ (DELETE ์์ฒญ)
DELETE http://localhost:3000/todos/์ฌ๊ธฐ์_์ค์ _ID_์
๋ ฅ
yml ์ฝ๋ ์ค ์ผ๋ถ
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/compose-todo-api ./backend
run: docker push ${{ secrets.DOCKER_USERNAME }}/compose-todo-api
๋ DockerHub ๋ก๊ทธ์ธ์์ ์กฐ๊ธ ๋งํ์๋ค.
์ค์: GitHub Secrets์ DOCKER_NAME์ด๋ผ๊ณ ์ฐ๊ณ yml์ DOCKER_USERNAME์ด๋ผ๊ณ ์ฐ๊ธฐ(๋ถ์ผ์น)
์ฌ๋ฌ๋ฒ์ push ๋์ ์ฑ๊ณต

์ฌ๊ธฐ๊น์งํ๋ฉด
GitHub์ ์ฝ๋ ํธ์ โ ์๋์ผ๋ก ์ต์ Docker ์ด๋ฏธ์ง๊ฐ ๋น๋๋จ
DockerHub์ latest ํ๊ทธ๋ก ์
๋ก๋๋จ
์ด์ ๋๊ตฌ๋ docker pull๋ก ๋ฐ์์ ์คํ ๊ฐ๋ฅํจ!
์ด ๊ฐ๋ฅํ๋ค
PORT=3000
MONGO_URL=mongodb://mongo:27017/todos
EC2 ์ธ์คํด์ค ๋ง๋ค๊ธฐ
chmod 400 ์ด๋ฆ.pem
ssh -i ์ด๋ฆ.pem ubuntu@ํผ๋ธ๋ฆญIP์ฃผ์
wsl์์ EC2๋ก ์ ์ํ ๋

์ด๋ฐ ๋ฌธ๊ตฌ๊ฐ ๋ ์ ์ข ๋นํฉํ๋๋ฐ, ๋ฆฌ๋
์ค๋ ๋งฅ์๋ SSH์ ๊ทผ์ ํญ์ ๋ฌผ์ด๋ณด๋ ์ง๋ฌธ์ด๋ผ๊ณ ํ๋ค.
[Linux / Mac] SSH ์ ๊ทผ์ "Are you sure you want to continue connecting (yes/no)?" ์์ด
์ด ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ์ฌ ํด๊ฒฐํ๋ค.
์ ์์ฑ๊ณต

๊ทธ๋ค์ ๋ค์ด๋ฐ์ .pem ํ์ผ์ wsl๋ก ์ฎ๊ฒจ์ค์ผํ๋๋ฐ,
explorer.exe .
์ด ๋ช ๋ น์ด๋ฅผ wsl์ ์ ๋ ฅํด์ ํ ์ ์์๋ค. ์ ๊ธฐํ๊ฒ ์๋์ฐ์ ํ์ผ ๋ณต์ฌํ๋ฏ์ด ctrl+c ctrl+v๊ฐ ๊ฐ๋ฅํ๋ค.
๋ฐฐํฌ ์๋ฃ

๋ญ๊ฐ ์ด๋ ๊ฒ ๋จ๋๋
curl http://localhost:3000/todos
์ ์ ๋ ฅํ๋ [] ์ด ์ ๋์๋ค.
์๊ฐ:
์ด๋ฒ ์ค์ต์ ํตํด ๋จ์ํ API ์๋ฒ๋ฅผ ๋์ด์ ๋์ปคํ โ ์๋ํ โ ๋ฐฐํฌ๊น์ง ํ ๋ฒ์ ๊ฒฝํํ ์ ์์ด ์ข์๋ค. ์์ง๋ ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง ๊ณ์ ํ๋ค๋ณด๋ฉด ์กฐ๊ธ์ด๋ผ๋ ์๊ฒ๋์ง ์์๊น.