최근 Google API를 사용할 때 하루 호출량 제한에 걸려서 곤란한 적이 있었습니다. 서비스 계정을 여러 개 만들어서 순차적으로 돌리면 되겠다! 싶었는데, 매번 계정을 바꾸는 코드가 너무 지저분해서 다른 방법이 없을까 찾아보다가 itertools.cycle()를 발견했습니다. 반복 가능한 객체를 무한히 순환할 수 있는 함수였는데 오늘은 이 함수와 제가 활용한 코드를 예시로 소개하고자 합니다.
itertools.cycle(iterable)
기본 개념
itertools.cycle(iterable)은 주어진 iterable을 무한히 반복하는 반복자(iterator)를 만들어줍니다. 한번 순회한 값을 메모리에 저장해두고, 마지막까지 순회한 뒤에는 다시 처음부터 반복해요.
사용방법
iterable 객체를 cycle()에 넣고, next()를 호출해서 한 번에 하나씩 값을 꺼내 사용합니다. 무한 반복이기 때문에 반복 횟수는 개발자가 제어해줘야 합니다. 간단하게는 for문으로 제한된 횟수만 반복하게 만들 수 있습니다.
주의할 점
cycle()은 입력받은 iterable의 모든 요소를 내부적으로 저장해두고 재사용하는 방식입니다. 그래서 입력 데이터가 너무 크면 메모리를 과도하게 사용할 수 있다는 점에 주의해야 해야합니다. 예를 들어 수천 개 이상의 요소가 있는 리스트를 cycle에 넘기면, 반복의 이점보다 성능 저하와 메모리 부담이 클 수 있습니다.
예제 코드
import itertools
colors = ['red', 'green', 'blue']
cycler = itertools.cycle(colors)
for _ in range(10):
print(next(cycler))
출력 결과:
red
green
blue
red
green
blue
red...
💡 활용 사례: Google API 호출 허용량 우회
Google API 많은 요청을 하면 허용량 초과 오류가 뜹니다. 해당 오류를 피하기 위해 서비스 계정 .json 파일을 여러 개 만들어두고, cycle()로 순차적으로 바꿔가며 API를 호출하도록 구현했습니다. 이 방식으로 매 호출마다 계정을 순환해 사용하면 허용량을 효과적으로 분산할 수 있었습니다.
import itertools
import json
from google.oauth2 import service_account
from googleapiclient.discovery import build
# 여러 개의 서비스 계정 키 파일 리스트
json_files = ["acc1.json", "acc2.json", "acc3.json"]
credentials_cycle = itertools.cycle(json_files)
# API 호출 함수 예시
def get_service():
json_path = next(credentials_cycle)
creds = service_account.Credentials.from_service_account_file(json_path)
service = build('drive', 'v3', credentials=creds)
return service
# 반복해서 호출
for _ in range(5):
service = get_service()
print("Google Drive API 호출")
현재는 처음의 서비스 계정으로 돌아왔을 때 허용량 초과 오류가 나올 수 있으니 전체 요소를 모두 순환하면 잠시 텀을 두도록 코드를 디밸롭해서 사용하고 있습니다. 간단한 기능이지만 반복 패턴을 구현할 때 유용하게 쓸 수 있는 도구같습니다. 반복적으로 순환하며 사용해야 할 상황에 도움이 되었으면 좋겠습니다. 오늘도 읽어주셔서 감사합니다.