개요
안녕하세요! 빈코입니다. 오늘은 제가 실무에서 개발을 진행하다 대용량 데이터를 다뤄야 하는 상황을 맞닥뜨리게 되었습니다. 사실 개발을 하다 보면 대용량인 데이터를 다뤄야 하는 상황이 왕왕 생깁니다. 기능상 문제가 없을지라도, 사용적인 측면에서 잘못된 코드로 속도가 느린다면 문제가 되겠죠? 그래서 오늘은 자주 접하는 반복문과 배열을 사용했을 때의 시간 차이점을 알아보려고 합니다😊
For 문(반복문)📙
For문은 일반적으로 반복을 제어하는데 사용합니다. 가장 보편적이면서 편한 방법이죠! 편한 이유는 복잡한 조건도 설정하기 쉽기 때문입니다. 대용량 데이터가 아닐 경우에는 사실 반복문을 쓰던, 배열을 쓰던 성능 차이가 미미하기 때문에 대부분 반복문을 선택합니다. 추후 클라이언트의 요구사항이 달라져서 복잡한 비즈니스 코드가 들어가야 할 수도 있기 때문이에요.
복잡한 비즈니스 로직은 어떤 것이 있을까요? 예를 들어, 반복문을 돌 때 그 안에서 10가지의 조건이 일치하는지 확인해야 한다고 가정했을 때 수많은 조건문이 들어갈 것입니다. 이뿐만일까요? 조건이 모두 일치할 경우에는 특정값을 변경해줘야 하는 로직도 들어가야 할 수도 있습니다. 이런 무수한 가능성이 있기 때문에 대용량으로 데이터를 다루지 않아도 되는 경우에는 for문을 자주 사용합니다.
For문의 시간복잡도는 O(n)입니다. 즉, 배열의 모든 요소 하나하나를 다 확인하다는 뜻입니다. 예시를 한번 살펴볼까요?
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
// 일치하는 요소를 찾음
}
}
}
만약 array1의 배열의 요소가 3만개라면? 또, array2의 배열의 요소가 2만 개라면? 어떻게 될까요?
실제로 제가 3만개의 데이터 중에 2만 개와 비교해야 하는 실무 코드가 있어서 위의 예시처럼 이중 반복문으로 구현을 했을 때의 걸린 시간입니다. 무려 12초나 걸렸습니다.. 어느 누가 기능 하나 실행하는데 12초를 기다려줄까요?
당연히 안되기 때문에, 다른 방법을 선택해야 합니다. 이런 대용량 데이터를 다룰 때는 배열을 사용하는 방법도 있고, HashSet을 사용하는 방법도 있는데 오늘은 배열을 사용하는 방법에 대해 알아보려고 합니다.
💡 For문 요약
반복을 제어하는 구문으로, 복잡한 비즈니스 로직을 다룰 때 용이하지만 대용량 데이터를 다룰 때는 적합하지 않은 방법이다.
Array.contains(배열)📘
배열은 인덱스를 통해 직접적으로 요소에 접근하기 때문에 빠른 접근 속도를 가지고 있습니다. 또한, 배열의 크기가 커지면 메모리 상에서의 연속성이 중요해지는데, 이로 인해 캐시 효율성이 좋아져 성능이 향상되기도 합니다.
배열은 요소에 직접 접근하는데 걸리는 시간은 O(1)입니다. 하지만 원하는 요소를 찾지 못할 경우 배열 전체를 순회하기 때문에, 이때는 시간복잡도가 O(n)이 됩니다.
if (Arrays.asList(array).contains(targetElement)) {
// 배열에 요소가 포함되어 있음
}
이중 반복문을 도는것과 Arrays.asList().contains()를 쓰는 것은 맥락은 비슷하지만, 한 가지 크게 차이나는 점은 요소를 찾고 난 후입니다.
이중 반복문은 해당 코드 예시처럼 요소를 찾아도 일단 끝까지 반복문을 돌게 됩니다. 그래서 무조건적으로 3만X2만 번의 작업을 수행하게 되죠. 하지만 배열의 contains 함수는 요소를 찾으면 해당 반복문을 끝내게 됩니다. 그래서 위에 말한 것처럼 배열의 시간복잡도는 O(1)이 될 수도 있고, 최악의 경우 O(n)이 될 수도 있다는 뜻입니다. 못 찾으면 반복문처럼 끝까지 돌아야 하니깐요!
For문과 비교해 봤을 때 확연한 차이가 나지 않나요? Arrays.contains() 함수를 사용하니깐 0.059초로 속도가 개선되었습니다😁
저의 경우 배열이 순차적으로 저장되어 있기 때문에, 시간 차이가 많이 나는 것을 확인할 수 있습니다. 하지만, 여러 번 검색을 수행해야 하는 상황이거나 빈번한 검색이 발생하는 경우에는 최악의 상황 O(n)의 시간이 걸릴 수 있기 때문에, 그럴 때는 HashSet, HashMap이나 TreeSet 같은 자료구조를 사용하는 것이 좋습니다.
HashSet이나 TreeSet 같은 자료구조는 상수 시간 안에 원소의 존재 여부를 확인할 수 있기 때문에 성능상 이점을 가질 수 있고, HashMap은 해싱을 사용하기 때문에 대용량 데이터를 조회하는데 좋은 성능을 발휘합니다.
종합적으로, 성능 측면에서는 배열 사용이 이중 반복문보다 빠르지만 이것도 주어진 상황과 데이터의 따라 다르기 때문에 실제 사용 시에는 충분한 테스트를 거쳐 상황에 맞는 자료구조를 선택하는 것이 현명합니다😃
마치며
지금까지 반복문과 배열에 대해 간단히 알아보았습니다. 하지만, 늘 상황에 더 적합한 자료구조는 있습니다. 우리가 모를 뿐... 다음시간에는 다른 자료구조인 HashMap에 대해 포스팅할 예정입니다🙇♂️
👨👩👦👦 오픈채팅방 운영
취업을 준비하는 예비 개발자분들을 위한 질문&답변할 수 있는 공간을 만들었습니다. 취업과 이직을 하기 위해서 어떤 걸 중점적으로 준비해야 하는지부터 포트폴리오&이력서 작성법 등 다양한 질문들을 받고 답변을 드립니다. 참여하셔서 다양한 정보 얻고 가시면 좋을 것 같네요😁
참여코드 : 456456
https://open.kakao.com/o/gVHZP8dg
👨💻 전자책 출간
아울러 제가 🌟비전공자에서 2년 만에 보안 전문 중견기업으로 이직 한 방법들을 정리한 전자책을 출간하게 되었습니다. 어떤 걸 공부해야 하는지, 이직을 위해서 무엇을 준비해야 하는지, 제가 받았던 기술 면접 리스트 등 다양한 목차로 구성되어 있습니다. 또한, 구매 시 1:1 채팅을 이용하여 포트폴리오 첨삭을 도와드리고 있습니다. 🐕전자책으로 얻은 모든 수익은 유기견 센터 '팅*벨 입양센터'에 후원될 예정입니다. 관심 있으신 분들은 아래 링크를 참고해 주세요😁
'TIL' 카테고리의 다른 글
Java 대용량 데이터 HashSet 기본개념 및 사용법(예시) (2) | 2024.02.08 |
---|---|
Java 대용량 데이터 HashMap 기본개념 및 시간복잡도(예시) (0) | 2024.02.02 |
Java 엑셀 만드는 방법 완벽정리(JS에서 Controller까지) (0) | 2024.01.15 |
Java Spring Message 사용하는 방법 완벽정리 (1) | 2024.01.10 |
jstree 핸들링 방법(이전 선택 값 남아있는 오류) (1) | 2024.01.09 |