# 210205 trouble shooting
## regenerator...
```
{
"plugins": ["@babel/plugin-transform-runtime"]
}
```
## Route의 컴포넌트로 props 전달하기
구글 로그인과 카카오 로그인을 할 때 같은 컴포넌트로 처리를 하고 싶었다. 서버로 보내는 api는 두 로그인이 같고 api의 parameter 하나만 다를 뿐이었다. api 요청을 보낼 때 구글 로그인인지, 카카오 로그인인지를 나타내는 social 값만 다르게 하고 싶었다. 정리를 하자면, Route에서 다른 url로 요청이 오지만 같은 컴포넌트로 social prop만 다르게 줘서 처리를 하고 싶었다.
https://sustainable-dev.tistory.com/117
render props를 사용하는 방법이 best practice라고 했다.
그런데 생각을 해보니 url의 파라미터에서 정보를 가져오면 될 것 같았다.
```javascript=
// App.jsx 중..
<Route path="/callback/:social" component={AuthCallbackPage} />
// AuthCallbackPage.jsx
const AuthCallbackPage = ({ match }) => {
const { social } = match.params;
return <AuthCallback social={social} />;
};
```
Route에서 parameter 값이 컴포넌트의 match.params로 전달이 되었다.
## 쿠키가 설정이 안 되는 문제
```javascript=
// 프론트
const { data } = await axios.post(
`${serverUri}/api/user/signIn/${social}`,
{ code }
);
```
```javascript=
// 백엔드
res.cookie('accessToken', accessToken, { HttpOnly: true });
```

쿠키가 설정이 되지 않았다.
이것은 withCredential을 설정을 해주지 않아서 생기는 문제였는데 withCredential은 cross-site Access-Control requests에서 credential을 사용하는지 설정을 해주는 속성이었다. 따라서 프론트 코드를 다음과 같이 바꿔주니 해결이 되었다.
```javascript=
const { data } = await axios.post(
`${serverUri}/api/user/signIn/${social}`,
{ code },
{ withCredentials: true },
);
```
## 몽고디비 collection을 조회 하지 못하는 문제
```javascript=
const GameTypeSchema = new mongoose.Schema({
name: { type: String },
image: { type: String },
rule: { type: String },
});
module.exports = mongoose.model('GameType', GameTypeSchema);
```
위와 같이 GameType 스키마를 만들고 DB에서 조회를 했다. DB는 미리 compass를 통해서 GameTypes라고 만들어놨었는데, 조회가 되지 않았다.
알고보니 mongoose에서 collection 이름을 모두 소문자로 간주해서 작업을 해서 다른 collection에서 조회를 하려고 해서 조회가 되지 않았던 것이었다.
## authRoute의 베스트 케이스
- 먼저 react-router의 라우팅 match 과정은 다음과 같다
- 라우터 컴포넌트의 path에 적어준 route와 일치하는 컴포넌트를 보여준다.
- 이때 exact속성을 넣어주면 정확히 일치하는 경우에만 해당 컴포넌트를 보여주게 된다.
- 라우터 컴포넌트를 <Switch></Switch> 로 감싸주면, 하위의 라우터 컴포넌트를 위에서 부터 읽으면서, 일치하는 하나의 컴포넌트만을 보여주게 된다.
react-router가 4.0으로 업데이트 되면서 라우터 컴포넌트 내부에 라우터 컴포넌트를 쓸 수 있게 되었고, 이를 코드 스플리팅에 사용한다.* 코드 스플리팅을 할 경우 페이지를 불러오는 방식이 통일되어야해서 이를 활용한다고 한다.
이번 프로젝트에서, 페이지를 라우팅 하기 전에, 로그인한 사용자인지 여부에 따라 라우팅을 다르게 해주는 것이 필요했다. 이를 위해 로그인이 필요한 페이지들을 하나의 라우터로 묶고, 해당 라우터에서 인증여부를 판단하여 리디렉션을 해주는 방식을 취했다.
- app.jsx
~~~
<Router>
<Switch>
<Route path="/login" component={LoginPage} />
<Route path="/callback" component={AuthCallback} />
<RouteIf path="*" />
</Switch>
</Router>
~~~
- RouteIf.jsx
~~~
<Route
exact={exact}
path={path}
render={() => {
if (authenticated) {
return (
<Router>
<Switch>
<Route exact path="/" component={Main} />
</Switch>
</Router>
);
}
return <Redirect to="/login" />;
}}
/>
~~~
이 경우 라우터안에 라우터를 또 넣는 부분이 부자연스럽다고 판단하여, 다른 방식으로 분리 하였다
- app.jsx
```
<Router>
<Switch>
<Route path="/signin" component={SigninPage} />
<Route path="/callback/:social" component={AuthCallbackPage} />
<Route path="/" component={MainPage} />
<AuthRoute path="/" component={MainPage} />
</Switch>
</Router>
```
- AuthRoute.jsx
```
const authCheck = async () => {
try {
await oauthAPI.authCheck();
setuthenticated(true);
} catch (error) {
history.push('/signin');
alert('인증 실패했습니다. 다시 시도해주세요');
}
};
useEffect(() => {
authCheck();
}, []);
return <Route exact={exact} path={path} component={authenticated && component} />;
}
```
AuthRoute에서 인증여부를 판단하고, 전달받은 컴포넌트를 인증여부에 따라 렌더링하도록 하였다.
변경 후가 코드 면에서 훨씬 깔끔하다고 본다.
###### tags: `trouble shooting`