728x90

jQuery를 쓸일이 거의 없지만

퍼블리싱된 파일을 검토하던중 이슈를 발견했다.

 

 

* 문제상황

easescroll을 적용한 상태에서

transition 효과가 있는 모달을 닫자마자 스크롤링을 하면

모달이 완전히 사라지기 전에 스크롤이 모달위에서 동작하면서

사용자 입장에서는 스크롤이 동작하지 않는것처럼 보인다.

 

하지만, 실제로 모달에 scroll 이벤트를 등록해서 모니터링해보면

모달을 닫자마자 스크롤 할 때, 모달에 스크롤 이벤트가 먹으며

모달이 사라지지 않는 버그가 발생한다.

 

 

* 해결방법

modal이 열릴때는 transition효과를 주되,

modal이 닫힐때는 transition효과를 제거하고

바로 닫히게 하는것이다.

 

easescroll이 페이지 전체의 분위기를 차지하는 반면

modal을 거의 쓰이지 않거나 가끔 쓰일것이다.

 

기능상의 중요성을 따져보면 easescroll이 우선이기 때문에

modal의 닫힘 기능에서 약간의 양보를 하는것이 맞아보인다.

아니면 easescroll을 대신 다른 라이브러리를 찾아보는것도 방법니다.

728x90
반응형
728x90
<textares
  style={{ resize: 'none' }}
  onKeyDown={e => {
    const numberOfLines = (e.target.value.match(/\n/g) || []).length + 1;
    if (e.which === 13 && numberOfLines >= 3) {
      e.stopPropagation();
      e.preventDefault();
      return false;
    }
  }}
  onChange={onChange}
/>
728x90
반응형
728x90

[react-native-code-push 적용하기]

https://honeystorage.tistory.com/290

 

[앱 버전 관리, 어떻게 하는게 좋을까?]

https://honeystorage.tistory.com/310

 

위 두 포스팅을 통해

code-push를 적용하는 방법과

적용 후 어떻게 버전관리를 할지에 대한

저의 고민들을 살펴볼 수 있습니다.

 

마지막으로

저의 코드푸시 세팅을 공유하고

왜 이런 세팅을 하게되었는지

저의 생각을 정리하고자 포스팅합니다.

 

 

코드 푸시 & 버전 체크 플로우

1. 앱이 실행됨

2. 상위 앱 버전이 출시되었는지 API를 호출해 체크

2-1. 상위 앱 버전 존재 -> A

2-2. 상위 앱 버전 없음 -> B

 

A-1. 필수 업데이트  Alert 오픈

A-2. Alert 버튼 클릭 -> 스토어로 이동

 

B-1. checkForUpdate메서드로 업데이트 버전이 있는지 체크

B-2-1. 앱 업데이트 버전 없음 -> ㄱ

B-2-2. 앱 업데이트 버전 있음 -> ㄴ

 

ㄱ-1. 앱 메인 실행

 

ㄴ-1. 업데이트 패키지  download 진행

ㄴ-2-1. 기준 시간(ex. 10초)이내에 앱 업데이트 완료 -> a

ㄴ-2-2. 기준 시간(ex. 10초)이내에 앱 업데이트 실패 (지연됨) -> b

 

a-1. 앱 메인 실행

 

b-1. 앱 메인 실행

b-2. 백그라운드에서 앱 업데이트 패키지 다운로드 계속 실행

b-3. 패키지 다운로드 완료

b-4. 앱 업데이트 진행 안내  Alert 오픈

b-5-1. Alert, 취소 버튼 터치 -> 앱 계속 사용

b-5-2. Alert, 업데이트 버튼 터치 -> 앱 재실행

 

도식화

악필이지만

좀더 쉬운 이해를 위해

도식화해봤습니다.

 

위의 흐름에서 저의 고민의 흐름은 이렇습니다.

1) 버전 관리 전략을 어떻게할까?

2) 코드푸시는 핫픽스에만 사용, 최신버전 필수 업데이트는 스토어에서

3) 어떻게 최신버전을 서빙할까? 서버에서 체크

4) 코드푸시가 종종 지연되네...

5) 코드푸시 서버 상태로 업데이트가 지연되면 어쩌지?

6) 업데이트 페이지 뛰어넘기 + 백그라운드 설치

7) 백그라운드 설치 완료 후 업데이트 안내 팝업

8) 중요 업데이트 진행 안내 + 업데이트 권장

 

좋은 처리 방안인지는

조금 더 생각해볼 여지가 있지만

자체 코드푸시 서버를 구축하지 않는한

이정도의 처리가 최선이 아닐까 하는 생각이 듭니다.

728x90
반응형
728x90

scrollview, flatlist 등 

스크롤 기반 컴포넌트 위에서

텍스트 selectable 기능이 먹지 않는 증상이 있다.

 

해당 문제는 

스크롤뷰 컴포넌트에

removeClippedSubviews={false}

위의 속성 하나만 추가해주면 해결 가능하다.

 

728x90
반응형
728x90

피보나치 수 문제를 풀어보았다

팩토리얼과 마찬가지로

기본적인 재귀함수 구현에 대한 문제였다.

 

피보나치 수는

F0 = 0;

F1 = 1;

Fn = F(n-1) + F(n-2) 라는 공식이 있다.

 

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().split(" ");
const value = parseInt(input[0]);

function fibonacci(m, n, arr) {
  const a = arr[0];
  const b = arr[1];

  if (m > n) {
    console.log(b);
  } else {
    const newArr = [b, a + b];
    const _m = m + 1;
    fibonacci(_m, n, newArr);
  }
}

if (value === 0) {
  console.log(0);
} else if (value === 1) {
  console.log(1);
} else {
  fibonacci(2, value, [0, 1]);
}
728x90
반응형
728x90

재귀의 가장 기본이라고 할수있는

팩토리얼 문제를 풀어보았다.

 

팩토리얼이란

주어진 수 까지의 차례곱을 의미한다.

 

예) 5! = 1 * 2 * 3 * 4 * 5 = 120

 

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().split(" ");
const value = parseInt(input[0]);

function factorial(n, sum) {
  if (n === 0) {
    console.log(sum);
  } else {
    const multi = sum * n;
    const m = n - 1;
    factorial(m, multi);
  }
}

factorial(value, 1);

 

 

https://github.com/jaekwangLee/algorithm

 

GitHub - jaekwangLee/algorithm

Contribute to jaekwangLee/algorithm development by creating an account on GitHub.

github.com

 

728x90
반응형
728x90

한달 전 앱을 론칭해 운영중에있다.

초기 서비스인 만큼 많은

굉장히 짧은 주기로 버전 업데이트를 진행하고있다.

 

문제는

1. 사용자들이 배포된 업데이트를 진행할것인가?

2. 코드 푸시는 만능일까?

3. 어떤게 최선의 방법이지?

 


 

문제 1. 사용자들이 배포된 업데이트를 진행할것인가?

사용자들이 와이파이를 환경에서

자동업데이트를 하는게 아니라면

직접 업데이트를 진행하는 경우는 매우 드물었다.

따라서, 사용자들 간에 다른 버전을 쓰는 경우가

많아지기 시작했다.

 

문제 2. 코드 푸시는 만능일까?

우리는 사용자가 업데이트를

잘 하지 않는다는것을 확인하고

코드 푸시를 통해 업데이트를 진행하기 시작했다.

 

아주 만족스럽게도

업데이트 내용을 대다수의 사용자에게

온전히 제공할 수 있었다.

 

문제는 다른곳에서 발생했다.

코드 푸시는 앱 버전 단위로 진행되게 되는데,

한 버전에서 많은(3회 이상) 푸시를 하고나니

업데이트를 내려 받는 속도가 굉장히 느려졌다.

 

또한, ms appcenter의 서버가

해외에 있다보니 업데이트 체크 및 진행 속도가

들쭉날쭉 해졌다.

 

결국 업데이트에 3-5분이상

소요되어버리는 지경에 이르렀다.

 


 

해결책. 버전관리 전략 수립 및 배포전략 수립

간혹 보면 상용 서비스에서

앱 업데이트를 강제하는 경우가있다.

거기에는 다 이유가 있었다.

 

더 질 좋은 서비스를 잘 만들어 놨는데

사용자가 쓰지를 않는다면...

혹은, 문제점을 개선해서 배포를 했는데

사용자가 구버전에서 계속 에러리포트를 한다면...

 

우리 개발자들은 현타가 올것이다.

 

따라서, 우리는 버전관리와 배포전략을 통해

위와 같은 문제들을 해결하기로 했다.

 

앱 버전은 a.b.c로 구성된다.

a: 주요 업데이트 (스토어에서 배포)

b: 서브기능 추가 (스토어에서 배포)

c: 핫픽스, 워딩 수정 (code push후 버전 올려서 스토어에서 배포)

 

가장 작은 단위의 수정인 c부터 보면

간혹 미흡한 예외처리나 오타를 위해

수정 배포해야되는 경우가 있다.

이때는 코드푸시를 통해 버전의 문제를 즉시 처리하고, 

앱 버전 c 를 하나 올려 빌드해 스토어에 배포한다.

이렇게 하면 기존 버전 사용자도 문제 수정이 진행되고

새 버전 다운로드 사용자도 문제 수정 버전을 설치하게된다.

 

 

앱의 큰 축의 변화는 아니지만

list만 되던 부분이 추가/수정도 가능하게 된다는지 등의 기능 업데이트가 발생하면

b를 하나 올려 빌드해 스토어에 배포한다.

 

업데이트 심사의 경우 앱스토어/플레이스토어 모두

1 영업일 (길게는 2영업일) 이내면 처리되기 때문에

앱 버전 관리를 배포를 통해 하더라도

크게 답답할 일이 없다.

 

다만, 위해서 언급한것처럼 사용자들은

앱 업데이트를 잘 진행하지 않는다.

그렇기에 우리는 강제 업데이트 (필수 업데이트)

기능을 추가해둘 필요가 있다.

 

a단위로 강제 업데이트를 할지

b단위로 강제 업데이트를 할지는

회사 내규 운영방책을 정해서 진행하면 될듯하다.

 

우리는 프리미엄 서비스 + 소수의 사용자를

타겟으로 하고있어, b단위로 강제업데이트를 진행한다.

 

강제 업데이트를 하는 방식

1) 서버에 현재 배포된 각 플랫폼의 최신 버전을 응답하는 api추가

2) 앱이 켜질때 앱 버전과 서버에서 응답한 버전을 비교

3) 앱 버전이 서버에서 응답 받은 최신버전 보다 구 버전이라면 강제 업데이트 진행

4) 강제 업데이트는 Alert + Redirect(store로 linking) 을 통해 진행했다.

5) 주의 사항은 지속적으로 서버 버전을 잘 관리해야된다는 것

+ 새 버전으로 서버 버전을 올릴때 새 버전이 스토어에 반영됐는지 꼭 확인할것
(앱 심사가 통과되더라도 새 버전이 스토어에 반영되기까지 어느정도 시간이 소요되기 때문)

728x90
반응형
728x90

기존의 파일 업로드 방식으로는

모바일 사파리 브라우저에서

한글 파일 깨짐 이슈가 발생햇다.

 

// 기존의 간단한 파일 업로드
const formConfig = (form: FormData) => ({ 
  headers: { 'Content-Type': 'multipart/form-data;' },
});

const pdfForm = new FormData();
pdfForm.append('file', state.teaser);
await axios.post('/common/pdf/upload', pdfForm, formConfig(teaserForm));

 

항상 한글깨짐 이슈는 UTF-8 인코딩과

연관되어 있던던 과거의 경험에 의해

issue 트랙킹을 한 결과

 

아래와 같이 약간의 옵션을 추가해줌으로써

한글 깨짐에 대처할 수 있었다.

 

// 기존의 간단한 파일 업로드
const formConfig = (form: FormData) => ({ 
  headers: { 'Content-Type': 'multipart/form-data; charset: UTF-8;' },
  transformRequset: [function() {
    return form;
  }]
});

const pdfForm = new FormData();
pdfForm.append('file', state.teaser);
await axios.post('/common/pdf/upload', pdfForm, formConfig(teaserForm));
728x90
반응형
728x90

react-native-audio

라이브러리를 적용중에

ios에서는 문제없지만

android에서 위와 같은 이슈가 발생하였다.

 

문제는 github에서도 논의 중

별다른 해결책 없이 끝난것같다

(github issue tracking: 링크)

 

에러 추적결과

위 문제는 필요한 권한이 부족하여 나타난 현상이었다.

 

위 문제 해결을 위해서는

react-native-permissions를 통해

라이브러리 사용전 필요한 권한 요청을

사용자로 부터 허락받아야한다.

 

const prepare = (path: string) => {
  const config = {
    SampleRate: 22050,
    AudioEncoding: 'aac',
    Channels: 1,
    AudioQuality: 'Low',
    AudioEncodingBitRate: 32000
  };
  
  return new Promise((resolve, reject) => {
    if (Platform.OS === 'android') {
      requestMultiple([
        PERMISSION.ANDROID.WRITE_EXTERNAL_STORAGE,
        PERMISSION.ANDROID.READ_EXTERNAL_STORAGE,
        PERMISSION.ANDROID.RECORD_AUDIO
      ]).then((isAuthorized) => {
        if (
          isAuthorized['android.permission.READ_EXTENRAL_STORAGE'] === 'denied'
          || isAuthorized['android.permission.WRITE_EXTENRAL_STORAGE'] === 'denied' 
          || isAuthorized['android.permission.RECORD_AUDIO'] === 'denied'
        ) {
          reject('no permission')
        } else {
          AudioRecorder.prepareRecordingPath(path, config);
          resolve('has permission')
        }
      })
    } else {
      AudioRecorder.prepareRecordingPath(path, config);
      resolve('has permission')
    }
  })
}

 

이런식으로

외부 저장소 읽기/쓰기, 오디오 레코딩 권한을 획득해야만

"Exception in native call from JS" 에러없이 진행할 수 있다.

728x90
반응형
728x90

위 에러를 겪었다.

 

https://github.com/software-mansion-labs/reanimated-2-playground/commit/71642dbe7bd96eb41df5b9f59d661ab15f6fc3f8

 

Android · software-mansion-labs/reanimated-2-playground@71642db

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

github.com

 

위 링크에 변경사항을 따라서

라이브러리 관련 작업을 해서

많은 사람들이 해결됐다고 하는데

 

 

나는  proguard설정에 따른 이슈였어서

아래의 코드를 추가해줌으로써

이슈를 해결할 수 있었다.

// android/app/proguard-rules.pro

-keep class com.swmansion.reanimated.** { *; }
-keep class com.facebook.react.turbomodule.** { *; }
728x90
반응형