728x90
반응형

자연스럽게 배열값에 접근을 하다가

 

const newChatRoom = chatRoomList.map(oldChatRoom => {
if (조건) {
return {
...oldChatRoom,
chat_room_title: chatTitle,
alarm_yn: isAlarmOff ,
bookmark_yn: isPinned ,
};
}
return oldChatRoom;
});

 

이런 코드를 작성할 일이 생겼다.

콘솔로 찍어보니 해당 데이터들이 key값은 유지되고 value 값들이 null 값들이 나와서

deep copy를 사용했다

 

해당코드 중 retrun구분을

 

const n = Object.assign(oldChatRoom, {
chat_room_title: chatTitle,
alarm_yn: isAlarmOff,
bookmark_yn: isPinned,
}); // deep copy;

console.log('i검색::::::::::' + JSON.stringify(n, null, 2));

return n;

 

형태로 바꿔줬더니 정상 작동하였다.

728x90
반응형
728x90
반응형

ios js engine 이 업데이트 되고, 기존 react-native-debugger 가 ios real device 에서 정상작동을 하지 않고있다.

 

그래서 메트로를 통해서 콘솔을 보며 개발하고있었는데

 

문득

 

warn no apps connected. sending "reload" to all react native apps failed. make sure your app is running in the simulator or on a phone connected via usb.

 

이런 에러가 나면서 안되는 문제가 발생했다.

당연히 캐시들을 날리고 시작해보는 시도는 모두 해보았는데,

 

여전히 디버깅이 안돼서 급한 일정에 초조했다.

 

stackoverflow에서 어떤 개발자가 

info.plist 에 해당 키값을 추가해보라고했는데,

 

새로운 키값을 추가하는건 사실 이해가되지않아서 진행하지않았는데

 

갑자기 메트로가 연결되었다.

 

문제는 캐시였던것같다.

 

결국 

 

  1. yarn start --reset-cache
  2. yarn start
  3. cd ios && pod cache clean --all && pod deintegrate && rm Podfile.lock && pod install
  4. rebuild from Xcode and clean the build folder
  5. rm -rf node_modules and yarn to install the packages again

가 답이었다.

728x90
반응형
728x90
반응형

어떤 프로젝트를 할때마다 항상 한번에 깔끔하게 진행하지 못하는 문제다

getPhotos로 edges 에 해당하는 파일들을 가져올때, ios 는 ph:// 로 시작하는 파일 패스가 나온다.

 

항상 

 

import {Platform} from 'react-native';
import RNFS from 'react-native-fs';

export const phPathToFilePath = async (
uri: string,
type: string,
ext: string | null,
) => {
const fileURI = encodeURI(uri);

if (Platform.OS === 'ios' && uri.startsWith('ph://')) {
const extension = typeToExt(type, ext);
const copyPath = `${
RNFS.DocumentDirectoryPath
}/${new Date().toISOString()}.${extension}`.replace(/:/g, '-');

// ph경로의 이미지를 file로 옮기는 작업
if (type === 'video') {
return await RNFS.copyAssetsVideoIOS(uri, copyPath);
}
if (type === 'image') {
return await RNFS.copyAssetsFileIOS(uri, copyPath, 360, 360);
}
}

return fileURI;
};

const typeToExt = (type: string, ext: string | null) => {
if (type === 'video') {
return 'mov';
}
if (type === 'image') {
return 'jpg';
}
return ext;
};

이런식으로 ios용으로 form-data 에 들어갈 파일들의 path 를 파싱해주는 함수를 사용한다.

728x90
반응형
728x90
반응형

기존에 portrait mode / landscape mode 를 확인하기위해 

const useScreenDimensions = () => {
  const [screenData, setScreenData] = useState(Dimensions.get('screen'));

  useEffect(() => {
    const onChange = (result) => {
      setScreenData(result.screen);
    };

    Dimensions.addEventListener('change', onChange);

    return () => Dimensions.removeEventListener('change', onChange);
  });

  return {
    ...screenData,
    isLandscape: screenData.width > screenData.height,
  };
};

해당하는 훅을 잘사용했는데

 

import {useWindowDimensions} from 'react-native';

이제 훅을 아예 RN에서 만들어줬다

해당훅의 return 타입은

export interface ScaledSize {
width: number;
height: number;
scale: number;
fontScale: number;
}

이며

export const useLayout = () => {
const {width, height} = useWindowDimensions();
const PAGE_WIDTH = width;
const PAGE_HEIGHT = height;
return {PAGE_WIDTH, PAGE_HEIGHT};
};

로 사용하면 된다. 

728x90
반응형
728x90
반응형

내가 보려고 작성하는 typescript 정리

 

1. 배열에서 객체의 타입을 지정해주기

 

json파일에서 가져온 배열의 객체 타입을 따로 타입을 지정하는데 어려움이 있어

type CountryType = (typeof Countries)[number];

이런 방식으로 해결했다.

 

2. NonNullable ts util 사용하기

 

NonNullable ts util을 사용하면 파라미터값의 type을 따로 지정해주지않아도된다.

 

참고

 

https://www.typescriptlang.org/docs/handbook/utility-types.html

 

const onChangeText: NonNullable<TextInputProps['onChangeText']> = text => {
setEnable(text.length > 9);
updateInputs({tel: text});
};
728x90
반응형
728x90
반응형

개발중인 RN 앱에 react-native-vision-camera 를 적용했는데, ios 빌드가 되지 않았다

 

에러 내용은 xcode로 확인해봤을때

 

No member named 'ShareableValue' in namespace 'reanimated'

 

로 확인할 수 있었다.

 

npm 이슈탭에서 찾다보니

 

"react-native-reanimated": "^3.1.0",

해당 라이브러리가 3버전부터는 

"react-native-vision-camera": "^2.15.4",

에서 사용하는 name space를 제공하지 않는다는 것을 알게 됐고

 

"react-native-reanimated": "2.15.0",
"react-native-vision-camera": "^2.15.4",

로 버전을 맞추니 정상 빌드됐다.

 

주의했던 점은 앱내에서 사용하고 있는

"react-native-reanimated-carousel": "^3.3.2",

 

"react-native-reanimated": "2.15.0",

 

의 2.0.0 버전 이상이어야 된다는 docs를 보고 해당 버전을 2버전중 최고버전으로 세팅했다.

 

728x90
반응형
728x90
반응형

 

Xcode 로 종종 ios 를 열때, indexing processing files 에서 계속 멈춰있는 경우가 있다.

 

이는 /Xcode/DerivedData 를 삭제하면 해결된다

 

미리 빌드된 모듈이 충돌되서 그런듯하다

 

명령어는

 rm -rf ~/Library/Developer/Xcode/DerivedData 

 

또는

 

cd /Users/사용자명/Library/Developer/Xcode/DerivedData
rm -rf *

 

다시 xcode 실행하면 정상작동한다.

728x90
반응형
728x90
반응형

정말 간단하지만 RN에서 꼭 필요한 lib중에 한 4,5년전쯤에 나온 라이브러리들이 있다.

해당 library들은 readMe 에보면 compile .. 등으로 dependcies에 가져온다.

compile, runtime, testCompile, testRuntime 은 Gradle 4.10 (2018.8.27) 이후로 deprecate 되었다.
그리고 Gradle 7.0 (2021.4.9) 부터 삭제되었다.

 

예전 라이브러리들의 

compile -> implementation

runtime -> runtimeOnly

testCompile -> testImplementation

testRuntime -> testRuntimeOnly

 

등으로 수정해주면 된다.

728x90
반응형
728x90
반응형

현재 android java 로 개발된 서비스 중인 앱은 sms 인증 방식을 restful api로 서버에 요청하고,

서버에서 aws를 통해 문자를 보내주는 형식으로 전화번호 인증을 하고있다.

저번주에, vpn을 통해 과도한 문자청구가 되고, 백엔드 개발팀이 rate limiting을 통해 악의적인 유저를 블락하려고 해봤으나,

금주에도 동일한 공격이 발생했다.

 

그래서 FE에서 구글 sms 를 사용하기로 했다. 구글 firebase 는 recapcha 방식을 통해 악의적인 공격을 막아주기 때문이다.

 

전에 firebase sms auth로 sms 를 사용했을때, 트래킹이 되지않아 현재의 방식으로 개발했는데,

vpn을 쓰며 천천히 인증을 계속 돌리는 상황이 막상 닥치니 빨리 구글 인증으로 바꾸는 방식으로 회의를 마쳤다.

 

일단 현재 앱은 google Oauth를 사용하고 있기에,  gradle 파일에 세팅은 완료 된 상태이다.

 

따라서, api를 쏴주던 함수만 수정하면된다.

 

if(parsedPhoneNumber != null){
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            "+"+parsedPhoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            this,               // Activity (for callback binding)
            mCallbacks);        // OnVerificationStateChangedCallbacks
}

해당 부분으로 실행해주고, 

 

private void initCallback(){

        mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

            @Override
            public void onCodeAutoRetrievalTimeOut(String verificationId) {
                btnNext.setEnabled(true);
//                if (progressDialog != null) {
//                    dismissProgressDialog(progressDialog);
//                }
//                notifyUserAndRetry("Your Phone Number Verification is failed.Retry again!");
            }

            @Override
            public void onVerificationCompleted(PhoneAuthCredential credential) {
                btnNext.setEnabled(true);
                Log.d("onVerificationCompleted", "onVerificationCompleted:" + credential);
//                if (progressDialog != null) {
//                    dismissProgressDialog(progressDialog);
//                }
//                signInWithPhoneAuthCredential(credential);
            }

            @Override
            public void onVerificationFailed(FirebaseException e) {
                btnNext.setEnabled(true);
                Log.w("onVerificationFailed", "onVerificationFailed", e);

//                if (progressDialog != null) {
//                    dismissProgressDialog(progressDialog);
//                }

                if (e instanceof FirebaseAuthInvalidCredentialsException) {
                    Log.e("Exception:", "FirebaseAuthInvalidCredentialsException" + e);
                } else if (e instanceof FirebaseTooManyRequestsException) {
                    Log.e("Exception:", "FirebaseTooManyRequestsException" + e);

                }

//                notifyUserAndRetry("Your Phone Number Verification is failed.Retry again!");
            }

            @Override
            public void onCodeSent(String verificationId,
                                   PhoneAuthProvider.ForceResendingToken token) {
                btnNext.setEnabled(true);
                Log.e("onCodeSent", "onCodeSent:" + verificationId);
                Log.e("Verification code:", verificationId);
                Intent intent = new Intent(getApplicationContext(), PhoneCertification.class);

                intent.putExtra("parsedPhoneNumber", parsedPhoneNumber);
                intent.putExtra("conuntryCd", conuntryCd);
                intent.putExtra("verificationId",verificationId);
                startActivity(intent);
                finish();
            }
        };
    }

콜백함수를 등록해준다.

 

6자리 인증하는 부분에서는

먼저 함수를 작성해주고

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(PhoneCertification.this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        //verification successful we will start the profile activity
                        Log.e("성공 :::::::::","성공했다 ::::");

                    } else {


                        String message = "Somthing is wrong, we will fix it soon...";

                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            message = "Invalid code entered...";
                        }
                        Log.e("실패했다 :::::",message);


                    }
                }
            });
}

해당함수를 PhoneAuthCredential 객체를 만들고 param으로 넘겨줬다

try{
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, certification);
    signInWithPhoneAuthCredential(credential);
}catch (Exception e){
    Log.e("PhoneAuthCredential error ::::", String.valueOf(e));
}

RN에선 instance 를 사용하며 6자리까지 인증했던 기억이 나는데,

java에선 보내고, 해당 id 로 instance 에서 PhoneAuthCredential 객체를 생성한후, 그 객체에 대한 값을 확인하는 로직으로 돌아가는걸 알 수 있었다.

 끝

728x90
반응형
728x90
반응형

이번에 샘플 앱을 프론트 / 백을 같이 개발하면서 Node js 에 점점 흥미를 느끼고있다.

 

하지만 시연용이긴 하지만 처음 실사용자수들이 있는 프로젝트라서 백엔드에서 처음 보는 에러들이 많이 발생했다.

 

  code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
  fatal: false

 

등이 그 것이다.

 

mysql 을 사용하는데, 일정시간동안 요청이 없으면 db 커넥션을 끊는다는 것을 이번 디버깅을 통해 알게됐다.

 

미봉책으로 

 

// {"code":"PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR","fatal":false} 해당 에러을 발생으로
// mysql에 연결이 connection 문제가 발생하여 미봉책으로 5초에 한번씩 connection 유지를 위해
// query 문을 보낸다. 이는 리소스를 많이 잡아먹기때문에 추후 반드시 수정해야하는 부분
setInterval(function () {
try {
connection.query("SELECT * FROM 테이블 ");
logging("db connection !!");
} catch (error) {
logging("db connection failed !!");
}
}, 5000);

이런식으로 5초에 한번 쿼리문을 날려 해당 에러를 수정했고, 팔로우업 중이다.

 

물론 이방식은 리소스를 많이 잡아 먹기에 추후 실서비스가 될때 반드시 수정돼야 하는 부분이라 주석처리 해놓았다.

728x90
반응형

'Node js' 카테고리의 다른 글

[ Node js ] db 정보 보안처리  (0) 2023.06.20
[ Node js ] PROTOCOL_ENQUEUE_AFTER_QUIT  (0) 2023.06.09

+ Recent posts