Loading...

Spring/Tistory / / 2022. 5. 4. 11:08

블로그-V3. 프로필 사진 미리보기 테스트

반응형

이미지를 클릭했을 때 파일 선택창이 떠야 하고,

파일 선택창에서 파일을 선택하면 변화가 발생한 상태이기 때문에

change 메서드를 사용한다.

 

css 선택자로 선택한 돔의 값이 변화할 경우 캐치하는 메서드이다.

 

프로젝트에 적용하기 전에 테스트 파일을 만들어 테스트해보자.

 

<select id="testChange">
    <option value="">김길동</option>
    <option value="홍길동">홍길동</option>
    <option value="최철수">최철수</option>
    <option value="나길동">나길동</option>
</select>
$("#testChange").change((event) => {
    console.log(event);
});

 

event가 가지고 있는 것에 어떤 게 있는지 살펴보자.

클릭했을 때 콘솔에 찍히는 게 아니라 값이 변경되었을 때 찍힌다.

 

 

event는 활용할 수 있는 옵션 값을 매우 많이 가지고 있다.

target도 있고, targer의 옵션 값도 다 들고 온다.

 

input 태그도 잘 동작하는지 테스트해보자.

<body>
    <select id="testChange">
        <option value="">김길동</option>
        <option value="홍길동">홍길동</option>
        <option value="최철수">최철수</option>
        <option value="나길동">나길동</option>
    </select>

    <input type="file" id="fileChange">

    <script>
        $("#testChange").change((event) => {
            console.log(event);
        });

        $("#fileChange").change((event) => {
            console.log(event);
        });
    </script>
</body>

 

콘솔을 확인해보면 파일 선택 버튼을 클릭했을 때 이벤트가 발생하는 게 아니라

파일을 선택하여 값이 변경되었을 때 이벤트가 발생하여 콘솔에 로그가 찍힌다.

 

 

fileChange의 이벤트에 target 속성 안에 files라는 옵션을 가지고 있다.

이 files가 뭔지 출력해보자.

 

$("#fileChange").change((event) => {
    console.log(event.target.files);
});

 

FileList를 뱉어준다.

어떤 이벤트에 하나가 아니라 여러 개의 변화가 있을 수 있기 때문에 배열로 반환해준다.

우리는 하나의 파일만 변하기 때문에 0번지에 우리가 원하는 파일의 객체가 저장되어 있다.

 

정확하게 보기 위해서 0번지까지 지정해서 콘솔에 찍어줘 보자.

$("#fileChange").change((event) => {
    console.log(event.target.files[0]);
});

 

File이라는 자바스크립트 오브젝트로 나온다.

이 File의 정보 중에 type이 중요하다.

 

 

user 오브젝트는 이미 생성되어있고, profileImg 부분만 수정하는 것이기 때문에 put 요청을 할 것이다.

사실 부분 변경은 patch를 사용해야 하는데 구분하지 않고 put을 사용한다.

이 이미지의 MIME 타입은 "image/png"이다.

이 타입을 알아야 구분해서 파일을 전송할 수 있다.

 

파일을 선택할 때 이미지가 아닌 다른 파일이 들어올 수 없게 막아야 한다.

MIME 타입의 앞단에 나오는 대전제 타입이 image가 아닌 것은 들어올 수 없게 막는다.

 

let f = event.target.files[0];

if (!f.type.match("image.*")) { // 문자열 비교 match
    // 쪼까내기
    alert("이미지를 선택해주세요!!");
    return;
}

 

자바스크립트에서 문자열을 비교할 때는 그냥 f.type == "image/png"라고 비교하면 되는데

정확히 "image/png"와 동일한지 비교하려는 게 아니라

"image/~~~~" 형태를 가졌는지 비교하려고 하기 때문에 match를 사용한다.

 

. 으로 찾겠다는 말이 아니라 연결의 역할이다.

image로 시작하는 것을 찾는다는 것이다.

 


 

모든 파일은 form 태그에 multipart/form-data 타입으로 전송해주는 게 가장 쉬운 방법이다.

우리가 실제로 form 태그를 사용하여 전송하는 게 아니기 때문에

FormData 데이터 객체를 생성해준다.

이 객체는 form 태그와 똑같은 것이다.

 

객체 내부가 비어있기 때문에 여기에 input 데이터를 넣어줄 것이다.

id="fileForm"을 찾아서 FormData에 넣어주자.

 

fileForm을 찾으면 0번지에 우리가 찾는 form 데이터가 있다.

 

<form id="fileForm">
    <input id="fileChange" name="profileImg" type="file">
</form>
let fileForm = $("#fileForm")[0];
let formData = new FormData(fileForm);

 

formData는 form 태그 자바스크립트 객체이다.

생성자에 form 태그를 주입만 해주면 자바스크립트 객체로 바꿔준다.

 

form 태그 key:value 데이터로 변환해준다.

 

이제 fetch로 데이터를 전송해주면 된다.

지금 테스트 파일에서는 fetch를 할 수 없으니 생략해두고

미리 보기 로직을 만들어보자.

 

 

 

자바스크립트의 function 내부의 this는 내부의 필드를 가리키는 게 아니라

해당 메서드를 호출한 사람의 this가 적용된다.

 

이때 화살표 함수로 메서드를 만들면 해당 메서드 내부의 this를 가리킨다.

 

// fetch();

let reader = new FileReader();

// 아직 실행안됨 : 콜 백 함수
reader.onload = (event) => {
    $("#user-profile-img").attr("src", event.target.result);
}

// reader.onload(); // 메서드 실행
reader.readAsDataURL(f);

 

reader.onload 함수는 직접 호출하지 않았지만 실행 함수이다.

 

reader.readAsDataURL 함수가 파일을 읽는 함수이다.

메모리나 하드 디스크에 있는 파일을 읽는 행위는 cpu가 하는 게 아니라 오래 걸린다.

 

읽는 행위가 10초라고 한다면 이게 동기적으로 실행되었을 때 10초 동안 화면이 뻗어버리게 된다.

그래서 이런 애들은 무조건 비동기로 실행된다.

 

스레드가 하나밖에 없기 때문이다.

 

내부적으로 await, async가 걸려있는 promise이다.

 

내부적으로 pending 기간이 있고 다운로드가 완료되면 reader.onload를 호출해준다.

 

내가 직접 실행하는 게 아니라 어떠한 이벤트가 끝났을 때 실행되는 함수를 콜백 함수라고 한다.

 

이벤트 리스너와 같은 게 모두 콜백 함수이다.

 

reader.onload 함수는 항상 reader.readAsDataURL보다 위에 적혀있어야 한다.

reader.readAsDataURL에서 비동기적으로 I/O가 일어나는 시간보다

cpu가 아래로 내려가는 시간이 더 빠르기 때문에 reader.onload를 먼저 실행하게 될 수도 있다.

그럼 아직 데이터가 도착하지 못했기 때문에 null 값을 참조하게 된다. 주의하자.

 

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 
반응형