ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

Issue

ํ”„๋กœ์ ํŠธ ์ค‘, ๋กœ์ปฌ PC์—์„œ ๊ฐ€์ ธ ์˜จ ์ด๋ฏธ์ง€๋ฅผ preview๋กœ ๋ณด์—ฌ์ฃผ๋ฉฐ ์ €์žฅํ•˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ํ•„์š”ํ–ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ผ ์ค„ ์•Œ์•˜์ง€๋งŒ ์ƒ๊ฐ๋ณด๋‹ค ๋งŽ์€ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ฒช์—ˆ๊ธฐ์— ํ•ด๋‹น ๋‚ด์šฉ์„ ํฌ์ŠคํŒ…ํ•˜๊ณ ์ž ํ•œ๋‹ค.

 

Code

 

1) Input ์Šคํƒ€์ผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

 

์šฐ์„ , Input ํƒœ๊ทธ ๋‚ด์— 'type=file' ์†์„ฑ์„ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋กœ์ปฌ PC์—์„œ ์ด๋ฏธ์ง€ ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ ์ง€์ • ์Šคํƒ€์ผ์ด ์›ํ•˜๋˜ ๋ฐฉํ–ฅ์ด ์•„๋‹ˆ๊ธฐ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด JSX๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

         <>
	  <S.FileBox>
            <S.FileLabel htmlFor="file">๋‚ด PC์—์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ</S.FileLabel>
            <S.FetchLocalPC type="file" id="file" onChange={storeImage}/>
          </S.FileBox>
          <>

์‹ค์ œ ๋กœ์ปฌ PC์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ๋Šฅ์€ FetchLocalPC ์ปดํฌ๋„ŒํŠธ์ด์ง€๋งŒ ์Šคํƒ€์ผ์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๊ธฐ ์œ„ํ•ด์„œ FileLabel ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ๋‘ ์ปดํฌ๋„ŒํŠธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์Šคํƒ€์ผ์„ ์ง€์ •ํ•ด์ฃผ์—ˆ๋‹ค.

export const FileLabel = styled.label`
  padding: 20px 50px;
  border: 1px solid #f0f0f0;
  border-radius: 2px;
  font-size: 20px;
  line-height: 3;
  background-color: #f0f0f0;
  color: #616161;
  cursor: pointer;
`;

export const FetchLocalPC = styled.input`
  position: absolute;
  width: 0;
  height: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
`;

๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•˜๋Š” FetchLocalPC ์ปดํฌ๋„ŒํŠธ์˜ ์œ„์น˜๊ฐ’๊ณผ ์Šคํƒ€์ผ์„ ๋ชจ๋‘ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๊ณ  ์‹ค์ œ ์Šคํƒ€์ผ์„ ๋‹ด๋‹นํ•  FileLabel ์ปดํฌ๋„ŒํŠธ์— ์›ํ•˜๋Š” CSS ์†์„ฑ์„ ์ง€์ •ํ•ด์คŒ์œผ๋กœ์จ ์Šคํƒ€์ผ์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•ด์ฃผ์—ˆ๋‹ค.

 

2) ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ File ์ธํ„ฐํŽ˜์ด์Šค ์ฐธ์กฐํ•˜๊ธฐ

 

ํ•ด๋‹น input ํƒœ๊ทธ์—์„œ click ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์„ ๋•Œ ๋กœ์ปฌ PC์—์„œ ๊ฐ€์ ธ์˜จ ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ files ์ฐธ์กฐํ•˜์˜€๋‹ค.

https://developer.mozilla.org/ko/docs/Web/API/File

 

File - Web API | MDN

File ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํŒŒ์ผ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๊ณ , ์›น ํŽ˜์ด์ง€์˜ JavaScript๊ฐ€ ํ•ด๋‹น ๋‚ด์šฉ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

developer.mozilla.org

File ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํŒŒ์ผ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๊ณ , ์›น ํŽ˜์ด์ง€์˜ JavaScript๊ฐ€ ํ•ด๋‹น ๋‚ด์šฉ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. File ๊ฐ์ฒด๋Š” ๋ณดํ†ต FileList ๊ฐ์ฒด์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ fileList๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” files์— ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ์ฝ˜์†” ๊ฒฐ๊ณผ์ด๋‹ค.

FileList {0: File, length: 1}0: FilelastModified: 1648878872817lastModifiedDate: Sat Apr 02 2022 14:54:32 GMT+0900 (ํ•œ๊ตญ ํ‘œ์ค€์‹œ) {}name: "image4.jpeg"size: 79784type: "image/jpeg"webkitRelativePath: ""[[Prototype]]: Filelength: 1[[Prototype]]: FileList

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„  ๋‹จ์ผ ์ด๋ฏธ์ง€ ์„ ํƒ ๊ธฐ๋Šฅ ๋ฐ–์— ํ•„์š”์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด fileList ๋‚ด์—์„œ 0๋ฒˆ์งธ ์ธ๋ฑ์Šค์— ์ ์žฌ๋œ file ์ธํ„ฐํŽ˜์ด์Šค ๊ฐ’์„ ์ฐธ์กฐํ•˜์˜€๋‹ค.

const storeImage = async (e: React.ChangeEvent<HTMLInputElement>) => {
	// ํ•ด๋‹น async/await ๊ตฌ๋ฌธ์ด ์™œ ํ•„์š”ํ•œ์ง€ ๋’ค์— ๋‹จ๊ณ„์—์„œ ์„ค๋ช…
    const target = e.target as HTMLInputElement;
    
    const result = target.files && await parseFile(target.files[0]);
  }

 

3) ๋น„๋™๊ธฐ ์ž‘์—…๊ณผ ํ•จ๊ป˜ FileReader ์ธ์Šคํ„ด์Šค ์‚ฌ์šฉ

 

ํ•ด๋‹น file ์ธ์Šคํ„ด์Šค๋งŒ์„ ์ด์šฉํ•ด์„œ๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ด๋ฏธ์ง€ ์†Œ์Šค๋ฅผ ์ •์ƒ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋‹ค.

์ด๋ฏธ์ง€ ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” FileReader ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋‹ค.

https://developer.mozilla.org/ko/docs/Web/API/FileReader

 

FileReader - Web API | MDN

FileReader ๊ฐ์ฒด๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ ์œ„ํ•˜์—ฌ ์ฝ์„ ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๋Š”File ํ˜น์€ Blob ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ํŒŒ์ผ์˜ ๋‚ด์šฉ์„(ํ˜น์€ raw data๋ฒ„ํผ๋กœ) ์ฝ๊ณ  ์‚ฌ์šฉ์ž์˜ ์ปดํ“จํ„ฐ์— ์ €์žฅํ•˜๋Š”

developer.mozilla.org

FileReader ๊ฐ์ฒด๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ ์œ„ํ•˜์—ฌ ์ฝ์„ ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” File ํ˜น์€ Blob ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ํŒŒ์ผ์˜ ๋‚ด์šฉ์„(ํ˜น์€ raw data๋ฒ„ํผ๋กœ) ์ฝ๊ณ  ์‚ฌ์šฉ์ž์˜ ์ปดํ“จํ„ฐ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
const processFile = (currentFile: File): Promise<string | ArrayBuffer | null>  => {
    return new Promise(resolve => {
        const reader = new FileReader();
        reader.readAsDataURL(currentFile);
        reader.onload = () => {
            const result = reader.result;
            resolve(result);
        }
    })
}

FileReader ๊ฐ์ฒด ์ค‘ readAsDataURL ๋ฉ”์„œ๋“œ๋Š” File ๊ฐ์ฒด๋ฅผ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก Buffer ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ onload ๋ฉ”์„œ๋“œ์ด๋‹ค.

 

onload ๋ฉ”์„œ๋“œ๋Š” FileReader ๊ฐ์ฒด๊ฐ€ ์ฝ๊ธฐ ์ž‘์—…์„ ๋งˆ์น˜๊ณ  ์–ด๋– ํ•œ ์ž‘์—…์„ ํ• ์ง€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋„˜๊ธฐ๋Š”๋ฐ, ์ด๋•Œ ํ•ด๋‹น ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐœ์ƒํ•œ๋‹ค.

 

๋น„๋™๊ธฐ ์ž‘์—…(pending ์ƒํƒœ)์ด ์ œ๋Œ€๋กœ ์ด๋ค„์ง€๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด async/await ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜๋ฐ›๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

export const parseFile = async (currentFile: File) => {
    const parsedFile: string | ArrayBuffer | null = await processFile(currentFile);

    return parsedFile;
}

 

ArrayBuffer Type?

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‹ค๋ณด๋‹ˆ ๋ชจ๋“  ๊ฐ’์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์ง€์ •ํ•ด์ค˜์•ผ ๋ฌ๋Š”๋ฐ, FileReader ๊ฐ์ฒด์—์„œ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’์˜ ํƒ€์ž… ์ค‘ArrayBuffer ๋ผ๋Š” ํƒ€์ž…์ด ์žˆ์–ด, Buffer์— ๋Œ€ํ•œ ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค.https://curryyou.tistory.com/441

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฒ„ํผ(Buffer): ArrayBuffer, TypedArray ํŒŒํ—ค์น˜๊ธฐ!

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฒ„ํผ(Buffer)๋ฅผ ๊ตฌํ˜„ํ•œ ArrayBuffer, ArrayBufferView๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ ๋‹ค๋ฃฐ ๋‚ด์šฉ์„ ์š”์•ฝํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค. 1.  ๋ฒ„ํผ(Buffer)๋ž€? - ์ž„์‹œ๋กœ ๋ฐ”

curryyou.tistory.com

ํ•ด๋‹น ํฌ์ŠคํŒ…์—์„œ Buffer ๊ฐœ๋…์— ๋Œ€ํ•ด์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ฒ„ํผ๋ž€ ํŠน์ • ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด๋‘๋Š” ๊ฐ์ฒด์ด๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

ํ•˜์ง€๋งŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์šฉ๋„๊ฐ€ ๋‹ค์–‘ํ•ด์ง€๋ฉด์„œ ์˜ค๋””์˜ค, ๋น„๋””์˜ค ๋ฐ ์›น์†Œ์ผ“ ํ†ต์‹ ์—์„œ ์‚ฌ์šฉํ•˜๋Š” Raw Binary Data๋ฅผ ์ง์ ‘ ๋‹ค๋ฃฐ ํ•„์š”๊ฐ€ ์ƒ๊ฒผ๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ์˜ ํšจ์œจ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด Buffer๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

(์ด ์ค‘ ArrayBuffer๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง€์ •ํ•œ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋งŒํผ์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค)

 

๊ตฌํ˜„ ์˜์ƒ

๋Œ“๊ธ€
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2024/12   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ