Frontend/vue3

vue3 img src 동적 바인딩 (require)

dddzr 2023. 6. 16. 15:09

- 문제

컨텍스트 메뉴를 구현하던 중 이미지가 뜨지 않는 문제가 있었습니다.

 

콘솔 로그를 확인해 보니 정상적으로 불러와진 이미지는 파일명과 확장자 사이에 파일의 내용에 기반한 해시 값이 들어가있었습니다. 이 url을 눌리면 직접 img를 띄울 수 있습니다.

*이는 파일의 캐시된 버전을 나타내는 URL입니다. 브라우저는 이 URL을 통해 해당 파일의 최신 버전을 요청하고, 필요한 경우 캐시된 버전을 업데이트합니다.

반면 콘솔로그에 파일을 찾지 못했다는 에러에는 해시값이 빠져 있었습니다.

해시값은 vue에서 자동으로 처리되고 사용자가 제어할 필요 없는데 이게 이루어 지지 않은 것을 보고 src를 주소로 인식하지 못한 것을 확인했습니다.

 

처음 작성한 코드입니다.

<div class="main_quick_body" @mouseleave="quicktoolLeave($event)">
<div v-for="mainMenu in Menus" :key="mainMenu" :currentid="mainMenu.title">
  <div
    v-for="subMenu in mainMenu.children"
    :key="subMenu.key"
    class="btn_line"
    @mouseover="quicktoolhover($event)"
    @click="menuclick(subMenu.key)"
  >
    <img class="quick_icon" :src="'@img/main/contextmenu-' + subMenu.key.replaceAll(' ', '').toLowerCase() + '.svg'" />
    {{ subMenu.key }}
  </div>
  <div class="line"></div>
</div>
</div>

 

번들러는 일반적으로 JavaScript 모듈에 대해서만 번들링을 수행하고, 문자열 형태의 주소를 자동으로 처리하지 않습니다. 따라서 정적 파일로서 이미지를 가져오려면 require() 함수를 사용하여 번들러에게 이미지 파일을 로드하도록 명시적으로 지시해야 합니다.

 

- require함수 사용

Vue.js 템플릿에서 문자열을 동적으로 주소로 인식하려면 require() 함수를 사용하여 이미지 파일을 가져와야 합니다.

<img class="quick_icon" :src="require('@img/main/contextmenu-' + subMenu.key.replaceAll(' ', '').toLowerCase() + '.svg')" />

위의 코드처럼 고치면 이미지를 들고오는데

이미지 파일이 존재하지 않는 경우 require 함수는 오류를 발생시킵니다. 이로 인해 Vue 컴포넌트 전체가 로드되지 않을 수 있습니다.

 

- require함수 + try catch 사용

이미지 파일이 없는 경우에도 컴포넌트가 정상적으로 로드되도록 오류 처리를 한 코드 입니다.

<template>
  <div>
    <img
      class="quick_icon"
      :src="getSrcPath(subMenu.key)"
      alt="Icon"
      @error="handleImageError"
    />
    {{ subMenu.display }}
  </div>
</template>

<script>
export default {
  methods: {
    getSrcPath(key) {
      const normalizedKey = key.trim().toLowerCase().replaceAll(' ', '');
      try {
        return require('@/assets/img/main/contextmenu-' + normalizedKey + '.svg');
      } catch (error) {
        return require('@/assets/img/main/placeholder.svg');
      }
    },
    handleImageError(event) {
      event.target.src = require('@/assets/img/main/placeholder.svg');
    },
  },
};
</script>

try-catch 문을 사용하여 이미지 파일을 로드하고, 파일이 없는 경우에 대비해 오류를 처리합니다. 파일이 존재하지 않을 경우 require('@/assets/img/main/placeholder.svg')를 사용하여 대체 이미지 파일을 로드합니다. handleImageError 메서드는 이미지 로드 오류 시 호출되며, 대체 이미지 파일로 교체하기 위해 event.target.src를 설정합니다.