본문 바로가기
Study/FrontEnd

React(2)-이벤트 처리기

by 왕방개 2024. 1. 30.

1.React

1)SPA (Single Page Application)


=>하나의 HTML 파일을 이용해서 애플리케이션의 모든 화면을 출력하는 방식
=>이전의 애플리케이션은 여러개의 HTML 파일을 만들어서 화면전환을 이용해서 여러 콘텐츠를 출력했는데 화면전환을 하게 되면 이전 내용을 삭제하고 새로운 내용을 출력해야하기 떄문에 깜빡임이 발생하고 네트워크 에러가 발생하게 되면 호면 전체가 에러페이지를 출력하게됩니다.모바일의 경우는 에러 페이지를 보는 횟수가 증가합니다.
이를 해결하는 방법으로 로컬에 데이터를 저장해서 네트워크 에러가 발생한 경우 로컬의 데이터를 출력하는 방법으로 해결을 하기도 하고 하나의 화면을 여러 컴포넌트로 분할하고 분할한 컴포넌트 별로 별도로 데이터를 요청해서 출력하는 방식을 사용하기도 합니다.
=>SPA를 만들기 위한 프레임워크로 널리 사용되는 것이 angular,react,vue 입니다.
angular은 구글이 만든 것으로 공식적으로  이상 업데이트를 하지않는다고 발표를 했습니다.
현재 국내 플랫폼 기업이나 중소기업은  react 을 선호하는데 vue 를 사용하는 곳도 있습니다.

2)React


=>2013 년에 facebook에서 발표한 SPA를 구현하기 위한 오픈소스 JavaScript Framework
=>가상 DOM과 JSX라는 새로운 문법을 이용해서 동작
=>리액트에서 화면에 출력되는 개체 하나를 Component라고 합니다.
=>게임 엔진의 출력방식을 이용해서 출력을 빠르게 하고 가상의 DOM 메모리에 배치해서 일반 자바스크립트로 출력하는것보다 빠르게 출력
=>React 에는 React와 거의 유사한 React Native가 있는데 이거 한번 쓰면 아이폰 갤럭시 둘다 사용 가능한 앱을 만들 수 있고 피그마로 디자인 적용 가능

 

태그에서 공통되는 속성
id:JS에서 태그를 구별해서 가져오기 위한 값
document.getElementById
class(react에서는 className):css에서 동일한 디자인을 적용하기 위한 이름으로 중복 가능
document.getElementsByClassName
name:클라이언트에서 서버에게 전송할 떄 서버에서 읽기 위한 이름으로 중복 가능(체크 박스, select등)

react는 컴포넌트 기반의 재사용 메커니즘을 이용한 SPA를 위한 자바스크립트 프레임워크

태그:화면에 보여지는 개체
컴포넌트:하나의 영역을 나타내기 위한 태그와 코드의 집합
자체적으로 데이터를 가질 수 있고 데이터가 변경되면 자동으로 재출력하고 미리 구조를 만들어두고 다시 출력할 때는 변경된 부분만 다시 출력

-프레임워크 사용법
프레임워크가 제공하는 기능을 그대로 사용:클래스가 충분한 기능을 제공해주기 떄문에 클래스를 이용해서 인스턴스를 만들어서 바로 사용하는 방법
프레임워크가 Template 이라는 클래스를 제공
template = new Template()

프레임워크가 제공하는 기능을 상속받아서 재정의해서 사용:클래스가 충분한 기능을 제공해주지 않아서 내가 기능을 추가해서 사용하는 경우
상속을 받으면 상위 클래스의 모든 것을 하위 클래스가 물려받습니다.

 

React에서는 Component 라는 클래스가 Component의 기능을 전부 다 가지고 있는데 화면에 아무것도 출력하지 않아서 React에서 Component를 생성할 때는 React.Component 로 부터 상속을 받아서 render라는 method를 재정의해서 render에서 리턴하는 내용을 출력하도록 설계가 되어 있습니다.

 

3)설치


=>Node.js 설치(자바스크립트로 애플리케이션을 개발하기 위한 플랫폼)설치
=>https://nodejs.org/en
설치확인:node --version

=>패키지 관리자: npm과 yarn
패키지 관리자를 이용해서 패키지를 설치하면 package.json 이라는 파일에 의존성을 설정하고 node_modules 디렉토리에 패키지를 저장.
git hub에 upload를 할때 node_modules 는 할 필요가 없고 package.json만 있으면 빌드를 다시해서 설치 할 수 있습니다.

npm은 노드를 설치하면 자동으로 설치가 됩니다
yarn을 설치하려면 npm install --location=global yarn 
하둡 2.0 머신을 yarn이라고 함 따라서 데이터 관리하시는 분들한테는 조심!

4)react 프로젝트 생성 및 실행


=>생성:yarn create react-app 앱이름
=>실행:yarn start
localhost:3000 으로 실행되면 기본 브라우저가 자동으로 실행됩니다.

https://velog.io/@yerim1935/%EC%97%90%EB%9F%AC%EB%85%B8%ED%8A%B8-yarn-%EC%9D%B4-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%EC%84%9C-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%8B%A4%ED%96%89%ED%95%A0-%EC%88%98-%EC%97%86%EC%9C%BC%EB%AF%80%EB%A1%9C-CUsersuserAppDataRoamingnpmyarn.ps1-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EB%A1%9C%EB%93%9C%ED%95%A0-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4 

 

[에러노트] yarn : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\user\AppData\Roaming\npm\yarn.ps1

react 프로젝트를 만들고한 다음, 를 하려고 하는데, 에러가 났다.구글링 해 본 결과, 권한이 없어서 일어나는 에러라고 한다.Windows Powershell을 관리자 권한으로 실행해 준 뒤에,를 입력하고 Y를 누

velog.io

이 부분 실행할때 오류가 났었는데 위 블로그를 참고해서 오류를 해결했습니다.

 

5)UI 개발을 위한 패키지 설치
npm install --save --legacy-peer-deps @material-ui/core
npm install --save --legacy-peer-deps @material-ui/icons

6)컴포넌트를 만들어서 화면에 출력
=>componenet:화면에 출력되는 독립적인 객체
=>src 디렉토리에 ToDo.jsx(확장자는 js파일도 상관없지만 react 컴포넌트 파일이라는 것을 알려주기 위해서 jsx 로 생성) 파일을 생성하고 작성
extend는 상속 render는 출력

import React from "react"

class ToDo extends React.Component {
  render(){
    return(
      <div className="ToDo">
        <input type="checkbox" id="todo0" value="todo0"/>
        <label for="todo0">ToDo컴포넌트만들기</label>
      </div>
    )
  }
}
export default ToDo;

 

=>메인 페이지의 역할을 수행하는 App.js 파일을 수정해서 ToDo 컴포넌트를 출력

import './App.css';
import React from 'react';
import ToDo from "./ToDo"


function App() {
  return (
    <div className="App">
      <ToDo />
    </div>
  );
}

export default App;

 

-react 는 App.js 파일이 전체 화면을 출력하는 파일
-App.js에 작성한 내용이 출력됩니다.
jsx 파일 만들어서 return에 html구조로 내가 쓰고 싶은거 작성
끝나고 App.js에 컴포넌트 등록
react는 싱글 페이지 컴포넌트라 아주 복잡한 화면을 만들지 않음
대부분 모바일 페이지를 만들려고 사용


7)컴포넌트에서 데이터를 사용하는 방법


이건 원래 자바스크립트가 하는일. 하지만 데이터를 사용할수 있는데
=>props:상위 컴포넌트에서 넘겨주는 데이터
=>state:컴포넌트 내부에서 사용하는 데이터
react는 props 나 state에 변화가 생기면 화면을 다시 출력합니다.
=>context:로그인 정보로 주로 사용됨. 모든 컴포넌트에서 사용할수 있는 데이터
=>redux: 전역데이터를 만드는 외부 라이브러리

 

8)props와 state 사용하기
=>ToDo.jsx 파일의 코드 수정

import React from "react"

//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}
  }
  //화면에 출력할 내용을 리턴하는 메서드
  render(){
    return(
      <div className="ToDo">
        <input type="checkbox" 
        id={this.state.item.id} 
        name={this.state.item.id} 
        value={this.state.item.done}/>
        <label id={this.state.item.id}>id={this.state.item.title}</label>
      </div>
    )
  }
}

export default ToDo;

여기까지하면 위 화면이 나오는데 위 화면이 나오는 이유는 props은 상위 컴포넌트인데 지금까지 정의를 안했기 떄문에 props 에 id,title,done을 정의 해야합니다. 이를 App.js에서 정의를 아래코드를 활용해서 정리했습니다.

import './App.css'
import React from 'react'
import ToDo from "./ToDo"


class App extends React.Component {
  constructor(props){
    
    super(props)
    //this.state.item={item:{id:0,"title":"Hello React","done":"true"}
    //App.js에 this.state.item이라는 이름으로 데이터 생성
    //ToDo에게 item이라는 이름으로 데이터를 전달
    this.state={item:{id:0,"title":"Hello React","done":true}}
  }
  render(){
    return(
      <div>
        <ToDo item={this.state.item}/>
      </div>
    )
  }
}

export default App;

아래처럼 잘 나오게 되었습니다!

 

태그:화면에 보여지는 개체
컴포넌트:하나의 영역을 나타내기 위한 태그와 코드의 집합
자체적으로 데이터를 가질 수 있고 데이터가 변경되면 자동으로 재출력하고 미리 구조를 만들어두고 다시 출력할 때는 변경된 부분만 다시 출력

-프레임워크 사용법
프레임워크가 제공하는 기능을 그대로 사용:클래스가 충분한 기능을 제공해주기 떄문에 클래스를 이용해서 인스턴스를 만들어서 바로 사용하는 방법
프레임워크가 Template 이라는 클래스를 제공
template = new Template()

프레임워크가 제공하는 기능을 상속받아서 재정의해서 사용:클래스가 충분한 기능을 제공해주지 않아서 내가 기능을 추가해서 사용하는 경우
상속을 받으면 상위 클래스의 모든 것을 하위 클래스가 물려받습니다.

React에서는 Component 라는 클래스가 Component의 기능을 전부 다 가지고 있는데 화면에 아무것도 출력하지 않아서 React에서 Component를 생성할 때는 React.Component 로 부터 상속을 받아서 render라는 method를 재정의해서 render에서 리턴하는 내용을 출력하도록 설계가 되어 있습니다.

배열이나 리스트를 순회하면서 작업을 수행하는 함수
map:데이터를 변환해주는 함수,함수를 대입해서 함수에 데이터를 순서대로 대입해서 리턴한 결과를 모아서 다시 배열이나 리스트로 리턴해주는 함수

filter:데이터를 필터링해주는 함수, boolean을 리턴하는 함수를 대입해서 데이터를 순서대로 대입하고 return 값이 true인 데이터만 모아서 다시 배열이나 리스트로 리턴해주는 함수

reduce:계산을 수행해서 리턴해주는 함수로 연산을 한 후 리턴하는 함수를 대입해서 데이터를 순서대로 대입하고 return 값을 가지고 다음 함수 호출의 매개변수로 활용해서 결과를 하나의 값으로 리턴해주는 함수

 

10)material ui를 이용한 디자인 변경
=>material design: 구글이 제시한 PWA(모바일 앱과 같은 웹 UI)를 위한 디자인 방식
=>material-ui 패키지: 구글의 material design 을 적용한 리액트 패키지
npm install --save --legacy-peer-deps@material-ui/core
npm install --save --legacy-peer-deps@material-ui/icons

도큐먼트-mui.com 에서 코드를 따라서 사용가능

import './App.css'
import React from 'react'
import ToDo from './ToDo'

class App extends React.Component {
  constructor(props){
    
    super(props)
    //this.state.item={item:{id:0,"title":"Hello React","done":"true"}
    //App.js에 this.state.item이라는 이름으로 데이터 생성
    //ToDo에게 item이라는 이름으로 데이터를 전달
    this.state={
      items:[
    {id:0,title:"react",done:true},
    {id:1,title:"vue",done:false},
    {id:2,title:"angular",done:false}]
              }
  }
  render(){
    //배열을 순회하면서 출력할 내용을 생성
    //item은 배열을 순회할 떄 각각의 데이터이고 idx은 인덱스
    //배열을 순회하면서 출력물을 만들 때는 key를 설정해주어야합니다.
    //key를 설정하지 않으면 출력에는 문제가 없지만 콘솔에 에러가 출력됩니다.
    let display= this.state.items.map((item,idx)=>(
      <ToDo item={item} key={item.id}/>
    ));
    return(
      <div className="App">
        {display}
      </div>
      
    )
  }
}

export default App;

 

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

//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>

      </ListItem>
    )
  }
}

export default ToDo;

11)하나의 문자열을 입력할 수 있는 컴포넌트를 만들어서 화면에 추가

=>AddToDo.jsx 생성

import React from "react"

import {TextField,Paper,Button,Grid} from "@material-ui/core"

class AddToDo extends React.Component{
  constructor(props){
    super(props);
  }


  render(){
    return(
      <Paper style={{margin:16,padding:16}}>
          <Grid container>
            <Grid xs={11} md={11} item style={{paddingRight:16}}>
                <TextField placeholder="여기에 작성하시오!!!"fullwidth/>
            </Grid>
            <Grid xs={1} md={1} item>
              <Button fullWidth color="secondary">
                +
              </Button>
            </Grid>
          </Grid>


      </Paper>


    );
  }
}


export default AddToDo

AddToDo를 생성완료했으니 Apps에 추가를 합니다.

 

=>Apps.js 수정

import './App.css'
import React from 'react'
import ToDo from './ToDo'
import {Paper,List} from "@material-ui/core"
import AddToDo from './AddToDo'

class App extends React.Component {
  constructor(props){
    
    super(props)
    //this.state.item={item:{id:0,"title":"Hello React","done":"true"}
    //App.js에 this.state.item이라는 이름으로 데이터 생성
    //ToDo에게 item이라는 이름으로 데이터를 전달
    this.state={
      items:[
    {id:0,title:"react",done:true},
    {id:1,title:"vue",done:false},
    {id:2,title:"angular",done:false}]
              }
  }
  render(){
    //배열을 순회하면서 출력할 내용을 생성
    //item은 배열을 순회할 떄 각각의 데이터이고 idx은 인덱스
    //배열을 순회하면서 출력물을 만들 때는 key를 설정해주어야합니다.
    //key를 설정하지 않으면 출력에는 문제가 없지만 콘솔에 에러가 출력됩니다.
    var display= this.state.items.length>0 && (
      <Paper style={{margin:16}}>
        <List>
          {this.state.items.map((item,idx)=>(
          <ToDo item={item} id={idx}/>))}
        </List>
      </Paper>
    )
    return(
      <div className="App">
        <AddToDo/>
        {display}
      </div>
      
    )
  }
}

export default App;

 


12)이벤트처리-수정화면에서 문자열을 입력하고 Enter을 누르거나 + button을 누르면 입력한 내용을 추가해서 화면에 반영

함수는 일급 객체:파이썬과 자바스크립트가 여기에 해당합니다
-함수도 하나의 자료형
-함수를 이용해서 변수를 생성할 수 있고 함수를 매개변수로 대입할 수 있고 함수를 리턴할 수 있음

 

=>App.js파일에 data를 추가하는 메서드를 생성
 ★React는 props는 수정할 수없고 state는 수정이 가능하지만 원본을 직접 수정하는것은 안되고 setState 메서드를 이용해서만 수정이 가능합니다.

//데이터를 추가하는 함수
  add=(item)=>{
    //배열에 데이터를 추가하기 위해서 state 배열을 복사
    const thisItems=this.state.items;

    //item의 id와 done 값을 설정 - title 만 입력하기 때문.
    item.id="ID_"+thisItems.length;
    item.done=false;
    
    //복사한 데이터에 데이터를 추가
    thisItems.push(item)
    //복사한 데이터를 다시 state 에 적용
    this.setState({items:thisItems});
  }

이렇게 사용되었던게 관계형 데이터베이스입니다. 
관계형데이터베이스 테이블을 불러올때 테이블의 복사본을 가져옵니다.
복사본에 INSERT,DELETE,UPDATE를 수행

ROLLBACK: 복사본에 작업한 내역을 소멸
SAVEPOINT:작업의 로그를 기록하겠다.
COMMIT:복사본에 작업한 내역을 원본에 반영

금융은 한번에 insert,delete가 정말 잦기 때문에 Savepoint을 중간중간 지정해놓고 밤에 한번씩 정리합니다.

하고 나서 아래에 addcode부분을 수정합니다.

  render(){
    //배열을 순회하면서 출력할 내용을 생성
    //item은 배열을 순회할 떄 각각의 데이터이고 idx은 인덱스
    //배열을 순회하면서 출력물을 만들 때는 key를 설정해주어야합니다.
    //key를 설정하지 않으면 출력에는 문제가 없지만 콘솔에 에러가 출력됩니다.
    var display= this.state.items.length>0 && (
      <Paper style={{margin:16}}>
        <List>
          {this.state.items.map((item,idx)=>(
          <ToDo item={item} id={idx}/>))}
        </List>
      </Paper>
    )
    return(
      <div className="App">
        <Container maxWidth="md">
        <AddToDo add={this.add}/>
        {display}
        </Container>
      </div>
      
    )
  }
}

 

=>AddToDo.jsx파일을 수정해서 구현

import React from "react"

import {TextField,Paper,Button,Grid} from "@material-ui/core"

class AddToDo extends React.Component{
  constructor(props){
    super(props);
    //App.js파일에서 넘겨준 method을 add에 저장
    this.add=props.add;

    //입력한 문자열을 저장하기 위한 속성을 생성
    this.state={item:{title:""}}
  }

  //TextField에서 값을 입력할때마다 호출 되는 이벤트 리스너
  onInputChange=(e) =>{
    //state.title에 입력한 내용을 대입
    //this.state.item.title=e.target.value는 안됨.state은 직접 변경불가
    const thisItem=this.state.item
    thisItem.title = e.target.value;
    this.setState(({item:thisItem}));
    console.log(this.state.item.title)
  }

  //+버튼을 눌렀을때 호출되는 이벤트 리스너
  onButtionClick =(e) =>{
    //배열에 삽입하는 함수 호출
    this.add(this.state.item);
    //텍스트 필드를 초기화
    this.setState({item:{title:""}})
   
  }

  //Enter를 누르면 호출되는 이벤트 리스너
  enterKeyEventHandler =(e)=>{
    if(e.key === "Enter"){
      this.onButtionClick();
    }
  }

  render(){
    return(
      <Paper style={{margin:16,padding:16}}>
          <Grid container>
            <Grid xs={11} md={11} item style={{paddingRight:16}}>
                <TextField placeholder="여기에 작성하시오!!!"fullwidth
                onChange={this.onInputChange} value={this.state.item.title} onKeyPress={this.enterKeyEventHandler}/>
                
            </Grid>
            <Grid xs={1} md={1} item>
              <Button fullWidth color="secondary" onClick={this.onButtionClick}>
                +
              </Button>
            </Grid>
          </Grid>


      </Paper>


    );
  }
}


export default AddToDo

이렇게 완성했습니다!!

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

JavaScript(3)  (1) 2024.04.18
React(3)  (0) 2024.01.31
React(1)- Django + React.js Application  (1) 2024.01.30
FrontEnd  (0) 2024.01.18
HTML,CSS을 활용한 자기 페이지 만들기  (3) 2024.01.03