[React] Create-react-app 프로젝트에서 이미지 경로를 설정하는 4가지 방법

차유림·2021년 8월 25일
57
post-custom-banner

create-react-app 프로젝트에서 이미지를 사용한다면
이미지가 public 폴더에 있는지 src폴더에 있는지,
또는 jsx파일에서 사용하는지 css에서 사용하는지에 따라
경로설정하는 방법이 달라 헷갈릴 수 있다.

따라서 어느 경우에 public, src 폴더에서 이미지를 관리하면 좋은지,
jsx, css에서 어떻게 이미지 경로를 설정하는지 방법을 정리해보려고 한다.

create-react-app으로 프로젝트를 생성했을 때의 기본 템플릿에서
이미지의 경로만 아래와 같이 수정한 후 진행했다.
이미지 폴더 구조

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

📂 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을 사용하라고 나와있지만
단순히 /이미지경로, 이미지경로 이런 식으로 지정해도 잘 불러왔다.

즉 아래 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에러가 발생하여 코드를 작성할 때 수정할 수 있다.
compile error

  • import image path
    import logoPath from './src_assets/logo192.png'
  • 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 값을 확인했다.

content hash, dataURL

🖼 css 에서 이미지 경로 설정

🚧 public 폴더에 있는 이미지

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폴더에서 이미지를 관리하세요 였다.

9937번 이슈에서 atlanteh(Contributor)의 글을 정리하면 다음과 같다.
atlanteh 댓글

추가 정리 예정

    1. 처음에atlanteh가 scss에서 절대경로가 깨지는 이슈가 있어 이를 해결하였다.(CRA에 커밋-풀리퀘-머지 끝!)
    1. atlanteh은 public폴더에 이미지를 관리하지 않았기 때문에 이런 이슈를 몰랐다.

react-scripts@5.0.0-next.31 설치가 안되서 test 보류..
npm i react-scripts@5.0.0-next.31
Disable url resolving using the /* webpackIgnore: true */ comment

4. src 폴더에 있는 이미지

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

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

📚 참고

profile
🎨프론트엔드 개발자💻
post-custom-banner

1개의 댓글

comment-user-thumbnail
2021년 11월 17일

감사합니다!! 정말 큰 도움 되었어요🤩

답글 달기