Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 이미지 데이터 배열의 중복 객체 제거하기

JavaScript로 개발을 하다 보면 이미지 정보를 담은 객체 배열에서 중복된 항목을 걸러내야 하는 경우가 자주 발생합니다. 예를 들어 갤러리 기능을 구현할 때 같은 이미지가 여러 번 등록되어 있다면, 이를 정리해 주는 로직이 필요하죠.

문제 상황

다음과 같이 이미지 데이터가 담긴 배열이 있다고 가정해 보겠습니다.

const arr = [{
    'image': "jv2bcutaxrms4i_img.png",
    'gallery_image': true
},
{
    'image': "abs.png",
    'gallery_image': true
},
{
    'image': "acd.png",
    'gallery_image': false
},
{
    'image': "jv2bcutaxrms4i_img.png",
    'gallery_image': true
},
{
    'image': "abs.png",
    'gallery_image': true
},
{
    'image': "acd.png",
    'gallery_image': false
}];

위 배열을 보면 jv2bcutaxrms4i_img.png, abs.png, acd.png 세 개의 이미지가 각각 두 번씩 중복되어 들어 있는 것을 확인할 수 있습니다.

해결 방법

우리가 작성해야 할 함수는 이런 배열을 입력받아, 'image' 속성 값이 중복되는 객체들을 제거하고 고유한 항목만 남긴 새로운 배열을 반환하는 역할을 합니다.

핵심 아이디어는 간단합니다. 결과를 담을 빈 배열을 하나 준비한 뒤, 원본 배열의 객체를 하나씩 순회하면서 해당 객체의 image 값이 이미 결과 배열에 존재하는지 확인하고, 존재하지 않을 때만 추가하는 방식입니다.

구현 코드

const arr = [{
    'image': "jv2bcutaxrms4i_img.png",
    'gallery_image': true
},
{
    'image': "abs.png",
    'gallery_image': true
},
{
    'image': "acd.png",
    'gallery_image': false
},
{
    'image': "jv2bcutaxrms4i_img.png",
    'gallery_image': true
},
{
    'image': "abs.png",
    'gallery_image': true
},
{
    'image': "acd.png",
    'gallery_image': false
}];
const buildUnique = (arr = []) => {
    const unique = [];
    arr.forEach(obj => {
        let found = false;
        unique.forEach(uniqueObj => {
            if(uniqueObj.image === obj.image) {
                found = true;
            };
        });
        if(!found){
            unique.push(obj);
        };
    });
    return unique;
};
console.log(buildUnique(arr));

실행 결과

위 코드를 실행하면 콘솔에 다음과 같이 출력됩니다.

[
    { image: 'jv2bcutaxrms4i_img.png', gallery_image: true },
    { image: 'abs.png', gallery_image: true },
    { image: 'acd.png', gallery_image: false }
]

코드 동작 원리 살펴보기

  • buildUnique 함수: 기본값으로 빈 배열을 받도록 설정하여, 인자가 전달되지 않아도 안전하게 동작합니다.
  • unique 배열: 중복이 제거된 최종 결과를 저장하는 용도입니다.
  • forEach 반복문: 원본 배열의 각 객체를 순회하며, 내부 반복문으로 unique 배열에 같은 image 값을 가진 객체가 있는지 검사합니다.
  • found 플래그: 중복 발견 여부를 표시하며, 중복이 없을 때(!found)만 해당 객체를 결과 배열에 추가합니다.

더 나은 방법: Set을 활용한 최적화

위 방식은 이중 반복문을 사용하기 때문에 데이터 양이 많아지면 성능이 떨어질 수 있습니다(시간 복잡도 O(n²)). 다음과 같이 Set 객체를 활용하면 O(n)의 시간 복잡도로 더 효율적으로 처리할 수 있습니다.

const buildUniqueWithSet = (arr = []) => {
    const seen = new Set();
    return arr.filter(obj => {
        if(seen.has(obj.image)) {
            return false;
        }
        seen.add(obj.image);
        return true;
    });
};
console.log(buildUniqueWithSet(arr));

Set은 값의 존재 여부를 확인하는 작업이 평균적으로 O(1)이므로, 대용량 데이터를 다룰 때 훨씬 유리합니다. 또한 filter 메서드를 사용해 코드가 더 간결하고 읽기 쉬워졌습니다.

마무리

객체 배열에서 특정 속성 기준으로 중복을 제거하는 것은 실무에서 매우 흔한 작업입니다. 소규모 데이터라면 forEach 기반의 직관적인 방식으로 충분하지만, 성능이 중요한 환경이라면 Set을 활용한 방식을 사용하는 것이 좋습니다. 상황에 맞게 두 가지 방법을 적절히 선택해 활용해 보세요.