미니 프로젝트 #1을 통한 DSA 다시 살펴보기: HashMap으로 전화번호부 최적화
Source: Dev.to
Introduction
저는 각 주제마다 미니 프로젝트를 만들면서 자료구조와 알고리즘(DSA)을 다시 공부하고 있습니다. 이 방법을 통해 DSA 개념이 실제 애플리케이션에 어떻게 적용되는지 확인할 수 있고, 보여줄 수 있는 결과물도 얻을 수 있습니다.
이 시리즈의 첫 번째 프로젝트는 전화번호부 앱이며, 여기서 직접 사용해볼 수 있습니다: https://hashphonebook.netlify.app/
Initial Implementation (Array + Linear Search)
앱을 처음 만들었을 때는 연락처를 간단한 JavaScript 배열에 저장하고 선형 탐색을 사용했습니다:
// Sample data
let userArray = [
{ userName: "Jane", number: "1237893457" },
{ userName: "Oscar", number: "4562317895" }
];
// Linear search (O(n))
const result = userArray.find(contact => contact.userName === "Oscar");
몇 개의 항목만 있는 데모에서는 잘 동작하지만, 시간 복잡도가 O(n) 입니다. 만약 전화번호부가 100 000개의 연락처로 늘어난다면 최악의 경우 조회 비용이 현실적인 시나리오에서 크게 부담이 됩니다.
Why Performance Matters
긴급 상황에서 수천 개의 항목을 스캔하는 검색을 기다리는 것은 용납될 수 없습니다. 더 빠른 조회를 제공하는 자료구조가 필요합니다.
Optimized Implementation (HashMap / Object)
해시 맵(또는 일반 JavaScript 객체)은 평균 O(1) 의 조회 시간을 제공합니다. 연락처 이름을 키로 사용하면 전체 항목 수와 관계없이 즉시 번호를 가져올 수 있습니다.
// HashMap representation
let contactMap = {
"Jane": "1237893457",
"Oscar": "4562317895"
};
// Constant‑time lookup (O(1))
const number = contactMap["Jane"];
조회 속도는 연락처가 5개이든 50억 개이든 동일하게 유지됩니다.
Code Changes
Adding a Contact
Before (Array.push):
userArray.push({ userName, contactNumber });
After (Map key‑value):
// Store as a key‑value pair; make the search case‑insensitive
contactMap[userName.toLowerCase()] = {
originalName: userName,
number: contactNumber
};
Searching
Before (Array.find):
const result = userArray.find(contact => contact.userName === searchName);
After (Object lookup):
const entry = contactMap[searchName.toLowerCase()];
Takeaway
“작동하는 코드”가 항상 “좋은 코드”는 아닙니다. 선형 탐색은 작은 데모에 충분하지만 확장성이 없습니다. 해시 맵으로 전환하면 전화번호부가 효율적이고 실제 사용에 적합해집니다.
이것은 제 DSA 복습 여정의 첫 번째 단계일 뿐이며, 각 개념을 강화하기 위해 앞으로도 작은 프로젝트들을 계속 만들어 나갈 예정입니다.