sharingStorage

Create React App환경에서 이미지 불러오는 방법(public vs src) 본문

Front-End/React

Create React App환경에서 이미지 불러오는 방법(public vs src)

Anstrengung 2023. 1. 25. 15:10

팀 프로젝트를 진행하는 도중 매일 9시부터 10분씩 데일리 스크럼을 하는데 팀원 한분이 저에게 왜 proccess.env.PUBLIC_URL을 사용하냐고 여쭤보시더군요. 일반 public/asstes/ ,,, 으로 사용해도 되는데 말이죠 분명 저는 전자로 배우고 사용했었는데 막상 질문 받으니 한마디도 할 수 없었어요. 그래서 CRA(create-react-app)의 문서를 뒤져보고,  stack overflow와 github의 create-react-app/issue 도 참고하여 이해한 것을 바탕으로 글을 적어봅니다.

create-react-app은 CRA로 명칭해서 글을 작성하겠습니다.

 

 

1. public폴더와  src폴더

이 문제를 시작하기 앞서 CRA을 통해 만들어진 파일 구조와 쓰임을 확인해보겠습니다.  (CRA사용법이나 자세한 구조등은 다른 글에서 다루어 보도록 하겠습니다.)

1.1 public

  public 폴더는 CRA로 개발할 React 프로젝트의 정적인 파일들이 저장된 폴더입니다.

 대표적으로 index.html이 있는데 이는 개발한 React 프로젝트를 브라우저에 나타내기 위한 파일입니다.

1.1.1 public 폴더의 특징

  • webpack에 의해 관리되지 않습니다. 
  • 절대경로가 사용가능합니다 ex) /assets/photo1
  • 원본이 build폴더에 복사됩니다.

 

1.2 src

개발하면서 작업하는 대부분의 파일을 넣는 폴더

 

1.2.1 src폴더의 특징

  • webpack에 의해 관리됩니다.
  • 빠른 rebuild를 위해 src 안에 있는 파일들만 webpack에 의해 처리됩니다.
  • src.index.js는 자바스크립트의 진입점입니다.
  • 서버 요청 횟수를 줄이기 위해 10,000 bytes 이하의 이미지는 path대신 data URL을 반환합니다.

컴포넌트 안에서 사용하는 이미지는 src폴더에 있어야 하지만 fabicon과 같이 앱 밖에서 사용하는 이미지는 public 폴더에 있어야 합니다.

 

 

2. 리액트 컴포넌트에 이미지를 추가하는 방법

리액트에는 빌드 단계에 이미지를 포함할 방법이 필요합니다.

 

  2.1 이미지를 public 폴더에 넣어 img src로 불러오는 방법

  1. public/assets 폴더를 만들어 그 안에 image파일을 넣습니다.
  2. img 태그에 src 속성에 image의 경로를 넣습니다.
       <img
             src={process.env.PUBLIC_URL + `assets/filter.png`}
            onClick={search}
            alt="필터 이미지 오류"
          ></img>

 

2.1.1 proccess.env.PUBLIC_URL을 사용하는 이유

npm run build를 실행하면 CreateReact App이 %Public_URL%을 절대 경로로 대체하므로 클라이언트 측 라우팅을 사용하거나 루트가 아닌 URL에서 호스트를 해도 프로젝트가 작동합니다.   

public 폴더에 있는 이미지를 jsx에서 사용할 경우 공식문서에서는 환경변수의 PUBLIC_URL을 사용하라고 권장하며 

 index.html 에서는 proccess.env.PUBLIC_URL 대신 %PUBLIC_URL%를 사용한다.

 

  2.2 이미지를 src폴더에 넣어 컴포넌트로 임포트하는 방법

  1.  먼저 image파일을 src폴더 아래 원하는 위치에 넣습니다.
  2. import를 통해 image 파일을 가져옵니다.
  3. img 태그를 렌더링하고 해당 변수를 src로 전달합니다.
  4. 가져온 이미지를 사용하기 위해 src={} 처럼 중괄호를 사용합니다.(js변수 프롭으로 전달)

예시

import filterImg from "./../images/filter.png";

    	<img
            src={filterImg}
            onClick={search}
            alt="검색 이미지 오류"
          ></img>

 

 

2.3 컴퓨터 파일 경로 사용하지 않기

저도 마찬가지였듯이 초보 개발자의 치명적인 실수는 src를  C:\Program Files\photo1 과 같이 본인의 컴퓨터의 파일 경로로 설정하는 것입니다. 요즘 브라우저는 대부분 샌드박스 처리가 되어있어 디스크의 경로로 파일에 엑세스할 수 없습니다.

그리고 웹 서버가 같은 위치에 해당파일을 가지고 있지 않기 때문에 웹이나 앱을 배포하거나 테스트하는 과정에서 오류가 발생할 수 있습니다. 

 

 

3. create-react-app 환경에서 image 파일을 public과 src중 어디에 넣어야할까?

3.1 public 폴더로 관리하고 불러오기.

  • public 폴더의 어떤 파일도 전처리(prefix)되거나  경량화(minified, 또는 최적화)되지 않습니다. 
  • 파일이 누락되어도 해당 파일은 컴파일 단계에서 에러가 발생하지 않고, 사용자에게 404오류가 발생할 수 있습니다.
  • 결과 파일 이름에는 콘텐츠 해시가 포함되지 않으므로 변경될 때마다 쿼리 인수를 추가하거나 이름을 바꿔야 합니다.

 

3.2 src 폴더에 관리하고 import 하기.

  • 추가 네트워크 요청을 피하기 위해 script와 style sheet가 전처리되어 번들링 됩니다.
    • 트리셰이킹, css 퍼지 등의 최적화가 가능합니다.
  • 누락된 파일은 사용자에게 404 오류 대신 컴파일 오류를 발생시킵니다.
    • 배포 전에 오류를 쉽게 발견할 수 있습니다.
  • 결과 파일 이름에는 콘텐츠 해시가 포함되므로 브라우저가 이전 버전을 캐싱하는 것에 대해 걱정할 필요가 없습니다.

 

 

4. 리액트에서 import한 이미지 동작 방식

import는 react가 처리하지 않고 번들러에 의해 처리됩니다

Create-React-App 을 사용하는 경우 Webpack.

 

 

5. public을 사용해야될 때가 있다.

  • 빌드 결과물에 특정 이름을 가진 파일이 필요할 때
  • 수천 개의 이미지가 있고 해당 경로를 동적으로 참조해야 할 때. (데이터가 많아 CDN을 통해야할 때)
  • 번들 코드 외부의 작은 스크립트를 포함하고 싶을 때.
  • 일부 라이브러리는 webpack과 호환되지 않고 <script>태그로 포함하는 것 외에 다른 옵션이 없을 때

 

 

6. 결론

즉, 바로 위의 예외적인 case를 제외하곤(import를 사용해서도 위의 예외를 처리할 방법이 있을것이다.) 기본적으로 앱에 포함되는 리소스는 src에 넣어 번들링 하는 것이 좋습니다.

 

 

7. 번외 

Create React App 4 버전 이후 public 폴더 리소스 접근 오류가 있습니다.

https://github.com/facebook/create-react-app/issues/10022  

 

CRA 4 fails to compile when css background-image ulr('url') not resolved · Issue #10022 · facebook/create-react-app

I have a css file that is imported in my react app, it is something like: styles.css .flag { ... background-image: url("/img/flags.png") !important; } It is imported in my react file ->...

github.com

 

 

 

 

출처

Comments