Upgrade to Pro — share decks privately, control downloads, hide ads and more …

드로이드나이츠 2024 - API Mocking으로 생산성 올리기

Avatar for GROOT GROOT
June 15, 2024

드로이드나이츠 2024 - API Mocking으로 생산성 올리기

드로이드나이츠 2024에서 발표한 "혹시 API Mocking 해주실 수 있으신가요? API Mocking으로 생산성 올리기" 의 발표 자료입니다.

Avatar for GROOT

GROOT

June 15, 2024
Tweet

Other Decks in Programming

Transcript

  1. Introduction ❏ 안.드.로.이.드.개.발.자. ❏ 카카오뱅크에서 안드로이드 장기근속 중 ❏ 개발

    뱡향성 ❏ 새로운 기술 도입해보는 것 좋아함 ❏ 개발할 때 필요한 간단한 Tool 개발 좋아함 ❏ 이것저것 다 해보자
  2. 주제선정 이유 { "금액" : "3000000000000", "이름" : “테스트 대출입니다

    123456789012345678901234” } 3조원 테스트 대출입니다 1234567890123456789.. EDIT
  3. API Mocking이 왜 필요할까? 기획 및 요구사항 분석 백엔드 개발

    프 UI개발 론 트 엔드 개발 배포 배포 배포
  4. API Mocking이 왜 필요할까? 기획 및 요구사항 분석 백엔드 개발

    프론트엔드 개발 UI개발 배포 배포 배포
  5. API Mocking이 왜 필요할까? 기획 및 요구사항 분석 백엔드 개발

    프론트엔드 개발 UI개발 배포 배포 배포
  6. API Mocking이 왜 필요할까? 기획 및 요구사항 분석 백엔드 개발

    프론트엔드 개발 UI개발 배포 배포 배포
  7. Mocking을 위한 다양한 방법들 1 . Mocking의 정석 2 .

    임시로 하드코딩 3. 백엔드 개발자에게 부탁하기 4. 도구 이용하기
  8. ❏ Android UI Test 코드 작성 ❏ MockWebServer를 이용한 목킹

    가능 ❏ 장점 ❏ 완벽 그 자체 ❏ 단점 ❏ 테스트 코드 작성 시간 증가 ❏ 테스트 수행 시간 증가 1 . Mocking의 정석 : 테스트 코드
  9. 1 . Mocking의 정석 : 테스트 코드 APP Mock Api

    Server Server Request A 다양한 서버로직 Response A'
  10. 2. 임시로 하드코딩 _imageDocuments.value = kakaoRepository.getImages(query) .documents.orEmpty() //TODO groot.iam API가

    아직 안나와 테스트 데이터 _imageDocuments.value = listOf( KakaoImageDocument( "Test", " 2 0 2 4 0 6 1 1 ", "드로이드나이츠", "https://test.url", 5 1 2 , 5 1 2 ) )
  11. 3. 백엔드 개발자에게 부탁하기 서버 개발자님 ** API 응답에 **기관

    오류로 내려주실 수 있으신가요?👱 서버 네! 변경완료했어요.
  12. 3. 백엔드 개발자에게 부탁하기 서버 서버 개발자님 ** API 응답에

    **기관 오류로 내려주실 수 있으신가요?👱 요고 B 팀에서 담당하고 있는 부분이라..👱 🧒
  13. 3. 백엔드 개발자에게 부탁하기 서버 서버 개발자님 ** API 응답에

    **기관 오류로 내려주실 수 있으신가요?👱 요고 B 팀에서 담당하고 있는 부분이라..👱 🧒 서버 저희 팀에서 보내고 있는 값이긴 한데 C 팀에서 만들어줍니다..👱 🧒 🧓
  14. 3. 백엔드 개발자에게 부탁하기 서버 서버 개발자님 ** API 응답에

    **기관 오류로 내려주실 수 있으신가요?👱 서버 저희 팀에서 보내고 있는 값이긴 한데 C 팀에서 만들어줍니다..👱 🧒 🧓 서버 값 임시로 오류로 내려가도록 처리해놨어요! 👱 🧒 🧓 👩 요고 B 팀에서 담당하고 있는 부분이라..👱 🧒
  15. 3. 백엔드 개발자에게 부탁하기 서버 서버 개발자님 ** API 응답에

    **기관 오류로 내려주실 수 있으신가요?👱 요고 B 팀에서 담당하고 있는 부분이라..👱 🧒 서버 저희 팀에서 보내고 있는 값이긴 한데 C 팀에서 만들어줍니다..👱 🧒 🧓 서버 값 임시로 오류로 내려가도록 처리해놨어요! 👱 🧒 🧓 👩 서버 갑자기 ** API에서 장애 문구가 노출되는데 확인부탁드려요. 😇
  16. 4. 도구 활용하기 : Charles APP Server Request A 다양한

    서버로직 Response A Request A' Response A'
  17. ❏ Proxy 서버의 역할 수행 ❏ 장점 ❏ API Mocking

    뿐 만 아니라 네트워크 속도 조절 ❏ 다양한 기능 제공 ❏ 단점 ❏ 초기 설정이 어려움 (프록시/인증서 등등) ❏ 항상 서버 역할을 할 PC가 필요함 ❏ 스니핑, 스푸핑 방지 기능을 제거해야함 ❏ 유료.. 4. 도구 활용하기 : Charles
  18. 직접 만들어보자 1 . 비개발자도 사용하는 API Mocking 2 .

    일관된 데이터로 신뢰성 확보하기 3 . API 목록 저장하기 4 . API 응답 마음대로 바꾸기 5 . API 서버 응답 지연 만들기
  19. 1. 비개발자도 사용하는 API Mocking ❏ 별도의 프로그램 없이 간편하게

    앱에서 Mocking이 가능할 것 ❏ 개발자 뿐만 아니라 QA/기획자 등 비개발 직군도 함께 사용 가능
  20. object MockingActivityLifecycle:Application.ActivityLifecycleCallbacks { override fun onActivityResumed(activity: Activity) { val rootView

    = activity. fi ndViewById<View>(android.R.id.content) rootView.addView(createMockingView(), - 1 , createParams()) } } 1. 비개발자도 사용하는 API Mocking
  21. 2. 일관된 데이터로 신뢰성 확보하기 ❏ 프로덕션 코드에 영향이 가지않고

    일관성 있게 데이터를 조작할 수 있을 것 ❏ Mocking 데이터를 받았을 때와 실제 서버에서 해당 데이터를 받았을 때 일 관된 동작을 보장해야 한다.
  22. { "금액" : "3000000", “이름" : “대출1" } { 다

    } 2. 일관된 데이터로 신뢰성 확보하기
  23. { "금액" : "3000000", “이름" : “대출1" } { "금액"

    : "3000000000000", "이름" : "테스트 입니 다.1234567890123456789" } 2. 일관된 데이터로 신뢰성 확보하기
  24. override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request()

    room.saveRequest(request) // 요청을 데이터베이스에 저장 val response = chain.proceed(request) room.saveResponse(response) // 응답을 데이터베이스에 저장 return response } 3 . API 목록 저장하기
  25. override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request()

    room.saveRequest(request) // 요청을 데이터베이스에 저장 val response = chain.proceed(request) room.saveResponse(response) // 응답을 데이터베이스에 저장 return response } 3 . API 목록 저장하기
  26. override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request()

    room.saveRequest(request) // 요청을 데이터베이스에 저장 val response = chain.proceed(request) room.saveResponse(response) // 응답을 데이터베이스에 저장 return response } 3 . API 목록 저장하기
  27. 4 . API 응답 마음대로 바꾸기 { "금액" : "3000000",

    "이름" : "지급보증담보대출" }
  28. { "금액" : "3000000000000", "이름" : “테스트 대출입니다 123456789012345678901234” }

    3만억원 테스트 대출입니다 12345678901234567890123451234567 4 . API 응답 마음대로 바꾸기
  29. { "금액" : "3000000000000", "이름" : “테스트 대출입니다 123456789012345678901234” }

    3조원 테스트 대출입니다 1234567890123456789.. 4 . API 응답 마음대로 바꾸기
  30. internal val changedResponseData = mutableMapOf<String, InterceptorBody>() onMockClicked { changedResponseData.put(url, changedResponse)

    } { "금액" : "3000000000000", "이름" : “테스트 대출입니다 123456789012345678901234” } 4 . API 응답 마음대로 바꾸기
  31. override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request()

    val key = request.toMockingKey() val response = chain.proceed(request) val changeResponse = changedResponseData[key]?.body return if (!changeResponse.isNullOrEmpty()) { … } else { response } } 4 . API 응답 마음대로 바꾸기
  32. override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request()

    val key = request.toMockingKey() val response = chain.proceed(request) val changeResponse = changedResponseData[key]?.body return if (!changeResponse.isNullOrEmpty()) { … } else { response } } 4 . API 응답 마음대로 바꾸기
  33. override fun intercept(chain: Interceptor.Chain): Response { … val response =

    chain.proceed(request) val changeResponse = changedResponseData[key]?.body return if (!changeResponse.isNullOrEmpty()) { response.newBuilder() .body(changeResponse.toResponseBody(response.body?.contentType())) .build() } else { response } } 4 . API 응답 마음대로 바꾸기
  34. override fun intercept(chain: Interceptor.Chain): Response { ... val delayTime =

    responseDelayData[key] ?: return response val totalConnectionTime = response.receivedResponseAtMillis - response.sentRequestAtMillis if (delayTime > totalConnectionTime) { runBlocking { delay(delayTime - totalConnectionTime) } } return response } 5 . API 서버 응답 지연 만들기
  35. override fun intercept(chain: Interceptor.Chain): Response { ... val delayTime =

    responseDelayData[key] ?: return response val totalConnectionTime = response.receivedResponseAtMillis - response.sentRequestAtMillis if (delayTime > totalConnectionTime) { runBlocking { delay(delayTime - totalConnectionTime) } } return response } 5 . API 서버 응답 지연 만들기
  36. 유의사항 A Interceptor val response = chain.proceed(request) // => 다음

    Interceptor 호출 B Interceptor override fun intercept(chain: Interceptor.Chain) { … }
  37. 유의사항 B Interceptor return if (!changeResponse.isNullOrEmpty()) { … } else

    { response } A Interceptor val response = chain.proceed(request) // 종료 val changeResponse = changedResponseData[key]?.body
  38. 유의사항 Call API Interceptor A Interceptor B Interceptor C Received

    API Interceptor A Interceptor B Interceptor C Server
  39. Reference ❏ https://square.github.io/okhttp/ ❏ Charles 로 iOS, Android 디바이스 테스트

    하기 - 환경설정 ❏ Designer icons created by Dreamcreateicons - Flaticon ❏ Bank icons created by Freepik - Flaticon ❏ Ssl icons created by Freepik - Flat-icon ❏ Code icons created by juicy_fish - Flaticon ❏ Smatr icons created by pocike - Flaticon