이번 주에는 state와 props, router 를 이용하여 리액트에서 페이지를 이동하는 방법을 배우고,
fetch를 이용하여 직접 api 와 통신하는 실습을 하였다.
그리고 협업을 할 때 초기세팅을 하고, 클론하고 git 을 사용하는 방법까지 다시 한번 실습할 수 있었다.
여러명이 함께 작업하는 것이 처음이었기 때문에 처음에는 초기셋팅에도 많은 시행착오가 있었다.
먼저는 한명이 cra 를 생성하고 router, sass 까지 설치한 뒤
각자 작업하기 편하게끔 각자의 폴더/페이지 별로 구분을 해두고(우리조는 3명이라 JIA/GH/NW 로 파일명/폴더명을 구분하였다)
Routes.js 파일에 하기와 같이 엔드포인트를 넣어 페이지 이동이 가능하게끔 셋팅해둔다.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Switch,
} from 'react-router-dom';
import Login_JIA from './Pages/JIA/Login_JIA/Login_JIA';
import Main_JIA from './Pages/JIA/Main_JIA/Main_JIA';
import SignUp_JIA from './Pages/JIA/SignUp_JIA/SignUp_JIA';
import Login_GH from './Pages/GH/Login_GH/Login_GH';
import Main_GH from './Pages/GH/Main_GH/Main_GH';
import SignUp_GH from './Pages/GH/SignUp_GH/SignUp_GH';
import Login_NW from './Pages/NW/Login_NW/Login_NW';
import Main_NW from './Pages/NW/Main_NW/Main_NW';
import SignUp_NW from './Pages/NW/SignUp_NW/SignUp_NW';
class Routes extends React.Component {
render() {
return (
<Router>
<Switch>
<Route exact path="/" component={Login_JIA} />
<Route exact path="/main_jia" component={Main_JIA} />
<Route exact path="/signup_jia" component={SignUp_JIA} />
<Route exact path="/gh" component={Login_GH} />
<Route exact path="/main_gh" component={Main_GH} />
<Route exact path="/signup_gh" component={SignUp_GH} />
<Route exact path="/nw" component={Login_NW} />
<Route exact path="/main_nw" component={Main_NW} />
<Route exact path="/signup_nw" component={SignUp_NW} />
</Switch>
</Router>
)
}
}
export default Routes;
이미지 파일도 각각 구분해서 넣어준 뒤, 경로지정을 다시 해 주어야 했었다.
(url 로 이미지 경로를 저장해 주는 것이 더 편할 것이라는 생각이 들었다)
여러명의 작업 내역을 합치는 과정에서 다른 사람의 scss 가 내 js 파일에 적용이 되는 문제가 발생했었는데,
이는 js 파일 내의 최상위 태그의 class 명이 같아서 생긴 문제였다.
이를 통해서 최상위 div 의 클래스명을 컴포넌트의 이름과 같이 하는 것이 좋다고 했던 이유를 알게 되었다
(이렇게 div className="Login-jia"를 해 주니 적절한 scss가 제대로 적용 되었다. scss 내의 클래스명도 함께 변경)
render() {
return (
<div className="Login-jia">
<main>
<article className="bothside">
<div className="login-page">
<div className="left-side">
<img src={phone} alt="phone-img" />
</div>
<div className="right-side">
<div className="login-box">
<h1>
<img
className="insta-logo"
src={logo}
alt="instagram-logo"
가입하기 글씨를 누르면 사인업 페이지로 이동하게 하는 link는 원래 작성했던 a 태그와 동일한 역할을 한다.
<p>
계정이 없으신가요?{" "}
<Link to="/signup_jia" className="link-to-sign">
가입하기
</Link>
</p>
처음에 위와 같이 js 파일 내에 작성만 하고 적용이 되지 않아 문제가 무엇인지 살펴 보았는데
알고보니 import 를 써주지 않아 생긴 문제였다... 다음부터는 빼먹지 말아야지
import { Link } from 'react-router-dom';
class Login_JIA extends Component {
state = {
loginById: "",
loginByPw: "",
btState: true,
};
typeId = (e) => {
this.setState({
loginById: e.target.value,
});
};
typePw = (e) => {
this.setState({
loginByPw: e.target.value,
});
};
//id 와 비밀번호 창에 onkeyup 이벤트가 일어날 때 key값을 지정하여 입력된 value 를 state에 담아준다.
informationHandler = () => {
if (
this.state.loginById.includes("@") &&
this.state.loginByPw.length >= 4
) {
this.setState({ btState: false });
} else {
this.setState({ btState: true });
}
};
//입력된 아이디에 @가 포함되어 있고,
//입력된 pw의 길이가 4자 이상일 경우 적용되는 클래스가 변경되면서 로그인 버튼의 색깔이 변경된다.
<div className="user-login">
<input onChange={this.typeId} onKeyUp={this.informationHandler} className="login-by-id"
type="text"placeholder="전화번호, 사용자 이름 또는 이메일"/>
<input onChange={this.typePw} onKeyUp={this.informationHandler} className="type-password"
type="password" placeholder="비밀번호" />
<button className={this.state.btState ? "login-bt" : "login-bt-login"}
//삼항연산자 : true 일 경우 앞부분이 실행되고, false 일 경우 뒷부분이 실행된다.
onClick={this.clickEvent} type="submit">로그인 </button>
fetch 함수를 사용해서 api 와 통신을 해본다.
<회원가입>
fetch("http://10.58.4.172:8000/account/signup", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
//fetch 함수가 실행되면 첫번째 인자로 백엔드로부터 받은 url 주소를 넣어준다.
//내가 작성한 내용을 서버에 전달하는 것이므로 method는 post이다.
//적어주지 않을 경우 default 는 get이므로 post를 할 경우에는 꼭 적어줘야 한다.
//헤더에 들어가는 application/json 은 body가 json 형식이라는 내용이며 생략 가능하다.
body: JSON.stringify({
'email' : this.state.SignUpEmail,
'name' : this.state.SignUpName,
'nick_name' : this.state.SignUpNick,
'password' : this.state.SignUpPw
})
})
//body에 들어가는 JSON/stringify는 아래의 내용들을 json 형식으로 변환하겠다는 의미이며
//백엔드 쪽과 맞추어놓은 key 와 state에 저장된 value 값을 넘겨준다.
.then(response => response.json())
//응답이 오면 json 형태로 온 응답을 js형태로 변환하겠다는 의미
//이 부분에 console.log를 넣어 확인하게 되면 다음에 오는 코드들이 실행이 멈춰버리므로 주의한다.
.then(response =>
{if (response.message=="SUCCESS") {
alert("회원가입에 성공하였습니다 로그인을 해주세요");
//resopnese의 message 키의 값이 백엔드가 정해놓은 대로 success일 경우, 메인 로그인 페이지로 이동한다.
//만약 resopnse.status==200이나 reponse.ok 과 같이 코드값으로 확인하고 싶은 경우에는
//response를 js 형태로 변환하지 않고 json형태에서 바로 실행해야 한다.
this.props.history.push("/");
} else {
alert("중복된 회원정보가 있습니다.");
this.props.history.push("/signup_jia")
//아닐 경우, 알림창을 띄워주고 회원가입 창을 리로드 한다.
}
}
)
<로그인>
clickEvent = () => {
console.log(this.state.loginById);
console.log(this.state.loginBy);
fetch("http://10.58.7.154:8000/accounts/signin", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
//fetch 함수의 첫번째 인자로 통신할 주소를 백엔드로부터 받아서 넣는다.
//마찬가지로 정보를 서버에 보내는 것이므로 post method를 사용한다.
body: JSON.stringify({
'email': this.state.loginById,
'password': this.state.loginByPw,
})
})
.then(response => response.json())
.then(response => {
//로그인의 경우 서버쪽에 저장된 회원아이디/비밀번호가 일치할 경우 서버에서 토큰을 발행하여 보내주게 된다.
if (response.token) {
console.log(response);
localStorage.setItem("wtw-token", response.token);
//토큰이 오는 경우 로컬스토리지에 토큰을 저장하게 되는데 앞부분은 임의로 지정한 토큰의 키 값이다.
this.props.history.push("/main_jia");
//토큰을 저장한 후 메인페이지로 이동하게 된다.
} else if (!response.token) {
alert("올바른 회원이 아닙니다");
this.props.history.push("/signup_jia");
//토큰이 오지않는 경우=회원정보가 다른 경우 이므로 알림을 띄워주고 회원가입창으로 이동한다.
}
});
};
이번 주에는 처음으로 git 과 github를 자주 사용할 수 밖에 없게 되었는데, 그동안 막연하게 두렵게 생각했던 git과 조금 더 친숙해 질 수 있었던 좋은 기회였다.
먼저는 git clone을 한 후에 보니 gitignore 때문에 node_modules 파일이 없어 이를 강제로 옮기는 시행착오를 겪었는데
알고보니 git clone을 한 뒤, npm install 을 해 주면 node modules 와 필요한 패키지들까지 쉽게 설치가 된다는 것을 알고 허탈해졌다..
다음부터는 무조건 git clone 뒤에는 npm install
그리고 같은 조원의 크롬에 문제가 있어 내 크롬에서 확인을 해 보느라, 다른분의 작업중인 js 파일을 건드리게 되었는데
나중에 git push를 하려고 보니 conflict 가 나면 어쩌나 하는 걱정이 되어 구글링을 해보니 git add -p라는 아주 편리한 기능이 있었다.
git add .처럼 모두 add 를 하기에 위험성이 있을 때 git add -p 를 해주면 그동안 modified 한 내용들을 하나하나 확인해 보면서 add 할지말지를 결정할 수 있다.
그래서 내 파일들만 안전하게 push 할 수 있었다.
계속해서 commit 메세지 작성과 pull request 템플릿 작성을 구체적으로, 성의껏 할 것을 강조하셨는데
귀찮게 여겨질 수도 있지만 나만을 위해서가 아니라 다른 사람이 알아보기 쉽도록 작성할 수 있는 습관을 들이는 것이 중요할 것 같다.
어렵게 생각했던 기능들을 직접 구현해 보고 초기세팅과 git과 조금 더 친해진 것에 대해 개인적으로 큰 의미를 두고 싶었다.
실제로 api 와 통신해서 토큰이 콘솔에 찍히는 것을 보고 백엔드 조원분과 이게 정말 된다며 뿌듯함을 느꼈던 순간을 잊지 못할 것 같다.