[코드잇] ObjectURL

iberis2·2023년 4월 13일
0

React 리액트

목록 보기
17/20

ObjectURL

파일 객체를 ObjectURL로 만들면 파일에 대한 주소를 만들 수 있다. 이렇게 만들어진 파일 주소는, 사용자 컴퓨터에 있는 파일을 (인터넷에 올린 파일 링크와 같이) 사용할 수 있도록 한다.

function FileInput({ onChange, value, name }) {
  const [preview, setPreview] = useState();
  const inputRef = useRef();

// value = e.target.files[0]; 로, 파일 input 객체이다.  
// handleChange, handleClearClick 생략
  
  useEffect(() => {
    if (!value) return; // 값이 없는 경우 바로 리턴

// ObjectURL 생성하고, preview 를 이미지 주소값으로 사용
    const nextPreview = URL.createObjectURL(value); 
    setPreview(nextPreview);
  }, [value]);


  return (
    <div>
      <img src={preview} alt="이미지 미리보기" />
      <input type="file" onChange={handleChange} ref={inputRef} />
      {value && <button onClick={handleClearClick}>X</button>}
    </div>
  );
}

ObjectURL을 만들면 웹 브라우저는 메모리를 할당하고 파일에 해당하는 주소를 만들어준다.

  • 위 코드에서 컴포넌츠는 레더링하는 과정에서 리액트 외부의 상태를 바꾸게 된다.

사이드 이펙트 : 컴포넌트 함수에서 외부의 상태를 변경하는 것

  • 네트워크 리퀘스트, 메모리 할당 등
function FileInput({ onChange, value, name }) {
  const [preview, setPreview] = useState();
  const inputRef = useRef();
  
// value = e.target.files[0]; 로, 파일 input 객체이다.
 // handleChange, handleClearClick 함수 생략

  useEffect(() => {
    if (!value) return;

    const nextPreview = URL.createObjectURL(value);
    setPreview(nextPreview);

    return () => { // 사이드 이펙트 정리 함수
      setPreview();
      URL.revokeObjectURL(nextPreview); // 할당되었던 메모리 정리
    };
  }, [value]);

  
  return (
    <div>
      <img src={preview} alt="이미지 미리보기" />
      <input type="file" accept="image/png, image/jpeg" onChange={handleChange} ref={inputRef} />
      {value && <button onClick={handleClearClick}>X</button>}
    </div>
  );

파일이 바뀔 때마다 메모리를 할당하기만 하면 메모리가 낭비된다.
따라서 다른 파일을 선택하거나 선택을 해제했을 때 revokeObjectURL 을 이용해 메모리도 같이 해제해주어야 한다.

useEffect에서 사이드 이펙트를 만든 후 정리하는 방법 : 리턴 값으로 함수를 리턴하면 된다.

① 사용자가 파일 선택 
② value 값이 배뀌고 재랜더링 발생
③ 랜더링이 끝나고 useEffect 안의 콜백함수가 실행되면서 objectURL을 만들고 preview의 상태를 바꾼다. 
(사이드 이펙트 : 메모리 할당)
④ return에 있는 사이드 이펙트 정리 함수를 등록해둔다.
⑤ 다음 value 값이 바뀌었을 때, 등록해둔 함수가 먼저 실행되며 사이드 이펙트를 정리하고,
⑥ 다시 useEffect 안의 함수들이 실행된다.

정리 함수가 실행되는 시점
쉽게 말해서 콜백을 한 번 실행했으면, 정리 함수도 반드시 한 번 실행된다.

① 새로운 콜백 함수가 호출되기 전에 실행되거나 (앞에서 실행한 콜백의 사이드 이펙트를 정리),
② 컴포넌트가 화면에서 사라지기 전에 실행된다 (맨 마지막으로 실행한 콜백의 사이드 이펙트를 정리).

+덧 : <input type="file" />accept="image/png, image/jpeg" 속성을 추가하면 이미지 파일만 받을 수 있다.

profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글