스팀 앱 개발기 #164 - 개발 완료: 저자/큐레이션 보상 내역 API 연동 (SDS API)
개발 완료: 저자/큐레이션 보상 내역 API 연동 (SDS API)
No. 164
2026. 09. 03 (목) | Written by @dorian-mobileapp
지갑 화면에 송수신 내역을 보여주는 탭 화면들을 추가했었죠. 이번에 개발할 기능은 '보상 내역 보여주기'입니다. 우선 저자/큐레이션 보상 내역을 보여주기로 했습니다. (보상 요청 내역은 추후 고려 예정) 이것 또한 SDS API를 사용하기로 했습니다. 스팀 API로도 가능은 하지만, 개수 제한(최대 20개)과 필터링을 해야 하는 문제가 있어 구현이 매우 까다롭기 때문입니다.
구현 내용 (638daec + 49a320d 최종본 기준)
WalletScreen의 '보상 목록' 기능을 위한 API 연동, Repository, Use Case 계층입니다.
Domain
| 파일 | 내용 |
|---|---|
Reward.kt | time, type, amount, author, permlink |
RewardType.kt | AUTHOR, CURATION |
SteemWorldRepository.kt | readAuthorRewards / readCurationRewards(account, fromTime, toTime) — 오프셋·리밋 없이 기간만 받음 |
ReadAuthorRewardsUseCase.kt, ReadCurationRewardsUseCase.kt | 기간 기본값(1L ~ 9999999999L, 전체 이력)만 제공하는 얇은 위임 |
Data
| 파일 | 내용 |
|---|---|
SteemWorldService.kt | getRewards(op, account, fromTime, toTime, offset, limit) 엔드포인트 하나 + op/시간 상수 |
GetRewardsResponseDTO.kt | 공통 RewardDTO + op별 매핑 함수(toAuthorRewardList/toCurationRewardList). VESTS→SP 환산, 지급 단위만 골라 "0.323 SBD, 78.416 SP" 형태로 표시 |
SteemWorldRepositoryImpl.kt | private readRewards 헬퍼: DGP·첫 페이지 병렬 요청 → 페이지가 꽉 찰 때까지 반복(offset += 10000) → code 검사 → 전체를 모아 역순 반환 |
핵심 설계 결정
- 오름차순 고정 API 대응:
rewards_api는 정렬 파라미터가 없고 시간 오름차순 고정이며,limit이 기간의 오래된 쪽을 잘라냅니다. 그래서 최신순 목록을 만들려면 기간 전체를 다 읽은 뒤 뒤집는 방식을 택했습니다. - 기간이 유일한 작업량 제어 수단: Repository/UseCase는
offset/limit파라미터 없이fromTime/toTime만 받습니다. 페이지네이션은 Repository 내부(HTTP 요청 단위)에만 존재하고, 화면에는 완성된 리스트 하나만 노출됩니다. - 기간 안의 데이터는 전부 반환: 다중 페이지가 필요하면(예: dorian-lee curation 이력 64,572건, 7회 요청) 끝까지 읽어 전부 돌려줍니다. 데이터를 조용히 버리지 않는 대신, 큰 기간을 조회하지 않도록 하는 책임은 UI(기간 선택)에 있습니다.
- 테스트로 확인한 API 특성:
offset은get_account_history의from과 달리 SQLOFFSET처럼 동작해 페이지 경계에서 중복이 생기지 않습니다(getRewards_curation_case4로 검증). 단, SDS 원본 데이터 자체에 드물게 중복 행이 존재함을 확인했습니다(단일 요청에서도 재현, 페이징 버그 아님).
삭제된 내용 (638daec에서 추가 → 49a320d에서 제거)
638daec는 처음에 "기간이 너무 크면 최신 10,000건만 남기고 오래된 쪽을 자동으로 잘라내는" 안전장치를 포함했으나, 다음 이유로 제거되었습니다.
| 삭제된 항목 | 위치 | 문제 |
|---|---|---|
절단 로직 (if (rewards.size > MAX_REWARD_COUNT) rewards.subList(0, ...).clear()) | SteemWorldRepositoryImpl.readRewards | 잘려나간 오래된 보상은 앱 어디에도 보관되지 않아 완전히 유실됨 |
MAX_REWARD_COUNT = 10000 상수 | Repository 및 두 UseCase | 결과 크기가 정확히 이 값이어도 "잘렸다"는 신호가 API 계약에 없어, 호출자가 잘린 결과와 정상 결과를 구분하려면 매번 이 상수와 크기를 비교해야 했음 |
관련 테스트 단언 (data.size <= MAX_REWARD_COUNT, 절단 후 최초 보상 유실 검증) | ReadRewardsUseCaseTest | 절단 자체가 없어졌으므로 반대 성질(전 구간 무손실)을 검증하도록 재작성 |
절단을 없앤 대신, 기간을 좁게 유지해 조회량을 제한하는 책임을 UI(시작일/종료일 선택) 로 넘기기로 사용자와 협의했습니다. 이 과정에서 애초에 넣으려던 "두 페이지가 겹치지 않는지" 검증(무중복 단언)이 SDS 원본 데이터의 실제 중복 행 때문에 실패해, 검증 방식을 데이터 유일성이 아닌 오프셋 이어붙이기 동치성으로 바꾸고 getRewards_curation_case4 테스트를 새로 추가했습니다.
GitHub Commit
보다 자세한 코드는 아래 commit을 참고하세요.
- Feat: Add author/curation reward history API using SteemWorld rewards_api
- Refactor: Drop the reward count cap and read the whole time range
지난 스팀 앱 개발기
- #163 - 개발 완료: 지갑 화면에 탭 도입 (잔액, 보낸 목록, 받은 목록)
- #162 - 개발 완료: 패키지 관련 오류 수정
- #161 - 개발 완료: 피임대 중인 스팀 파워 목록 화면 구현
- #160 - 개발 완료: 스팀 파워 임대 목록 화면 구현
- #159 - 개발 완료: 포스트의 댓글 정렬 오류 수정
- #158 - 개발 완료: 추가 개선 6, 7, 8, 9
- #157 - 개발 완료: 추가 개선 4, 5
- #156 - 개발 완료: 추가 개선 1, 2, 3
- #155 - 개발 계획: 추가 개선 적용
- #154 - 개발 완료: 테스트 코드 개선
- #153 - 개발 완료: Architecture 개선 작업
- #152 - 개발 완료: 레거시 의존성 제거 작업 요약
- #151 - 개발 완료: Compose 마이그레이션 연장선
- #1 ~ #150
Layout provided by Steemit Enhancer hommage by ayogom
안녕하세요.
SteemitKorea팀에서 제공하는 'steemit-enhancer'를 사용해 주셔서 감사합니다. 개선 사항이 있으면 언제나 저에게 연락을 주시면 되고, 관심이 있으신 분들은 https://cafe.naver.com/steemitkorea/425 에서 받아보실 수 있습니다. 사용시 @응원해 가 포함이 되며, 악용시에는 모든 서비스에서 제외될 수 있음을 알려드립니다.
안녕하세요.
이 글은 SteemitKorea팀(@ayogom)님께서 저자이신 @dorian-mobileapp님을 응원하는 글입니다.
소정의 보팅을 해드렸습니다 ^^ 항상 좋은글 부탁드립니다
SteemitKorea팀에서는 보다 즐거운 steemit 생활을 위해 노력하고 있습니다.
이 글은 다음날 다시 한번 포스팅을 통해 소개 될 예정입니다. 감사합니다!
Upvoted! Thank you for supporting witness @jswit.