SMART LOTTO 개발기 2편 — 1,000회분 데이터를 앱에 넣은 이유

가장 먼저 풀어야 할 문제
통계 기능을 만들기로 결정했을 때 제일 먼저 생각한 건 기술이나 UI가 아니었습니다.
데이터를 어디서 어떻게 가져오느냐.
SMART LOTTO의 통계는 역대 로또 당첨 번호 전체를 기반으로 합니다. 2002년 1회부터 지금까지. 그게 대략 1,000회 분량의 데이터입니다.

동행복권 API를 발견하다
다행히 동행복권에서 회차별 당첨 번호를 반환해주는 API가 있다는 걸 검색으로 확인했습니다. 공식 Open API 형태는 아니었지만, 회차 번호를 파라미터로 넘기면 해당 회차의 당첨 번호를 JSON으로 돌려주는 URL이 있었습니다.
https://www.dhlottery.co.kr/common.do?method=getLottoNumber&drwNo=1
이 형태로 drwNo 값을 바꾸면 어느 회차든 데이터를 가져올 수 있었습니다. 문제는 이걸 어떻게 활용하느냐였습니다.
"매번 1,000번 호출하면 되지 않나?"는 안 된다
가장 단순한 방법은 앱을 열 때마다 1회부터 최신 회차까지 전부 API를 호출하는 겁니다.
하지만 이건 여러 이유로 말이 안 됩니다.
- 앱을 열 때마다 수백 개의 HTTP 요청이 발생합니다
- 네트워크가 불안정하면 중간에 끊길 수 있습니다
- 이미 가져온 데이터를 또 가져오는 건 낭비입니다
- 동행복권 서버에도 부담을 줍니다
처음부터 이 방법은 배제했습니다.
내가 선택한 방법: 초기 데이터는 앱 안에 넣어두기
해결책은 이렇게 세 단계로 설계했습니다.
1단계 — 초기 데이터를 JSON으로 번들링
개발 시점 기준으로 약 1,000회분의 당첨 번호 데이터를 직접 JSON 파일로 만들어서 앱 리소스에 포함시켰습니다. 앱을 처음 설치하면 이 데이터가 기본으로 깔려 있습니다.
2단계 — 마지막 날짜 이후부터 API로 업데이트
앱 실행 시 로컬에 저장된 마지막 회차 날짜와 오늘 날짜를 비교합니다. 차이가 있으면 그 간격만큼만 API를 호출해서 새 데이터를 가져옵니다.
3단계 — 모든 데이터는 RealmSwift에 로컬 저장
가져온 데이터는 전부 RealmSwift를 통해 기기 내 로컬 DB에 저장합니다. 한 번 저장된 회차 데이터는 다시 API를 호출하지 않습니다.
재귀함수로 회차를 순서대로 가져오기
API 호출은 재귀함수 형태로 구현했습니다. 누락된 회차를 순서대로 하나씩 가져오되, 오늘 날짜에 맞는 회차까지 도달하면 멈추는 방식입니다.
func fetchMissingRounds(from round: Int, to latestRound: Int) {
guard round <= latestRound else { return }
API.fetchLotto(round: round) { result in
// RealmSwift에 저장
self.save(result)
// 다음 회차 재귀 호출
self.fetchMissingRounds(from: round + 1, to: latestRound)
}
}
실제 코드는 오류 처리나 중복 체크가 더 들어갔지만, 핵심 구조는 이런 형태였습니다.
설계가 맞았던 이유
이 설계 덕분에 사용자 경험이 훨씬 좋아졌습니다.
- 첫 실행 시 대기 시간이 거의 없습니다 (대부분 데이터가 이미 앱 안에 있으므로)
- 매주 추첨 후 앱을 열면 새 회차 데이터 1개만 가져오면 됩니다
- 오프라인에서도 통계를 볼 수 있습니다
개발을 시작한 지 얼마 안 된 시점에 이 설계를 잡은 게 지금 돌아보면 운이 좋았다고 생각합니다. 데이터 설계가 잘못됐으면 통계 기능 전체가 흔들렸을 테니까요.
다음 편에서는 완성된 앱을 앱스토어에 제출했을 때 예상치 못한 이유로 반려된 이야기를 해보겠습니다.