IT/React

React에서 이미지(images) 경로 설정 방법

라임웨일 2022. 5. 9. 16:48
반응형

 

React에서 이미지를 사용해야 할 때 해당 이미지가 public폴더에 있는지 src폴더에 있는지, 또는 jsx파일에서 사용하는지 css에서 사용하는지에 따라 경로 설정하는 방법이 달라 처음 경로를 설정할 때 혼란스러운 경험이 있을 수 있습니다. 

 

React에서 이미지를 사용하는 방법을 정리해 보았습니다. 

어느 폴더에서 관리하는 게 좋은가?

📂 public

  • webpack에 의해 관리되지 않습니다.
    (minify되지 않고, content hash가 포함되지 않습니다. 대신 원본이 build폴더에 복사됩니다.)
  • public 폴더에 접근하기 위해서는 PUBLIC_URL 환경변수를 사용해야 합니다.
  • 경로가 잘못 되었거나 파일이 없을 경우 컴파일 단계에서 에러가 발생하지 않고, 404 에러가 발생합니다.
  • CRA 문서에서 다음과 같은 경우에만 public 폴더에서 관리하는 것이 유용하고, 이외에는 src 폴더 관리를 추천합니다.
    • manifest.webmanifest처럼 build 된 결과물에서 특정한 파일 이름이 필요한 경우
    • 수천 개의 이미지 파일을 동적으로 참조해야 하는 경우

📂 src

  • 파일을 찾지 못하는 경우, 컴파일 단계에서 에러를 잡을 수 있습니다.
  • import 할 경우 참조할 수 있는 경로(path) 문자열을 출력합니다.
  • content hash가 파일명에 포함되기 때문에 브라우저가 오래된 버전(파일 수정 전)의 파일을 캐싱하고 있는 경우를 고려하지 않아도 됩니다. (파일이 변경되었을 때만 hash값이 변경됩니다.)
  • 서버 요청 횟수를 줄이기 위해 10,000 bytes 이하의 이미지는 path대신 data URL을 반환합니다.
    (bmp, gif, jpg, jpeg, png 파일에만 적용, SVG 파일 제외)
    이때, 파일 크기 기준(10,000 byte)은 IMAGE_INLINE_SIZE_LIMIT 환경변수로 설정을 변경할 수 있습니다.

 

jsx 에서 이미지 경로 설정

1. public 폴더에 있는 이미지

function App() {
  return (
    <img
      src={`${process.env.PUBLIC_URL}/public_assets/logo512.png`}
      className='App-logo'
      alt='React'
    />
  );
}

export default App;

파일을 못찾을 경우 컴파일 에러는 발생하지 않고 이미지가 출력되지 않습니다.

public 폴더에 있는 이미지를 jsx에서 사용할 경우 공식문서에서는 환경변수의 PUBLIC_URL을 사용하라고 나와있지만
단순히 /이미지경로, 이미지 경로 이런 식으로 지정해도 호출이 가능합니다. 다만 Github에 소스코드를 올릴 경우에는 PUBLIC_URL로 경로를 설정해 주어야 정상적으로 이미지가 노출됩니다.

즉 아래 3가지 경로 다 가능
1. src={`${process.env.PUBLIC_URL}/public_assets/logo512.png`}
2. src={'/public_assets/logo512.png'}
3. src={'public_assets/logo512.png'}
4. src={'./public_assets/logo512.png'} 도 가능

2. src 폴더에 있는 이미지(import)

import logo from './src_assets/logo192.png';

function App() {
  return (
    <img src={logo} className='App-logo' alt='React' />
  );
}

export default App;

webpack을 사용하면 CSS 파일을 import 하는 것처럼 이미지 파일을 import하여 사용할 수 있습니다. 파일 최상단에서 사용하는 모든 이미지를 import하여 사용하는 동기적인 방법으로 webpack이 이미지 파일을 번들에 포함시키며. 파일을 못찾을 경우 compile에러가 발생하여 코드를 작성할 때 수정할 수 있습니다.

  • 방법1) import image path 
    => import logoPath from './src_assets/logo192.png'
  • 방법2) image src 설정
    => <img src={logoPath} />

3. src 폴더에 있는 이미지(require)

function App() {
  return (
    <img src={require('./src_assets/logo192.png').default} className='App-logo' alt='React' />
  );
}

export default App;

node.js 환경이기 때문에 require로 문서 어디서나 파일을 불러올 수 있습니다. 이 방법을 사용하면 inline으로 src의 이미지 파일 경로를 바로 지정할 수 있습니다. 처음에 모든 이미지 파일을 import 하지 않아도 되기 때문에 편리합니다.

<img src={require('./src_assets/logo192.png').default} />

✅ content hash, dataURL 확인

import logo from './src_assets/logo.svg';

function App() {
  return (
    <>
      <img src={require('./src_assets/logo.svg').default} className='App-logo' alt='React' />
      <img src={logo} className='App-logo' alt='React' />
    </>
  );
}

import 와 require 방식의 차이가 있을까 궁금하여 두 개의 img를 비교해 보았습니다. 두 방식의 차이는 없었지만, logo192.png 파일의 경우 10,000byte 이하여서 dataURL이 리턴된 것을 확인할 수 있었고, logo.svg 파일로 테스트했을 경우에 파일명 뒤에 동일한 content hash 값을 확인할 수 있었습니다.

 

css 에서 이미지 경로 설정

public 폴더에 있는 이미지

Failed to compile ./src/App.css (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-4-1!
css파일에서 public 폴더에 접근하려고 하면 위와 같은 에러가 발생합니다. css파일에서 절대 경로를 설정하면 src폴더를 기준으로 경로를 찾기 때문에 src폴더 내에서는 해당 파일을 찾을 수 없다는 에러를 노출합니다. 

그렇다면 public 폴더에 있는 이미지를 css파일에서 불러오는 방법은? 아직 못 찾았습니다..
(craco를 사용해서 css-loader 설정을 변경하면 되는 것 같기도...)

꼭 public 폴더의 이미지를 적용해야 한다면 inline-style로 css를 적용할 수는 있습니다.
<div style={{ backgroundImage: 'url(/public_assets/logo512.png)' }}></div>

🚨 절대 경로 설정 시 루트 폴더 기준
jsx파일에서 절대 경로는 public 폴더를 기준으로 합니다.
css파일에서 절대경로는 src 폴더를 기준으로 합니다.

 CRA 이슈 정리

이와 관련해서 CRA 레포에도 이슈와 많은 댓글이 등록되어 있습니다. 절대 경로의 기준이 다르고, public 폴더의 이미지를 설정할 수 없어서 불편함을 느끼는 사람들이 있었지만, 결론은 src폴더에서 이미지를 관리하라는 게 주요 내용이었습니다.

 

src 폴더에 있는 이미지

절대 경로도 src 폴더를 기준으로 하기 때문에 아래처럼 상대 경로, 절대 경로 다 사용 가능합니다.

background: url("./src_assets/logo192.png");
background: url("src_assets/logo192.png");

 

출처 : https://velog.io/@rimo09/React-Create-react-app-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90%EC%84%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B2%BD%EB%A1%9C%EB%A5%BC-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-4%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95

반응형