본문 바로가기

Local Oriented/Vue.js

'Vue + Vite' 에서의 이미지 사용 요령

 0.1 Vite 는 dev 또는 build 시..
    /src/ 에서 먼저 이미지를 찾고
    /src/ 에 없으면 /public/ 에서 찾으며
    /src/ 와 /public/ 에 없으면 에러(또는 이미지 표시X)

0.2 Vite 는 build 시..
    /src/ 에 이미지가 있으면, 이미지 파일 사이즈에 따라 base64 인코딩, 또는 /dist/img/ 경로에 신규 생성
    /public/ 에 파일이 있으면, /dist/ 에 무조건 그대로 복사 (파일명과 생성일자 변경 없음).

   vite.config.ts 파일의 build.rollupOptions.output 항목 참조.

    /src/assets/ 아래에 존재하는 이미지 중 .vue 에서 기술된 파일만 적용하는게 아니라면..

    /public/ 아래에 이미지를 넣고 사용해도 되는데,

    이 경우 아래와 같은 경향이 반영되지 않고 또 다른 양상이 발생함에 유의.

0.3 src 적용
    - 내부 이미지 (Vue 프로젝트 내부에서 제공)
      정적 사용시: @/assets/aaa.png
      동적 사용시: new URL(`../../assets/${ fname }`, import.meta.url).href
            .vue 파일과 /src/assets/ 이미지와의 상대 경로 (/src/ 가 root) 적용됨에 유의
    - 외부 이미지 (Vue 프로젝트 외부에서 /images/ 경로로 제공한다고 가정)
      정적 사용시: /images/bbb.png
            dev 에서는 이미지 표시 X, build 후 웹서버에 배포하면 이미지 표시 O
            /public/images/bbb.png 파일 존재시, dev 에서도 이미지 표시 O
      동적 사용시: new URL(`${ '/images/' + fname }`, import.meta.url).href
            또는 new URL() 없이 '/images/' + fname

    - 다른 코드로도 사용 가능하지만, 때에 따라 되기도 하고 아니기도 해서..

       일반적으로 이렇다고 생각하면 좀더 일관되게 작업 가능.


1. <img src="...">
    1.1 내부 정적 이미지
      @/assets/aaa.png
    1.2 외부 정적 이미지
      /images/bbb.png
    1.3 내부 동적 이미지: 불가
    1.4 외부 동적 이미지: 불가

2. v-bind 와 ` (back-tick 백틱) 사용
    <img v-bind:src="`...`">
    2.1 내부 정적 이미지: 불가
    2.2 외부 정적 이미지
      /images/bbb.png
    2.3 내부 동적 이미지: 불가
    2.4 외부 동적 이미지
      ${ '/images/' + fname }

3. v-bind 와 import 사용
    <img v-bind:src="imgSrc">
    import imgSrc from '...';
    3.1 내부 정적 이미지
      @/assets/aaa.png
    3.2 외부 정적 이미지
      /images/bbb.png
    3.3 내부 동적 이미지: 불가
    3.4 외부 동적 이미지: 불가

4. v-bind 와 new URL() 사용
    <img v-bind:src="imgSrc">
    const fname = 'aaa.png';
    const imgSrc = new URL(..., import.meta.url).href;
    4.1 내부 정적 이미지
      '@/assets/aaa.png'
    4.2 외부 정적 이미지
      '/images/bbb.png'
      const imgSrc = '/images/bbb.png'; 형식도 가능
    4.3 내부 동적 이미지
      `../../assets/${ fname }`
    4.4 외부 동적 이미지
      `${ '/images/' + fname }`
      `/images/${ fname }` 는 이미지 표시 X
      const imgSrc = '/images/' + fname; 형식도 가능

5. ref 와 new URL() 사용
    <img ref="refImg">
    const fname = 'aaa.png';
    const refImg = ref<HTMLImageElement>();
    refImg.value!.src = new URL(..., import.meta.url).href;
    사용 방법은 #4 와 동일

6. template 에서의 루프
    <div v-for="(item, index) of list">
      <p><img v-bind:src="..."></p>
    </div>
    const list = [
      {img: 'aaa.png'},
    ];
    6.1 내부 동적 이미지: 불가
    6.2 외부 동적 이미지
      `${ '/images/' + item.img }`

7. script 에서의 루프
    <div ref="refDiv"></div>
    const refDiv = ref<HTMLElement>();
    list.forEach((item: any) => {
      const img = document.createElement('img');
      img.src = new URL(..., import.meta.url).href;
      refDiv.value?.append(img);
    });
    7.1 내부 동적 이미지
      `../../assets/${ item.img }`
    7.2 외부 동적 이미지
      `${ '/images/' + item.img }`
      `/images/${ item.img }` 는 이미지 표시 X
      img.src = '/images/' + fname; 가능

 

 

 

 

 

<template>

  <div ref="refDiv"></div>

</template>

 

<script>

import { ref, onMounted } from 'vue';

import { html, render } from 'lit-html';

 

const refDiv = ref<HTMLElement>();

 

const list = [{ code: .., title: ... }, ...];

 

const foo1 = () => { // forEach() 사용시 매 item 마다 return, map() 사용시 루프 작업후 1번 return

  // 이벤트를 처리해야 해서, () => foo2() 사용.

  // 이벤트를 주입하려면, (e: any) => foo2(e, ...) 와 같이 변형
  return list.map((item) =>
    html`<button @click="${ () => foo2( item.code) }" style="...">
        <div>
          <img src="${ new URL(`../assets/${ item.code }.png`, import.meta.url).href }">
          <p>${ item.title }</p>
        </div>
      </button>`
  );
} // img.src 에 직접 넣음. v-on:click 시 작동하지 않으므로, @click 사용 유의

 

const foo2 = (code: string) => { ... }

onMounted(() => {
  render(foo1(), refDiv.value!);
});

</script>