React/React 문법

[React]파일 업로드 구현

DevStory 2022. 7. 11.

파일 업로드 구현

파일 업로드 버튼을 외부 라이브러리에서 제공하는 버튼 컴포넌트를 사용하고 싶은데 해당 라이브러리에서 파일 업로드 기능을 지원하지 않을 수 있습니다.

 

외부 라이브러리 대신 input 태그를 사용하면 파일 업로드 기능을 사용할 수 있지만 디자인이 마음에 들지 않습니다. 디자인 때문에 컴포넌트를 제작하기에는 얼마만큼의 시간이 소모될지 모릅니다.

 

하지만, DOM 엘리먼트를 접근할 수 있는 Ref를 활용한다면 외부 라이브러리의 버튼 컴포넌트를 사용하여 파일 업로드 기능을 구현할 수 있습니다.

 

이번 포스팅은 외부 라이브러리에서 제공하는 버튼 컴포넌트에서 파일 업로드 기능을 사용할 수 있는 방법을 소개합니다. 


JavaScript 파일 업로드

JavaScript에서 파일 업로드를 구현해야 하는 경우 input 태그의 type 속성을 "file"로 설정합니다.

<input type="file" id="fileUpload" />

만약, 여러 개의 파일을 업로드해야 하는 경우 multiple 속성을 true로 설정합니다.

<input type="file" multiple={true} id="fileUpload" />

input 태그를 사용한다면 파일 업로드하는 방법은 간단합니다.

 

[JavaScript]파일 업로드 구현

이번 포스팅은 JavaScript에서 파일 업로드 구현하는 방법을 소개합니다. HTML input 태그 작성 html 파일에서 input 태그를 작성 후 type = 'file' 로 설정하고 input 태그의 id를 지정합니다. 하나 이상의 파

developer-talk.tistory.com

하지만 디자인이 마음에 들지 않습니다.

외부 라이브러리에서 제공하는 버튼 컴포넌트에서 onClick 이벤트가 발생하면 input 태그가 동작하도록 할 수 없을까?

해결 방법

React에서 제공하는 Ref를 활용하면 버튼 컴포넌트에서 onClick 이벤트가 발생했을 때 input 태그가 동작하도록 할 수 있습니다.

 

순서 1. input 태그를 추가하고 style에 display: none을 추가합니다.

[클래스 컴포넌트]

class App extends React.Component {
  render() {
    return (
      <React.Fragment>
        <input type="file"
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => () => {
  return (
    <React.Fragment>
      <input type="file"
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

 

순서 2. 외부 라이브러리에서 제공하는 버튼 컴포넌트를 추가합니다.

[클래스 컴포넌트]

class App extends React.Component {
  render() {
    return (
      <React.Fragment>
        <Button>파일 업로드</Button>
        <input type="file"
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => props => {
  return (
    <React.Fragment>
      <Button>파일 업로드</Button>
      <input type="file"
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

 

순서 3. 버튼 컴포넌트에 onClick 이벤트 핸들러 함수를 추가합니다.

[클래스 컴포넌트]

class App extends React.Component {

  handleButtonClick = e => {
  };
  
  render() {
    return (
      <React.Fragment>
        <Button onClick={this.handleButtonClick}>파일 업로드</Button>
        <input type="file"
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => props => {

  const handleButtonClick = e => {
  };
  
  return (
    <React.Fragment>
      <Button onClick={handleButtonClick}>파일 업로드</Button>
      <input type="file"
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

 

순서 4. Ref를 사용하여 input 태그를 참조합니다.

[클래스 컴포넌트]

class App extends React.Component {

  fileInput = React.createRef();
  
  handleButtonClick = e => {
    fileInput.current.click();
  };
  
  render() {
    return (
      <React.Fragment>
        <Button onClick={this.handleButtonClick}>파일 업로드</Button>
        <input type="file"
               ref={fileInput}
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => props => {
  const fileInput = React.useRef(null);
  
  const handleButtonClick = e => {
    fileInput.current.click();
  };
  
  return (
    <React.Fragment>
      <Button onClick={handleButtonClick}>파일 업로드</Button>
      <input type="file"
             ref={fileInput}
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

3번 과정에서 작성된 onClick 이벤트 핸들러 함수를 수정합니다. input 태그를 참조하는 Ref를 사용하여 버튼 컴포넌트에서 클릭 이벤트가 발생하면 input 태그에 강제로 클릭 이벤트를 발생시킵니다.

 

순서 5. input 태그에 onChange 이벤트 핸들러 함수를 추가합니다.

[클래스 컴포넌트]

class App extends React.Component {

  fileInput = React.createRef();
  
  handleButtonClick = e => {
    fileInput.current.click();
  };
  
  handleChange = e => {
  };
  
  render() {
    return (
      <React.Fragment>
        <Button onClick={this.handleButtonClick}>파일 업로드</Button>
        <input type="file"
               ref={fileInput}
               onChange={handleChange}
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => props => {
  const fileInput = React.useRef(null);
  
  const handleButtonClick = e => {
    fileInput.current.click();
  };
  
  const handleChange = e => {
  };
  
  return (
    <React.Fragment>
      <Button onClick={handleButtonClick}>파일 업로드</Button>
      <input type="file"
             ref={fileInput}
             onChange={handleChange}
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

 

순서 6. 업로드된 파일을 불러옵니다.

[클래스 컴포넌트]

class App extends React.Component {

  fileInput = React.createRef();
  
  handleButtonClick = e => {
    fileInput.current.click();
  };
  
  handleChange = e => {
    console.log(e.target.files[0]);
  };
  
  render() {
    return (
      <React.Fragment>
        <Button onClick={this.handleButtonClick}>파일 업로드</Button>
        <input type="file"
               ref={fileInput}
               onChange={handleChange}
               style={{ display: "none" }} />
      </React.Fragment>
    );
  }
}

[함수형 컴포넌트]

const App => props => {
  const fileInput = React.useRef(null);
  
  const handleButtonClick = e => {
    fileInput.current.click();
  };
  
  const handleChange = e => {
    console.log(e.target.files[0]);
  };
  
  return (
    <React.Fragment>
      <Button onClick={handleButtonClick}>파일 업로드</Button>
      <input type="file"
             ref={fileInput}
             onChange={handleChange}
             style={{ display: "none" }} />
    </React.Fragment>
  );
}

파일 탐색기 창에서 선택된 파일을 불러올 수 있습니다.

반응형

댓글