document.getElementById("ID 입력").addEventListener('이벤트', (e)=>{ // ajax 객체 생성 // open을 해서 연결 설정 // 전송할 데이터 생성 // 전송 // 전송이 성공했을 때 수행할 동작을 작성 })
수행 흐름 입니다.
요청 응답 응답받은 데이터를 파싱 사용
- 요청
- 파라미터를 어떻게 전송하고 전송 방식은 어떻게 할 것인가?- 파싱
- 일반 Flat File, XML, JSON 중 어떤 형태인가?
- JSON이 최근에 많이 사용됨
- 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>
- callback
- Event가 발생했을 때 처리하는 함수를 별도로 설정하는 방식request.send(param); // 응답 결과 처리 request.addEventListener('load', (e)=>{ alert(request.responseText) })
- 단점
- 콜백 함수 안에 콜백 함수가 위치해야 하는 경우, 가독성이 매우 떨어짐
- 코드를 분리시켜 작업하기에 연관성이 바로 느껴지지 않는다.
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가 쓰기 더 간결하다.
옵션에는 전송방식, 파라미터 설정이 들어간다.
ajax를 편리하게 사용할 수 있도록 만든 JS Lib
JS에서는 동일한 의미를 가진 애들이 많다.
function 이름(매개변수){ 내용 } let 이름 = function(매개변수){ 내용 } function(매개변수){ 내용 } 는 (매개변수)=>{내용}과 동일합니다.
npm install --location=global yarn
yarn --version
node_modules
를 제외하고 업로드 후, 다른 곳에서 다운로드 이후 npm install
명령만 수행해주면 패키지가 다시 설치됩니다.yarn create react-app 앱이름
yarn start
scr/index.js
- App의 시작 파일입니다.
- 이 파일에서 APP이라는 컴포넌트를 출력
여기서 시작합니다.
src/App.js
- 이 파일이 첫 화면입니다.
node_modules 디렉토리
- 패키지가 저장된 디렉토리
- 이거 빼고 git에 올리고, 다운받을때는 npm install
package.json
- 노드 기반 프로젝트의 설정 파일
- 이게 보이면 노드 기반이라 생각하시면 됩니다.
function App() { return ( <h1>Hello React?</h1> <h2>안녕하세요?</h2> ); }
오류납니다.
function App() { return ( <> <h1>Hello React?</h1> <h2>안녕하세요?</h2> </> ); }
빈 태그(<></>)로 묶어줍시다.
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> </> ); }
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> </> );
왜 함수형 컴포넌트를 권장할까?
- 클래스 형 컴포넌트 생성 및 출력
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;
- 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;
이름=값
을 같이 기재한다면, 하위 컴포넌트에서는 this.props.이름
으로 props사용이 가능합니다.
- 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;
import './App.css';
import Sample from './Sample';
function App() {
return (
<>
<Sample job="student"/>
</>
);
}
export default App;
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
props
는 상위 컴포넌트에서 설정해서 하위 컴포넌트에서 사용하는 데이터이고, 하위 컴포넌트에서는 props의 값을 변경할 수 없습니다.
- 객체지향에서는 특별한 경우가 아니면 속성을 직접 수정을 하지 않는다.
- 메모리에 직접 접근을 안한다.
- getter, setter로 접근
this.state={state이름:초기값,....}
this.setState({stat이름:값,....})
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 발생
- 원본과 변경된 내용을 비교할 수 있어야 하는데, 원본이 변경되어서 비교할 수 없기 때문이다.
on이벤트이름
이고, 함수를 대입하면 됩니다.
- 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;
- Database
- MySQL- Programming Language
- Python- Framework
- Django- IDE
- Pycharm
- Framework
- React- IDE
- Visual Studio Code
- ToDo 생성
- ToDo 목록 보기
- ToDo 수정
- ToDo 삭제
- 추가할 내용
- 회원가입
- 로그인
- 로그아웃
- 백엔드 서비스 테스트를 프론트 엔드를 구현한 후 하면 한꺼번에 수정해야 할 부분이 늘어납니다.
- 백엔드 테스트를 위한 도구를 사용할 예정입니다.- postman을 이용할 예정입니다.
- https://www.postman.com/downloads
- 서비스를 구현 한 후, 데이터베이스를 백업하고 서버와 클라이언트 애플리케이션 이미지를 생성해서 다른 컴퓨터에서 구동이 가능하도록 만드는 것입니다.
- 사용할 데이터 베이스를 생성하거나 확인
create database minoToDo; show databases; use minoToDo;
루트 프로젝트에서 실시함
- 생성
python -m venv 이름
- 활성화
이름\Scripts\activate
pip install django pip install mysqlclient pip install djangorestframework
django-admin startproject ToDoProject
python manage.py startapp todoapplication
- app 등록(rest_framework 잊지 말자)
"todoapplication", "rest_framework",
- db 접속 정보 변경
- 시간 대역 수정
잘못된 설정이 있는지 서버를 구동해서 확인해보자