이 글은 img-compressor의 결과 카드와 삭제 흐름을 기준으로 작성했습니다. 브라우저에서 파일을 서버로 보내지 않고 처리할 때는 미리보기 URL의 수명도 직접 관리해야 합니다.

문제: Object URL은 화면에서 사라져도 자동으로 끝나지 않는다

URL.createObjectURL은 사용자가 선택한 파일이나 변환 결과를 빠르게 미리보기로 보여 주기에 좋습니다. 이미지 압축 도구에서는 결과 카드마다 원본 또는 출력 파일의 URL을 만들고, 다운로드 링크에도 같은 방식을 사용할 수 있습니다. 문제는 이 URL이 React 상태에서 사라졌다고 해서 곧바로 해제되는 것이 아니라는 점입니다.

파일을 여러 번 추가하고 삭제하는 도구라면 이 차이가 중요합니다. 사용자가 20장의 이미지를 넣고, 일부를 지우고, 다시 20장을 넣는 흐름이 반복될 수 있습니다. 이때 만들어진 URL을 정리하지 않으면 브라우저가 이전 파일 데이터를 계속 붙잡고 있을 수 있습니다.

삭제 동작은 두 종류로 나눈다

img-compressor 같은 결과 목록 UI에서는 개별 삭제와 전체 삭제가 모두 필요합니다. 개별 삭제는 특정 카드의 URL만 해제하고 배열에서 제거합니다. 전체 삭제는 현재 목록에 있는 모든 URL을 순회하면서 해제한 뒤 상태를 비웁니다. 두 흐름을 분리해야 사용자가 일부 결과만 남기는 작업을 안전하게 할 수 있습니다.

images.forEach((image) => {
  URL.revokeObjectURL(image.url);
  if (image.webpUrl) {
    URL.revokeObjectURL(image.webpUrl);
  }
});

여기서 WebP 변환 결과의 URL도 따로 확인하는 이유는 한 카드에 원래 압축 결과와 WebP 결과가 함께 존재할 수 있기 때문입니다. 카드가 하나라고 해서 URL도 하나라고 가정하면 변환 후 만들어진 링크가 남을 수 있습니다.

다운로드 직후에 바로 해제하지 않는 이유

다운로드 버튼을 누른 직후 URL을 바로 해제하는 방식도 가능하지만, 결과 카드를 계속 화면에 보여 주는 도구에서는 조심해야 합니다. 사용자가 같은 파일을 다시 다운로드하거나, WebP 변환 전후를 비교할 수 있어야 한다면 카드가 살아 있는 동안 URL도 유지되어야 합니다. 그래서 정리 시점은 다운로드 순간보다 카드 삭제 또는 전체 초기화가 더 자연스럽습니다.

반대로 임시로 만든 링크가 화면에 남지 않는 일괄 다운로드라면 사용이 끝난 뒤 해제하는 방식을 고려할 수 있습니다. 중요한 기준은 URL을 만든 코드가 아니라, 사용자가 그 URL을 다시 사용할 가능성이 있는 화면 상태입니다.

점검 체크리스트

  • 결과 카드마다 만들어지는 URL이 몇 개인지 확인합니다.
  • 개별 삭제 시 해당 카드의 모든 URL을 해제합니다.
  • 전체 삭제 시 현재 목록에 남아 있는 URL을 모두 해제합니다.
  • WebP 변환처럼 나중에 추가되는 URL도 정리 대상에 포함합니다.
  • 삭제 후 새 파일을 넣었을 때 이전 미리보기가 섞이지 않는지 확인합니다.

한계와 다음 확인 항목

Object URL 정리는 성능 점수를 즉시 올리는 기능이라기보다, 브라우저 파일 도구의 안정성을 지키는 기본 작업입니다. 실제 메모리 회수 시점은 브라우저 구현과 상황에 따라 달라질 수 있으므로, 개발자 도구의 메모리 패널로 반복 처리 시나리오를 확인하는 것이 좋습니다.

사용자가 페이지를 떠날 때 정리하는 흐름도 별도 점검 대상입니다. 컴포넌트 언마운트 시 현재 목록의 URL을 해제하면, 장시간 사용 후 이동하는 상황에서도 이전 파일 참조가 남을 가능성을 줄일 수 있습니다.