Syw.Frontend

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

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

2-4. ์ง€๊ธˆ ์ฃผ๋ชฉํ•  ์„ ์ƒ๋‹˜ ๊ธฐํš์ „ UI ๊ตฌ์„ฑ

โœ… ํƒ€๊ฒŸ ๊ตฌ์กฐ

  • 2๋‹จ ๊ทธ๋ฆฌ๋“œ ์นด๋“œํ˜• ๋ ˆ์ด์•„์›ƒ
  • ๊ฐ ์นด๋“œ์—:
    • ๊ฐ•์‚ฌ ์ด๋ฆ„ + ์ง๋ ฌ
    • ํƒ€์ดํ‹€ (๊ตต๊ฒŒ)
    • ๋ถ€์ œ ์„ค๋ช…
    • ์šฐ์ธก ํ”„๋กœํ•„ ์ด๋ฏธ์ง€
  • ๋‘ฅ๊ทผ ๋ฐฐ๊ฒฝ ์นด๋“œ ์Šคํƒ€์ผ

๐Ÿ“ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์„ฑ

components/
โ”œโ”€โ”€ TeacherPromoCard.vue       โ† ์นด๋“œ 1๊ฐœ
โ”œโ”€โ”€ TeacherPromoSection.vue    โ† ์ „์ฒด ์„น์…˜
views/
โ”œโ”€โ”€ HomePage.vue               โ† ์‚ฝ์ž…

โœ… 1. TeacherPromoCard.vue

<template>
  <div class="promo-card">
    <div class="text-area">
      <h4 class="title">{{ title }}</h4>
      <p class="desc">{{ description }}</p>
      <p class="subject">{{ subject }} {{ name }}</p>
    </div>
    <img class="profile-img" :src="img" :alt="name" />
  </div>
</template>

<script>
export default {
  name: "TeacherPromoCard",
  props: {
    title: String,
    description: String,
    name: String,
    subject: String,
    img: String,
  },
};
</script>

<style scoped>
.promo-card {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #f9f9f9;
  border-radius: 16px;
  padding: 20px 24px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  transition: 0.2s ease;
}

.promo-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.text-area {
  flex: 1;
}

.title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 6px;
  color: #111;
}

.desc {
  font-size: 14px;
  color: #666;
  margin-bottom: 10px;
}

.subject {
  font-size: 13px;
  color: #333;
  font-weight: 500;
}

.profile-img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 50%;
  margin-left: 16px;
}
</style>

โœ… 2. TeacherPromoSection.vue

<template>
  <section class="teacher-promo-section">
    <h3 class="section-title">์ง€๊ธˆ ์ฃผ๋ชฉํ•  ์„ ์ƒ๋‹˜ ๊ธฐํš์ „</h3>
    <div class="grid">
      <TeacherPromoCard v-for="(card, i) in promoList" :key="i" v-bind="card" />
    </div>
  </section>
</template>

<script>
import TeacherPromoCard from "./TeacherPromoCard.vue";

export default {
  components: { TeacherPromoCard },
  data() {
    return {
      promoList: [
        {
          title: "ํ๋ฆ„์€ ์ƒˆ๋กญ๊ฒŒ, ๋ณธ์งˆ์€ ๊ทธ๋Œ€๋กœ\n2026 ์ „ํšจ์ง„ ์ปค๋ฆฌํ˜๋Ÿผ",
          description: "ํ๋ฆ„์€ ์ƒˆ๋กญ๊ฒŒ, ๋ณธ์งˆ์€ ๊ทธ๋Œ€๋กœ\n2026 ์ „ํšจ์ง„ ์ปค๋ฆฌํ˜๋Ÿผ",
          name: "์ „ํšจ์ง„",
          subject: "ํ–‰์ •๋ฒ•",
          img: "https://img.megagong.net/profphoto/gong/wjsgywls1/main_intro2.png",
        },
        {
          title: "๊ฐ„ํ˜ธ์ง ์ตœ์‹  ์ด์Šˆ ์ด์ •๋ฆฌ\nNEW ์›”๊ฐ„ ์†ก์•„๋ฆ„",
          description: "์ตœ์‹  ์ด์Šˆ๋ฅผ ๋ณด๋ฉด ์‹œํ—˜๋ฌธ์ œ๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค.",
          name: "์†ก์•„๋ฆ„",
          subject: "์ง€์—ญ์‚ฌํšŒ๊ฐ„ํ˜ธ",
          img: "https://img.megagong.net/profphoto/gong/megapassnurse/main_intro2.png",
        },
        {
          title: "2026 ๋ฐ•์ƒ๋ฏผ\nํ˜•์‚ฌ์ •์ฑ… ๊ฐœ๋… ์™„์„ฑ",
          description: "๋” ๊ฒฌ๊ณ ํ•˜๊ฒŒ ๋งŒ๋“  ์‹ฌํ™”์™„์„ฑ",
          name: "๋ฐ•์ƒ๋ฏผ",
          subject: "ํ˜•์‚ฌ์ •์ฑ…",
          img: "https://img.megagong.net/profphoto/gong/p3672303/main_intro2.png",
        },
        {
          title: "๊ฒฝ์„ ์‹ ๊ณต๋ฌด์› ์˜๋‹จ์–ด\n์ดˆ์Šคํ”ผ๋“œ ์•”๊ธฐ๋น„๋ฒ•",
          description: "์‹œํ—˜์— ๋งž๋Š” ์–ดํœ˜๋“ค ๋‹ค์‹œ ํƒœ์–ด๋‚ฌ๋‹ค!",
          name: "๊ฒฝ์„ ์‹",
          subject: "์˜์–ด",
          img: "https://img.megagong.net/profphoto/gong/incredvoc/main_intro2.png",
        },
        {
          title: "VocaGram ํ•˜ํ”„๋ชจ๊ณ \n๋ฐ•์ˆ˜์—ฐ ์˜์–ด",
          description: "ํ•˜ํ”„ ๋ชจ์˜๊ณ ์‚ฌ๋กœ ๋ฌธ์ œํ’€์ด ์ง‘์ค‘๋ ฅ UP",
          name: "๋ฐ•์ˆ˜์—ฐ",
          subject: "์˜์–ด",
          img: "https://img.megagong.net/profphoto/gong/sooyeon/main_intro2.png",
        },
        {
          title: "2026 ์ง์—…์ƒ๋‹ด์‹ฌ๋ฆฌํ•™\nNext Road ์ปค๋ฆฌํ˜๋Ÿผ",
          description: "๋‹ค์Œ ๋„์ „์ž๋„ ํ•ฉ๊ฒฉ์ž…๋‹ˆ๋‹ค.",
          name: "๊น€ํ˜•์ค€",
          subject: "์ง์—…์ƒ๋‹ด์‹ฌ๋ฆฌํ•™",
          img: "https://img.megagong.net/profphoto/gong/pt1969/main_intro2.png",
        },
      ],
    };
  },
};
</script>

<style scoped>
.teacher-promo-section {
  margin-top: 60px;
  padding: 0 20px;
  width: 790px;
}

.section-title {
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 24px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}
</style>

โœ… 3. HomePage.vue์— ์‚ฝ์ž…

import TeacherPromoSection from "@/components/TeacherPromoSection.vue";

export default {
  components: {
    ...,
    TeacherPromoSection,
  },
};
<!-- ๊ธฐ์กด ๊ตฌ์กฐ ์•„๋ž˜์— ์ถ”๊ฐ€ -->
<MainTabs />
<TeacherPromoSection />

๐ŸŽ‰ ๊ฒฐ๊ณผ

  • "์ง€๊ธˆ ์ฃผ๋ชฉํ•  ์„ ์ƒ๋‹˜ ๊ธฐํš์ „" ๋ ˆ์ด์•„์›ƒ์ด ์Šคํฌ๋ฆฐ์ƒท๊ณผ ๋™์ผํ•œ ๊ตฌ์กฐ๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค
  • ์นด๋“œ๋“ค์€ grid๋กœ 2์—ด ์ •๋ ฌ๋˜๊ณ , ๋ฐ˜์‘ํ˜• ๋Œ€์‘์€ ๋‹ค์Œ ๊ฐ•์—์„œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

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

์•„๋ž˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ณด์„ธ์š”!

  1. src\components\TeacherPromoSection.vue ์—์„œ ๋ฐ›์€ ์„ ์ƒ๋‹˜ ๊ธฐํš์ „ ๋ฐ์ดํ„ฐ์˜ title์ด๋‚˜ description์˜ ๊ฐ’ \n์„ ์ธ์‹ํ•ด์„œ src\components\TeacherPromoCard.vue ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ค„๋‚ด๋ฆผ์ด ๋˜๋„๋ก ์ฒ˜๋ฆฌ
  2. ๋ฉ”์ธ ์ „์ฒด๊ฐ€ ํ˜„์žฌ ๋ง‘์€ ๊ณ ๋”•์ฒด๋กœ ๋‚˜์˜ค๋Š”๋ฐ Noto Sans KR๋กœ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋„๋ก base.scss ๋‚ด๋ถ€ ์ˆ˜์ •

GitHub - heroyooi/vue2-megagong at ch4

๐Ÿ’ฌ ๋Œ“๊ธ€

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