Skip to content

Week5 ‐ 멘토링

이재한 edited this page Dec 7, 2023 · 2 revisions

멘토링

AOS

  • Safe from Runtime Exception 이란게 어떻게 Exception들을 처리하면 Safe 하다고 말할 수 있는지 궁금합니다!
    • DataStore와 SharedPreference를 비교하는 걸 보고 있는데, DataStore는 Runtime Exception에 safe 하다고 적혀있더라고요.
    • Runtime Exception을 safe 하게 처리하는 방법이라고 하면 예외 상황을 조건문 같은걸로 잘 처리해서 적절한 에러 메세지를 보여준다던가, 예외 상황에서도 잘 작동하게 하는거라고 생각합니다.
    • 그런데 제가 생각하기에는 아무리 잘 처리해도 예상치 못한 상황이 있을 수 있으니까 모든 예외를 처리했다고 자신있게 말하기는 힘들 것 같은데, 저렇게 Safe 하다 고 말할 수 있는건 어떤 기준인가요? 예를 들어 ‘1년동안 테스트 했는데 예상치 못한 Runtime Exception이 안발생했다!’ 하면 Safe하다고 정의한다던가 하는 기준이 있나요?
    • 또 저는 보통 예외처리를 토스트(or 스낵바) 메세지를 띄워주는 식으로 하고 있는데, 현업에서는 예외처리를 어떻게 하시는지 궁금합니다!
  • 어떤 화면에서든 api 요청을 보냈다가 Refresh Token 만료 응답을 받으면 로그인 화면으로 이동이 돼야합니다.
    • Refresh Token 만료 이벤트를 Authenticator 에서 받기 때문에 Activity/Fragment와 Authenticator 의 소통 역할로 Repository를 만들었습니다.
    • 그리고 해당 Repository에서 이벤트가 발생되는건 모든 화면에서 collect 해야되니까 BaseViewModel을 만들고, BaseViewModel과 BaseActivity에서 repository를 가지고 있고, collect하도록 할 생각합니다.
    • 이런식으로 모든 화면에 공통된 이벤트가 발생할 수 있을 때 보통 어떤 식으로 처리하시는지 궁금합니다.
  • 현재 retrofit2를 이용해서 http 통신을 하고 있습니다. 이때 http 요청을 보내고 response를 받을 때, Response<SpaceResponse>이런식으로 응답 내용 body에 대한 역직렬화가 일어납니다. 그런데 정상응답(200번대)를 받을 때와 400, 500 번대 응답을 받을 때의 body가 아예 달라서 200번대 응답으로 정의해놓은 클래스로는 역직렬화가 되지 않는 이슈가 있었습니다.
    • 정상응답 / 401 응답 예시

      • 정상응답

        {
          "nickname": "new nickname",
          "image": "new image.png"
        }
      • 401 응답

        {
            "message": "Unauthorized",
            "statusCode": 401
        }
    • 처음에는 404 에러 같은 경우 저희가 잘못 보낸거고, 잘못 보내는 경우가 없도록 짜면 받지 않을 거라는 생각에 문제가 되지 않았습니다.

    • 그런데 401 에러 (Access Token 만료) 등이 생기면서 역직렬화 문제로 앱이 터집니다.

    • 그래서 해당 문제를 모든 응답을 다음과 같은 형식으로 공통적으로 보내달라고 백엔드분께 요청드리는걸로 해결했는데, 뭔가 다른 해결법도 있는지 궁금합니다.

      {
        "status": 200,
        "body": {
          "nickname": "사용자닉네임",
          "image": "https://example.com/path/to/image.jpg"
        }
      }
    • 사실 Authenticator를 구현했으니 401 에러는 따로 처리가 돼서 문제가 없을 줄 알았는데 api.postSpace() 이렇게 요청을 보내면 body를 역직렬화 하는 과정이 Authenticator보다 먼저 실행이 되는 것 같더라고요.ㅠㅠ

    • response에서 status code나 body 같은 걸 이미 타입으로 제공해줘야되는데 저런식으로 하게 되면 같은 정보를 두번 적어야되는 것 같다는 점에서 다른 방법이 있는지 찾아보고 싶은데 못찾겠어서 여쭤보고 싶습니다..

      • 어려운 방법이면 저희가 이제 시간이 많이 안남아서 적용은 하기 힘들 것 같지만,, 궁금해서 여쭤봅니다!
  • API에 대한 response를 받아오고 성공, 실패에 대한 처리가 공통적으로 이뤄지고 있는데, 성공을 했다면 바디를 검사하고 이러한 과정이 계속 반복적으로 진행되는거 같아서 하나의 함수로 재사용하고싶은데,
    • 말이 좀 이상한데 API에 대한 response를 받아서 성공,실패 여부와 body를 전송해주는 큰 파일?을 만들어서 각각 repositoryImpl에서 사용하면 좋지 않을까.. 라는 고민에서 출발한 생각입니다.
    • 백엔드와 본격적으로 API 통신을 하려다보니 미숙한 점이나 어려운게 좀 많은거 같아요

image| image


BE

  • 마인드맵 트리에 대한 데이터를 계속해서 메모리 상에서 들고 있는 것이 좋은 동작일까요? 보드에 대한 데이터는 MongoDB를 사용해서 저장할 생각입니다. crdt의 작업만 계속 들고 있다가 주기적으로 혹은 사용자가 방에 들어왔을 때, 트리 객체로 만들고 작업을 적용하고 다시 문자열로 직렬화해서 데이터를 집어넣는 방식으로 처리하는 게 좋을까요? 아니면 계속 메모리에 들고 있으면서 모두 마인드맵 보드에서 나갔을 때, 메모리 상에서 제거하는 방식이 좋을까요?
    • 어떤 데이터가 메모리 상에 올라가 있는 경우가 많이 있나요? 아니면 데이터는 DB에만 있고 서버에서는 DB의 정보를 가공해서 전달해주기만 하는 경우가 많이 있나요?
  • 현재 서버를 나누었다가, 보안적인 요소를 고려하는건 후 순위 일 것 같아서 다시 합친 상태 입니다. 만약 서버를 live server 와 api server로 나눌 경우에 서버 간 통신에서 보안적으로 고려해야 할 것은 어떤 것이 있을까요?

✔️ 멘토링 내용

BE

  • 첫번째 질문
    • [메모리상의 데이터]
      • 마인드맵에 대한 트리를 서버에서 새로운 사용자가 들어오면 전송해야함.
        • 다른 사람은 작업하고 있는 상황,
      • 들고있어야 하는가, 아니면 잠깐잠깐 꺼냈다가 꺼내서 저장을 해야하는지,
      • 장단점이 존재.
        • 메모리 → 속도가 빠르고 전달하기 좋지만 휘발성이 있어서 문제가 생길경우 대처가 힘들다.
          • 문제가 생길 경우 사용자 간의 트리의 불일치가 발생
          • 복구에 대한 기준이 있어야 함.
      • 목적에 따라 다르다.
        • 게임인 경우 메모리에 올려둔다. → DB까지 전달하고 전달받는 과정이 느릴 수 있기 때문
        • DB는 안정성이 높다.
          • 멘토님은 DB를 추천. 속도가 느리더라도 그렇게 느리지 않을것이라고 판단.
        • 속도가 느리다. → 메모리
      • 둘다 해보는것도 괜찮을거 같다.
  • 두번째 질문
    • 프라이빗 통신을 할 경우 보안적으로 신경쓸 것이 없다.
    • 보안적으로 시도해보고싶은것이 있다면 시도해도 좋을것같다.
    • 보안은 후순위, 생각만 일단 해두고 나머지가 정리되면 고려
  • LiveServer → SocketIo , API Server → 연결된 서버
    • 둘다 클라이언트랑 통신을 하는데 퍼블릭으로 열어야 하는거 아닌가.
      • 클라이언트와 통신은 퍼블릭 (API[SQL Injection 조심, TCP/IP 보안프로토콜을 지키자)
      • Oauth를 통해서 accessTocken과 refreshToken을 이용
      • 일정이상 응답이없을경우 키를 폐기,
  • 몽고디비 사용의 이유
    • 보드 데이터는 자주 변경될 우려가 있어서 선택을 했다.
    • 몽고디비는 관계형디비가 아니라 가로로 늘리기 좋다.
    • 보드의 데이터는 가로로 늘어났기 때문에 몽고디비가 적합하다고 판단했다.
    • 예상질문
      • 몽고디비의 트랜잭션은 어떻게 진행될까요?
        • 정답 : 몽고디비는 mysql보다 트랜잭션의 융통성이 높다.
      • 데이터가 소실될 경우 Mysql이 복원하기 편하다. MongoDB는 복원하기 어렵다.

AOS

  • 첫번재 질문
    • 라이브러리나 sdk 때문에 런타임 에러가 발생할 수 있다.
      • 버그 수정이 되는 라이브러리를 사용해야 안전하다.
      • ex)ViewPager → 에러 발생률이 높다.
    • 화면이 많을수록, 기능이 많을수록 완벽하게 비정상종료가 안되는 경우가 없다.
    • 프레임워크단에서 발생하더라도 Log에 쌓이니까 상황을 유추해서 이슈들을 해결해야함.
    • 앱상에서 사용하다가 생기는 트래시가 없을 경우 Safe하다고 할 수 있다.
    • try~catch, 코투린 핸들러로 Exception처리를 잘 한다면 에러를 확인할 수 있다.
    • 하지만 모두 대응불가능하기 때문에 테스트코드가 있고, 회사에서 다른 부서가 있는것.
  • 1-2 두번째 질문
    • 에러 처리 → 토스트, 스낵바
    • 런타임 Exception을 다루는 이유
      • 노티 형식의 팝업 토스트 스낵
        • 문구로 사용자에게 설명!
        • 가벼운 과정이나 버튼의 클릭 처리
        • 가장 일반적인 방법
      • 팝업에 재시도 버튼을 도입해서 재시도를 유도
        • 이미지 최적화를 하는 과정에서 에러가 발생하더라도 다시 시도하면 에러가 발생하지 않을 수 있다.
        • 화면에서 버튼을 눌렀을때 이미지 최적화 과정→ 이미지를 최적화 하는 과정에서 이미지가 크거나 해상도가 높을 경우 에러가 발생할 수 있다.
        • 이런 경우에는 다시 시도를 하면 에러가 발생하지 않을 확률이 있어서 다시 시도를 유도
        • 간헐적인 에러 발생은 화면을 나가거나 하는 기회비용이 너무 크기 때문에 다시 시도를 유도
      • 팝업으로 버튼을 둬서 로그인화면에 이동이거나 앱을 종료시키는 문구를 사용자에게 제공해서 프로세스를 처음으로 돌아가게끔 유도하는 방식
        • 잘 안쓰이는 방식
        • 로그인이 문제라면 사용할 수는 있다.
        • 리프레시 토큰이 만료된다면 API통신을 할 수없는 경우가 있다.
        • 로그인을 다시 해야 프로세스를 진행할 수 있다면 팝업으로 앱을 종료 or 로그인 화면으로 이동한다는 문구를 제공해서 프로세스를 다시 진행하도록 유도.
  • 2-1
    • 화면마다 공통된 이벤트 관리는 이벤트버스로 관리
      • sharedFlow, EventWraper 패턴
        • 개인적으로는 EventWraper를 권장
          • 실력에 맞게 구현할 수 있음. 업그레이드 할 수 있음.
        • SharedFlow는 Flow에 대해서 알아야하고, StateFlow와 차이를 알아야 하는 런닝커브가 높다.
      • 패턴이 여러개 있다는 것은 각각의 장단점이 있을것이고, 간단한 방식으로 하고, 업그레이드 하는 방식으로 .
  • 세번째
    • 정상 응답, 에러 응답을 동일하게 포맷을 맞추는것이 권장이다.
    • 두 개의 응답이 달라진다면 바디를 파싱하는 과정이 생기기 떄문에 또 번거로운 과정이라서 모든 응답에 대한 같은 형식으로 요청을 하는것이 좋은 판단이다.
      • 코드 , 메시지, 바디
    • 레트로핏을 이용한 HTTP 통신은 코드와 메시지값은 서버에서 주는 코드와 메시지와 다를 수 있다.
      • 성공 → 200
        • 서버에서 주는 결과값이 성공인지 아닌지를 판단하는것이 맞다.
      • HTTP 통신에 대해서 정답 응답인지 판단하고 서버의 응답이 정상인지 아닌지 판단하는것이 맞다
  • 네번째
    • 공통처리를 헬퍼나 클래스 최상위 함수로 구현하는것은 선택인데.
    • 여러가지 Response를 들어올 수 있기 때문에 generic으로 할지 추상으로 묶을지 이런것을 선택이 될것이다.
  • 레트로핏을 선택한 이유
    • OkHTTP, Retrofit, HttpClient
    • 코투린으로 suspend를 사용가능한데 HTTPClient는 callback으로 처리해야해서 불편함을 느꼈다.
    • 기술 선택에 대해서 코루틴 → 이유가 불충분하다.
    • 네트워크 모듈로 레트로핏2를 많이 사용하지만 이유가 중요하다.
      • 따라서 장점을 찾아봐야 할 것 같다.
      • OkHTTP를 매핑하는것은 맞고, 어노테이션을 통해서 구현이 쉽다.
      • Header, GET, POST 이런 어노테이션 → 레트로핏의 장점
      • 조금 더 정리해보면 좋을것 같다.
  • 에러가 발생할 케이스들을 대응하는게 좋을것같다.
    • 여러가지 방법으로 앱을 죽일 수 있고 그러한 처리를 해줘야 한다.
    • 각 화면에서 회전을 바꿔가면서 확인
    • 사용자가 앱을 사용할 때 예상하면서 한번씩 해보면서 죽는지 테스트
    • 개발자 옵션에서 활동유지안함→으로 테스트 (여유가 있다면)
  • Flow와 LiveData중에서 Flow를 선택한 이유에 대해서 조사해보자. ⭐️
  • repeatOnLifeCycle → 공부.. ⭐️
  • viewModelLifeCycle , viewModelScope,
    • AndroidX → AndroidX, AndroidSupportingLibary 차이
      • 왜 바꼈는지도 찾아보면 좋을것같다.
      • 코투린 Exception Handler를 사용하면 좋을것같다.
Clone this wiki locally