정말 바쁘게 1주차를 보냈다. 첫 주를 보내면서 너무 재밌다고 느꼈다. 이렇게 하루종일 코드를 어떻게 작성해야 될 지에 대해 고민했던 적이 그동안 없었고, 코드를 작성하는 것이 이렇게 재밌게 느껴진 적도 없었다.
아직 로그인이랑, 작은 에디터 프로토타입만 만들었는데, 다른 사람들에게 보여질 수도 있다는 생각이 드니까 "코드를 이렇게 쓰는게 맞을까?" 라는 고민이 더 해지는 것 같다. 그리고 조금 더 꼼꼼하게 코드를 확인하게 된다.
한 주간 가장 기억에 남는 것은 첫 째로 기획 단계를 간과하고 넘어간다는 것이었다. 나도 "당연히 노션 만드는 거겠지?" 라는 생각에 기획부분은 작성하지 않고, 어떻게 프론트와 백을 구성했는지에 대해서만 README에 적었었는데, 이후에는 이 부분을 개선해야겠다는 생각이 들었다. 기획이 선행되어야, 기술적인 요구사항들을 확인할 수 있고, 여기서 기간을 산출할 수 있다. 기획 - 기술적인 요구사항 - 프로젝트 진행 의 단계를 지켜가면서 프로젝트를 진행하는 연습을 이번 기회를 통해 할 수 있어서 좋았다.
두 번째로는 의사소통의 중요성이다. 민태님도 (아마도 의사소통의 중요성을 두 번째 시간에 말씀하시기 위해 첫 날 구체적으로 설명하지 않으신 것 같다.) 우리가 `당연히 이렇게 해오겠지?` 하고 구체적으로 말씀을 하지 않으셨고, 나도 "이렇게 하는게 맞나요?" 하고 질문하지 않았다. 이해가 되지 않거나 모호한 부분은 꼭 질문을 하고 넘어가는 자세의 중요성을 이번에 느끼게 되었고, 그동안 제대로 이해하지 못했는데 이해했던 척을 해왔던 것을 반성하게 되었다.
세 번째로는 프론트와 백엔드 부분의 리포를 분리하는 것이다. 프론트와 백의 배포 주기가 같으면 좋겠지만, 다른 경우가 대부분이다. 백엔드만 수정해서 배포하고, 프론트엔드만 수정해서 배포하는 상황을 위해서 둘을 분리하는 것이 좋다.
네 번째로는 어떤 선택에도 이유가 있어야 한다는 점이었다. 내가 마크다운 파서를 선택했던 것에 대한 이유가 조금 부족하지 않았나 라는 생각이 들었다.
추가로, CRA와 같은 툴은 오버 엔지니어링일 수 있다는 설명이 굉장히 흥미로웠다. 하지만 아직 webpack을 사용해 빌드하는 것에 어려움이 있어서, 이번 프로젝트는 CRA로 진행해야 할 것 같다. 이번 주말에 webpack을 사용해서 리액트를 실행하고, 로그인을 추가하려고 해봤는데, 내가 발견한 내용으로는 html-webpack-plugin
과 react-router-dom
의 페이지 이동을 같이 사용할 때 에러가 발생했다. 아직 이에 대한 해결 방법을 찾지 못해서, webpack에 대한 공부는 일단 미뤘는데 이번에 누군가가 포크해서 진행을 했다면, 유심히 살펴봐야겠다.
1주차 (06.01 ~ 06.07)
초기 세팅
React - Typescript 사용해 프론트 세팅했습니다.
백엔드는 여기에서 확인할 수 있습니다. (프론트엔드와 백엔드의 개발 및 배포 사이클이 다르기 때문에 분리해서 진행하는 것이 더 좋을 수 있습니다.)
create-react-app
을 사용해 프론트엔드를 구성했습니다. webpack을 사용해 직접 구성하려 했지만, react-router-dom
과 react-google-login
을 같이 사용할 때 발생하는 에러를 아직 해결하지 못해, 이렇게 사용하려 합니다.
npx create-react-app . --template typescript
마크다운 파서
codesandbox에 에디터 프로토타입을 만들었습니다.
둘 모두 완전한 커스터마이징을 제공하고, 다양한 플러그인이 존재합니다. typescript 지원 면에서는 draft-js 가 더 잘 되어 있다는 생각이 들었습니다. 하지만 키다운을 사용해 기능을 추가하는 slate-js의 사용법이 저에게 더 편리하게 느껴졌고, 별도의 플러그인을 사용하지 않아도 다양한 마크다운 기능을 추가할 수 있을 것 같다는 판단이 들어서 slate-js를 사용하여 진행할 예정입니다.
OAuth 2.0 적용
구글 로그인과 네이버 로그인 기능을 추가했습니다. 구글 로그인은 react-google-login
을 사용해 여기서 지원하는 컴포넌트를 이용해서 쉽게 구현했습니다. 네이버 로그인의 경우는 javascriptSDK를 추가해서 구현했습니다.
네이버 로그인의 특이한 점은 프론트쪽에서 유저 정보를 요청하면 에러 메시지를 보냅니다. 프론트 단에서는 access token만 받을 수 있고, 이를 백엔드로 전달하고, 백엔드에서 access token을 사용해 네이버에 유저 정보를 요청하고, 이를 다시 프론트로 보내는 과정을 통해 로그인을 진행했습니다.
Typescript를 사용해 네이버에서 access token을 받을 때, window.naver.loginWithnaverId(...)
를 사용할 경우 에러가 발생합니다. window 객체에 naver가 없다는 에러가 발생하는데, 이는 아래와 같이 비구조화 할당을 통해 에러를 피했습니다.
const {naver} = window as any
구글 로그인
구글 로그인을 추가하는 방법은 간단합니다. 일단 react-google-login
패키지를 설치한 후 아래와 같이 이용합니다.
import GoogleLogin from 'react-google-login';
const GoogleLoginButton: React.FC = (props: any) {
...
return (
<GoogleLogin
clientId={googleApiKey}
onSuccess={googleLoginSuccess}
onFailure={googleLoginFailure}
cookiePoliy={'single_host_origin'}
/>
)
}
만들어진 버튼을 클릭하면, 구글 로그인 창이 나타나고, 구글 로그인을 진행하면 유저의 정보를 가져올 수 있습니다.
- clientId: 구글 로그인을 사용하기 위해 구글 api에서 애플리케이션을 등록하고 발급받은 키를 입력합니다.
- onSucess: 로그인에 성공했을 때 실행할 콜백 함수를 넣습니다.
- onFailure: 로그인에 실패했을 때 실행할 콜백 함수를 넣습니다.
네이버 로그인
네이버 로그인을 사용하기 위해, 일단 index.html
파일에 아래의 태그를 추가합니다.
<script type="text/javascript" src="https://static.nid.naver.com/js/naveridlogin_js_sdk_2.0.0.js" charset="utf-8"></script>
Typescript에서 window.naver
를 사용하기 위해서 비구조화 할당을 사용합니다.
import React, {useEffect} from 'react'
const {naver} = window as any;
const NaverLoginButton: React.FC = () => {
const initializeNaverLogin = () => {
const naverLogin = new naver.LoginWithNaverId({
clientId: '네이버 developer에서 발급받은 키',
callbackUrl: '이동할 Url',
isPopup: true, // 팝업을 열 것인지, 현재 페이지에서 진행할 것인지
loginButton: {color: 'green', type: 3, height: '43'} // 네이버 로그인 버튼 디자인 선택
});
naverLogin.init();
useEffect(() => {
initializeNaverLogin();
}, []);
return (
<div id="naverIdLogin" /> // id 입력 필수
)
}
주의해야 할 점은 컴포넌트가 반환하는 div에 id를 꼭 naverIdLogin으로 해주어야 하는 점입니다. loginButton에서 선택한 디자인이 여기에 적용됩니다.
그리고 위의 과정을 통해 유저의 정보를 가져오지는 못하고, access token만 발급 받을 수 있습니다. access token의 정보는 callbakUrl에 get 파라미터로 전달됩니다.
그래서 해당 위치에서 받은 access token을 서버로 전달하고, 서버에서는 이를 사용해 유저의 정보를 요청한 후, 다시 프론트에게 전달해 줍니다.