관리 메뉴

열심히 일한 당신 떠나라

코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 16일차 본문

정보교육/프런트엔드

코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 16일차

@thiskorea 2024. 7. 8. 06:34

10장 데이터 통신하기


10.1 데이터 통신에서 알아야 할 개념

1. HTTP와 메서드

통신 프로토콜: 데이터 통신에 필요한 특정한 규칙과 규약

클라이언트에서 서버로 HTTP 요청

서버는 요청에 대해 HTTP 응답

주요 HTTP 메서드

GET: 데이터 가져오기

POST: 데이터 쓰기(추가하기)

PUT: 데이터 전체 변경하기

PATCH: 데이터 일부 변경하기

DELETE: 데이터 삭제하기

 

2. API

API: Application Programming Interface, 클라이언트와 서버는 HTTP를 사용해 데이터를 주고받을 때 필요한 데이터를 어떻게 요청하고 어떻게 응답받을지 정하는 약속

엔드포인트: 클라이언트에서 직접 API의 기능을 사용하려고 호출하는 끝점


10.2 Node.js로 웹 서버와 API 만들기

// vue.js.frontend/ch10/server/server.js
const express = require('express');
const fs = require('fs/promises');
const path = require('path');
const app = express();
const port = 3000;
const dataFilePath = path.join(__dirname, 'data.json');
app.use(express.json());
// CORS 에러 해결하기(server)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
  next();
});

// GET: 모든 데이터 가져오기
app.get('/api/data', async (req, res) => {
  try {
    const data = await readDataFile();
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});
// POST: 새로운 데이터 추가하기
app.post('/api/data', async (req, res) => {
  try {
    const newData = req.body;
    const data = await readDataFile();
    const writeData = {
      id: data.length + 1,
      name: `${newData.name} ${data.length + 1}`,
      description: `${newData.description} ${data.length + 1}`,
    };
    data.push(writeData);
    await writeDataFile(data);
    res.json(newData);
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
});
// PUT: 데이터 업데이트하기
app.put('/api/data/:id', async (req, res) => {
  try {
    const id = Number(req.params.id);
    const updatedData = req.body;
    const data = await readDataFile();
    const index = data.findIndex((item) => item.id === id);
    if (index !== -1) {
      data[index] = { ...data[index], ...updatedData };
      await writeDataFile(data);
      res.json(data[index]);
    } else {
      res.status(404).json({ error: 'Not Found' });
    }
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});
// PATCH: 데이터 부분 업데이트하기
app.patch('/api/data/:id', async (req, res) => {
  try {
    const id = Number(req.params.id);
    const partialData = req.body;
    const data = await readDataFile();
    const index = data.findIndex((item) => item.id === id);
    if (index !== -1) {
      data[index] = { ...data[index], ...partialData };
      await writeDataFile(data);
      res.json(data[index]);
    } else {
      res.status(404).json({ error: 'Not Found' });
    }
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});
// DELETE: 데이터 삭제하기
app.delete('/api/data/:id', async (req, res) => {
  try {
    const id = Number(req.params.id);
    const data = await readDataFile();
    const index = data.findIndex((item) => item.id === id);
    if (index !== -1) {
      const deletedItem = data.splice(index, 1)[0];
      await writeDataFile(data);
      res.json(deletedItem);
    } else {
      res.status(404).json({ error: 'Not Found' });
    }
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});
// Helper 함수: 데이터 파일 읽기
async function readDataFile() {
  const data = await fs.readFile(dataFilePath, 'utf-8');
  return data ? JSON.parse(data) : [];
}
// Helper 함수: 데이터 파일 쓰기
async function writeDataFile(data) {
  await fs.writeFile(dataFilePath, JSON.stringify(data, null, 2), 'utf-8');
}
app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});
// vue.js.frontend/ch10/server/data.json
[
  {
    "id": 1,
    "name": "update data",
    "description": "update description"
  },
  {
    "id": 2,
    "name": "new data 2",
    "description": "sample data 2"
  }
]


10.3 Fetch API로 데이터 통신하기

 

1. 기본문법

2. HTTP 메서드 사용법

3. 뷰에서 사용하기

// vue.js.frontend/ch10/src/App.vue
<script setup>
const getData = () => {
  fetch('/api/data')
    .then((response) => response.json())
    .then((result) => console.log(result))
    .catch((error) => console.error('데이터를 가져오던 중 에러 발생:', error));
};
const postData = () => {
  fetch('/api/data', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'new data',
      description: 'sample data',
    }),
  })
    .then((response) => response.json())
    .then((result) => console.log(result))
    .catch((error) => console.error('데이터를 추가하던 중 에러 발생:', error));
};
const putData = () => {
  fetch('/api/data/1', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: 'update data',
      description: 'update description',
    }),
  })
    .then((response) => response.json())
    .then((result) => console.log(result))
    .catch((error) =>
      console.error('전체 데이터를 업데이트하던 중 에러 발생:', error)
    );
};
const patchData = () => {
  fetch('/api/data/1', {
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      description: 'update description',
    }),
  })
    .then((response) => response.json())
    .then((result) => console.log(result))
    .catch((error) =>
      console.error('데이터를 부분 업데이트하던 중 에러 발생:', error)
    );
};
</script>
<template>
  <div>
    <button @click="postData">POST</button>
    <button @click="getData">GET</button>
    <button @click="putData">PUT</button>
    <button @click="patchData">PATCH</button>
  </div>
</template>

4. CORS 에러 해결하기

- 서버에서 해결하기

// CORS 에러 해결하기(server)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
  next();
});

- 클라이언트에서 해결하기

// CORS 에러 해결하기(client)
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
      },
    },
  },
})