깃허브 주소 ▼
개요
목표
메인 화면의 컴포넌트는 어느정도 다 만들었다고 생각이 들어 약간의 수정을 한 뒤, 라우팅을 넣기로 했다. 또한 현재 매직넘버와 반복되는 세세한 코드들이 너무 많다고 생각되어 전역 스타일과 자주 사용되는 값들을 관리하는 객체를 만들기로 했다. 또한 이제와서 코드를 다시 훑어보니 Stateless하지 않은 컴포넌트가 몇 보여 이 역시도 수정하기로 했다.
그래서 이번 목표는 전역 스타일 수정, Stateless하게 수정, 라우팅이다.
전역 스타일 수정
기존에 구성해 놓은 화면을 보니 좌우에 패딩이 너무 부족하다는 생각이 들어 값을 주려던 찰나, 지금 이렇게 개별적으로 패딩 값을 넣게 되면 이후에 만드는 모든 페이지에서도 개별적으로 패딩 값을 넣어야한다는 생각이 들었다. 아주 조금씩이지만 분명 엄청난 시간 낭비가 될 것이고, 만약 전체 패딩을 수정해야하는 일이 생긴다면 그동안 만든 N개의 페이지의 모든 패딩을 직접 수정해줘야한다. 아주 당연한 작업인데 React로 개발하는 것이 처음이다 보니 이 부분을 놓치고 있었다. (Flutter로 개발 할 때는 BaseWidget혹은 BasePage를 만들어놓고 이를 상속받아서 사용한다.) ▼
트러블 슈팅 : 네비게이션 바 이동
전역 스타일을 설정하는건 어려운 일이 아니기에 아래와 같이 `margin: 0 5.2rem;` 한 줄 추가로 쉽게 설정했다. ▼
body {
margin: 0 5.2rem;
font-size: 1rem;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #181818;
}
허나 이렇게 추가하고 나니 네비게이션 바가 오른쪽으로 이동해버렸다. 네비게이션 바 전체를 감싸는 `StyledWrap`에 `margin: 0;`을 넣었음에도 적용이 되지 않았다. 적용의 우선순위에서 생긴건가 생각을 하면서도 오른쪽 영역의 margin은 왜 적용이 안되는지 의문이었다. ▼
오른쪽의 `margin`이 적용되지 않은 이유
약간 생각을 하다가 이렇게 되는게 당연하다는 결론에 이르렀다. 현재 네비게이션 바는 `width: 100%`로 너비가 정해진 상태이다. 너비가 먼저 정해진 다음에 왼쪽 `margin`이 적용되고, 그 다음에 오른쪽 `margin`이 적용된건데, `margin`자체로는 컴포넌트의 너비를 강제로 줄여버리기가 안되어 그냥 오른쪽으로 이동해버리게 된 것이다. ▼
해결
해결은 간단했다. `position: fixed`로 설정이 되어있으니, 왼쪽 끝과 오른쪽 끝에 고정해버리면 되는 것이었다. 사실 오른쪽 끝에는 고정할 필요가 없긴 하다. 왼쪽 끝만 정해줘도 오른쪽 끝은 자동으로 정해지기 때문이다. 그래서 아래와 같이 `left: 0;`, `right: 0`을 넣어 네비게이션 바를 고정해주었다. ▼
const StyledNavigationBar = styled.div`
width: 100%;
display: flex;
z-index: 2000;
position: fixed;
left: 0;
top: 0px;
background: ${theme.color.background};
`;
Stateless하게 수정
앞에서 NavigationBar를 고치면서 코드를 보니 아래와 같이 하드 코딩 해놨었다. 네비게이션 자체의 스타일을 바꾸는 일이면 그나마 낫지만, 내부 데이터들을 수정할 일이 생기게 되면 상당히 귀찮은 작업이 될 수 있다. 또한 아래와 같이 작성하면 네비게이션 바에 들어가는 항목이 많아질 경우 단순 코드량이 늘기도 한다.
사실 네비게이션 바에 들어가면 뭐 얼마나 들어간다고 생각이 들기도 했다. 기껏 들어가봐야 아래의 코드에 나와있는 3가지에서 4가지 정도 항목이다. 그래서 코드량이 엄청 많아지지는 않겠지만, 추가와 삭제에서 귀찮음이 유발될 것 같다는 생각이 들었다.
function NavigationBar() {
return (
<StyledWrap>
<StyledNavigationBar>
<NavbarLogo />
<StyledListWrap>
<ul>
<StyledListCell><StyledAnchor href="#hello">가이드</StyledAnchor></StyledListCell>
<StyledListCell><StyledAnchor href="#hello">문의</StyledAnchor></StyledListCell>
<StyledListCell><StyledAnchor href="#hello">회원가입/로그인</StyledAnchor></StyledListCell>
</ul>
</StyledListWrap>
</StyledNavigationBar>
</StyledWrap>
);
}
export default NavigationBar;
만약에 새로운 네비게이션 항목이 생겼다고 해보자, 가이드, 문의가 아니라 새로운 딜레마 만들기 항목이 네비게이션에 들어간다고 해보자. 그러면 아래와 같이 코드를 한 줄 더 추가해야한다. ▼
/* 코드 생략... */
<ul>
<StyledListCell><StyledAnchor href="#hello">새로운 딜레마 추가</StyledAnchor></StyledListCell>
<StyledListCell><StyledAnchor href="#hello">가이드</StyledAnchor></StyledListCell>
<StyledListCell><StyledAnchor href="#hello">문의</StyledAnchor></StyledListCell>
<StyledListCell><StyledAnchor href="#hello">회원가입/로그인</StyledAnchor></StyledListCell>
</ul>
/* 코드 생략... */
'코드 한 줄 치는게 뭐 얼마나 귀찮냐...' 할 수 있지만 현재와 같이 혼자 작업하고 언제든지 구성이 바뀔 수 있는 상황에서는 여기에 들어가는 시간이 상당히 많을 수 있다. 지금 약간 귀찮더라도 미래의 혹시 모를 시간 소모를 줄이는게 좋은거 같아 `NavigationBar`의 데이터를 따로 관리하고 `NavigationBar`자체는 Stateless하게 수정했다. ▼
function NavigationBar({data}) {
return (
<StyledWrap>
<StyledNavigationBar>
<NavbarLogo />
<StyledListWrap>
<ul>
{data.map((item, index) => (
<StyledListCell key={index}>
<StyledAnchor href={item.href}>{item.titleText}</StyledAnchor>
</StyledListCell>
))}
</ul>
</StyledListWrap>
</StyledNavigationBar>
</StyledWrap>
);
}
그리고 메인 페이지에서는 아래와 같이 호출했다. navBarData는 라우팅이 설정되고 나면 다시 수정할 예정이다. ▼
const navBarData = [
{titleText: "가이드", href: "#guide"},
{titleText: "문의", href: "#faq"},
{titleText: "회원가입/로그인", href: "#login"},
]
function MainPage() {
return (
<>
<NavigationBar data={navBarData}></NavigationBar>
<ButtonContainer data={buttonsData}></ButtonContainer>
<DilemmaList data={listData}></DilemmaList>
</>
);
}
라우팅
설치와 사용
설치
이제 메인 페이지에 있는 요소들은 얼추 다 만들어서 이제 다른 페이지들을 만들고 페이지 이동이 가능하게 하기 위해 라우팅 하는 법을 찾아봤다. 우선 아래의 명령어로 react-router 라이브러리를 설치했다. ▼
npm install react-router-dom@6
사용
초기 사용법은 간단했다. 아래와 같은 레이아웃에 페이지들을 채우면 됐다. 페이지간 데이터 전달이나 다른 설정들까지 생각하면 더 복잡해지겠지만 우선 단순 이동은 아래와 같이 간단하게 등록할 수 있다. ▼
import { Routes, Route, BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path={"path"} element={<Element />}/>
/*필요하면 더 추가*/
</Routes>
</BrowserRouter>
);
}
export default App;
이전에 정의해 놓은 `RoutePaths`가 있어 이를 사용하여 짠 코드는 아래와 같다. ▼
const RoutePaths = [
{ title: "MainPage", href: "/" },
];
export default RoutePaths;
import MainPage from "./pages/MainPage";
import { Routes, Route, BrowserRouter } from "react-router-dom";
import RoutePaths from "./constants/RoutePaths";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path={RoutePaths[0].href} element={<MainPage />}/>
</Routes>
</BrowserRouter>
);
}
export default App;
트러블 슈팅 : 좀 더 깔끔하게 코드 짜기
위와 같이 코드를 짜는 것도 큰 문제가 되는 것은 아니지만, 몇 가지 문제가 있다. 앞의 문제들과 같은 문제인데, 코드가 지저분해지고 새로운 페이지가 생기면 위의 코드 한 줄을 통째로 다시 써야한다는 것이었다. 페이지가 별로 없으면 그래도 돌아가는데 상관은 없겠지만, 이를 좀 더 편하게 하려고 `RoutePaths`까지 만들어놓고 이렇게 코드를 짜면 `RoutePaths`를 만든 이유가 없어진다.
그래서 아까와 같이 `.map`을 통해 코드를 짜려고 하니 `element={}`가 문제였다. 기존의 `RoutePaths`에는 페이지 컴포넌트가 없었기 때문이다. 그래서 혹시 이렇게도 가능하려나 하고 `element={<{RoutePaths[0].title}>}`와 같이 코드를 쳐봤는데 당연히 안됐다. 쩝. 이렇게 하면 더 간편하게 할 수 있으니 혹시 될수도? 하고 해봤는데 안되어 `RoutePaths`에 페이지 컴포넌트를 넣어주었다. ▼
import MainPage from "../pages/MainPage";
const RoutePaths = [
{ title: "MainPage", href: "/", page: <MainPage /> },
];
export default RoutePaths;
그리고 `App`의 코드를 아래와 같이 바꿨다. 훨씬 간결해졌고, 라우팅에 관해 수정이 필요할 때 `App`에 접근할 필요가 없어졌다. 이제는 라우팅에 대해 수정이 필요하면 다른 파일을 건들지 않고 `RoutePaths`만 건드리면 된다. ▼
import { Routes, Route, BrowserRouter } from "react-router-dom";
import RoutePaths from "./constants/RoutePaths";
function App() {
return (
<BrowserRouter>
<Routes>
{RoutePaths.map((item) => (
<Route path={item.href} element={item.page}/>
))}
</Routes>
</BrowserRouter>
);
}
export default App;
마치며
이번에는 map을 사용하여 Stateless하게 만들고 전체적인 세세한 중복들을 없앴다. 아직 매직넘버는 건들지 못했으니 차차 수정해나가자.
'Develop > React' 카테고리의 다른 글
[React][개발기] 8. Login 모달, 그리고 전체 점검의 필요성 (0) | 2024.07.18 |
---|---|
[React][개발기] 7. RoutePaths, NavBarData 등 데이터를 효율적으로 (0) | 2024.07.17 |
[React][개발기] 5. Component 이어서 만들기와 고민 해결 (0) | 2024.07.16 |
[React][개발기] 4. Styled-Component로 Component 만들기 (0) | 2024.07.16 |
[React][개발기] 3. 우선 기초적인 것들부터 학습2(HTML, CSS, JS) (0) | 2024.07.14 |