업로드 할 이미지 파일 미리보기 구현하기

업로드 할 이미지 파일을 선택했을 때 업로드 하기 전에 선택한 이미지 미리보기가 되면 잘못된 이미지를 업로드 하는 실수를 줄일 수 있습니다.

쇼핑몰 백엔드, 또는 사용자 후기에 이미지 업로드 기능을 구현할 때 이미지 미리보기를 사용할 수 있습니다.

선택한 이미지 파일의 썸네일을 표시하기 위한 간단한 HTML과 CSS가 아래처럼 있다고 가정하고 이미지 파일을 선택해 썸네일을 표시하는 방법을 알아보겠습니다.

<style>
  .dellink{
    display: none;
  }
</style>


<input type="file" class="hidden_input" id="imageSelector" name="imageSelector" 
accept="image/jpeg, image/jpg, image/png" multiple />
<img src="" class="thumb"/>
<a href="javascript:void(0);" class="dellink">썸네일삭제</a>

이미지 파일만 선택하도록 하기

먼저 태그에 기본설정으로 이미지 파일만 필터링해서 보이도록 "accept" 속성을 부여합니다.

실제로 이미지 파일을 선택했는지는 자바스크립트로 체크를 하지만, 파일 선택 편의를 위해 태그에 속성을 부여하는 것은 기본 원칙입니다.

여러개의 파일 포맷을 필터링 하려면 아래처럼 콤마로 구분해 여러개를 사용할 수 있습니다.

<input type="file" class="hidden_input" id="imageSelector" name="imageSelector" 
accept="image/jpeg, image/jpg, image/png" multiple />

"accept" 속성을 태그에 지정한 경우에도 사용자는 선택적으로 다른 포맷을 선택할 수 있습니다.

따라서 반드시 자바스크립트로 파일 확장자 체크를 해야합니다.

먼저 선택한 파일의 객체를 파라메터로 넘겨 파일 타입을 비교하는 방법입니다.

간편하고 빠르게 비교할 수 있습니다.

//이미지 객체 타입으로 이미지 확장자 밸리데이션
var validateType = function(img){
  return (['image/jpeg','image/jpg','image/png'].indexOf(img.type) > -1);
}

잘 알려진 일반 확장자가 아닌 경우에는 위의 메서드로는 판단을 할 수 없는 경우가 있습니다.

이런 경우에는 파일 이름을 기준으로 확장자를 구분해서 비교해야합니다.

지원하는 파일 확장자는 "extensions" 배열 변수에 담습니다.

var validateName = function(fname){
  let extensions = ['jpeg','jpg','png'];
  let fparts = fname.split('.');
  let fext = '';


  if(fparts.length > 1){
      fext = fparts[fparts.length-1];
  }


  let validated = false;
  
  if(fext != ''){
      extensions.forEach(function(ext){
          if(ext == fext){
              validated = true;
          }
      });
  }


  return validated;
}

이미지 파일을 <img> 태그 썸네일 데이터로 붙이기

확장자 체크가 완료되면 선택한 이미지 파일의 경로 정보와 바이너리 데이터를 얻어 <img> 태그에 적용해야 합니다.

선택한 이미지 파일의 파일 경로에서 파일 바이너리 데이터를 추출해서 붙이는 메서드는 

URL.createObjectURL(fileElement.files[0]);

입니다.

URL.createObjectURL 은 파라메터로 받은 경로에 있는 파일의 바이너리 데이터를 읽는 메서드입니다.

읽은 바이너리 데이터는 썸네일 이미지 태그(<img>)의 소스 경로(src) 속성에 적용합니다.

src 속성은 URI 경로 외에 바이너리 이미지 데이터도 붙여넣을 수 있습니다.

이미지 확장자 체크를 해서 이미지 파일이면 이미지 바이너리 정보를 이미지 태그에 소스로 붙여넣습니다.



var elem = document.getElementById('imageSelector'); //파일 선택 필드 요소 얻기


if(validateType(elem.files[0])){ // 파일 확장자 체크해서 이미지 파일이면
  let preview = document.querySelector('.thumb'); // 미리보기 썸네일 <img> 엘리먼트 얻기
  preview.src = URL.createObjectURL(elem.files[0]); //파일 객체에서 이미지 데이터 가져옴.
  document.querySelector('.dellink').style.display = 'block'; // 이미지 삭제 링크 표시
  //이미지 로딩 후 객체를 메모리에서 해제
  preview.onload = function() {
    URL.revokeObjectURL(preview.src);
  }
}else{
  console.log('이미지 파일이 아닙니다.');
}


입력 필드와 썸네일 미리보기 이벤트 연결

파일 입력 필드에서 파일을 선택하면 자동으로 파일 확장자 체크를 해서 이미지 파일일 경우 썸네일로 표시되도록 이벤트 리스너로 연결을 합니다.

파일 입력 필드는 파일을 선택하면 "change" 이벤트가 발생합니다.

"change" 이벤트 리스너를 등록하면 파일 선택시 바로 썸네일 미리보기 처리를 할 수 있습니다.

앞서 작성한 코드를 개선해보겠습니다.


// 파일 선택 필드에 이벤트 리스너 등록
document.getElementById('imageSelector').addEventListener('change', function(e){
  let elem = e.target;
  if(validateType(elem.files[0])){
      let preview = document.querySelector('.thumb');
      preview.src = URL.createObjectURL(elem.files[0]); //파일 객체에서 이미지 데이터 가져옴.
      document.querySelector('.dellink').style.display = 'block'; // 이미지 삭제 링크 표시
      preview.onload = function() {
          URL.revokeObjectURL(preview.src); //URL 객체 해제
      }
  }else{
    console.log('이미지 파일이 아닙니다.');
  }
});

썸네일 이미지 삭제

미리보기한 썸네일 이미지가 원하는 이미지가 아닐 경우 다른 이미지로 선택해야 합니다.

선택하기 전에 메모리에 로드된 썸네일 이미지를 해제해야 메모리 누수가 발생하지 않습니다.


document.querySelector('.dellink').addEventListener('click', function(e){
  let dellink = e.target;
  let preview = dellink.previousElementSibling;
  preview.src = ''; // 썸네일 이미지 src 데이터 해제
  document.querySelector('.dellink').style.display = 'none';
});

동작하는 완성된 소스는 다음 링크를 클릭해 다운로드 할 수 있습니다.

upload.zip0.00MB