Vue HTTP API 통신 방법 / json-server, axios 사용하여 게시판 구현

테스트용 JSON API 서버 설치

API 호출 테스트를 위한 가상 API 서버를 구축합니다.

json-server 라이브러리 설치

npm install -D json-server@0.17.4

-D 옵션은 개발용 의존성으로 설치하며, devDependencies에 추가합니다.
-G 옵션은 전역으로 설치되어 모든 프로젝트에서 CLI 명령어로 사용할 수 있습니다.

JSON Server 실행

npx json-server --watch db.json --port 5000

프로젝트 루트 경로에 db.json 자동 생성 후, 5000번 포트로 JSON 서버가 실행됩니다.
터미널에서 ctrl + c로 종료할 수 있습니다.

JSON Server 실행 스크립트 등록

"scripts": {
  "db": "json-server --watch db.json --port 5000"
}

package.json 파일에 JSON Server 실행 명령어를 스크립트로 등록할 수 있습니다.
npm run db 명령어로 JSON 서버를 쉽게 실행할 수 있게 됩니다.
뒤에 –delay 1000 옵션을 추가하면, API 서버 응답을 1초 지연시켜 로딩 테스트 시 유용합니다.

db.json 파일 예시

{
  "posts": [
    { "id": 1, "title": "제목1", "content": "내용1", "createdAt": "2022-01-04" },
    { "id": 2, "title": "제목2", "content": "내용2", "createdAt": "2024-05-12" },
    { "id": 3, "title": "제목3", "content": "내용3", "createdAt": "2024-07-15" },
    { "id": 4, "title": "제목4", "content": "내용4", "createdAt": "2025-10-06" },
    { "id": 5, "title": "제목5", "content": "내용5", "createdAt": "2025-12-12" }
  ]
}

게시글 객체들을 저장하고 있는 JSON server 데이터 파일 예시입니다.


Vue HTTP API 통신 방법

API 통신 모듈 설치

npm install axios
또는
npm i axios

서버와 통신하기 위한 비동기 통신 모듈 axios를 설치합니다.

axios API 통신 js 코드 작성

import axios from 'axios';

// db.json 파일에 작성한 posts 전체 데이터 조회
export function getPosts(params) {
  return axios.get('http://localhost:5000/posts', { params });
}

export function getPostById(id) {
  return axios.get(`http://localhost:5000/posts/${id}`);
}

export function createPost(data) {
  return axios.post('http://localhost:5000/posts', data);
}

export function updatePost(id, data) {
  // 데이터 전체 필드 수정 : put
  // 데이터 일부 필드 수정 : patch
  return axios.patch(`http://localhost:5000/posts/${id}`, data);
}

export function deletePost(id) {
  return axios.delete(`http://localhost:5000/posts/${id}`);
}

src/api 폴더 내에 js 파일 생성 후 위와 같이 작성합니다.

axios 모듈화 방법

import axios from 'axios';

function create(baseURL, options) {
  const instance = axios.create({
    baseURL: baseURL,
    ...options
  });
  또는
  const instance = axios.create(Object.assign({ baseURL }, options));
  // { baseURL } 객체 = { baseURL: baseURL } 객체 (ES6 단축 속성명 문법)

  return instance;
}

export const posts = create('http://localhost:5000/posts');

export const users = create('http://localhost:5000/users');

baseURL, 파라미터 옵션을 파라미터로 받아서 axios 인스턴스를 생성하는 JS 모듈을 생성합니다.
해당 모듈은 아래와 같이 import 후 사용할 수 있습니다.

// 현재 경로의 index.js 모듈 파일 import
import { posts } from '.';

export function getPosts(params) {
  return posts.get('/', { params });
}

export function getPostById(id) {
  return posts.get(`/${id}`); // id type이 Number인 경우, String으로 변환
}

axios 기본 URL 설정

import axios from 'axios';

axios.defaults.baseURL = import.meta.env.VITE_APP_API_URL;

export const API호출함수 = () => {
  return axios.get('/경로');
}

위와 같이, axios 객체에 baseURL을 설정해두면 더 간편하게 사용할 수 있습니다.
API 주소 변경 시에도 환경변수 값만 수정하면 됩니다.

데이터 전체 조회 API 함수 호출 Vue 코드

<script setup>
import { ref } from 'vue';
import { getPosts } from '@api/JS파일명';

const posts = ref([]);

// 날짜 내림차순 정렬 파라미터 정의
const params = ref({
  _sort: 'createdAt',
  _order: 'desc'
})

// 데이터 전체 조회 API 호출 함수 정의
const fetchPosts = async () => {
  try {
    const { data } = await getPosts(params.value);
    posts.value = data;
    또는
    ({ data: posts.value } = await getPosts(params.value));

  } catch (error) {
		console.error(error);
	}
}

// 데이터 전체 조회 API 호출
fetchPosts();
</script>

API 호출 응답을 반응형 데이터로 관리하고, template에 출력할 수 있습니다.
async await은 then()처럼 promise 기반 비동기 처리를 수행하며, 응답을 기다립니다.

게시글이 없는 경우 분기처리

<template>
  <template v-if="posts.length > 0">
    <div v-for="post in posts" :key="post.id">
      <h3></h3>
      <p></p>
    </div>
  </template>

  <template v-else>
    <div>작성된 글이 없습니다.</div>
  </template>
</template>

데이터 단건 조회 API 함수 호출 Vue 코드

<script setup>
import { ref } from 'vue';
import { getPostById } from '@api/JS파일명';
import { onMounted } from 'vue';

// Route로 전달된 :id를 props로 받음
const props = defineProps(['id']);

const post = ref({});

// 데이터 단건 조회 API 호출 함수 정의
const fetchPost = async () => {
  try {
    const { data } = await getPostById(props.id);
    setPost(data);

  } catch (error) {
		console.error(error);
	}
}

// 데이터 객체 저장 함수
const setPost = ({ title, content, createdAt }) => {
  post.value.title = title;
  post.value.content = content;
  post.value.createdAt = createdAt;
}

// 데이터 단건 조회 API 호출
onMounted(() => {
  fetchPost();
});

데이터 저장 API 함수 호출 Vue 코드

<template>
  <div>
    <form @submit.prevent="save">
      <input v-model="form.title" type="text" id="title" />
      <input v-model="form.content" type="text" id="content" />

      <button>저장</button>
    </form>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { createPost } from '@api/JS파일명';
import { useRouter } from 'vue-router';

const router = useRouter();

const form = ref({
  title: null,
  content: null,
});

// 데이터 생성 API 호출 함수 정의
const save = async () => {
	try {
		await createPost({
			...form.value, // form 객체 복사
			createdAt: Date.now(),
		});

		router.push({ name: '이동할페이지별칭' });

	} catch (error) {
		console.error(error);
	}
};
</script>

데이터 수정 API 함수 호출 Vue 코드

<template>
  <div>
    <form @submit.prevent="edit">
      <input v-model="form.title" type="text" id="title" />
      <input v-model="form.content" type="text" id="content" />

      <button>수정</button>
    </form>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { getPostById, updatePost } from '@api/JS파일명';
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();

// Route로 전달된 :id를 props로 받음
const props = defineProps(['id']);

const form = ref({
  title: null,
  content: null,
});

// 데이터 단건 조회 API 호출 함수 정의
const fetchPost = async () => {
  try {
    const { data } = await getPostById(props.id);
    setForm(data);

  } catch (error) {
		console.error(error);
	}
}

// 데이터 수정 API 호출 함수 정의
const edit = async () => {
  try {
    await updatePost(props.id, { ...form.value });

    router.push({ name: '이동할페이지별칭', params: { id: props.id } });

  } catch (error) {
		console.error(error);
	}
}

// 데이터 객체 저장 함수
const setForm = ({ title, content }) => {
  form.value.title = title;
  form.value.content = content;
}

// 데이터 단건 조회 API 호출
onMounted(() => {
  fetchPost();
});

게시글 상세 페이지에서 데이터 수정 API 호출하는 Vue 코드 예시입니다.

데이터 삭제 API 함수 호출 Vue 코드

<template>
  <div>
    <form @submit.prevent="remove">
      <input v-model="form.title" type="text" id="title" />
      <input v-model="form.content" type="text" id="content" />

      <button>삭제</button>
    </form>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { getPostById, deletePost } from '@api/JS파일명';
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();

// Route로 전달된 :id를 props로 받음
const props = defineProps(['id']);

const form = ref({
  title: null,
  content: null,
});

// 데이터 단건 조회 API 호출 함수 정의
const fetchPost = async () => {
  try {
    const { data } = await getPostById(props.id);
    setForm(data);

  } catch (error) {
		console.error(error);
	}
}

// 데이터 삭제 API 호출 함수 정의
const remove = async () => {
  try {
    if (confirm('삭제하시겠습니까?') === false) {
      return;
    }

    await deletePost(props.id);
    router.push({ name: '이동할페이지별칭' });

  } catch (error) {
		console.error(error);
	}
}

// 데이터 객체 저장 함수
const setForm = ({ title, content }) => {
  form.value.title = title;
  form.value.content = content;
}

// 데이터 단건 조회 API 호출
onMounted(() => {
  fetchPost();
});

게시글 상세 페이지에서 데이터 삭제 API 호출하는 Vue 코드 예시입니다.


JSON Server API 활용

페이징 기능 구현

<template>
  // 부트스트랩 네비게이션 바
  <nav class="mt-5" aria-label="Page navigation example">
    <ul class="pagination justify-content-center">
      // 이전 페이지
      <li class="page-item" :class="{ disabled: !(params._page > 1) }">
        <a class="page-link" href="#" aria-label="Previous" @click.prevent="goPrevPage">
          <span aria-hidden="true">&laquo;</span>
        </a>
      </li>

      // 페이지 번호 반복
      <li v-for="page in pageCount" :key="page" class="page-item" :class="{ active: params._page === page }">
        <a class="page-link" href="#" @click.prevent="goPage(page)">## 테스트용 JSON API 서버 설치

API 호출 테스트를 위한 가상 API 서버를 구축합니다.

### json-server 라이브러리 설치

npm install -D json-server@0.17.4

-D 옵션은 개발용 의존성으로 설치하며, devDependencies에 추가합니다.  
-G 옵션은 전역으로 설치되어 모든 프로젝트에서 CLI 명령어로 사용할 수 있습니다.

### JSON Server 실행

npx json-server –watch db.json –port 5000

프로젝트 루트 경로에 db.json 자동 생성 후, 5000번 포트로 JSON 서버가 실행됩니다.  
터미널에서 ctrl + c로 종료할 수 있습니다.

<mark>JSON Server 실행 스크립트 등록</mark>

“scripts”: { “db”: “json-server –watch db.json –port 5000” }

package.json 파일에 JSON Server 실행 명령어를 스크립트로 등록할 수 있습니다.  
npm run db 명령어로 JSON 서버를 쉽게 실행할 수 있게 됩니다.  
뒤에 --delay 1000 옵션을 추가하면, API 서버 응답을 1초 지연시켜 로딩 테스트 시 유용합니다.

### db.json 파일 예시

{ “posts”: [ { “id”: 1, “title”: “제목1”, “content”: “내용1”, “createdAt”: “2022-01-04” }, { “id”: 2, “title”: “제목2”, “content”: “내용2”, “createdAt”: “2024-05-12” }, { “id”: 3, “title”: “제목3”, “content”: “내용3”, “createdAt”: “2024-07-15” }, { “id”: 4, “title”: “제목4”, “content”: “내용4”, “createdAt”: “2025-10-06” }, { “id”: 5, “title”: “제목5”, “content”: “내용5”, “createdAt”: “2025-12-12” } ] }

게시글 객체들을 저장하고 있는 JSON server 데이터 파일 예시입니다.

---

## Vue HTTP API 통신 방법

### API 통신 모듈 설치

npm install axios 또는 npm i axios

서버와 통신하기 위한 비동기 통신 모듈 axios를 설치합니다.

### axios API 통신 js 코드 작성

import axios from ‘axios’;

// db.json 파일에 작성한 posts 전체 데이터 조회 export function getPosts(params) { return axios.get(‘http://localhost:5000/posts’, { params }); }

export function getPostById(id) { return axios.get(http://localhost:5000/posts/${id}); }

export function createPost(data) { return axios.post(‘http://localhost:5000/posts’, data); }

export function updatePost(id, data) { // 데이터 전체 필드 수정 : put // 데이터 일부 필드 수정 : patch return axios.patch(http://localhost:5000/posts/${id}, data); }

export function deletePost(id) { return axios.delete(http://localhost:5000/posts/${id}); }

src/api 폴더 내에 js 파일 생성 후 위와 같이 작성합니다.

<mark>axios 모듈화 방법</mark>

import axios from ‘axios’;

function create(baseURL, options) { const instance = axios.create({ baseURL: baseURL, …options }); 또는 const instance = axios.create(Object.assign({ baseURL }, options)); // { baseURL } 객체 = { baseURL: baseURL } 객체 (ES6 단축 속성명 문법)

return instance; }

export const posts = create(‘http://localhost:5000/posts’);

export const users = create(‘http://localhost:5000/users’);

baseURL, 파라미터 옵션을 파라미터로 받아서 axios 인스턴스를 생성하는 JS 모듈을 생성합니다.  
해당 모듈은 아래와 같이 import 후 사용할 수 있습니다.

// 현재 경로의 index.js 모듈 파일 import import { posts } from ‘.’;

export function getPosts(params) { return posts.get(‘/’, { params }); }

export function getPostById(id) { return posts.get(/${id}); // id type이 Number인 경우, String으로 변환 }


<mark>axios 기본 URL 설정</mark>

import axios from ‘axios’;

axios.defaults.baseURL = import.meta.env.VITE_APP_API_URL;

export const API호출함수 = () => { return axios.get(‘/경로’); }

위와 같이, axios 객체에 baseURL을 설정해두면 더 간편하게 사용할 수 있습니다.  
API 주소 변경 시에도 환경변수 값만 수정하면 됩니다.

### 데이터 전체 조회 API 함수 호출 Vue 코드
API 호출 응답을 반응형 데이터로 관리하고, template에 출력할 수 있습니다.  
async await은 then()처럼 promise 기반 비동기 처리를 수행하며, 응답을 기다립니다.

<mark>게시글이 없는 경우 분기처리</mark>

### 데이터 단건 조회 API 함수 호출 Vue 코드

### 데이터 수정 API 함수 호출 Vue 코드