여기 어때
의 홈 화면 구성만 클론 코딩하기에는 사실상 HTML/CSS
만 다루고 React
를 아예 안쓰는 것 같아
상세페이지, 장바구니, 결제 플로우
를 구현해보기로 했다
발생한 문제
1. 해당 기능을 구현하려면 DB가 필연적인데 어떻게 할 것인가
2. 서버는 어떻게 구현할 것인가
고민하다가 Next.js(서버/라우팅이 편함, 리액트 기반) / MongoDB(JSON-BSON이라 러닝커브가 비교적 작음)를 도입하려고 했었다
문제는 프로그래머스 데브코스가 3월부터 다시 팀 프로젝트가 시작되고 + RN을 새로 배우게 되는데
해당 과정을 진행하면서 Next.js 프로젝트까지 같이 해버리면 얼마 못 가 끝날 것 같아서 차라리 RN
을 각자 미리 공부해고 프로젝트를 어떻게 진행할지 결정해보려고 한다
그래서 연습 느낌으로 RN + Styled Component 조합으로 공부해볼 생각이다
ReactNative
는 React
와는 다르게 브라우저에 띄워서 작업하지 않고 Expo
를 통해서 안드로이드 기반 에뮬을 띄워서 작업한다.
그러다 보니 React
에서는 겪어보지 못한 많은 문제들을 만나게 되고 이왜안(이게 왜 안되지...?)
의 늪에 빠지게 된다
다행히도 나보다 앞서 에러를 경험한 사람들이 문제를 해결해놔서 검색해놓으면 대부분 해결이 된다.
TypeError: Invalid character in header content ["X-React-Native-Project-Root"]
이 문제는
node_modules/@react-native-community/cli-server-api/build/statusPageMiddleware.js
파일로 가서
function statusPageMiddleware(_req, res) {
res.setHeader('X-React-Native-Project-Root', process.cwd());
res.end('packager-status:running');
}
process.cwd()
를 new URL()
로 감싸주면 된다
function statusPageMiddleware(_req, res) {
res.setHeader('X-React-Native-Project-Root', new URL(process.cwd()));
res.end('packager-status:running');
}
이렇게 바꿔주면 된다
이후
npm cache clean --force
로 캐시를 비우고
리로드 한 후 npm run android
를 해주면 해결된다.
계속 진도가 안나가고 여러 문제가 발생한다...
React Native는 내가 기존에 알던 리액트와 너무 다르다는 게 느껴진다
리액트에서는 5초만에 끝나는 단순한 CSS font 바꾸는 것도
한참을 찾아봤다
import * as Font from 'expo-font';
async function loadFonts() {
await Font.loadAsync({
Pretendard: require('./assets/fonts/PretendardVariable.ttf'),
Sokcho: require('./assets/fonts/SokchoBadaDotum.ttf'),
});
}
export default function App() {
loadFonts(); // 여기서 실행
return (
<ThemeProvider theme={theme}>
<AppView>
<MyText>장바구니</MyText>
<Header />
</AppView>
</ThemeProvider>
);
}
expo-font
install 후에
assets/fonts 안에 폰트 파일을 넣고 불러오면 된다
styled-components
예시
const MyText = styled.Text`
font-size: 55px;
color: ${(props) => props.theme.colors.primary};
background-color: ${(props) => props.theme.colors.secondary};
font-family: Pretendard;
`;
렌더링이 끝난 후 폰트가 불러와질 수 있어서
async/await
활용해서 폰트 로딩 후 렌더링하는 방식을 사용하는 것 같다
Styled-Components에서 CSS 변수화하기
// theme.js
const theme = {
colors: {
primary: '#ffffff',
secondary: '#2ecc71',
},
};
export default theme;
변수 지정하고
import styled, { ThemeProvider } from 'styled-components';
import theme from './theme';
const MyText = styled.Text`
font-size: 55px;
color: ${(props) => props.theme.colors.primary};
background-color: ${(props) => props.theme.colors.secondary};
font-family: 'Pretendard';
`;
export default function App() {
return (
<ThemeProvider theme={theme}>
<AppView>
<MyText>ss</MyText>
</AppView>
</ThemeProvider>
);
}
ThemeProvider
컴포넌트로 감싸주고 프롭으로 theme
를 전해주고 사용하면 된다
살짝 번거로운 것 같아서 다른 좋은 방법은 없나 찾는 중이다
RN은 svg파일을 읽지 못한다.......
해결 방법
npm install react-native-svg
npm install react-native-svg-transformer
설치 후
// './assets/icons/ArrowIcon.js'
import Svg, { Path } from 'react-native-svg';
const ArrowIcon = () => (
<Svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<Path
d="M15.705 16.59L11.125 12L15.705 7.41L14.295 6L8.29498 12L14.295 18L15.705 16.59Z"
fill="black"
/>
</Svg>
);
export default ArrowIcon;
import ArrowIcon from '../assets/icons/ArrowIcon';
const Header = () => {
return (
<HeaderView>
<ArrowIcon />
</HeaderView>
);
};
이런 식으로 컴포넌트화 해서 불러오면 된다
컴포넌트 별로 다른 크기로 쓰고 싶다면
import Svg, { Path } from 'react-native-svg';
const ArrowIcon = ({ width = '24', height = '24' }) => (
<Svg
width={width}
height={height}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<Path
d="M15.705 16.59L11.125 12L15.705 7.41L14.295 6L8.29498 12L14.295 18L15.705 16.59Z"
fill="black"
/>
</Svg>
);
export default ArrowIcon;
이런 식으로 초기화 및 동적으로 받을 수 있게 해주고
const Header = () => {
return (
<HeaderView>
<ArrowIcon width="50px" height="50px" />
<HeaderText>속초바다</HeaderText>
</HeaderView>
);
};
이렇게 하면 된다
난 리액트 네이티브가 밉다...