PromleeBlog
sitemap
aboutMe

posting thumbnail
Vue 조건부 렌더링과 스타일링 - Vue 기본기 다지기 8편
Vue Conditional Rendering and Styling - Vue Basics Part 8

📅

🚀

들어가기 전에 🔗

오늘은 Vue.js 애플리케이션을 더욱 동적으로 만들어주는 아주 중요한 기능들에 대해 배워보겠습니다.
사용자의 행동이나 특정 데이터 상태에 따라 화면의 일부를 보여주거나 숨기고, 목록 데이터를 예쁘게 표시하는 방법을 알아볼 것입니다.
바로
조건부 렌더링
리스트 렌더링
입니다.
여기에 더해, 각 컴포넌트의 스타일이 서로 섞이지 않도록 깔끔하게 관리하는
Scoped CSS
에 대해서도 함께 살펴보겠습니다.

이 개념들은 React의 조건부 렌더링이나 JSX 내부의 map 함수와 비슷한 역할을 하지만, Vue는 v- 접두사를 붙인 특별한 속성, 즉
디렉티브
를 사용해서 훨씬 직관적으로 처리합니다.

🚀

상황에 따라 화면을 그리는 조건부 렌더링 🔗

웹 애플리케이션을 만들다 보면 '로그인했을 때만 프로필 버튼을 보여주기'나 '에러 메시지가 있을 때만 화면에 표시하기'처럼 특정 조건에 따라 UI를 다르게 보여줘야 할 때가 아주 많습니다.
이럴 때 사용하는 것이 바로
조건부 렌더링
입니다.
Vue에서는 v-ifv-show라는 두 가지 디렉티브를 사용해 이 기능을 구현할 수 있습니다.

v-if 🔗

v-if는 조건이 참(true)일 때만 해당 HTML 요소를 화면에 그리고, 거짓(false)이면 아예 그리지 않습니다.
정말로 DOM 트리에서 요소를 제거하거나 추가하는 방식입니다.
예를 들어, 사용자가 로그인했는지 여부를 나타내는 isLoggedIn이라는 데이터가 있다고 상상해 봅시다.
<button v-if="isLoggedIn">로그아웃</button>
위 코드에서 isLoggedIntrue이면 '로그아웃' 버튼이 화면에 보입니다.
만약 false가 되면, 버튼은 DOM에서 완전히 사라져서 마치 처음부터 없었던 것처럼 됩니다.


v-elsev-else-if를 함께 사용하면 더 다양한 조건을 처리할 수 있습니다.
마치 자바스크립트의 if-else if-else 구문과 같습니다.
<div v-if="status === 'success'">
  <p>성공적으로 처리되었습니다!</p>
</div>
<div v-else-if="status === 'error'">
  <p>오류가 발생했습니다.</p>
</div>
<div v-else>
  <p>로딩 중...</p>
</div>
v-if
v-if

v-show 🔗

v-showv-if처럼 조건에 따라 요소를 보여주거나 숨깁니다. 하지만 결정적인 차이가 있습니다.
v-show는 조건이 false가 되어도 요소를 DOM에서 제거하지 않습니다.
대신 CSS의 display: none; 속성을 이용해 화면에서 보이지 않게 숨길 뿐입니다.

항상 DOM에 존재하기 때문에, 초기 렌더링 비용은 v-if보다 높을 수 있습니다.
<h1 v-show="isOk">안녕하세요!</h1>
위 코드는 isOk 값에 따라 '안녕하세요!'라는 텍스트를 보여주거나 숨깁니다.
isOkfalse여도 개발자 도구로 보면 h1 태그는 존재하고 style="display: none;"이 적용된 것을 확인할 수 있습니다.

v-if와 v-show, 언제 무엇을 쓸까요? 🔗

면접에서 이 둘의 차이점을 묻는 경우가 종종 있습니다.
핵심을 정리해 드릴 테니 잘 기억해 두세요.

결국,
성능
과 관련이 있습니다.
컴퓨터가 일을 덜 하도록 상황에 맞는 도구를 선택하는 것이 좋은 개발자의 덕목이라고 할 수 있습니다.

🚀

v-for 🔗

이번에는 할 일 목록이나 상품 리스트처럼 반복되는 데이터를 화면에 표시하는 방법을 알아보겠습니다.
v-for 디렉티브를 사용하면 배열이나 객체의 각 항목을 순회하며 요소를 렌더링할 수 있습니다.

예를 들어, 다음과 같은 할 일 목록 배열이 있다고 해봅시다.
// <script setup> 안의 코드
import { ref } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Vue 공부하기' },
  { id: 2, text: '블로그 글쓰기' },
  { id: 3, text: '운동하기' }
])
todos 배열을 v-for를 사용해 <li> 태그 목록으로 만들 수 있습니다.
<ul>
  <li v-for="item in todos" :key="item.id">
    {{ item.text }}
  </li>
</ul>
v-for="item in todos" 부분은 "todos 배열을 돌면서 각 요소를 item이라고 부를게" 라는 의미입니다.
그러면 Vue는 배열의 개수만큼 <li> 요소를 반복해서 만들어줍니다.

:key 속성 🔗

위 예제에서 :key="item.id" 부분이 눈에 띄실 겁니다.
v-for를 사용할 때 :key는 필수적으로 작성해야 하는 매우 중요한 속성입니다.

Vue는 화면을 업데이트할 때, 기존 요소들을 최대한 재사용하여 효율성을 높이는
가상 DOM(Virtual DOM)
방식을 사용합니다.
이때 어떤 항목이 변경되고, 추가되고, 삭제되었는지 정확히 추적하기 위한
신분증
같은 것이 바로 key입니다.
key는 각 항목을 식별할 수 있는 고유한 값이어야 합니다.
예제에서는 각 할 일 항목이 가진 idkey로 사용했습니다.

만약 key가 없거나, 배열의 인덱스처럼 고유하지 않은 값을 사용하면 목록의 순서가 바뀌거나 항목이 추가/삭제될 때 Vue가 혼란에 빠져 예상치 못한 화면 오류를 일으키거나 성능이 저하될 수 있습니다.
이것은 Vue가 사용하는
diffing 알고리즘
의 효율성과 직접적으로 연결되는 중요한 개념이니 꼭 기억해 주세요.

🚀

컴포넌트 스타일링과 조건부 렌더링 🔗

이제 각 컴포넌트의 스타일을 어떻게 관리하는지 알아보겠습니다.
여러 컴포넌트를 조합해 페이지를 만들다 보면, A 컴포넌트에서 작성한 CSS가 B 컴포넌트에 영향을 주는
스타일 충돌
문제가 발생할 수 있습니다.

스타일 충돌을 막는 scoped CSS 🔗

Vue의 단일 파일 컴포넌트(.vue 파일)에서는 <style> 태그에 scoped 속성을 추가하여 이 문제를 간단히 해결할 수 있습니다.
<template>
  <div class="message">안녕하세요!</div>
</template>
 
<style scoped>
.message {
  color: blue;
}
</style>
이렇게 scoped를 붙이면, .message라는 스타일은
오직 이 컴포넌트 내부의 요소
에만 적용됩니다.
다른 컴포넌트에서 똑같이 .message라는 클래스 이름을 사용하더라도 서로의 스타일에 전혀 영향을 주지 않습니다.

Vue는 이 기능을 구현하기 위해 컴파일 과정에서 HTML 요소에 data-v-xxxx 형태의 고유한 속성을 추가하고, CSS 셀렉터에도 해당 속성을 추가하여 스타일의 범위를 제한합니다.
따라서 개발자는 다른 컴포넌트와의 충돌 걱정 없이 편안하게 스타일을 작성할 수 있습니다.

전역 스타일링 구조 🔗

물론 프로젝트 전체에서 공통으로 사용될 버튼 스타일이나 폰트 설정 등은 전역으로 관리하는 것이 효율적입니다.
이런 경우, assets 폴더 등에 main.css 같은 파일을 만들고, 이를 main.js 파일에서 import하여 전역으로 적용할 수 있습니다.
대부분의 프로젝트는 전역 스타일과 컴포넌트별 scoped 스타일을 함께 사용하는 방식을 택합니다.

🚀

결론 🔗

오늘은 Vue 애플리케이션의 화면을 동적으로 제어하는 필수적인 방법들을 배웠습니다.

참고 🔗