Skip to content

Commit

Permalink
게시글 작성 시 이미지 파일을 보낼 때 webp 로 압축하여 성능 개선 (#614)
Browse files Browse the repository at this point in the history
* feat: (#555) browser-image-compression 설치 및 본문 이미지 훅에 적용

* feat: (#555) 선택지 옵션 사진을 webp로 변환하도록 구현
  • Loading branch information
Gilpop8663 authored Sep 14, 2023
1 parent 20d37ff commit d95eed6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 11 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"dependencies": {
"@tanstack/react-query": "^4.29.19",
"browser-image-compression": "^2.0.2",
"dotenv": "^16.3.1",
"msw": "^1.2.3",
"react": "^18.2.0",
Expand Down
18 changes: 13 additions & 5 deletions frontend/src/hooks/useContentImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ChangeEvent, useRef, useState } from 'react';

import { MAX_FILE_SIZE } from '@components/PostForm/constants';

import { convertImageToWebP } from '@utils/resizeImage';

export const useContentImage = (imageUrl: string = '') => {
const [contentImage, setContentImage] = useState(imageUrl);
const contentInputRef = useRef<HTMLInputElement | null>(null);
Expand All @@ -11,13 +13,23 @@ export const useContentImage = (imageUrl: string = '') => {
if (contentInputRef.current) contentInputRef.current.value = '';
};

const handleUploadImage = (event: ChangeEvent<HTMLInputElement>) => {
const handleUploadImage = async (event: ChangeEvent<HTMLInputElement>) => {
const { files } = event.target;

if (!files) return;

const file = files[0];

const webpFileList = await convertImageToWebP(file);

event.target.files = webpFileList;

const reader = new FileReader();

const webpFile = webpFileList[0];

reader.readAsDataURL(webpFile);

event.target.setCustomValidity('');

if (file.size > MAX_FILE_SIZE) {
Expand All @@ -27,10 +39,6 @@ export const useContentImage = (imageUrl: string = '') => {
return;
}

const reader = new FileReader();

reader.readAsDataURL(file);

reader.onloadend = () => {
setContentImage(reader.result?.toString() ?? '');
};
Expand Down
22 changes: 16 additions & 6 deletions frontend/src/hooks/useWritingOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { ChangeEvent, useState } from 'react';

import { MAX_FILE_SIZE } from '@components/PostForm/constants';

import { convertImageToWebP } from '@utils/resizeImage';

const MAX_WRITING_LENGTH = 50;

export interface WritingVoteOptionType {
Expand Down Expand Up @@ -78,13 +80,26 @@ export const useWritingOption = (initialOptionList: WritingVoteOptionType[] = IN
setOptionList(updatedOptionList);
};

const handleUploadImage = (event: React.ChangeEvent<HTMLInputElement>, optionId: number) => {
const handleUploadImage = async (
event: React.ChangeEvent<HTMLInputElement>,
optionId: number
) => {
const { files } = event.target;

if (!files) return;

const file = files[0];

const webpFileList = await convertImageToWebP(file);

event.target.files = webpFileList;

const reader = new FileReader();

const webpFile = webpFileList[0];

reader.readAsDataURL(webpFile);

event.target.setCustomValidity('');

if (file.size > MAX_FILE_SIZE) {
Expand All @@ -94,11 +109,6 @@ export const useWritingOption = (initialOptionList: WritingVoteOptionType[] = IN
return;
}

const reader = new FileReader();

// readAsDataURL 메서드를 통해 파일을 모두 읽고 나면 reader의 loadend 이벤트에서 이미지 미리보기 결과를 확인할 수 있습니다.
reader.readAsDataURL(file);

reader.onloadend = () => {
const updatedOptionList = optionList.map(optionItem => {
if (optionItem.id === optionId) {
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/utils/resizeImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import imageCompression from 'browser-image-compression';

export const convertImageToWebP = async (imageFile: File) => {
const compressedBlob = await imageCompression(imageFile, {
maxWidthOrHeight: 1280,
initialQuality: 0.5,
fileType: 'image/webp',
});

const outputWebpFile = new File([compressedBlob], `${Date.now().toString()}.webp`);

const dataTransfer = new DataTransfer();

dataTransfer.items.add(outputWebpFile);

return dataTransfer.files;
};

0 comments on commit d95eed6

Please sign in to comment.