수업 23일차

galoo·2023년 7월 27일
0

HelloVision Dx Data School

목록 보기
23/72
post-thumbnail

✔ Ajax

  • 비동기적으로 서버에 데이터를 요청하는 것
  • 최근에는 웹 서버와 웹 클라이언트를 별개의 프로그램으로 구현하기 때문에, 웹 클라이언트에서 웹 서버로 데이터를 요청해서 응답을 받아 출력하는 형태로 작성합니다.
document.getElementById("ID 입력").addEventListener('이벤트', (e)=>{
        // ajax 객체 생성
        // open을 해서 연결 설정
        // 전송할 데이터 생성
        // 전송
        // 전송이 성공했을 때 수행할 동작을 작성
    })

수행 흐름 입니다.

목적

  • 다른 부분에 영향을 주지 않고 UI를 실시간으로 갱신하는 것

작업 과정


요청 \rarr 응답 \rarr 응답받은 데이터를 파싱 \rarr 사용


  • 요청
    - 파라미터를 어떻게 전송하고 전송 방식은 어떻게 할 것인가?
  • 파싱
    - 일반 Flat File, XML, JSON 중 어떤 형태인가?
    - JSON이 최근에 많이 사용됨

✔ FORM에 데이터를 입력받아서 삽입하기

ajax.html 수정

  • HTML BODY에 form태그 생성
    - name을 Serializer랑 동일하게 해야 한다.
<body>
	<!-- form 에는 action, method, enctype, id 정도가 들어가.
    action은 처리할 서버의 url, method는 전송 방식(get, post) 생략시 get,
    enctype은 파일이 있을 때만 multipart/form-data 로 설정
    (multipart가 들어가면 무조건 파일관련) 파일 단위가 아닌 패킷단위 전송임
    잘라서 온거인지 받은애가 알아야 하기 때문에 적어줘야 한다.
    파일을 나누는데 EOF, BOF 만들어 그 사이에 쪼개진 파일 넣고 보냄-->
    <!-- ajax에는 form에 id만 있어도 된다.-->
    <h3>여기서 부터 form태그 전송입니다.</h3>
    <form id="bookform">
        <p>bid<input type="number" name="bid"/></p>
        <p>titile<input type="text" name="title"/></p>
        <p>author<input type="text" name="author"/></p>
        <p>category<input type="text" name="category"/></p>
        <p>pages<input type="number" name="pages"/></p>
        <p>price<input type="number" name="price"/></p>
        <p>published_date<input type="date" name="published_date"/>
        </p>
        <p>description<textarea name="description" 
        rows="4" cols="20"></textarea></p>
        <p><input type="button" value="전송" id="insert"/></p>
    </form>
</body>
  • 스크립트 부분
<script>
    document.getElementById("insert").addEventListener('click',(e)=>{
        //form에 입력한 데이터 가져오기
        let bookform=document.getElementById("bookform");
        let formdata=new FormData(bookform);
        //ajax 요청 객체 생성
        let request=new XMLHttpRequest();
        //요청 생성
        // open(전송방식, url, )
        request.open('POST','../example/fbv/books', true);
        // form data를 post 방식으로 전송하기 위한 데이터로 변경
        request.setRequestHeader("Content-type",
        "application/x-www-form-urlencoded");
        let param="";
        for (let pair of formdata.entries()){
            param+=pair[0]+'='+pair[1]+"&";
        }
        // 요청 전송
        request.send(param);
        // 응답 결과 처리
        request.addEventListener('load', (e)=>{
            alert(request.responseText)
        })
    })
</script>

fetch API

  • XMLHttpRequest는 callback 함수를 이용하는 구조
  • callback
    - Event가 발생했을 때 처리하는 함수를 별도로 설정하는 방식
request.send(param);
// 응답 결과 처리
request.addEventListener('load', (e)=>{
    alert(request.responseText)
})
  • 단점
    - 콜백 함수 안에 콜백 함수가 위치해야 하는 경우, 가독성이 매우 떨어짐
    - 코드를 분리시켜 작업하기에 연관성이 바로 느껴지지 않는다.
  • fecth API
document.getElementById("fetchbtn").addEventListener('click', (e)=>{
        // ajax 객체 생성
        // open을 해서 연결 설정
        // 전송할 데이터 생성
        // 전송
        // 전송이 성공했을 때 수행할 동작을 작성
        // fetch API를 이용해서 전체 데이터 가져오기 사용법
        // 훨씬 간결하다
        fetch('../example/fbv/books', {//옵션 설정}).then((response)=>
        response.json()).then((data)=>alert(data))
        .catch((error)=>alert(error))
        // fetch 함수를 호출하게 된다면, 서버에게 요청을 전송
        // 함수를 XMLHTTP는 만들어야 하지만, then에 함수를 설정하면
        // then 에게 전송받은 데이터가 전달됨
        // 전달된 데이터가 json이라면, json method를 호출하면
        // 전달한 데이터를 파싱하고 그 결과를 다음 함수에게 
        // 전달 ()이 자리에 넘겨주는거임 단계별로
        // 예외처리를 하고 싶다면? .catch
    })

Fetch가 쓰기 더 간결하다.
옵션에는 전송방식, 파라미터 설정이 들어간다.

axios 라이브러리

function 이름(매개변수){
			내용
}
let 이름 = function(매개변수){
			내용
}
function(매개변수){
			내용
} 는 
(매개변수)=>{내용}과 동일합니다.

CORS

  • Cross Origin Resource Sharing
  • 이게 나오기 전, SOP(Same Origin Policy - 동일 출처 정책) 이 있다.
    - 다른 출처에서 가져온 리소스와 상호 작용하는 것을 제한하는 브라우저의 보안 방식이다.
  • ajax나 fetch api를 이용해서는 자신의 애플리케이션이 아니면 데이터를 받아오지 못합니다.
    - ajax나 fetch api를 이용해서 다른 애플리케이션이 제공하는 데이터를 받아서 사용하고자 한다면 서버쪽에서 CORS 설정을 해서, 특정 클라이언트가 데이터를 받아갈 수 있도록 하거나, 클라이언트쪽에서 Proxy를 구축해서 직접 받지 않고, 다른 프로그래밍 언어가 받아서 전달해주도록 하면 됩니다.

CSRF

  • 보안을 위한 장치

✔ 전체 구조

✔ React 시작

  • vscode에서 해보자.

node?

  • 플랫폼
  • JS : 제약이 정말 많다.
  • web browser 밖에서 작업을 하고 싶을 때 proxy로 사용하는 플랫폼이다. (중간자 역할)
  • 버전은 짝수 버전(LTS)을 설치
    - 홀수는 테스트

npm?

  • python pip 와 비슷한 친구
  • 발전된 yarn을 주로 사용한다.
npm install --location=global yarn
yarn --version
  • hadoop의 echo : yarn이랑 다르다.

✔ React

  • node 기반의 프로젝트들은 node_modules 라는 디렉토리에 패키지를 다운로드 받아서 사용
  • 패지키에 대한 정보는 package.json이라는 파일에 모두 기재되어있습니다.
  • git hub에 업로드 할 떄는 node_modules를 제외하고 업로드 후, 다른 곳에서 다운로드 이후 npm install명령만 수행해주면 패키지가 다시 설치됩니다.

앱 생성 및 실행

앱 생성

  • yarn create react-app 앱이름

앱 실행 - 기본적으로 localhost:3000으로 접속 가능

  • yarn start

  • 이런 창이 뜬다!

앱 구조

Entry Point

  • scr/index.js
    - App의 시작 파일입니다.
    - 이 파일에서 APP이라는 컴포넌트를 출력

    여기서 시작합니다.

  • src/App.js
    - 이 파일이 첫 화면입니다.

  • node_modules 디렉토리
    - 패키지가 저장된 디렉토리
    - 이거 빼고 git에 올리고, 다운받을때는 npm install

  • package.json
    - 노드 기반 프로젝트의 설정 파일
    - 이게 보이면 노드 기반이라 생각하시면 됩니다.

화면 구성

  • 노드는 컴포넌트 기반의 화면 출력이다.
    - 전체 화면을 만들고, 그 안에 component 단위로 화면 요소를 배치

JSX

  • JS에 XML을 추가한 확장형 문법
  • XML 안에 {}를 이용해서 JS를 감싸는 구조
  • 실행될 때 JS 코드로 변환되어서 실행됩니다.

규칙

  • 여러 개의 Component가 존재한다면, 반드시 하나로 묶어야 합니다.
  • App.js 수정
function App() {
  return (
    <h1>Hello React?</h1>
    <h2>안녕하세요?</h2>
  );
}

오류납니다.

function App() {
  return (
   <>
      <h1>Hello React?</h1>
      <h2>안녕하세요?</h2>
   </> 
  );
}

빈 태그(<></>)로 묶어줍시다.

JS 데이터를 출력하고자 하는 경우에는 {}로 감싸면 됩니다.

function App() {
  let msg="안녕하세요?"
  return (
   <>
      <h1>Hello React?</h1>
      <h2>{msg}?</h2>
   </> 
  );
}
  • 골때리게 if를 사용 못해요
function App() {
  let msg="안녕하세요?"
  //if는 사용이 안되서 삼항 연산자 사용
  // let userid="mino"
  let userid=undefined // 이러면 로그인 튀어나옴
  return (
   <>
      <h1>Hello React?</h1>
      <h2>{msg}?</h2>
      <p>{userid ? userid : "로그인"}</p>
   </> 
  );
}

스타일 적용

  • 스타일은 객체 형태로 생성해서 적용
  • class 대신에 className 사용
let style={
    backgroundColor:"black",
    color:"magenta",
    fontSize:'40px'
  }
  return (
   <>
      <h1>Hello React?</h1>
      <h2>{msg}?</h2>
      <p>{userid ? userid : "로그인"}</p>
      <div style={style}> 스타일을 적용한 div </div>
   </> 
  );

컴포넌트 작성 방법

  • Component 클래스를 상속받아서 생성
    - render method를 재정의해서 리턴한 내용을 화면에 출력
  • 함수를 이용해서 생성 (권장)
    - return을 하면 그 냉용이 화면에 출력됨

왜 함수형 컴포넌트를 권장할까?

  • class 상속 시, 필요하지 않은 부분까지 상속받기 때문이다.

클래스 형 컴포넌트 생성 및 출력

  • 클래스 형 컴포넌트 작성을 위한 파일을 생성하고 작성
    - src/MyComponent.jsx
    - 무조건 대문자로 시작하자
  • App.js 수정(Entry Point)
  • 클래스 형 컴포넌트 생성 및 출력
import React, {Component} from "react";
class MyComponent extends Component{
    render(){
        return(
            <div>첫 번째 컴포넌트</div>
        )
    }
}
export default MyComponent;
  • App.js
import './App.css';
import MyComponent from './myComponent';
function App() {
  let msg="안녕하세요?"
  //if는 사용이 안되서 삼항 연산자 사용
  // let userid="mino"
  let userid=undefined // 이러면 로그인 튀어나옴
  let style={
    backgroundColor:"black",
    color:"magenta",
    fontSize:'40px'
  }
  return (
   <>
      <h1>Hello React?</h1>
      <h2>{msg}?</h2>
      <p>{userid ? userid : "로그인"}</p>
      <div style={style}> 스타일을 적용한 div </div>
      <MyComponent/>
   </> 
  );
}
export default App;

함수 형 컴포넌트 생성 및 출력

  • 함수 형 컴포넌트 작성을 위한 파일을 생성하고 작성
    - src/Sample.jsx
    - 무조건 대문자로 시작하자
  • App.js 수정(Entry Point)
  • Sample.jsx
function Sample(){
    return(<div>이번에는 함수형 컴포넌트에요</div>);
}
export default Sample;
  • App.js
import MyComponent from './MyComponent';
import Sample from './Sample';
function App() {
  let msg="안녕하세요?"
  //if는 사용이 안되서 삼항 연산자 사용
  // let userid="mino"
  let userid=undefined // 이러면 로그인 튀어나옴
  let style={
    backgroundColor:"black",
    color:"magenta",
    fontSize:'40px'
  }
  return (
   <>
      <h1>Hello React?</h1>
      <h2>{msg}?</h2>
      <p>{userid ? userid : "로그인"}</p>
      <div style={style}> 스타일을 적용한 div </div>
      <MyComponent/>
      <Sample/> // 함수형 컴포넌트 사용했습니다.
   </> 
  );
}
export default App;

props

개요

  • 상위 컴포넌트가 하위 컴포넌트에게 전달하는 데이터
  • 상위 컴포넌트에서 하위 컴포넌트를 출력할 때, 이름=값을 같이 기재한다면, 하위 컴포넌트에서는 this.props.이름으로 props사용이 가능합니다.
  • 만약, 함수형 하위 컴포넌트에서 props를 사용하고자 할 때는, 함수를 만들 때 매개변수에 이름을 하나 기재할 수 있는데, 이 이름이 props 전체를 매개변수로 받아옵니다.

App.js에서 MyComponent에게 데이터를 전달해서 출력해보기

  • class형 컴포넌트는 이렇게 this를 쓰면 됩니다.
  • App.js
import './App.css';
import MyComponent from './MyComponent';
function App() {
  return (
   <>
      <MyComponent name="mino"/>
   </> 
  );
}
export default App;
  • MyComponent.jsx
import React, {Component} from "react";
//현재 App.js에서 name="mino"라고 해놨다.
class MyComponent extends Component{
    render(){
        return(
            <div>제 이름은 {this.props.name} 입니다.</div>
        );
    }
}
export default MyComponent;

App.js에서 Sample에게 데이터를 전달해서 출력해보기

  • 함수 형 컴포넌트는 this를 빼주자. 이거 굉장히 중요해요
  • props를 매개변수로 받아와서 써야 하는 형태입니다.
  • App.js
import './App.css';
import Sample from './Sample';
function App() {
  return (
   <>
      <Sample job="student"/>
   </> 
  );
}
export default App;
  • Sample.jsx
function Sample(props){
    return(<div>저의 현재 신분은 {props.job}입니다.</div>);
}
export default Sample;

하위 컴포넌트와 태그 사이의 문자열

  • 하위 컴포넌트에서 자신의 태그 사이에 입력된 문자열을 읽고자 할 때는 props.children 입니다.
  • App.js 수정
import './App.css';
import Sample from './Sample';
function App() {
  return (
   <>
      <Sample job="student">샘플데이터에용</Sample>
   </> 
  );
}
export default App;
  • Sample.js
function Sample(props){
    return(<div>저의 현재 신분은 {props.job}입니다. 
    그리고 새로 만든 태그 사이 문자열은 {props.children} 입니다.</div>);
}
export default Sample;
  • Sample.js 구조 분해 할당
function Sample(props){
    //JS의 구조 분해 할당
    // = 오른쪽에 객체를 설정하고, 
    // 왼쪽 중괄호 안에 변수를 설정하면
    // 변수이름과 동일한 객체의 속성이 분해되어서 대입됩니다.
    const {job, children}=props;
    return(<div>저의 현재 신분은 {job}입니다. 
    그리고 새로 만든 태그 사이 문자열은 {children} 입니다.</div>);
    // 여기서는 {this.props.job} 이렇게 작성이 불가능합니다.
}
  • props.job 보다 구조 분해 할당해서 하는게 무조건 좋습니다.
  • .은 결국 한 번 더 메모리 참조를 해야 한다는 것이다.

구조 분해 할당

a=10
b=20
temp=a
a=b
b=temp 

python

b,a=a,b //tuple

💥this, self

  • this나 self는 JS 또는 Python에서 method에서 인스턴스 자신을 가리키는 포인터입니다.

✨method

  • method는 클래스 안에 만들어져서 인스턴스 또는 클래스가 사용하는 것입니다.
  • 함수는 클래스 외부에 만들어집니다.
  • 즉, 함수에서는 this를 못쓴다.
    - 함수형 component에서는 사용을 못해요
    - this를 빼고, props parameter를 받아와야 합니다.

React

State

개요

  • props는 상위 컴포넌트에서 설정해서 하위 컴포넌트에서 사용하는 데이터이고, 하위 컴포넌트에서는 props의 값을 변경할 수 없습니다.
  • state는 Component 내부에서 읽고 쓰기가 가능한 데이터 입니다.
  • 기본값을 설정해야만 사용할 수 있으며, method를 통해서만 수정이 가능
  • 객체지향에서는 특별한 경우가 아니면 속성을 직접 수정을 하지 않는다.
    - 메모리에 직접 접근을 안한다.
    - getter, setter로 접근

생성 및 초기값 설정

  • 클래스 형 컴포넌트에서는 constructor에서 초기화
  • 초기화 할 때는 this.state={state이름:초기값,....}
  • 수정은 this.setState({stat이름:값,....})
    - 한꺼번에 여러개 초기화, 수정이 가능합니다.

  • 함수형 컴포넌트에서는 useState에서 생성과 초기화를 수행합니다.

객체나 배열로 된 state의 수정

  • 객체나 배열로 된 state를 수정할 때는 반드시 복사본을 만들고 복사본을 수정한 후, 복사본을 원본에 대입해서 수정합니다.

1개짜리와 0개 이상의 데이터를 가진 것을 구분해야 합니다.

  • 1개짜리는 데이터를 복사하는 형태가 됩니다.
    - 연산자를 이용해서 다른 곳에 대입하면 데이터 자체를 복사해서 사용하는 형태가 됩니다.

  • 0개 이상의 데이터를 가진 것은 참조를 복사해서 사용하는 형태가 됩니다.
**1개짜리**
a=10
b=a
b=20
print(a) -> a=10 // 복제와 동일하게
_0개 이상의 데이터_
ar=[10,20,30]
br=ar
br[0]=1000
print(ar) -> 1000, 20, 30  // 참조를 복사해오기에 변합니다.

💥 이거 잊어버리면 안됩니다.

  • React는 변경사항만 변경합니다.
  • 이때, 원본(기준)이 바뀌면 해당 원본이 깨집니다.
  • 원본을 직접 수정을 하면 react는 error 발생
    - 원본과 변경된 내용을 비교할 수 있어야 하는데, 원본이 변경되어서 비교할 수 없기 때문이다.

Event Handling

개요

  • 이벤트가 발생했을 때, 동작을 수행하도록 하는 것
  • 이벤트 이름은 on이벤트이름이고, 함수를 대입하면 됩니다.

Input의 내용을 변경할 때, 변경된 내용을 Console에 출력하고 state에 저장하기

  • class형 컴포넌트를 작성하기 위해서 EventComponent.jsx 생성
import React, {Component} from 'react';
class EventComponent extends Component{
    // content라는 state를 생성
    state={
        content:''
    }
    render(){
        return(
        <>
            <h1>이벤트 연습<br/>{this.state.content}</h1>
            <input type='text'
            onChange={
                (e)=>{
                    console.log(e.target.value)
                    this.setState({content:e.target.value})
                }
            }
            />
        </>
        );
    }
}
export default EventComponent;
  • state는 render(==메서드) 밖에 써야 한다. 안그러면 해당 메서드에서만 쓰는 것으로 인식되기 때문이다.
  • App.js
import './App.css';
import EventComponent from './EventComponent';
function App() {
  return (
   <>
      <EventComponent/>
   </> 
  );
}
export default App;

✔ Django & MySQL & React를 이용한 ToDo

  • 도커 이미지 배포를 곁들인
  • git은 실행 단위별로 올릴거에요

개발환경

Back End

  • Database
    - MySQL
  • Programming Language
    - Python
  • Framework
    - Django
  • IDE
    - Pycharm

Front End

  • Framework
    - React
  • IDE
    - Visual Studio Code

구현 기능

  • ToDo 생성
  • ToDo 목록 보기
  • ToDo 수정
  • ToDo 삭제
  • 추가할 내용
    - 회원가입
    - 로그인
    - 로그아웃

Back End Test Tool

  • 백엔드 서비스 테스트를 프론트 엔드를 구현한 후 하면 한꺼번에 수정해야 할 부분이 늘어납니다.
    - 백엔드 테스트를 위한 도구를 사용할 예정입니다.
  • postman을 이용할 예정입니다.
    - https://www.postman.com/downloads

목표

  • 서비스를 구현 한 후, 데이터베이스를 백업하고 서버와 클라이언트 애플리케이션 이미지를 생성해서 다른 컴퓨터에서 구동이 가능하도록 만드는 것입니다.

데이터베이스 작업

  • 사용할 데이터 베이스를 생성하거나 확인
create database minoToDo;
show databases;
use minoToDo;

Django 프로젝트 생성 및 설정

프로젝트 디렉토리를 생성

가상 환경 생성 및 활성화(수동으로 한다면)

루트 프로젝트에서 실시함

  • 생성
    python -m venv 이름
  • 활성화
    이름\Scripts\activate

필요한 패키지 설치

pip install django
pip install mysqlclient
pip install djangorestframework

Django 프로젝트 생성

django-admin startproject ToDoProject

Django 애플리케이션 생성

python manage.py startapp todoapplication

settings.py 파일에 설정 변경

  • app 등록(rest_framework 잊지 말자)
"todoapplication",
"rest_framework",
  • db 접속 정보 변경
  • 시간 대역 수정

잘못된 설정이 있는지 서버를 구동해서 확인해보자

profile
밀가루 귀여워요

0개의 댓글