Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/feature/create-album/utils/heicToJpeg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ describe('convertHeicFilesToJpeg', () => {
expect(result[0].type).toBe('image/jpeg');
// The second file should remain as is
expect(result[1].name).toBe('image.jpg');
expect(Toast.alert).toHaveBeenCalledWith(
'1개의 HEIC 파일을 변환 중입니다...',
);
expect(Toast.alert).toHaveBeenCalledWith('변환 중... 0/1');
expect(Toast.alert).toHaveBeenCalledWith('변환 중... 1/1');
});

it('should handle conversion failure gracefully', async () => {
Expand Down
62 changes: 37 additions & 25 deletions src/feature/create-album/utils/heicToJpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,47 @@ export async function convertHeicFilesToJpeg(files: File[]): Promise<File[]> {
/heic|heif/i.test(file.type) || /\.heic$|\.heif$/i.test(file.name),
);

if (heicFiles.length > 0) {
Toast.alert(`${heicFiles.length}개의 HEIC 파일을 변환 중입니다...`);
if (heicFiles.length === 0) {
return files;
}

const convertedFiles = await Promise.all(
files.map(async (file) => {
if (/heic|heif/i.test(file.type) || /\.heic$|\.heif$/i.test(file.name)) {
try {
const jpegBlob = await heicTo({
blob: file,
let convertedCount = 0;
const totalCount = heicFiles.length;

// 초기 메시지 표시
Toast.alert(`변환 중... 0/${totalCount}`);

const convertedFiles: File[] = [];

for (const file of files) {
if (/heic|heif/i.test(file.type) || /\.heic$|\.heif$/i.test(file.name)) {
try {
const jpegBlob = await heicTo({
blob: file,
type: 'image/jpeg',
quality: 0.9,
});
const convertedFile = new File(
[jpegBlob],
file.name.replace(/\.(heic|heif)$/i, '.jpg'),
{
type: 'image/jpeg',
quality: 0.9,
});
return new File(
[jpegBlob],
file.name.replace(/\.(heic|heif)$/i, '.jpg'),
{
type: 'image/jpeg',
lastModified: file.lastModified,
},
);
} catch (e) {
Toast.alert(`${file.name} 파일의 변환에 실패했습니다.`);
return file;
}
lastModified: file.lastModified,
},
);
convertedFiles.push(convertedFile);

// 변환 완료마다 진행률 업데이트
convertedCount++;
Toast.alert(`변환 중... ${convertedCount}/${totalCount}`);
} catch (e) {
Toast.alert(`${file.name} 파일의 변환에 실패했습니다.`);
convertedFiles.push(file);
}
return file;
}),
);
} else {
convertedFiles.push(file);
}
}

return convertedFiles;
Comment on lines +10 to 52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

안녕하세요. HEIC 변환 진행 상태를 표시하는 기능은 좋은 시도입니다. 하지만 현재 구현에는 두 가지 큰 문제점이 있습니다.

  1. 성능 저하: for...of 루프와 await를 사용하여 파일 변환을 순차적으로 처리하고 있습니다. 이전의 Promise.all을 사용한 병렬 처리에 비해 여러 파일을 변환할 때 응답 속도가 크게 느려질 수 있습니다.
  2. 토스트 메시지 남발 및 버그 가능성: 변환이 성공할 때마다 Toast.alert를 호출하면 짧은 시간에 많은 토스트 메시지가 생성되어 사용자 경험을 해칩니다. 또한, 현재 Toast 컴포넌트의 구현 방식 상, Toast.alert를 빠르게 연속 호출하면 unmount 타이머 관련 race condition이 발생하여 예기치 않은 UI 버그를 유발할 수 있습니다.

이러한 문제들을 해결하기 위해, Promise.all을 사용하여 병렬 변환을 유지하고 토스트 메시지 사용을 최소화하는 방식으로 리팩토링하는 것을 강력히 권장합니다. 아래 제안 코드는 병렬 처리를 복원하고, 변환 시작과 개별 파일 변환 실패 시에만 토스트를 보여주도록 수정한 것입니다. 실시간 진행률 표시는 현재 Toast 컴포넌트로는 불안정하므로, 더 안정적인 대안(예: Toast 컴포넌트 수정 또는 다른 UI 사용)을 고려해보시는 것이 좋겠습니다.

  if (heicFiles.length === 0) {
    return files;
  }

  Toast.alert(`${heicFiles.length}개의 HEIC 파일을 변환합니다...`);

  const convertedFiles = await Promise.all(
    files.map(async (file) => {
      if (/heic|heif/i.test(file.type) || /\.heic$|\.heif$/i.test(file.name)) {
        try {
          const jpegBlob = await heicTo({
            blob: file,
            type: 'image/jpeg',
            quality: 0.9,
          });
          return new File(
            [jpegBlob],
            file.name.replace(/\.(heic|heif)$/i, '.jpg'),
            {
              type: 'image/jpeg',
              lastModified: file.lastModified,
            },
          );
        } catch (e) {
          Toast.alert(`${file.name} 파일의 변환에 실패했습니다.`);
          return file;
        }
      }
      return file;
    }),
  );

  return convertedFiles;

}
Loading