문제 상황
다음과 같은 객체가 있다고 가정해 보겠습니다.
const obj = {
"100": "Jaipur",
"101": "Delhi",
"102": "Raipur",
"104": "Goa"
};이 객체를 첫 번째 인수로, 검색어(query)를 두 번째 인수로 받는 JavaScript 함수를 작성해야 합니다. 이 함수는 SQL의 LIKE 연산자처럼 동작하여, 전달받은 검색어를 값에 포함하는 모든 키/값 쌍을 반환해야 합니다.
접근 방법
가장 직관적인 해결 방법은 객체의 모든 키를 하나씩 순회하면서 각 값이 검색어를 포함하는지 확인하는 것입니다. 조건에 맞는 항목이 발견되면 결과 객체에 해당 키/값 쌍을 추가하고, 순회가 끝나면 결과 객체를 반환합니다.
검색 시 toLowerCase() 메서드를 활용해 양쪽 모두 소문자로 변환하면 대소문자를 구분하지 않는(case-insensitive) 검색이 가능해져, 실제 검색 기능에서 훨씬 실용적으로 동작합니다.
예제 코드
const obj = {
"100": "Jaipur",
"101": "Delhi",
"102": "Raipur",
"104": "Goa"
};
const findByQuery = (obj, query) => {
const keys = Object.keys(obj);
const res = {};
keys.forEach(key => {
// 대소문자를 구분하지 않는 검색
if(obj[key].toLowerCase().includes(query.toLowerCase())){
res[key] = obj[key];
}
});
return res;
};
console.log(findByQuery(obj, 'Pur'));출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
{ '100': 'Jaipur', '102': 'Raipur' }검색어 'Pur'는 소문자로 변환되어 'pur'이 되며, 'Jaipur'과 'Raipur'이 이 문자열을 포함하므로 해당 두 항목만 결과 객체에 담기게 됩니다. 반면 'Delhi'와 'Goa'는 조건에 맞지 않아 제외됩니다.
대안: Object.entries()를 활용한 간결한 구현
Object.entries()와 Object.fromEntries()를 함께 사용하면 같은 로직을 훨씬 간결하게 표현할 수 있습니다.
const findByQuery = (obj, query) =>
Object.fromEntries(
Object.entries(obj).filter(([key, value]) =>
value.toLowerCase().includes(query.toLowerCase())
)
);이 방식은 필터링 조건이 한눈에 들어오고, 원본 객체를 수정하지 않으면서 새로운 객체를 반환한다는 장점이 있어 함수형 프로그래밍 스타일에도 잘 어울립니다. 두 방법 모두 성능 차이는 미미하므로, 상황에 맞는 스타일을 선택하면 됩니다.