ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] 리액트 프로젝트 사용 기술 정리
    기타/FE 2020. 6. 9. 15:57
    반응형

    React 프로젝트

     

    사용한 기술 라이브러리

     

    생겼던 문제들

    이미지 용량 nginx

    이모티콘 utf 처리

    timezone

     

    0. 기본 레이아웃 및 큰 컴포넌트 

    index/Root/App에서 Login or Dashboard로

     

    0-1. React-router-dom 

    // Root.js
    import {BrowserRouter} from “ React-router-dom “
    
            <BrowserRouter>
                <App/>
            </BrowserRouter>
    
    

     

    Q) 이렇게 이유 +  react-router-dom이란? react, react-dom, reat-router-dom

    Q) 컴포넌트란 ??리액트란??

    Q) 리액트 기본 구조 이해하기

    Class hello extend Component{
    
    render(){
    
    return();
    
    }
    
    }
    
    export default hello

     

    0-2. axios.defaults.baseURL='http://localhost:8080';

    baseURL 제일 밖으로 빼놓음

     

    0-3. index.js에서

    serviceWorker.unregister();

    이걸 resgister로 하면 서버 캐시 지워서 새로 들어갈때까지 이전 프로젝트 변경 전 모습으로 남아있음

    Q) servicework - register, unregister란?

     

    1. 로그인 컴포넌트 ( 대시보드 밖/ 안 따로 )

    대시보드 밖 ( 로그인 전, storage에 token없음)

    sign/Login

    ----/Logout

    Q) sessionstorage, localstorage란? 나는 왜 토큰 session에 했지..?

    Q) event.preventDefault()란?

     

    이메일, 비밀번호 입력받아서 event.target.[name].value 에 따라서 focus()해주거나 검사하거나 ,, 로그인해주거나 함

    axios.post로 formdata에 email, password값 보내고 token얻어와 sessionstorage에 저장하고 url /로 보내줌

    Q)axios란? .then .catch란?

    Q)this.props.history.push란?

    Q)error.response status ,, 

     

    sign/PasswordUpd

    ----/signup

    ----/userList

    ----/CheckAuth

    ----/info

    ----/infoUpd

    회원가입은 pw.match(정규식)이렇게 양식 비교해보고 중복확인은 버튼 누르면 check api보내는식으로 함

    Q) react에 onchange, onclick, => handlechange, handleclick 바닐라자바스크립트로도 생각해보기

     

     

    2. 관리자페이지 Dashboard

     

    2.1 토큰검증

    axios.interceptors.request.use(
      config => {
          if(config.url.match("dapi.kakao.com")){
            config.headers['Authorization'] = 'KakaoAK ';
          }
          else{
          const token = window.sessionStorage.getItem("jwtToken");
          if (token) {
              config.headers['Authorization'] = 'Bearer ' + token;
          }
          }
          return config;
      },
      error => {
          Promise.reject(error)
      });
    
    
    //Add a response interceptor
      if(window.location.pathname!=="/user/login"){
    axios.interceptors.response.use((response) => {
      return response
    }, function (error) {
      if(error.response.status===404||error.response.status===500||error.response.status===409)return Promise.reject(error);
      console.log(error.response);
      if(error.response.status===403){
    
        if(window.sessionStorage.getItem("jwtToken")!==null)
        message.warning("토큰이 만료되어 로그아웃 됩니다");
      
      window.sessionStorage.removeItem("jwtToken");
      this.props.history.push('/user/login');
      return Promise.reject(error);
      
      }
    });
    }

    axios.interceptors.request.use 를 이용해서 jw 토큰 넣어줬음

    Q) 이 인터셉터 request, response 알아보기 

     

    2.2 eventListenr

        window.addEventListener('resize', this.windowSize);
        
          windowSize=e=>{
      //화면 확대할때 side bar접히게
        if(Math.round(window.devicePixelRatio * 100)>300){
          this.setState({
            collapsed:true,
          })
        }
        else if(window.screen.width<=500){
          this.setState({
            collapsed:true,
          })
        }
        else{
          this.setState({
            collapsed:false,
          })
        }
      }

    윈도우 사이즈 resize 될때 window.devicePixelRatio 또는 window.screen.width로 가로길이 잼

     

    2.3. 코드 리뷰 받고싶은부분 ? 

        if(this.props.location.pathname.match("/web/notice")){
          this.setState({
            openKeys:['sub4'],
            defaultKeys:['6'],
          })
        }
        if(this.props.location.pathname.match("/wefl/user")){
          this.setState({
            openKeys:['7'],
            defaultKeys:['7'],
          })
        }

    네브바에 색이 칠해지는데 그게 새로고침을하고나면 초기화돼서 그거 지정해주려고 componentdidmount될때 url보고 지정해줬었음

    이게 맞는건가!

     

    그리고 원래는 뭐 location.어쩌고 바뀐거 적용했는데

    componentDidUpdate(prevProps, prevState) {
        const location = this.props.history.location;
        const accessToken=window.sessionStorage.getItem("jwtToken");
        
        if(prevProps!==this.props) {
    
    
          if(location.pathname.match("store")){
            this.setState({
              openKeys:['1'],
              defaultKeys:['1'],
            })
          }
    
    
          if(location.pathname==="/user/info"){
            this.setState({
              openKeys:['sub5'],
              defaultKeys:['8'],
            })}  
    }}

    componentDidupdate로 prevProps와 지금의 상태를 비교해서 다를때만 바꿔줄수있었음

    Q) react life cycle?

    ㅇㅇ

     

                     <Switch>
                     <Route exact path="/" component={this.state.isExpired?Logout:Main}/>
                     <Route exact path={["/store/list/","/store/list/:page","/store/insert","/store/update/:sid"]} component={this.state.isExpired?Logout:ManageStore} />
             
                     <Route exact path={["/store/detail/:sid","/store/payment/:sid" ,"/store/data/:sid","/store/webpage/:sid"
                                         ,"/store/log/:sid"]} component={this.state.isExpired?Logout:StoreDetail} />
                     <Route exact path={["/web/notice","/web/notice/insert","/web/notice/update/:id","/web/notice/detail/:id"]} component={this.state.isExpired?Logout:WebsiteManage} />
                     <Route exact path={["/wefl/user"]} component={this.state.isExpired?Logout:WeflUser}/>
                     
                     <Route exact path={["/user","/user/info","/user/list"]} component={this.state.isExpired?Logout:Admin}/>
                     <Route exact path={["/check/wait/:page","/check/new/:page","/check/return/:page"]}component={this.state.isExpired?Logout:Check}/>
                     <Route exact path={["/check/detail/:status/:sid","/check/webpage/:status/:sid","/check/log/:status/:sid"]} component={this.state.isExpired?Logout:Detail}/>
                     
                     <Route exact path={["/store/error","/check/error"]} component={this.state.isExpired?Logout:StoreError}/>
                     <Route component={this.state.isExpired?Logout:NotFound}/>
                     </Switch>
              

     

     

    2.4 

    breadcrumb 

     

        const pathSnippets = window.location.pathname.split("/").filter(i => i);
            const extraBreadcrumbItems = pathSnippets.map((_, index) => {
              const url = `/${pathSnippets.slice(0, index + 1).join("/")}`;
              return (
                <Breadcrumb.Item key={url}>
                  {breadcrumbNameMap[url]}
                </Breadcrumb.Item>
              );
            });
            const breadcrumbItems = [
              <Breadcrumb.Item key="main">
                <Link to="/">위플</Link>
              </Breadcrumb.Item>
            ].concat(extraBreadcrumbItems);

     

    2.5

    페이징 처리

    totalsize, pagecount, 

    검색하고 삭제하는데 만약에 1페이지가 아닌 상태면 문제생기니깐 다 관리해줬음

    다음매장잉 없으면 이전매장을 얻어온다음 그 이전매장의 페이지번호

    if(res.data%this.state.pageSize===0) page = res.data/this.state.pageSize;

    else page=Math.floor(res.data/this.state.pageSize)+1;

    얻어오고 다음매장이 있으면 다음매장의 페이지번호얻어왔음

     

    this.unlisten = this.props.history.listen((location, action) => {

    원래 didupate하기전엔 이랬음

     

    Q)queryString.parse location의 search랑 hash 차이

     

     

    2.6. insert

    처음엔 insertStore component불러와서 매장 정보 입력받고 그당므엔 insertWeb불러왔음

    뒤로가도 남아있게 , 뒤로간다음 다시 돌아왔을때 남아있게 처리해주느게 어려웠음.

     

     

    2.7 webpage hash

        componentDidUpdate(prevProps,prevState){
            if(prevProps!==this.props){
                const anchor = this.props.history.location.hash.split('?')[0].split('#')[1];
                if(anchor!==undefined&&anchor!==""){
                const offset = document.getElementById(anchor).offsetTop;
                window.scrollTo(0,offset-100);
                }
        
        
                const query = queryString.parse(this.props.history.location.hash.split('?')[1]);
                if(query.key!==undefined){
                    this.setState({
                        searchKey:query.key,
                        searchValue:query.value,
                    })
                }
            }
        }

     

     

     

    ----

    예전에 적어둔거 발견해서 붙여넣는다..

     

    - 바벨
     : 바벨은 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 코드 자체를 변환시킨다.
    
    
    
    - create-react-app
    :페이스북은 쉽게 리액트 프로젝트를 셋업하고 바로 개발에만 집중할 수 있도록 도구를 만들었는데 그게 create-react-app이다.   
    npm install create-react-app으로 설치할 수 있다.  
     (yarn을 쓰는 사람들은 yarn을 써도 된다. yarn은 npm과 같이 자바스크립트 패키지 매니저다.  
     npm이 가진 이슈들을 해결하기 위해 페이스북, 구글 등이 힘을 합쳐 만든 새로운 자바스크립트 패키지 매니저다.)  
     create-react-app을 사용하면 
     ‘create-react-app my_project’와 같이 순식간이 리액트로 된 페이지를 띄울 수 있는 구조가 만들어진다.
    
     
    - 리액트 초반 필수 설치 라이브러리  
    react: 리액트를 사용하려면 당연히 리액트 라이브러리가 필요하지 않겠는가?  
    react-dom: 원래는 react에 함께 있었으나 이렇게 따로 떨어져 나왔다.   
    react와 DOM 사이에 연결해주는 역할을 한다.  
    react-scripts: 리액트 프로젝트 초기 셋업을 하는 것은 힘든 일이다. 그걸 보다 쉽고 간편하게 해준다.  
    babel-cli: 바벨을 터미널에서 사용하기 위해 필요하다. 바벨을 왜 쓰는지는 위에서 설명했다.  
    babel-preset-env: 바벨은 babel-preset-es2017과 같이 여러 버전이 있다. 딴거 말고 이거 깔면 알아서 해준다.  
    babel-preset-react: 바벨을 리액트에서 사용하게 해준다  . 우리는 리액트를 쓸거니까 이게 필요하다. 달리 말하면 바벨과 리액트는 별개 프로젝트다.  
    webpack: 웹팩을 쓰기 위해 필요하다.  
    babel-core: 웹팩용 바벨(?)이다. 터미널에서 쓸 때 babel-cli를 썼는데 이걸 웹팩에서 사용하는 용도다.  
    babel-loader: 웹팩에서 바벨을 로드할 때 이 로더를 쓴다.
    
    
    
    @ cors 오류  
    - import react
    파일에서 JSX 를 사용하려면, 꼭 React 를 import 해주어야 합니다. ( import 를 하는 것은, 우리가 webpack 을 사용하기에 가능한 작업입니다. )
    
    
     ---
    
    index.js에 
    ReactDOM.render(<App />, document.getElementById('root'));
    DOM id가 root인애를 public/index.html에서 찾아서 거기에다가 App을 그리도록 하는거
    
    ```
    import React ,{Component} from 'react';
    
    class App extends Component {
      render(){ //클래스 형태의 컴포넌트에는 꼭 render함수가 있어야함
        return (  //그 내부에서는 jsx리턴
          <div>
            hello my name is kangjisu
          </div>
      );
    }
    }
    
    export default App; //우리가 작성한 컴포넌트를 다른 곳에서 불러와 사용할 수 있도록 내보내기
    
    
    ```
    
    -두개이상의 엘리먼트는 무조건 하나의 엘리먼트로 감싸져있어야함.
    =>이때 Fragment 사용 (import {Fragment} from 'react'해주어야함)
    
    ```
    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        const name = 'react';
        return (
          <div>
            hello {name}!
          </div>
        );
      }
    }
    
    export default App;
    ```
    값을 바꿔줘야할땐 let, 고정되면 const
    
    
    ```
    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        const value = 1;
        return (
          <div>
            {
              (() => {
    		  if (value === 1) return (<div>하나</div>);
    		  if (value === 2) return (<div>둘</div>);
    		  if (value === 3) return (<div>셋</div>);
    		  })() // 화살표함수. this,arguments,supe개념이 없는 익명함수
    		  
            }
          </div>
        );
      }
    }
    
    export default App;
    ```
    
    {/* */} 주석은이렇게
    
     # 4편 :: props 와 state
     props 는 부모 컴포넌트가 자식 컴포넌트에게 주는 값. 자식컴포넌트에서는 props를 받아오기만 하고 수정할 수 없음
     state 는 컴포넌트 내부에서 선언하며 내부에서 값 변경 가능
     
     #5편
     componentDidMount() {
      // 외부 라이브러리 연동: D3, masonry, etc
      // 컴포넌트에서 필요한 데이터 요청: Ajax, GraphQL, etc
      // DOM 에 관련된 작업: 스크롤 설정, 크기 읽어오기 등
    }
    컴포넌트가 화면에 나타나게 됐을때 호출 , 필요데이터 요청위해 axios,fetch등을 통하여 ajax요청이나 돔 속성 읽거나 변경하는 작업 진행
    
    
     #7편 배열다루기
    리액트애서는 state 내부의 값을 직접적으로 수정하면 절대로 안됩니다. 이를 불변성 유지라고 하는데요, push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않습니다. 
    그 대신에, 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야합니다. 
    
    
    용어
    -파싱
    0렌더링
    
    ---
    
    공부순서
    팁탭토->https://velopert.com/3480->https://velopert.com/3486
    
    
    
     ---
    
     AWS, ec2 , nginx 공부 (날개의 노트 사이트 https://wingsnote.com/ 참고)
    
     - EC2 : 가상의 컴퓨터(ex:서버) 만들고 관리하는 서비스
     - 인스턴스 : EC2에서 만드는 가상의 컴퓨터 하나 ( 실제 컴퓨터의 OS가 아닌 EC2에서 지원해주는 OS사용)
     	- 인스턴스 타입 : 사양을 의미
     - AMI : 미리 만들어둔 아마존 가상 머신의 이미지
     	- AWS는 EC2인스턴스를 만들때 완전 빈 가상 컴퓨터가 아닌 최소한 이미 만들어진 OS가 설치돼있는 이미지 설치
    	 MyAMIs : 유저가 만든거
     - 가상화 타입 (HVM vs Paravirtualization)
     	- HVM : 안정성 HIGH 성능 LOW
    	 Paravirtualization : 안정성 LOW 성능 HIGH // 두개 비교해서 상대적으로 보면 이렇다는느낌~
     - 인스턴스 스토리지 : cdrive느낌 (휘발성이므로 ami,스냅샷 만들어줘야 안날라감)
     - EBS : 외장 HDD느낌 .지워지면 안되는 데이터들은 이거로 보통. (micro는 ebs)
    
     - EC2인스턴스는 보안을 위해 id/pw가 아닌 key 파일을 이용해 접속한다. -> ---.pem파일 (노출안되게 조심!!)
    
     - SSH: secure shell protocol  
    	:컴퓨터가 public network를 통해 통신할 때 보안상 안전하게 해주는 protocol
    
     - NGINX : 경량 웹서버 (아파치같은거.. 아파치는 프로세스와 쓰레드 기반, NGINX는 비동기이벤트방식으로 요청 처리 )  
    	: 모바일 서비스 쪽에 많이 쓰임
    
     - EC2 인스턴스 보안 그룹 설정 : 기본 SSH접근은 22. 웹 브라우저 가능하려면 HTTP 포트 80 설정 해주어야함

    '기타 > FE' 카테고리의 다른 글

    [React] 서머코딩 3주차 Context/Hook/mock-server  (0) 2020.07.20

    댓글

Designed by Tistory.