SPA(single Page Application)에서 화면을 전환하는 Routing, 스타일링을 편하게 해주는 CSS 전처리기(Preprocessor)에 대하여..
📢 학습목표
1. SPA가 뭔지 설명할수있다
2. react-router-dom을 이용해 Routes Component를 구현할 수 있다
3. react-router-dom에서 Routing을 하는 방법 2가지와 차이점에 대해 설명할수있다
4. <Link> Component와 <a>tag 차이점에 대해 설명할수있다
5. css 전처리기의 역할에 대해 설명할 수 있다.
6. sass 에서 제공하는 문법을 이용하여 css파일을 scss파일로 변화할 수있다
페이지 수만큼 html 파일이 존재 - MPA
리액트가 spa는 아님 리액트는 그냥 뷰를 그려주는 라이브러리
리액트를 통해서 spa로 만들어줄수도 있고.. 등등 알아보자
한개의 웹페이지(html)안에서 여러개의 페이지를 보여주는 방법 -> Routing
MPA(Multiple Page Application)
주소에 해당하는 파일을 다시 받아와서 띄어주는것
index.html - default 페이지다.
main.html
login.html
이런식으로 하면 매번 페이지를 요청해서 받아와야한다.
라우팅이란 다른 경로에 따라 다른 화면을 보여주는 것이다.
리액트 자체에는 이런 기능이 내장돼있지 않다.
react : UI를 만들기위한 자바스크립트 라이브러리.
라우팅 기능을 사용하기 위해 다른것을 가져와써야한다.
-> third party library : sass, react router
react-router는 리액트 라우팅의 기능을 위해 가장 많이 사용되는 라이브러리.
여기서 다시한번 집고 넘어가는 프레임워크 vs 라이브러리
비유: 음식 만들 때를 가정하자
프레임워크 : 라면, 조리도구, 조리실 모두 제공 받음
라이브러리 : 가스버너만 딱 가지고와서(나머지것들과 조합해서 쓸 수있다)
CRA에 특별히 routing을 위한 로직이 없기 때문에, 가장 인기 있는 routing solution인 react-router를 추가해서 routing 을 구현해보자
3-1 react-router 설치
npm install react-router-dom --save
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';// 네임드 컴포넌트로 내보낸것을 리액트 라우터 돔으로부터 3개를 임포트 한다.
import Login from './pages/Login/Login'; // default로 export한걸 가져올때 Login은 아무이름으로 작성 가능
import { Login } from './pages/Login/Login'; // named로 export한걸 가져올 때 반드시 {}로 가져와야하고 닉네임을 {}안에서 지정해줄수 있다. -> { Login as Lo }
import Main from './pages/Main/Main';
class Routes extends React.Component{
render(){
return{
<Router>
<Switch>
<Route exact path="/" component={Login} /> // 기본경로 "/" : localhost:3000
<Route exact path="/main" component={Main} /> // localhost:3000/main
// * exact속성을 부여하지 않으면 처음에 마주치는 /로 그냥 인식해버림. </Switch>
</Router>
}
}
}
export default Routes;
import React from 'react';
import { Link } from 'react-router-dom';
// react-router-dom에는 많은 것들이 export돼있다.
class Login extends React.Component {
render(){
return {
<div>
<h1>Hello Login!</h1>;
<Link to="/main">Go to main</Link>
</div>
}
}
}
Babel 통해 Link 태그가 a태그로 변환된다.
(개발자도구를 보면 a 태그로 변환돼있음)
로직(조건)을 같이 구현할 수 있기 때문에,
SPA의 효율 UP!
MPA(multiple page application)에선 주소가 바뀌면 그 파일을 새로 다운 받아온다. 주소를 받아오고 새로운 파일을 다운 받는다.
a tag를 쓰면 많은 파일들을 전부 다시 다 다운 받아오게 된다.전체파일 다운로드 및 화면을 다시 그려주는 비효율적인 움직임 발생
-> 바뀔 부분만 바꾸기 위해 탄생한게 Link component
link를 이용하면 주소는 바뀌지만, 서버에 다시 요청을 보내서 새로운 파일을 받아오는 행위는 제외한 a 태그가 만들어진다.
즉 주소만바꾼다.
파일을 새로 다운받아 오지 않는다. react-router-dom에서 화면만 바꿔주는 행위를 함.
링크 컴포넌트를 이용한 SPA로 구현.
a 태그는 전체 파일을 다 받아와서 새로 그린다.
그럼 a 태그는 아예 안쓸까?
ㄴㄴ 아예 다른 싸이트로 넘어가는 경우
(ex. 어떤 웹사이트 footer부분에 인스타그램이 아이콘),
하지만!! 메인 페이지에서 어떤 한 제품을 클릭했을 때 메인페이지의 nav bar.
상단의 것은 새롭게 불러올 필요가 없다. 이때 Link 사용
// export 방법 2가지에 따라 import 방법이 달라짐
export default Login;
export { Login };
import React from 'react';
import Routes from './Routes";
ReactDOM.render(<Routes />, document.getElementById("root"));
Go to main
# 페이지 이동시키는 2가지 방법
## 1. Link 컴포넌트를 이용하는법
✅ 특징) 클릭시 바로 이동
ex) nav bar, aside menu
## 2. 함수 호출을 하는법
this.props.history.push()
특징) 로직 구현 가능 -> 조건 만족시 이동
ex) login button 클릭시,
- 백앤드 API로 데이터(User info) 전송
- User Data 인증/ 인가
- response message
- Case 1 : 회원 가입 되어 있는 사용자 > Main page로 이동
- Case 2 : 회원 가입 돼있지 않는 사용자 > Signup page로 이동
```js // Login.js
import React from 'react';
import { withRouter } from 'react-router-dom';
class Login extends React.Component {
goToMain = () => {
this.props.history.push('./main');
}
render() {
return {
<<div>
<button
className="loginBtn" onClick={this.goToMain}
// this는 그 해당 컴포넌트 안의 함수를 지칭함.
>
로그인
</button>
</div>
}
}
}
export default withRouter(Login);
라우터의 기능 Routes의 역할
```<Switch> 안에 있는 것들 중, 경로에 따라 각각에 맞는 컴포넌트를 보여달라는 의미```
어떤 화면을 보여줄지 바꿔 끼워주는것.
스위치 밖에 위치시키면 항상 보인다.(ex. Nav 바 같은것), 인스타나 유튜브 로고도 마찬가지
# this.props.history.push()
- <Link/> 를 사용하지 않고 함수 호출을 통해 페이지를 이동하는 방법
- goToMain 이라는 이벤트 핸들러에서 구현한것처럼 props객체의 history객체의 메서드를 통해(this.props.history.push())이동할 수 있다.
- console.log(this.props.history)를 해보면 match etc..
```js
import React from 'react';
import { withRouter } from 'react-router-dom';
class Nav extends React.Component{
goToLogin = () => {
this.props.history.push("/");
}
goToMain = () => {
this.props.history.push("/main");
}
render(){
return (
<div>
<button onClick={this.goToLogin}>Go To Login</button>
<button onClick={this.goToMain}>Go To Main</button>
</div>
)
}
}
export default withRouter(nav);
withRotuer 역할 : Routes로 연결 안돼있는 애들에게 props로
history, location, match 같은 애들을 전달해주는 역할
withRouter도 하나의 컴포넌트
컴포넌트를 감싸는 컴포넌트(HOC : Higher Order Component)
syntactically awesome style sheet
브라우저가 읽을수 있는 문서 파일 html
브라우저가 읽을수 있는 스타일 시트 css
css전처리기: 좀더 편리한 문법들로 우리가 편한데로 적고 그파일을 css로 변환해준다. 브라우저는 css만 읽을수있으므로. 브라우저가 읽기전에 처리해준다 해서 전처리기.
전처리기는 종류가 많고 그중에 하나가 sass.
npm install node-sass@4.14.1 --save
한뒤 취약점이 있다는 경고문이 뜬다. 호환이 잘 안되고 있다고. 이건 라이브러리 자체 문제기 때문에 우리가 어쩔수가 없다.
spa이기 때문에
로그인페이지에서 import scss한것이 import 하지도 않은 main 에서도 먹힌다ㅁOㅁ?!
만든 모든 scss가 하나의 html에 다 연결된다.이거 해결 하기 위해선?
sol) 뭐안에 잇는 뭐다. 라고 정확히 지칭 해준다.
scss할때 한가지 컨벤션
컴포넌트를 만들때 최상위 태그를 컴포넌트 이름의 클래스를 만든다.
import React from 'react';
import './Login.scss';
class Login extends React.Component{
render(){
return(
<div className="Login">
<h1 className="title">
Hello<span>Login</span>
</h1>
<button className="btn'>Hello</button>
</div>
);
}
}
export default Login;
.Login { // 최상위를 컴포넌트 이름 클래스로 감싸준다.-> 다른 컴포넌트안의 클래스네임이 겹치는 것을 막기위해
.title{
color : red;
span{
font-weight : 700;
}
}
}
import React from 'react';
class Main extends React.Component{
render(){
return(
<div className="Main"> // 해당하는 컴포넌트의 최상위 요소의 클래스네임을 컴포넌트 이름과 똑같이 한다.
<h1 className="title">Hello Main</h1>
</div>
);
}
}
export default Main;
자주 쓰는것들 모아두는 거.
ex)
@mixin flex-center {
display: flex;
justify-content : center;
align-items : center;
}
위의 것을 사용할 때
@include flex-center; <- 위의것이 1줄로 적용됨
nesting과 & 함꼐 쓸 수 있다
ex)
button {
width : 200px;
height : 200px;
background-color : red;
}
button:hover{
background-color : red;
cursor:pointer;
}
아래처럼
button {
width : 200px;
height : 200px;
background-color : red;
&:hover {
background-color : red;
cursor:pointer;
}
}