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
반응형

사실 3년 좀 넘게 RN을 통해 앱을 개발하면서, 

종종 겪는 에러였다.

ios는 뭔가 android보다 항상 좀더 까다로운 느낌을 받는다.

 

IOS에서는 https 만 사용할 수 있도록 보안정책이 되어있기때문에

현재 http로 시작하는 api를 따로 설정해줘야한다

 

최종 info.plist는

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>api.base.url</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>

 

728x90
반응형
728x90
반응형

샘플앱을 안드로이드 버전만 요구하시다가, 급하게 ios 버전도 필요하시다는 말씀을 듣고나서

라이브러리들의 ios 세팅들을 하고있다.

 

env파일 android 세팅은 정말 한번에 끝냈지만, ios env세팅은 정말 힘들었다.

 

일단,

추가되어있는 env파일 들이다.

 

xcode의 프로젝트에서 우클릭 후, new file로  Config.xcconfig 을 생성한다.

해당파일에 

#include? "tmp.xcconfig"

를 추가해준다.

 

Product -> Scheme -> New Scheme 으로, dev / prodcution을 생성해준다.

 

Edit Scheme -> Build -> Pre-action 에 새로운 run script를 생성함으로써 적용할 수 있다.

내경우 .env가 release / .env.debug 가 dev환경이다.

 

따라서 dev 의 pre-action에는 

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env" > /tmp/envfile

"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"

 

production의 pre-action에는

 

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env.debug" > /tmp/envfile

"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"

를 작성해줬다.

 

xcode 로 빌드를 했더니

 

Please verify your .env file is correctly formatted.

라는 에러가 나왔는데,

이는 .env파일에 주석처리 되어있던 부분을 xcode에서 형식이 잘못되어있다고 읽어서 생긴 문제였다.

 

env에 있는 주석/한글 제거하고 하니 해결

728x90
반응형
728x90
반응형

샘플앱을 만들면서 안드로이드 apk만 필요하시다는 요구사항이 있어서, 급하게 프로젝트를 마무리했는데,

IOS 버전도 testflight를 통해 접근할 수 있도록 부탁한다는 요청사항을 받았다.

 

급하게 라이브러리들의 ios세팅을 마치고

xcode로 빌드를 하려는데

 

해당 에러가 나왔다.

xcode 버전을 내리라는 stackoverflow 의 답변들도 있었지만

 

cd ios && pod cache clean --all && pod install && cd ..

 

로 해결.

 

물론 메트로도 재시작했다.

 

RN을 하다보면 ./gradlew clean과 pod cache clean -all 을 자주 사용하는 것같다

728x90
반응형
728x90
반응형

디버그 / 릴리즈 모드에 따른 api를 __DEV__ 로 분리하곤 했는데,

이번에 회사에서 요구한 샘플앱에는 env 파일로 적용했다.

 

먼저 

 

yarn add react-native-config

로 react-native-config 세팅을 해준다.

 

docs에 나온것 처럼

 

project/android/app/build.gradle

 

 

project.ext.envConfigFiles = [
    debug: ".env.debug",
    release: ".env",
    anothercustombuild: ".env.staging",
]

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" // 추가


defaultConfig {
	        resValue "string", "build_config_package", "AndroidManifest파일 packageName입력" // 추가
            ...
}

 

등을 추가해준다.

 

해당 파일을 설치해주고, 

 

파일별로 

BASE_URL="base url";

을 추가해준뒤

import Config from 'react-native-config';
console.log('Config.BASE_URL ::::::' + Config.BASE_URL);

 

yarn android

 

react-native run-android --variant=release

 

로 dev일때, release일때 확인해보면 된다.

728x90
반응형
728x90
반응형

VScode로 코딩을 치고있는데, 자꾸 jsx return 컴포넌트 들에 붉은 에러 줄이 표시됐다.

물론 컴파일엔 문제가 없어서 vsCode문제겠거니 하고있었는데, 

그냥 눈이 편하게 하기위해 붉은 에러줄을 없애기로 했다.

 

tsconfig.json 에 가보니

 

{
"extends": "@tsconfig/react-native/tsconfig.json",
}

덩그러니 한줄만 있었고, 붉은 줄이 표시되고있었다.

 

해당 key-value의 에러 메세지는 file '@tsconfig/react-native/tsconfig.json' not found.

 

이었고,

"jsx": "react-jsx"

를 밑에 추가해주니, 

 

'jsx' should be set inside the compilerOptions 라는 붉은 줄이 나왔다.

tsconfig.json을 

{
"extends": "@tsconfig/react-native/tsconfig.json",
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"jsx": "react"
}
}

로 수정해주고

 

VScode를 재시작하니 해결

 

728x90
반응형
728x90
반응형

지금까지 RN 프로젝트를 해오면서, 짧은 개발기간을 핑계로 많은 상태관리 라이브러리가 있으면서

익숙하던 redux를 항상 고집해왔다.

zustand와 mobx도 실무에서 많이 사용하는 걸로 알고있는데

항상 무엇인가 가벼운(?) 프로젝트에서 많이 사용한다는 잘못된 선입견이 생겨서인지

신규 프로젝트를 구상할때 항상 redux / asyncstorage / persist-store 들로 상태관리를 했다.

 

성장하지 않는 느낌이 들어서, 이번에 짧은 개발기간임에도 불구하고, 이꽉물고 새로운 상태관리를 적용해보려했다.

결과적으로 말하자면 redux를 사용할때보다 보일러 플레이트가 현저히 줄어서, 코드 치기가 쉬웠다.

 

이번 글에선 react-native cli로 생성한 프로젝트에 mobx 를 적용하는 간단한 설명을 메모해 두려고한다.

항상 새로운 라이브러리를 쓴다는건 신나는 일이고, 결국엔 거의 비슷한 로직으로 돌아간다는게 참 재밌는거 같다.

 

당연히 mobx도, redux처럼 여러개의 store를 사용할수있고(redux에서 여러개의 reducer를 root reducer로 합치는 것과 동일)

하나의 store에 여러값을 저장 할 수 있다.

 

yarn add mobx                                                                             
yarn add mobx-react

 

일단 mobx 와 mobx-react 를 프로젝트에 import 해준다

( mobx-react-lite를 임포트 해주라는 글들도 있지만, mobx-react-lite 내가 적용할때는 babel쪽 syntax에러가 많이 발생해서

mobx-lite를 import해 줬다.)

 

기본 구조

hooks/useRootData.js 는 mobx를 쓰는 hook으로

 

소스코드는

import {useObserver} from 'mobx-react';
import React, {useContext} from 'react';
import {storesContext} from '../utils/context';

export const useStoreData = (context, storeSelector, dataSelector) => {
const value = useContext(context);
if (!value) {
throw new Error('No store');
}
const store = storeSelector(value);

return useObserver(() => {
return dataSelector(store);
});
};

export default dataSelector => {
return useStoreData(storesContext, contextData => contextData, dataSelector);
};

 

import {observable, runInAction} from 'mobx';

const createStore = () => {
const anotherStore = {
anotherKey: observable.box('anotherKey'),
changeAnotherKey: data =>
runInAction(() => anotherStore.anotherKey.set(data)),
};

return anotherStore;
};

const anotherStore = createStore();
export default anotherStore;

 

import {observable, runInAction} from 'mobx';

const createStore = () => {
const loginInfoStore = {
loginInfo: observable.box('userName'),
changeLoginInfo: data =>
runInAction(() => loginInfoStore.loginInfo.set(data)),
connect: observable.box(true),
changeConnect: data => runInAction(() => loginInfoStore.connect.set(data)),
};

return loginInfoStore;
};

const store = createStore();
export default store;

 

import loginInfoStore from './loginInfoStore';
import anotherStore from './anotherStore';

const createRootStore = () => {
return {
loginInfoStore,
anotherStore,
};
};

export default createRootStore;
import {useLocalObservable} from 'mobx-react';
import React, {createContext} from 'react';

import createRootStore from '../store/index';

export const storesContext = createContext(null);

export const StoreProvider = ({children}) => {
const store = useLocalObservable(createRootStore);

return (
<storesContext.Provider value={store}>{children}</storesContext.Provider>
);
};

이 소스코드들을 두가지 store에 한스토어당 2가지이상을 세팅하는 예제로 사용하면 된다.

 

상태값을 사용하고 싶은 component에서

 

const {loginInfo, changeLoginInfo, connect, changeConnect, anotherKey} =
useStoreData(({loginInfoStore, anotherStore}) => ({
loginInfo: loginInfoStore.loginInfo.get(),
changeLoginInfo: loginInfoStore.changeLoginInfo,
connect: loginInfoStore.connect.get(),
changeConnect: loginInfoStore.changeConnect,
anotherKey: anotherStore.anotherKey.get(),
}));

해당 hook으로 state, setState 값을 선언해주고

 

changeConnect(!connect);

이런식으로 사용해주면된다.

 

이번 프로젝트에 mobx의 기본 구조를 적용하면서, 내가 redux-saga / redux-thunk 등의 미들웨어가 mobx에서 어떻게 적용되는지,

mobx의 persist-store적용은 어떻게 하는지 등에 대해 궁금증이 생겼다. 

 

개발은 참 재미있다.

728x90
반응형
728x90
반응형

회사내에서 NFC카드 테그에따라 실행되며 앱안에서 몇가지의 비지니스 로직이 들어가는 샘플앱을 한 일주일만에

만들어 달라는 요청이 있었다.

 

새로나온 버전을 사용해보려고 룰루랄라 오랜만에 신나서 

 

react-native init 프로젝트이름  --template react-native-template-typescript

 

해당 명령어를 입력했는데

 

TypeError: cli.init is not a function

    at run (/usr/local/lib/node_modules/react-native-cli/index.js:302:7)

    at createProject (/usr/local/lib/node_modules/react-native-cli/index.js:249:3)

    at init (/usr/local/lib/node_modules/react-native-cli/index.js:200:5)

    at Object.<anonymous> (/usr/local/lib/node_modules/react-native-cli/index.js:153:7)

해당 에러가 떴다. 

 

오랜만에 리넥의 에러라 설레는 마음으로 찾아보니, react-native-cli 버전이 안맞아서 생기는 문제라고한다.

 

현재 버전을 react-native --version 으로 확인해보니

2.0.1 버전이라고 나왔다.

 

터미널 창에서

 

npm uninstall -g react-native-cli.

yarn global add @react-native-community/cli

react-native init 프로젝트이름 --template react-native-template-typescript

 

명령어들을 순서대로 입력했더니

 

Starting from React Native v0.71 TypeScript is used by default.

 

이런문구와 함께 생성되었다. 0.71버전부터는 typeScript가 디폴트로 적용된다는 기분좋은 안내문구였다.

 

잘실행되다가 

 

Installing Ruby Gems

error /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/universal-darwin21/rbconfig.rb:230: warning: Insecure world writable dir /Users/내이름/Library/Android/sdk/emulator in PATH, mode 040777

Installing Ruby Gems

error Looks like your iOS environment is not properly set. Please go to https://reactnative.dev/docs/environment-setup?os=macos&platform=android and follow the React Native CLI QuickStart guide for macOS and iOS.

 

해당 에러가 떠서

 gem install cocoapods

로 해결하려했지만, permission 에러가 발생해서

chmod go-w /Users/내이름

명령어 실행 후, 

 gem install cocoapods

로 다시 설치해주며 앱실행을 완료했다.

 

두근두근 0.71 버전이 업데이트되고 나서 리넥으로 처음 적용해서 만들어보는데, 씐난다.

 

<FlashList>를 드디어 사용해 볼 수 있겠다

 

728x90
반응형
728x90
반응형

요즘 계속 안드로이드 요구사항을 작업하다가, 오랜만에 react 로 된 웹페이지 요구사항이 들어왔다.

 

소켓 연결에 상태에 따른 버튼 추가 및 재연결 요청사항이었는데

 

오랜만에 리액트 코드를 보게되서 설렜다.

 

기본 원리는 redux 에 socket connected state 값을 하나 추가해주고, dispatch 를 통해 값을 바꿔주는 식으로 적용했다.

 

useDispatch  훅을 분리된 소켓 모듈에서 바로 import 해줘서 쓰지 못하기때문에,

 

App.tsx 에서

export const socektConnectedRef = React.createRef();

선언 후, App.tsx에서 ref값을 하나

socektConnectedRef.current =(connected)=>{ dispatch(setSocketConnected({ socketConnected: connected}));}

함수를 선언해주고

 

해당 소켓 모듈에서 

function error_handler(err) {
insert_system_message('error', 'socket.io error : ' + err.toString());
console.log('fnChat.js > socket.io error > err = ', err);
try {
socektConnectedRef?.current(false);
} catch (error) {
console.log("socektConnectedRef error :::",error);
}
}

이런식으로 사용해주었다.

 

리넥으로 앱을 할때는 ref값을 많이 사용하지 않도록 지양했고, 전역으로 쓰는 ref값을 맥시멈 4~5개로 제한했었는데, 

 

지금 웹뷰에 붙어있는 웹에선 전역 ref값을 하나만 사용중이라 이런식으로 처리했다.

 

당연히 소켓 연결상태에 따른 뷰변화는

 

const socketConnected = useSelector((state) => state.langData.socketConnected);

을 통해 적용했다.

 

안드로이드를 하면서 많이 느끼는거지만, js 가 좋다.

728x90
반응형
728x90
반응형

react native 로 aa를 할때, 모든 개발이 그렇듯, 공통 모듈을 분리해놓는 것이 좋다.

 

rn은 크로스플랫폼 개발이라서, ios 노치 디자인 등 신경써야 할 것들이 많다.

 

대부분의 개발자분들이 그렇듯, app.tsx app.js에 앱 전반에 영향을 미치는 부분들을 생각해서 기본구조를 짤것이다.

 

예시를 들어보면

 

<BackgroundTask>
<ReRenderProvider>
<ThemeProvider>
<LanguageProvider>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator

등으로 app.tx app.js를 구성하는 경우가 있었다.

 

앱의 foreground / background 상태를 체크하기 위한 BackgroundTask

강제 랜더링을 위한 ReRenderProvider

앱의 테마를 위한 ThemeProvider

언어 다국어 처리를 위한 LanguageProvider

local 저장소인 store를 위한 ProviderPersistGate

그 안에 네비게이션 컨테이너를 넣어준다.

 

기획과 스토리 보드에 따라

SafeAreaProvider

ErrorBoundary

도 적용하는 것이 좋다.

 

앱에서 주로쓰는 firebase noti 들과, 코드푸쉬는 주로 index.js에서 사용했다.

728x90
반응형

+ Recent posts