Syw.Frontend

๐Ÿงฉ Vue 2๋กœ ๋ฐฐ์šฐ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ธฐ์ดˆ

2๋‹จ๊ณ„. ๋„ฅ์ŠคํŠธ๊ณต๋ฌด์› ๋ฉ”์ธ Vue + Express๋กœ ๋กœ ํด๋ก ํ•˜๊ธฐ

2-8. Express API ๊ตฌ์ถ•๊ณผ ๋ฉ”์ธ ํŽ˜์ด์ง€ Axios ์š”์ฒญ

๐ŸŽฏ ๋ชฉํ‘œ

  • ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋ฅผ vue2-megagong-api ํด๋”์— ๋”ฐ๋กœ ๊ตฌ์„ฑ
  • JSON ํŒŒ์ผ์„ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ
  • ํ”„๋ก ํŠธ(Vue 2)์—์„œ Axios๋กœ API ์š”์ฒญํ•˜์—ฌ ๋ฉ”์ธ ์นด๋“œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

๐Ÿ“ ํด๋” ๊ตฌ์กฐ

vue2-megagong/
  โ””โ”€โ”€ src/
      โ””โ”€โ”€ components/
      โ””โ”€โ”€ views/
      โ””โ”€โ”€ App.vue
      โ””โ”€โ”€ main.js

vue2-megagong-api/
  โ”œโ”€โ”€ data/
  โ”‚   โ””โ”€โ”€ mainCards.json
  โ”œโ”€โ”€ server.js
  โ”œโ”€โ”€ package.json

๐Ÿ› ๏ธ 1. vue2-megagong-api Express ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

๐Ÿ“ฆ vue2-megagong-api/package.json

{
  "name": "vue2-megagong-api",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^5.1.0"
  },
  "devDependencies": {
    "nodemon": "^3.1.10"
  }
}

ํ˜น์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋ช…๋ น์–ด๋กœ ์„ค์น˜ํ•˜์‹œ๊ณ  scripts์˜ dev ๋ช…๋ น์–ด(nodemon server.js)๋ฅผ ๋”ฐ๋กœ ์ž‘์„ฑํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค.

cd vue2-megagong-api
npm init -y
npm i express cors
npm i -D nodemon

์ €์žฅ์†Œ๋กœ ๊ด€๋ฆฌํ•˜์‹œ๋Š” ๋ถ„๋“ค์„ ์œ„ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.

.gitignore

node_modules

๐Ÿ“„ vue2-megagong-api/data/mainSlides.json

[
  {
    "img": "https://img.megagong.net/m/2025/0724_pass/gong/pass_gong.png",
    "alt": "๋ฐฐ๋„ˆ1"
  },
  {
    "img": "https://img.megagong.net/m/2025/0724_pass/tech/pass_tech.png",
    "alt": "๋ฐฐ๋„ˆ2"
  },
  {
    "img": "https://img.megagong.net/m/2025/0724_pass/army/pass_army.png",
    "alt": "๋ฐฐ๋„ˆ3"
  }
]

๐Ÿ“„ vue2-megagong-api/server.js

const express = require('express');
const cors = require('cors');
const fs = require('fs');
const app = express();
const PORT = 4000;

app.use(cors());

app.get('/api/main-slides', (req, res) => {
  const data = fs.readFileSync('./data/mainSlides.json', 'utf-8');
  res.json(JSON.parse(data));
});

app.listen(PORT, () => {
  console.log(`๐Ÿš€ API ์„œ๋ฒ„ ์‹คํ–‰ ์ค‘: http://localhost:${PORT}`);
});

๐ŸŒ 2. vue2-megagong ํ”„๋ก ํŠธ์—”๋“œ์—์„œ Axios๋กœ API ์š”์ฒญ

๐Ÿ“ฆ ์„ค์น˜

npm install axios

๐Ÿ“„ src/components/MainSlide.vue

<template>
  <div class="main-slide">
    <swiper :options="swiperOption" class="swiper-container">
      <swiper-slide v-for="(item, i) in slides" :key="i">
        <img :src="item.img" :alt="item.alt" class="slide-img" />
      </swiper-slide>
      <div class="swiper-pagination" slot="pagination"></div>
      <div class="swiper-button-prev" slot="button-prev"></div>
      <div class="swiper-button-next" slot="button-next"></div>
    </swiper>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "MainSlide",
  data() {
    return {
      // slides: [
      //   { img: "https://img.megagong.net/m/2025/0724_pass/gong/pass_gong.png", alt: "๋ฐฐ๋„ˆ1" },
      //   { img: "https://img.megagong.net/m/2025/0724_pass/tech/pass_tech.png", alt: "๋ฐฐ๋„ˆ2" },
      //   { img: "https://img.megagong.net/m/2025/0724_pass/army/pass_army.png", alt: "๋ฐฐ๋„ˆ3" },
      // ],
      slides: [],
      swiperOption: {
        loop: true,
        autoplay: {
          delay: 3000,
        },
        pagination: {
          el: ".swiper-pagination",
          clickable: true,
        },
        navigation: {
          nextEl: ".swiper-button-next",
          prevEl: ".swiper-button-prev",
        },
      },
    };
  },
  async created() {
    try {
      const res = await axios.get("http://localhost:4000/api/main-slides");
      this.slides = res.data;
    } catch (error) {
      console.error("๋ฉ”์ธ ์Šฌ๋ผ์ด๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค", error);
    }
  },
};
</script>

<style>
.main-slide {
  width: 790px;
}
</style>

โœ… ์‹คํ–‰ ๊ฒฐ๊ณผ

  1. vue2-megagong-api ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ •์ƒ์ ์œผ๋กœ JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ด๋ณด์„ธ์š”.
cd vue2-megagong-api
npm run dev
  1. ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:4000/api/main-cards ์ ‘์†ํ•ด JSON ํ™•์ธ

  2. vue2-megagong์—์„œ ์นด๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ Œ๋”๋ง ๋˜๋Š”์ง€ ํ™•์ธ

FE ์ €์žฅ์†Œ

GitHub - heroyooi/vue2-megagong at ch8

BE ์ €์žฅ์†Œ

GitHub - heroyooi/vue2-megagong-api at ch8

๐ŸŽฏ ๋‹ค์Œ ๊ณผ์ œ

์•„๋ž˜ ์ปดํฌ๋„ŒํŠธ์—๋„ API๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์„ธ์š”!

  1. src\components\MainTabs.vue(๋„ฅ์ŠคํŠธ๊ณต๋ฌด์› 1์œ„ ๊ฐ•์‚ฌ์ง„), src\components\TeacherPromoSection.vue(์ง€๊ธˆ ์ฃผ๋ชฉํ•  ์„ ์ƒ๋‹˜ ๊ธฐํš์ „)
  2. axios ์š”์ฒญ์„ http://localhost:4000/api/promo-list ์ฃผ์†Œ๊ฐ€ ํฌํ•จ๋œ ๋ฐฉ์‹์ด ์•„๋‹Œ /api/promo-list ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ

๐Ÿ’ฌ ๋Œ“๊ธ€

    โ€ป ๋กœ๊ทธ์ธ ํ›„ ๋Œ“๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.