JIGGAG

2월 한달동안 로그

2021년 2월 27일

2/22 ~ 2/28

iOS 앱 출시

  • 올해 작은 소망 중 하나였던 iOS 앱 출시
  • 개발자 계정 만들고 거의 한달만에 드디어 출시를 해본다
  • 1단계 이뤘으니 2단계를 향해 가야지

@bugsnag/react-native

  • 안드로이드 js 에러 트래킹이 되지 않고 있다

  • Native 에러는 잡히고 있는데 js에서 Bugsnag.notify 보내면 에러를 뿜어낸다

  • 언제부터였을까

  • @bugsnag/react-native 업데이트 해보았다 -> 이번엔 다른 에러를 뿜는다

  • 에러를 뿜어내는 곳까지 타고 올라가보니 코드에 밑줄 쫙

  • 파라미터를 하나만 받고 있는데 두개를 보내고 있어서 에러가 나고 있다 -> 안받으면 되지 않나 왜 에러가 나는거지

  • @bugsnag/react-native v7.8.0에서 발생하는 오류는 bugsnag-android v5.6.2에 해결되었다

  • bugsnag-android PR

  • 그러나 @bugsnag/react-native v7.8.0에 포함되어있는 gradle의 com.bugsnag:bugsnag-android:5.6.2-react-native, com.bugsnag:bugsnag-android:5.6.2에서도 동일하지만 다른 오류가 계속 발생하고 있다

  • android 네이티브 라이브러리는 수정된 버전이 존재하지만 RN 버전으로는 아직 적용되지 않은 것 같다

  • 우선 @bugsnag/react-native v7.8.0로 업데이트하였고 com.bugsnag:bugsnag-androidcom.bugsnag:bugsnag-plugin-react-native 버전을 5.7.0로 명시하여 해결

  • 5.7.05.7.0-react-native의 차이가 무엇일까?

  • 단순히 버전 라벨이라고 생각하고 있었는데 5.6.2-react-native는 있지만 5.7.0-react-native는 없다

  • 5.7.0로 명시하니 정상 동작한다. 이 버전은 bugsnag-android 버전인데 이 버전안에 RN을 위한 것이 ~react-native 아닐까

  • 내가 임시로 사용한 버전 명시 업데이트는 RN을 위해 작성되지 않은 버전이라면 무언가 최적화라던지.. 미흡하지 않을까

  • @bugsnag/react-native v7.5.0@bugsnag/react-native v7.8.0에서 발생한 Bugsnag.notify 에러 로그

    // @bugsnag/react-native v7.5.0 -> Bugsnag.notify 에러
    Failed to call dispatch on bugsnag-plugin-react-native, continuing
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/bugsnag/android/HandledState;
    at com.bugsnag.android.EventDeserializer.deserialize(EventDeserializer.kt:23)
    at com.bugsnag.android.BugsnagReactNativePlugin.dispatch(BugsnagReactNativePlugin.kt:138)
    at com.bugsnag.android.BugsnagReactNative.dispatch(BugsnagReactNative.kt:167)
    ...
    
    // @bugsnag/react-native v7.5.0 -> android -> build.gradle
    api "com.bugsnag:bugsnag-android:5.2.1-react-native"
    api "com.bugsnag:bugsnag-plugin-react-native:5.2.1-react-native"
    
    // @bugsnag/react-native v7.8.0 -> Bugsnag.notify 에러
    Failed to call dispatch on bugsnag-plugin-react-native, continuing
    java.lang.NoSuchMethodError: No direct method <init>(Ljava/util/List;Lcom/bugsnag/android/Logger;) in class Lcom/bugsnag/android/Stacktrace;...
    at com.bugsnag.android.ErrorDeserializer.deserialize(ErrorDeserializer.java:30)
    at com.bugsnag.android.EventDeserializer.deserialize(EventDeserializer.kt:49)
    at com.bugsnag.android.BugsnagReactNativePlugin.dispatch(BugsnagReactNativePlugin.kt:140)
    at com.bugsnag.android.BugsnagReactNative.dispatch(BugsnagReactNative.kt:167)
    ...
    
    // @bugsnag/react-native v7.8.0 -> android -> build.gradle
    api "com.bugsnag:bugsnag-android:5.6.2-react-native"
    api "com.bugsnag:bugsnag-plugin-react-native:5.6.2-react-native"
    

codepush

styled-components

  • 앱 화면전환을 세로로 고정시켜두었다
  • 그런데 가로로 화면을 그렸을 경우에만 발생하는 현상이 VOC로 들어왔다
  • 어떻게 무슨 일이지
  • 해당 화면은 styled로 작성되었고 props 추가 없이 상수화 되어있었다
  • 상수화된 컴포넌트에서 바라보고 있는 Dimensions은 과연 바뀔까?
  • 앱을 세로로 고정시켜두긴 했지만 앱이 실행되는 순간에 가로로 되어있었고 Dimension이 그 순간 값을 가져오게 된다면?
    // 1. styled
    const Container = styled.View`
      width: ${Dimensions.get('window').width}px;
    `;
    
    // 2. props로 전달하는 경우
    <View width={Dimensions.get('window').width}>
    ...
    </View>
    

2/15 ~ 2/21

정전

  • 갑자기 집에 있는 라즈베리 서버가 접속이 안됨을 알게 되었다
  • 오류 났나 서버가 왜 죽었지 좀 기다리면 살아나려나 하고 집에 와서 봤더니 정전이였네
  • pm2로 오류로 노드서버가 죽은 경우에는 재실행 되는데 라즈베리 자체가 죽어버리는 것은 대응을 하지 못했다
  • pm2 startup이라는 좋은 방안이 있었다
  • pm2 startup -> pm2 설정 -> pm2 save
  • 현재 설정된 pm2가 그대로 다시 띄워진다
  • pm2 생각날때마다 보고 있는 라인의 pm2를 활용한 무중단 서비스

babel

  • 최신 자바스크립트 코드를 과거의 브라우저에서도 호환되도록 transpile
  • es6를 파싱해서 추상구문트리로 변환하고 추상구문트리를 변환하여 es5으로 출력
  • 어떤 코드(es6)를 타겟(es5)로 파싱하고 변환할지를 알려주는 plugin과 그런 plugin의 조합이 preset
  • babel은 이전 브라우저에서도 이미 존재하는 코드를 변환해주는 것
  • 만약 이전에는 존재하지 않았던 새로운 문법이라면? -> polyfil
  • babel (컴파일 타임), polyfill (런타임)
  • 자바스크립트 컴파일러 Babel

metro

iOS image

  • 계속 말썽이던 iOS 이미지
  • 분명 불러와지기는 했는데 왜 텍스트를 뽑아내지 못할까 -> 테스트폰은 되는데 리뷰어는 안된다고?!
  • 카카오 OCR API를 호출하는데 완전 잊고 있던 이미지 사이즈와 파일 크기
  • 명백하게 오류 코드를 반환하고 있었으나 로그를 봤으나 보지 못한 (보고 싶은 것만 봤다)
  • OS 차이 말고도 디바이스 크기의 차이도 있었으며 사진 자체의 용량도 제각각이였다 -> 이건 테스트폰에서도 용량은 달랐는데 마침 그 사진은 텍스트가 없어서 인식을 못하는구나 하며 넘어갔었다
  • 텍스트 추출 응답코드에 따라 상태값을 다르게 해주었다
  • 맹점

2/8 ~ 2/14

iOS image

  • 스크린샷 이미지를 가져오려고 라이브러리를 커스텀
  • 분명 image객체를 넘겼는데 앱에서 uri를 읽지 못하고 앱 크래시
  • base64를 못읽는건가 로그도 확인하고 크래시 로그도 확인해보았는데... 알 수 없었던 사이
  • persist로 앱에 갖고 있던 데이터가 테스트 데이터와 충돌이 발생하여 나타난 오류였다
  • 해당 persist를 초기화했더니 이미지가 잘 나오네!
  • 다음 문제: 메인스레드, 메모리 문제
  • 안드로이드와 다르게 iOS쪽은 날짜 커스텀 조건을 설정하지 않은 상태였는데 저장된 이미지 전체를 가져오면서 메모리 부족으로 크래시 발생
  • 그리고 메인스레드를 벗어나 발생하는 오류...
  • 테스트폰에서는 재현이 안되는데 리뷰어에게는 잘 나타난다 -> 둘의 차이는 OS 버전뿐인데
  • 우선 라이브러리를 하나하나 뜯어서 커스텀하며 OS버전에 따라 로직 분기하고 메인스레드로 탈 수 있게 dispatch_get_main_queue
  • 데이터가 너무 많은 경우 메모리 부족 현상 -> 30일 데이터를 가져오면서 dispatch_async + 백그라운드에서 처리할 수 없을까

react navigation

  • 탭에서 스택으로 화면 구조가 변경될때 이상함을 감지
  • 스택 애니메이션을 iOS와 안드로이드 둘 다 동일하게 옵션을 주었는데
  • 안드로이드에서는 해당 스타일이 적용되지 않아 화면이 깜박거리는 현상이 나타났다
  • 처음에는 어디선가 렌더링이 한번씩 더 되고 있는건지 의심을 했지만
  • 하나씩 정리해가다보니 결국 탭에서 스택으로 넘어가는 과정에서 나타난 현상이였다
  • 안드로이드 기본 UX를 무시하고 iOS와 동일하게 주려고 하는 이 옵션을 강제해도 되는 것일까?
  • 문서를 보다가 눈에 밟힌 옵션 하나 detachInactiveScreens
  • 애니메이션을 완전히 꺼버리는 것 말고는 다른 스타일들은 전부 깜박이는 문제를 해결해주지 못했다
  • 이 옵션을 false로 설정했더니 말끔하게 해결되었다 -> 왜?
  • 우선 원인을 명확하게 찾지 못했다
  • 이 옵션은 비활성화 되는 화면을 감지하는 것을 비활성화 시켜서 메모리를 사용하지 않는 것일까
  • react navigation: detachInactiveScreens

2/1 ~ 2/7

React Element

  • 타입스크립트를 사용하면서 props로 컴포넌트를 넘기게 되는 경우가 있다
  • 보통 라이브러리에 내장 되어있는 타입으로 명시해두었는데 커스텀 컴포넌트 또는 children의 경우 타입을 ReactNode로 사용하였다
  • 최근 JSX.Element와 ReactNode의 차이점에 대해 질문을 받았는데 ReactNode가 대부분의 타입 에러를 해결해주는 것으로 사용하고 있었기에 명확한 대답을 할 수 없었다.
  • 사용하는 의미를 제대로 알지 못하고 사용하고 있는 자신이 부끄러워지는 순간이였다
  • ReactNode, JSX.Element, ReactElement
  • Props로 children을 전달하는 경우 하위 컴포넌트는 계속 리렌더된다 -> ReactNode 객체를 계속 재생성 하기 때문에
  • 동일 props, state를 전달하면 컴포넌트가 다시 그려지지 않는다 -> 이때 key를 변경하면 단순히 상태가 초기화 되는 것이 아니라 컴포넌트 인스턴스 자체가 다시 생성되어 마치 리렌더가 발생한 것 처럼 보인다
  • 리액트 컴포넌트 제대로 만들기
  • 비제어 컴포넌트 - key 변경

iOS 리젝

  • SNS는 아니지만 다른 사람들과 에피소드를 공유할 수 있는 앱을 사이드 프로젝트로 진행하였다
  • 그리고 소소하게 앱스토어에 올려두고 운영하면서 실제 서비스를 운영하며 겪을 수 있는 여러 상황들을 테스트해보거나 시도해보려고 하였다
  • 그런데 1차 난관이 있었다
  • 앱 심사 리뷰를 통과하지 못했다
  • 다른 사람과 공유되는 내용에 대한 필터링, 신고, 대응을 필요로하는 리젝 사유였다
  • 다른 사람에게 불쾌감을 주는 내용인 경우 관리자가 조치를 취할 수 있다는 약관에 동의하는 기능도 필요로한다는 리젝 사유가 있었지만 이는 금방 해결되었다
  • 내가 보고 싶지 않은 내용을 필터링하는 기능으로 해당 에피소드를 비활성화 처리 할 수 있도록 하였으나 이는 리젝 해결방안이 되지 않았다
  • 사실 리젝 해결방안을 아직 생각중이다...
  • 다양한 상황을 경험해보고자 시도한 앱스토어 등록
  • 리젝 사유도 이런 것이 있음을 그동안 해보지 않은 카테고리의 앱이기에 처음 겪어 볼 수 있게 되었다

다크모드

  • 해보고 싶었으나 그동안 해보지 못한 다크모드
  • 설정이 변경되면 각각 매핑된 스타일로 일괄 변경
  • 지난번 봤었던 디자인 시스템

iOS 서명

  • Provision이 꼬여서 한참 헤맸다
  • 설정하려고 하다가 꼬였는데 결국 자동 설정