React 사진 업로드 하기 (ES6활용, 미리보기)

Andy·2020년 11월 6일
3
post-thumbnail

FrontEnd 개발에는 ES6를 제대로 알아야한다.

현재 FrontEnd에는 정말 다양한 라이브러리와 프레임워크가 존재한다. 그 중에 대표적으로 React, Vue, Angular를 꼽을 수 있다.

물론 이 세가지 라이브러리 혹은 프레임워크들이 프론트엔드에서 계속 살아남을것이라는 보장은 할 수 없을 것이다. 프론트엔드의 대표 셋도 정말 다양하게 변화하고 있는 실정이다. 그래서 어떤 기술을 사용하더라도 꼭 알아야하는 것이 바로 자바스크립트 ES6이다.

현재 내가 프론트엔드에서 사용하는 기술은 React이지만 어떤 기술을 사용하든 ES6문법을 제대로 활용할 수 있다면 제목에 있는 사진, 파일업로드는 어디서든 사용할 수 있을 것이라 생각된다.

html 코드

<form onSubmit={onSubmit}>
	<input
    value={kweet}
    type="text"
    placeholder={"What's on your mind?"}
    maxLength={120}
    onChange={onChange}
    />
    <input type="file" accept={"image/*"} onChange={onFileChange}/>
    <input type="submit" value={"Kweet"} />
    {image && (
    	<div>
    		<img src={image} alt="img" width={"50px"} height={"50px"}/>
    		<button onClick={onClearPhotoClick}>취소</button>
    	</div>
    )}
</form>

html 9번째 줄에 있는 onChange는 input태그에 변화가 있을 때 onFileChange라는 function을 작동시킨다.

위와 같이 input태그의 타입을 file로 바꾸고 accept에 image/*를 통해 이미지가 전달되는 input태그를 만들어준다.

Javascript 코드

const onFileChange = (e) => {
        const {
            target : {files},
        } = e;
        const theFile = files[0];
        const reader = new FileReader();
        reader.readAsDataURL(theFile);
        reader.onloadend = (finishedEvent) =>{
            const {currentTarget : { result }} = finishedEvent;
            setImage(result);
        }
    }

이후에 JS코드에서 발생한 이벤트에서 files를 찾아낸다. 여기서 주의해야할점은 files로 바로 받는게 아니라 files[0]로 받아야 한다는 점이다. files는 배열로 들어오기 때문에 그중에 0번째에 저장되어있는 파일을 받아야한다.

FileReader 메소드들은 MDN을 읽어보면 자세히 나와있다.

const [image, setImage] = useState("")

FileReader를 통해 URL을 읽고 state 관리를 위해 만들어 놓은 setImage에 결과값을 저장하면 된다.
위 코드는 노마드에서 나온 코드를 활용한 것이고 실제 프로젝트에서는 아래와 같은 코드로 image업로드 component를 작성했다.

팀프로젝트에서 사용한 코드

import React, {useState} from 'react';
import http from "./http";
import FittedImage from "react-fitted-image";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";

const imageReducer = ( state={}, action ) => {
    switch (action.type) {
        default: return state
    }
}

export const Image = ({path, setImgLink}) => {
    const[content, setContent] = useState(undefined)
    const[img, setImg] = useState(undefined)
    const[url, setUrl] = useState('')
    const[formData] = useState(new FormData())

    const addFile = (e) => {
        setContent(e.target.files[0]);
        setUrl(URL.createObjectURL(e.target.files[0]))
    };
    const uploadService = file => {
        formData.append("file", file)
        return http.post(`/${path}`, formData, {})
    }

    const upload = (e) => {
        e.preventDefault()
        if(url !== ''){
            let currentFile = content
            setImg(currentFile)

            uploadService(currentFile)
                .then((res)=>{
                    alert(`파일이 업로드되었습니다. imgLink : ${res.data}`)
                    setImgLink(res.data)
                    setContent(undefined)
                    setImg(undefined)
                    setUrl('')
                })
                .catch(()=>{
                    setImg(undefined)
                    setContent(undefined)
                    setUrl('')
                    window.location.reload()
                    alert('파일업로드 실패')
                })

        }else{
            alert("파일을 선택해주세요")
        }
    }

    const cancel = (e) => {
        e.preventDefault()
        setImg(undefined)
        setContent(undefined)
        setUrl('')
        window.location.reload()
    }

    return (


        <>
                {url ? (
                    <>
                        <div className="input-air-primary">
                            <b>미리보기</b>
                            <FittedImage fit="contain" src={url} alt="#" />
                        </div>
                    </>
                ) : (
                    ""
                )}
                <Container className="input-air-success">
                    <Row>
                        <Col/>
                        <Col>
                            <input type="file" onChange={addFile} />
                        </Col>
                        <Col/>
                    </Row>
                    <Row>
                        <Col/>
                        <Col>
                            <button className="btn btn-outline-primary" type="button" onClick={upload}>업로드</button>
                        </Col>
                        <Col>
                            <button className="btn btn-outline-danger" onClick={cancel}>취소</button>
                        </Col>
                        <Col/>
                    </Row>
                </Container>
        </>

    )
}

export default imageReducer

두가지 코드를 보며 느낀점

비슷하면서도 다른 코드인데 ES6를 좀더 공부하고 했다면 프로젝트에서 하드코딩이 줄어들지 않았을까 생각이든다. 노마드를 통해서 공부하면서 FrontEnd 개발자가 되고자한다면 ES6문법에 집중해야겠다는 생각이 들었다.

profile
Junior Software Developer

0개의 댓글