Syw.Frontend

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

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

2-5. ์ปจํ…์ธ  ์šฐ์ธก ์˜์—ญ UI ๊ตฌํ˜„

๐ŸŽฏ ํ•™์Šต ๋ชฉํ‘œ

  • ๋ฉ”์ธ ์Šฌ๋ผ์ด๋“œ ์˜ค๋ฅธ์ชฝ ์˜์—ญ์— ์žˆ๋Š” ์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธ ๊ตฌํ˜„
  • ๊ฐ ์ฝ˜ํ…์ธ ๋Š”:
    • ์•„์ด์ฝ˜ or ์ธ๋„ค์ผ ์ด๋ฏธ์ง€
    • ์ œ๋ชฉ + ์งง์€ ์„ค๋ช…
  • 1์—ด ์„ธ๋กœ ๋ฐฐ์น˜ ์นด๋“œ + ๋ฐ˜์‘ํ˜• ๋Œ€์‘ ํฌํ•จ

โœ… ๊ตฌ์„ฑ ์˜ˆ์‹œ

ํ•ญ๋ชฉ ๋‚ด์šฉ
๊ตฌ์กฐ MainRightContent.vue
ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ RightCard.vue (์ฝ˜ํ…์ธ  1๊ฐœ ์นด๋“œ)
๋ฐฐ์น˜ ์œ„์น˜ StickyPanel.vue ๋‚ด๋ถ€ (๊ธฐ์กด MainSlide ์šฐ์ธก์— ๊ณ ์ •๋œ ์˜์—ญ)

๐Ÿ“ ํด๋” ๊ตฌ์„ฑ

components/
โ”œโ”€โ”€ MainRightContent.vue   โ† ์ „์ฒด ๋ฆฌ์ŠคํŠธ
โ”œโ”€โ”€ RightCard.vue          โ† ์ฝ˜ํ…์ธ  ์นด๋“œ 1๊ฐœ
โ””โ”€โ”€ StickyPanel.vue        โ† ๊ธฐ์กด ํŒŒ์ผ, ๋‚ด๋ถ€์— MainRightContent ์ถ”๊ฐ€
โ””โ”€โ”€ TeacherPromoSection.vue โ† ๊ธฐ์กด ํŒŒ์ผ, scss ์ˆ˜์ •

views
โ”œโ”€โ”€ HomePage.vue           โ† ๋ฉ”์ธ ํŽ˜์ด์ง€ scss ์ˆ˜์ •

โœ… 1. RightCard.vue

<template>
  <div class="right-card">
    <img class="icon" :src="img" :alt="title" />
    <div class="text">
      <p class="title">{{ title }}</p>
      <p class="desc">{{ description }}</p>
    </div>
  </div>
</template>

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

<style lang="scss" scoped>
.right-card {
  display: flex;
  align-items: center;
  margin-bottom: 22px;
  transition: 0.2s ease;
  &:last-of-type {
    margin-bottom: 0;
  }
}

.icon {
  width: 140px;
  height: 90px;
  object-fit: cover;
  margin-right: 12px;
  border-radius: 8px;
}

.text .title {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 4px;
}

.text .desc {
  font-size: 12px;
  color: #666;
}
</style>

โœ… 2. MainRightContent.vue

<template>
  <div class="right-section">
    <RightCard
      v-for="(item, i) in items"
      :key="i"
      :img="item.img"
      :title="item.title"
      :description="item.description"
    />
  </div>
</template>

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

export default {
  components: { RightCard },
  data() {
    return {
      items: [
        {
          img: "https://files.megagong.net/board_data/banner/main/97372942848_20250718175514.png",
          title: "2026 ์ปค๋ฆฌํ˜๋Ÿผ ์•ˆ๋‚ด",
          description: "์ „๋ฒ”์œ„ ํƒ„ํƒ„ํ•œ ๊ฐœ๋…์ดํ•ด์™€ \n์ถ”๋ก ํ›ˆ๋ จ์œผ๋กœ ๊ณ ๋“์  ์™„์„ฑ",
        },
        {
          img: "https://files.megagong.net/board_data/banner/main/111851706690_20250711084722.png",
          title: "2026 ํ–‰์ •ํ•™ ์ปค๋ฆฌํ˜๋Ÿผ",
          description: "์ „๋ฒ”์œ„ ํƒ„ํƒ„ํ•œ ๊ฐœ๋…์ดํ•ด์™€ \n์ถ”๋ก ํ›ˆ๋ จ์œผ๋กœ ๊ณ ๋“์  ์™„์„ฑ",
        },
        {
          img: "https://files.megagong.net/board_data/banner/main/60393398016_20250623113547.png",
          title: "7-8์›” ์—…๋ฐ์ดํŠธ ๊ฐ•์ขŒ",
          description: "์ตœ์‹  ์ปค๋ฆฌํ˜๋Ÿผ ๋ฐ˜์˜!",
        },
      ],
    };
  },
};
</script>

<style scoped>
.right-section {
  display: flex;
  flex-direction: column;
  padding: 30px;
  border: 1px solid #ddd;
  border-radius: 20px;
}
</style>

โœ… 3. StickyPanel.vue์— ์‚ฝ์ž… ๋ฐ sticky ๊ธฐ๋Šฅ ์ถ”๊ฐ€

<template>
  <div class="sticky-panel">
    <MainRightContent />
  </div>
</template>

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

export default {
  components: { MainRightContent },
};
</script>

<style scoped>
.sticky-panel {
  position: sticky;
  top: 30px;
}
</style>

โœ… 4. views/Homepage.vue์— scss ์ „์ฒด ์ˆ˜์ •

<style lang="scss" scoped>
.layout-container {
  display: flex;
  position: relative;
}

.main-content {
  display: flex;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 40px 0;
  gap: 30px;
}

.main-left {
  display: flex;
  flex-direction: column;
  width: 790px;
  gap: 30px;
}

.main-right {
  width: 380px;
  position: relative;
  top: 0;
  gap: 30px;
}
</style>

โœ… 5. components/TeacherPromoSection.vue์— css ๋ถ€๋ถ„ ์ˆ˜์ •

<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>

โœ… ๊ฒฐ๊ณผ

  • MainSlide ์˜ค๋ฅธ์ชฝ์— ์ •์ ์ธ ์„ธ๋กœ ์นด๋“œ๋“ค์ด ๋‚˜ํƒ€๋‚จ
  • ํ–ฅํ›„ โ€œ๊ธฐํš์ „โ€, โ€œ๋ฌด๋ฃŒ ์ฝ˜ํ…์ธ โ€, โ€œํ™๋ณด๋ฐฐ๋„ˆโ€ ๋“ฑ์˜ ๋‚ด์šฉ์œผ๋กœ ํ™•์žฅ ๊ฐ€๋Šฅ
  • PC ํ™”๋ฉด ๊ธฐ์ค€ ๋„ˆ๋น„ ์•ฝ 300px ์ด์ƒ์œผ๋กœ ๊ณ ์ •, position: sticky ๊ฐ€๋Šฅ

GitHub - heroyooi/vue2-megagong at ch5

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

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

  1. MainRightSlide.vue ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ „์ฒด ์Šฌ๋ผ์ด๋“œ๋กœ ๊ตฌํ˜„

๐Ÿ’ฌ ๋Œ“๊ธ€

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