본문 바로가기
Study/FrontEnd

React(3)

by 왕방개 2024. 1. 31.

**CSR - 클라이언트 사이드 랜더링: 서버와 클라이언트 애플리케이션을 따로 구현

1.node 기반의 프로젝트를 clone 한 후 사용하는 방법


1) git에서 clone

2)필요한 패키지 설치
npm install
*강제 설치
npm install --save --legacy-peer-deps@material-ui/core
npm install --save --legacy-peer-deps@material-ui/icons

3)실행
yarn start

 

2.삭제 구현

1) 삭제 아이콘 구현
=>mui.com활용

https://mui.com/material-ui/material-icons/

 

import React from "react"
import {
    ListItem,
    ListItemText,
    InputBase,
    Checkbox,
    ListItemSecondaryAction,
    IconButton
} from "@material-ui/core"

import DeleteOutlined from "@material-ui/icons/DeleteOutlined"

//react 에서 컴포넌트 클래스를 만들기 위해 Component로부터 상속받기

class ToDo extends React.Component {
  //생성자
  constructor(props){
    super(props); //상위 클래스에서 넘겨준 모든 props를 현재클래스에 저장
    //state 생성
    //item 이라는 이름으로 props 중에서 item 이라는 값을 state로 저장
    //props은 상위 component 에서 전달한 data라 읽기만 가능
    //수정이나 삭제를 하고자 하는 경우는 state 로 변환해야함.
    this.state={item:props.item}
  }
  //화면에 출력할 내용을 리턴하는 메서드
  //props는 수정이 안되서 state로 변환
  render(){
    //자주 사용하는 데이터를 짧게 사용하기 위해서 다른 변수에 대입
    const item=this.state.item;
    return(
      <ListItem>
        <Checkbox checked={item.done}/>
        <ListItemText>
          <InputBase
            inputProps={{"aria-label":"naked"}}
            type="text" 
            id={item.id}
            name={item.id}
            value={item.title}
            multiline={true}
            fullWidth={true}
          />
        </ListItemText>
        <ListItemSecondaryAction>
                <IconButton aria-label="Delete ToDo">
                    <DeleteOutlined />
                </IconButton>
            </ListItemSecondaryAction>

      </ListItem>
    )
  }
}


2)삭제를 처리할 메서드를 App.js 파일에 생성


  //삭제를 위한 메서드
  delete=(item)=>{
    //state나 props 의 데이는 직접 편집이 안됩니다.
    const thisItems=this.state.items;

    //복사본에서 item을 제거
    //filter함수는 return type이 boolean 함수를 매개변수로 받아서
    //리턴결과 true인 데이터만 모아서 배열로 리턴하는 함수입니다.
    const newItems = thisItems.filter((e)=>e.id !== item.id);
    //원본에 다시 복사
    this.setState({items:newItems})
  }

 

3)ToDo.jsx에 삭제할 메서드 연결후 이벤트처리기

 

import React from "react"
import {
    ListItem,
    ListItemText,
    InputBase,
    Checkbox,
    ListItemSecondaryAction,
    IconButton
} from "@material-ui/core"

import DeleteOutlined from "@material-ui/icons/DeleteOutlined"

//react 에서 컴포넌트 클래스를 만들기 위해 Component로부터 상속받기

class ToDo extends React.Component {
  //생성자
  constructor(props){
    super(props); //상위 클래스에서 넘겨준 모든 props를 현재클래스에 저장
    //state 생성
    //item 이라는 이름으로 props 중에서 item 이라는 값을 state로 저장
    //props은 상위 component 에서 전달한 data라 읽기만 가능
    //수정이나 삭제를 하고자 하는 경우는 state 로 변환해야함.
    this.state={item:props.item}
    //App.js에서 넘겨준 삭제 함수를 현재 클래스의 데이터로 변환
    this.delete = this.props.delete //부모가 넘겨준함수는 this.delete로 변환
  }
  //화면에 출력할 내용을 리턴하는 메서드
  //props는 수정이 안되서 state로 변환

  //삭제 버튼 누를 떄 호출될 이벤트 핸들러
  deleteEventHandler=(e)=>{
    this.delete(this.state.item)
  }

  render(){
    //자주 사용하는 데이터를 짧게 사용하기 위해서 다른 변수에 대입
    const item=this.state.item;
    return(
      <ListItem>
        <Checkbox checked={item.done}/>
        <ListItemText>
          <InputBase
            inputProps={{"aria-label":"naked"}}
            type="text" 
            id={item.id}
            name={item.id}
            value={item.title}
            multiline={true}
            fullWidth={true}
          />
        </ListItemText>
        <ListItemSecondaryAction>
                <IconButton aria-label="Delete ToDo" onClick={(this.deleteEventHandler)}>
                    <DeleteOutlined />
                </IconButton>
            </ListItemSecondaryAction>

      </ListItem>
    )
  }
}

export default ToDo;

 

 이제 여기에 입력,삭제가 가능해집니다!

 

3.CORS

1)서버 애플리케이션 구동
예전에 만든 ToDo/Backend 구현
python manage.py makemigrations
python manage.py migrate
python manage.py runserver

 

2)클라이언트 애플리케이션의 App.js 파일에 데이터를 요청하는 코드를 App 클래스 안에 추가
//화면이 보여질때마다 호출되는 수명주기 함수

//화면이 보여질때마다 호출되는 수명주기 함수
  componentDidMount(){
    //ajax 요청 개체 생성
    let request = new XMLHttpRequest();
    //요청 준비
    request.open('GET',"http://127.0.0.1/todo/?userid=adam");
    //요청
    request.send('');
    //응답 처리
    request.addEventListener('load',()=>{
      //json 데이터 출력
      conseole.log(request.responseText)
    })

=>클라이언트 애플리케이션을 구동하면
=>브라우저에서 http://localhost:3000. 로 접속한 후 검사 창을 확인
CORS POLICY 에러가 출력됩니다

=>SOP(동일 출처 정책)
ajax나 fetch api는 브라우저의 동일 출처 정책에 따라 자신과 동일한 도메인의 데이터만 받아 올 수 있습니다.
동일 도메인이라는 것은 IP 주소와 포트번호까지를 의미합니다.
서버 애플리케이션과 클라이언트 애플리케이션을 따로 구현하면 SOP 정책에 따라 ajax나 fetch api를 이용해서는 서버의 데이터를 사용할 수 없습니다.
서버 애플리케이션은 127.0.0.1:80 구동중이고 클라잉너트 애플리케이션은 localhost(127.0.0.1):3000으로 구종중이라 데이터를 가져올 수 없습니다.

=>해결책
서버 애플리케이션에서 요청이 가능한 클라이언트 애플리케이션의 도메인을 등록해주어야 합니다.
서버 애플리케이션을 만들 때 CORS 설정을 확인해 두어야 합니다.

react의 경우는 react의 설정 파일에 설정을 해도 CORS 설정이 가능합니다.
이유는 react가 node.js플랫폼 위에서 동작을 하는데 node.js는 C/C++이라서 proxy 를 이용해서 react에 데이터를 넘겨줄 수 있습니다.

3)django의 CORS 설정
=>cors 관련 라이브러리 설치: pip install django-cors-headers

=>django 프로젝트의 settings.py파일에 애플리케이션을 등록

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "todoapplication",
    "corsheaders"
]

=>django 프로젝트의 settings.py파일에 corsheaders.middleware.CorsMisddleware 애플리케이션을 Middleware 맨앞에 등록

MIDDLEWARE = [
    "corsheaders.middleware.CorsMisddleware"
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

=>django 프로젝트의settings.py 파일에 허용할 List 등록
#허용할 도메인을 등록
#실제로는 배포하는 도메인을 등록
CORS_ORIGIN_WHITELIST=['http://127.0.0.1:3000','http://localhost:3000']
CORS_ORIGIN_CREDENTIALS=True

=>서버를 재구동

'Study > FrontEnd' 카테고리의 다른 글

JavaScript(4)  (0) 2024.04.23
JavaScript(3)  (1) 2024.04.18
React(2)-이벤트 처리기  (1) 2024.01.30
React(1)- Django + React.js Application  (1) 2024.01.30
FrontEnd  (0) 2024.01.18