BLE 장치 앱에 제조사 클라우드의 이력 조회를 붙이는데 스펙 문서가 있어서 그대로 짜면 될 것 같았다. 착수 전에 실제로 몇 번 호출해 응답을 받아 봤다.
Table of contents
Open Table of contents
배경 — 문서와 실제 응답의 타입 차이
문서에는 count 가 정수이고 active 가 불리언으로 적혀 있었다. 실제 응답에서는 둘 다 "12" 와 "true" 같은 문자열로 왔다.
정수로 파싱하는 코드를 짰으면 FormatException 이 났을 것이다. Dart 공식 문서대로 int.tryParse 는 parse 가 예외를 던질 자리에서 null 을 돌려주므로 문자열도 받아 null 이면 따로 다루게 파서를 만들었다.
해 본 것 — 없는 값을 한 번 불러 본다
존재하지 않는 장치 id 로 조회해 보니 문서에 적힌 결과 객체가 아니라 최상위가 [] 로 왔다. 구조 자체가 달라서 정상 응답 기준으로 접근하면 오류가 난다.
정상 응답만 보고 짜면 이 형태를 만날 수 없다. 빈 결과의 형태는 빈 결과를 실제로 받아 봐야 알 수 있고 그것을 안 해 본 어댑터는 운영에서 처음 만난다.
막힌 지점 — 세션 인증과 갱신
인증이 요즘 흔한 토큰 방식이 아니라 로그인해서 sessionId 를 받는 방식이었다. 로그인할 때 deviceId 와 앱 버전이 문서에는 선택이었는데 없으면 거부됐다.
세션은 만료되므로 캐싱과 갱신을 넣어야 했다. 유효하면 그대로 쓰고 없거나 만료면 로그인한다. 요청 중에 세션 오류가 나면 다시 로그인해 한 번 재시도하게 Dio 의 인터셉터에 넣었다.
조치 — 증분 조회가 없을 때
새 이력만 가져오려고 기간 범위 파라미터를 찾았는데 없었다. 있는 것은 days 로 최근 며칠을 받는 형태뿐이었다.
며칠치를 받아서 lastSyncedAt 이후만 우리 쪽에서 거르는 쪽을 골랐다. 이유는 상대가 안 해 주는 것은 우리가 하는 것이 어댑터의 몫이라서다. 대신 매번 며칠치 중복이 내려오는 트래픽을 감수했다.
주의 — 시험 환경이 없는 조건
별도 시험 환경이 없어서 실제 환경에서만 확인할 수 있었고 호출 한도까지 있었다. 그래서 응답을 fixtures/ 아래 JSON 으로 저장해 두고 파싱은 그것으로 반복 시험했다.
실호출은 형태를 확인할 때만 쓰고 한도를 세면서 진행했다. 발견한 특성은 어댑터 파일 상단에 목록으로 남겼는데 이 조사를 앞에서 한 시간이 뒤에서 파서 전체를 다시 쓰는 하루를 아꼈다.
정리
- 어댑터를 짜기 전에 실제 응답을 여러 번 받아 본다
- 문서의 타입이 실제와 다를 수 있다
- 없는 값으로 한 번 불러야 빈 결과의 형태를 안다
- 정상 응답만 보고 짠 어댑터는 운영에서 처음 그것을 만난다
- 문서가 선택이라고 한 항목이 실제로는 필수일 수 있다
- 상대가 증분 조회를 안 주면 우리가 거른다
- 시험 환경이 없으면 응답을 저장해 파싱만 반복 시험한다
- 발견한 특성을 어댑터 상단에 목록으로 남긴다