Back-End

기능은 됐는데 성능이 안 나오는 코드의 특징 5가지

김검정 2025. 5. 9. 16:00

코드는 돌아가기만 하면 되는 거 아니야?? 라는 생각을 처음엔 했었다. 하지만 서비스가 커지고 사용자 수가 늘어나거나, 잘못된 로직으로 인해 장애, 운영 비용 증가, 사용자 이탈로 이어지게 된다.

 

그래서 개발자는 기능과 성능을 동시에 잡는 코드를 짤 줄 알아야 한다.

 

그럼 성능이 안나오는 코드는 어떤 특징을 가지고 있는지 알아보자

 

 

1. 데이터 구조를 무시한 코드

일을 하다보면 무의식적으로 무조건 List에 담고 for문을 돌리는 경우가 있다. 그러다 해시맵을 써야 할 곳에 배열을 쓰게 되는 경우가 발생한다.

 

이렇게 되면 검색, 삽입, 삭제할 때 시간 복잡도가 폭발하게 된다.

// 10,000건 데이터 중에서 특정 ID 찾기
for (User user : userList) {
    if (user.getId() == targetId) {
        return user;
    }
}

 

처음부터 Map<Integer, User> 로 관리했다면 O(1) 시간에 찾을 수 있다.

 

 

2. 쓸데없이 많은 IO (DB/네트워크 호출)

for문 안에서 매번 DB나 API 호출하는 경우나 같은 데이터를 반복해서 조회하는 경우 네트워크 지연, DB부하 폭발 → 시스템 전체가 느려짐으로 연결될 수 있다.

 

for (Order order : orders) {
    Customer customer = customerRepository.findById(order.getCustomerId());
    // ...
}

 

위 코드에서 orders가 1만개라면 DB를 1만 번 호출하게 된다. 

 

이럴경우 한 번에 Customer 데이터를 IN 조건으로 미리 가져오거나 조인(Join)으로 조회해 DB 접근을 최소화 한다.

 

 

 

3. 캐시를 쓰지 않는다.

자주 조회하는 데이터를 매번 새로 계산하는 경우나 매번 외부 API를 호출하는 경우 CPU, 메모리 낭비 + 응답 지연이 발생할 수 있다.

 

예를 들어

public Product getBestSeller() {
    // 매번 DB를 때려서 상위 10개를 조회
    return productRepository.findTop10BySalesOrderByDesc();
}

 

하루에도 수만 번 호출될 수 있다.

 

인기상품 같은 건 5분 간격으로 캐시에 저장하거나 Redis, Caffeine 같은 캐시를 활용한다.

 

 

 

4. 데이터 양에 대한 고려가 없을 때

어차피 데이터가 몇 건 없을거야 가정하고 코딩을했을 때 만약 한 번에 100만건 select 후 메모리에 올리게 되면 어떻게 될까?

데이터가 늘어나면 OOM(OutOfMemoryError) 혹은 서버가 터질수도 있다.

 

List<User> allUsers = userRepository.findAll(); // 수십만 건

 

초반엔 문제 없을 수 있지만, 추후 데이터가 쌓이게 되면 대규모 트래픽 시 서버가 뻗을 수 있다.

페이징 처리(LIMIT, OFFSET) 혹은 스트리밍 처리(cursor 기반 조회) 으로 개선이 필요하다.

 

 

 

5. 비효율적인 반복 로직

이중 for문, 삼중 for문을 남발하는 경우 or 같은 계산을 여러 번 반복하는 경우 시간복잡도가 기하급수적으로 증가할 수 있다.

for (Item itemA : itemList) {
    for (Item itemB : itemList) {
        if (itemA.equals(itemB)) continue;
        // 비교 처리
    }
}

 

O(n^2) 알고리즘이다. 사전에 정렬하거나 해시셋(HashSet)을 활용, 필요없는 반복을 최소화해서 개선을 할 수 있다.

 

 

 

정리하자면 

항목 핵심 요약
데이터 구조 상황에 맞는 자료구조를 써야 한다
IO 최소화 DB, API 호출을 줄여야 한다
캐시 적극 사용 비싼 연산은 저장하고 재사용한다
데이터 양 고려 언제든 데이터가 늘어날 수 있다
반복 최소화 이중/삼중 for문은 반드시 경계한다