React

eg_kim·2024년 8월 19일

React

목록 보기
1/10
post-thumbnail

리액트에 대해 알아보자!

컴포넌트(사용자 정의태그)를 사용하여 가독성 및 재사용성 향상

  • 환경 설치/설정을 하지 않고 웹 브라우저에서 바로 웹 개발을 할 수 있도록 해주는 온라인 개발환경

    1. reactjs.org > get started > online placygrounds
    2. codepen
    3. codesandbox
    4. stackblitz
  • 순수 자바스크립트는 아니다. js라는 확장자를 사용하고 있지만 실제 확장자는 jsx를 사용하고 있으며 스크립트안에 태그를 직접 사용할 수 있다.

function App(){
	return(
    <div className="App">
    	<h2>Hello, ReactJS!</h2>
    </div>
    )
}

-> vue와 마찬가지로 최상위 엘리먼트는 항상 1개여야 한다.

툴 체인(Tool chain)

리액트 프로젝트 개발 시 목표에 따라 필요한 여러 가지 개발 환경 및 도구를 모아 한 번에 제공하는 도구

vue에서는 npm install -g @vue/cli > vue create . 혹은 vite 하면 뷰에서 사용 가능한 도구를 설치할 수 있었다.
이것처럼 리액트에도 툴 체인이라는 도구가 있다.

Create React App (CRA)

Next.js(풀스택 개발에 유용한 프레임워크)
Remix(중첩 라우팅을 활용하는 기술을 제공한다.)
Gatsby(cms 백엔드 개발에 유용한 기술 제공)
등이 있다.

리액트 설치방법

윈도우 운영체제 설치방법
1. npm install -g create-react-app

  • npm install @vue/cli 처럼 리액트를 설치한다.

맥 운영체제 설치방법
2. sudo install -g create-react-app

  • 명령어 입력 후 비밀번호 입력하면 설치 완료

설치 확인
3. create-react-app -V

npm vs npx

  1. npm == 프로그램 설치

  2. npx == 해당 프로그램을 한 번만 설치 후 자동 삭제
    => 컴퓨터 공간 낭비를 방지할 수 있다.
    => 설치할 때 마다 새로 다운로드 받기 때문에 항상 최신 상태를 유지할 수 있다.

개발 환경 준비하기

프로젝트 폴더의 경로에 한글이 포함되어 있으면 프로젝트 실행이 되지 않는 경우가 있으므로 주의해야 한다.

  1. 개발에 필요한 디렉토리 생성
    -> 디렉토리 이름은 react사용 불가

  2. 터미널 또는 cmd에서 디렉토리 이동
    -> cd

  3. 프로젝트 생성 명령 입력
    -> create-react-app [프로젝트명]
    -> create-react-app . (현재 디렉토리에 설치)

  4. npm start
    -> vue와 다르게 자동으로 실행이 된다. (vue는 ctrl을 함께 눌러야 실행이 되었다.)

구조 살펴보기

  1. app.js
    app.vue와 같은 역할

  2. index.js
    main.js와 같은 역할

  3. index.css
    -> reset.css 처럼 사용해도 된다.

  4. build
    -> npm run build 하면 dist가 아닌, build라는 파일이 생성된다.
    -> serve build 하면 미리보기 할 수 있다. (serve -s build)
    -> 빌드하기 전, npm start 했을 때와 빌드 후 serve build를 비교해보았을 때 용량의 차이가 크다. 배포하기 위해서는 build는 필수!

hook (컴포넌트 생성 방식)

class vs fuction

  • 기존에는 컴포넌트를 생성할 때 class방식을 사용했지만 함수방식을 사용하도록 많이 변경되었는데, class 방식이 함수방식에서 작동하지 않는 경우도 있기 때문에 함수방식에서도 사용할 수 있도록 hook을 이용한다.

  • 사용자 정의 hook은 이름이 use로 시작한다.
    그 중 가장 많이 사용하게 될 hook의 이름에는 use state, use effect 가 있다.

    • useState의 역할: 이미 로딩 된 화면의 데이터는 변화하지 않음. 그러나 useState를 사용하면 데이터를 변경할 수 있다.

useState

const 변수명 = useState(초기값, 변경될 값) << 두 개를 인자를 가지도록 되어있음

출력할 때 사용되고, 값을 바꿀 때 사용된다는 의미.

(사용 예시)

import './App.css';
import React, {useState} from "react"

function App(){

  const _number = useState(0)
  const number = _number[0]
  const setNumber = _number[1]

  let num=0
  return(
    <div>
      <h2>{number}</h2>
      <button
      onClick={
        ()=> {
          //num=num+1
          //console.log(num)
          //콘솔의 값은 변경되지만 브라우저의 값은 변경되지 않음
          setNumber(number+1)
      }
    }
    >ADD</button>
    </div>
  )
}
export default App;

(같은 내용 다른 코드)

비정형 배열: 배열은 배열인데, 불규칙적인 형식의 배열 형태

따라서 useState는 첫 번째 인자 담을 변수, 두 번째 인자 담을 변수가 필요하기 때문에 변수를 배열로 담으면 된다.

import './App.css';
import React, {useState} from "react"

function App(){

  // const _number = useState(0)
  // const number = _number[0]
  // const setNumber = _number[1]
  const [number,setNumber] = useState(1)

  let num=0
  return(
    <div>
      <h2>{number}</h2>
      <button
      onClick={
        ()=> {
          //num=num+1
          //console.log(num)
          //콘솔의 값은 변경되지만 브라우저의 값은 변경되지 않음
          setNumber(number+1)
      }
    }
    >ADD</button>
    </div>
  )
}
export default App;

[컴포넌트의 변화 예시, hook 사용 x]

class 방식 컴포넌트

(형식)

import React, {Component} from 'react';
class NAME extends Component {
      render(){
        return(

        )
      }
    }

(실제 예시)

import React, {Component} from 'react';
class App extends Component {
      render(){
        return(
			<div className="App">
            	Class Type Component!
           </div>
        )
      }
    }

함수 방식 컴포넌트
(형식)

function NAME(){
	return(
    
    )
}

컴포넌트 생성

App.js

  • 사용자 정의 컴포넌트
  • 유사 자바스트립트 (순수 자바스크립트 아님 !)
  • 코드를 쉽게 작성할 수 있도록 jsx 언어 사용

JSX (JAVASCRIPT XML)

  • 자바스크립트 코드 작성 시 따옴표 사용 등 까다로운 문법을 쉽게 작성
  • 페이스북에서 만든 언어
  • JSX로 코드 작성 시 Create React App이 자바스크립트 코드로 변환

<생성 예시>

function App() {
  return (
    <div className="app">
    <header>
        <h1>WEB</h1>
        <p>Wold Wide Web!</p>
    </header>

    <nav>
        <ul>
            <li><a href="1.html">HTML</a></li>
            <li><a href="2.html">CSS</a></li>
            <li><a href="3.html">JAVASCRIPT</a></li>
        </ul>
    </nav>

    <article>
        <h2>HTML</h2>
        <p>HTML is....</p>
    </article>
    </div>
  );
}

기존 app.js에서 컴포넌트를 생성하는 방법

규칙 1. 컴포넌트 이름은 첫 글자가 항상 대문자여야 한다.
-> 예를 들어 내가 만든 컴포넌트의 이름이 < header > 라면 기존 html element와 겹치기 때문에 인식할 수 없다. < Header > 처럼 첫글자를 대문자로 설정하여 사용자 이름을 정의해야 한다.

규칙 2. 최상위 엘리먼트 1개 고정, 함수를 생성하여 App에 태그를 불러온다.

function Subject(){
  return(
  <header>
        <h1>WEB</h1>
        <p>Wold Wide Web!</p>
    </header>
  )
}

function Nav (){
  return(
    <nav>
        <ul>
            <li><a href="1.html">HTML</a></li>
            <li><a href="2.html">CSS</a></li>
            <li><a href="3.html">JAVASCRIPT</a></li>
        </ul>
    </nav>
  )
}

function Component(){
  return(
    <article>
        <h2>HTML</h2>
        <p>HTML is....</p>
    </article>
  )
}

function App() {
  return (
    <div className="app">
    <Subject />
    <Nav></Nav>
    <Component></Component>
    </div>
  );
}

이렇게 새로운 함수를 생성하고 내용을 return() 안에 담은 뒤 App 안에 태그로 불러온다.

컴포넌트 분리하기

App.js 의 내용을 index.html로 연결시켜주고 있는 파일은 index.js이다.

1. src 폴더 안에 components 폴더 생성 후 안에 js 파일 생성하기

2. 내용 붙여넣기(js 파일 안에) 및 내보내기

function Subject(){
  return(
  <header>
        <h1>WEB</h1>
        <p>Wold Wide Web!</p>
    </header>
  )
}
export default Subject

=> 내보내야 할 함수가 1개라면 export default를 사용한다.

3. 불러오기

import Subject from './components/Subject';
 function App() {
 return (
   <div className="app">
   <Subject />
   <Nav></Nav>
   <Component></Component>
   </div>
 );
}

export default App;

-> 다른 함수들도 마찬가지로 export default 후 import 해서 app.js 로 불러오기 한다.

props

  • 같은 태그(컴포넌트)라도 다르게 사용 가능 - 재사용성 향상
  • 상위컴포넌트가 하위컴포넌트에 데이터를 전달하는 방식
//App.js
import Subject from './components/Subject';
function App() {
  return (
    <div className="app">
    <Subject title="WEB"></Subject>
    <Nav></Nav>
    <Component></Component>
    </div>
  );
}
//Subject.js
  function Subject(props){
    return(
    <header>
          <h1>{props.title}</h1>
          <p>Wold Wide Web!</p>
      </header>
    )
  }
  export default Subject

Spa 방식의 특징!
불필요한 부분은 수정되지 않고 수정되는 부분만 변환되어서 보여진다.
가상의 DOM을 생성하여 달라지는 부분만 보여지는 것이다.

=> console 창에 같은 데이터가 2번씩 보이는 이유이다.

  • html element처럼 적었지만 함수를 불러오는 과정이기 때문에 데이터를 전달해줄 인자가 필요하다.
  • 따라서 함수의 데이터를 전달할 인자를 출력해줄 수 있는 변수가 필요한데, 이를 props라고 할 수 있다.
  • 데이터는 객체로 저장되므로 props.title이라고 불러오기 하면 된다.
  • vue 이외의 다른 프레임워크들에서 변수를 불러올 땐 머스태시가 아닌 {} 일반적인 중괄호를 사용하면 된다.

    같은 표현 다른 방식

function Subject({title,content}){
    return(
    <header>
          <h1>{title}</h1>
          <p>{content}</p>
      </header>
    )
  }
  export default Subject

반복문을 사용한 props 데이터 전달하기

function Nav ( props ){

  //return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
  const content_list = []

  for(let i=0; i<props.data_list.length; i++){
    let data = props.data_list[i]
    content_list.push(
      <li key={data.id}>
        <a href={data.id + ".html"}>
          {data.title}
        </a>
      </li>
    )
  }

  return(
    <nav>
        <ul>
            {content_list}
        </ul>
    </nav>
  )
}

export default Nav

//app.js
function App() {

//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const data_list = [
  {id:1, title: "HTML", content: "HTML is..."},
  {id:2, title: "CSS", content: "CSS is..."},
  {id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
]

return (
  <div className="app">
  <Subject title="WEB" content="World Wide Web!"></Subject>
  <Nav data_list={data_list}></Nav>
  <Component articleTitle="HTML"></Component>
  </div>
);
}

export default App;

하위 컴포넌트에서 상위 컴포넌트로 데이터를 보내는 방식

사용자 정의 이벤트를 만들어야 한다.

  • 이벤트를 실행하는 명령어는 (ex) onclick) on 다음에 대문자가 오도록 한다. (ex) onClick)
  • 이벤트의 내부는 무조건 함수이다.
//app.js
  function App() {

  //return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
  const data_list = [
    {id:1, title: "HTML", content: "HTML is..."},
    {id:2, title: "CSS", content: "CSS is..."},
    {id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
  ]

  return (
    <div className="app">
    <Subject 
    title="WEB" 
    content="World Wide Web!"
    onTestEvent={
      (msg) => alert(msg)
    }
    ></Subject>
    <Nav data_list={data_list}></Nav>
    <Component articleTitle="HTML"></Component>
    </div>
  );
}
export default App;
  
  
  //subject.js
  
  function Subject(props){
    return(
    <header>
          <h1>
            <a
            href="#"
            onClick={
              (e)=>{
                e.preventDefault();
                props.onTestEvent('nct wish!')
              }
            }>
              {props.title}
            </a>            
            </h1>
          <p>{props.content}</p>
      </header>
    )
  }
  export default Subject

import './App.css';
import Subject from './components/Subject';
import Nav from './components/Nav';
import Component from './components/Component'



function App() {

//return은 최종적으로 내보내는 내용이니까 연산식은 return 전에 만든다.
const data_list = [
  {id:1, title: "HTML", content: "HTML is..."},
  {id:2, title: "CSS", content: "CSS is..."},
  {id:3, title: "JAVASCRIPT", content: "JAVASCRIPT is..."},
]

let selected = 0;

return (
  <div className="app">
  <Subject 
  title="WEB" 
  content="World Wide Web!"
  onTestEvent={
    (msg) => alert(msg)
  }
  ></Subject>
  <Nav 
  data_list={data_list}
  onChangeSubject={
    (get_id) => {
      //console.log(get_id)
      selected = (get_id-1) //실행되지 않음
      console.log("sc : ", selected)
      //return selected //실행되지 않음
      //변수값이 바뀌더라도 브라우저가 새로고침 되지 않음
  }
}
  ></Nav>
  <Component
  title={data_list[selected].title}
  content={data_list[selected].content}>
  </Component>
  </div>
);
}

export default App;


function Component(props){
  return(
    <article>
        <h2>{props.title}</h2>
        <p>{props.content}</p>
    </article>
  )
}

export default Component

값이 바뀌면 브라우저의 상태도 변경해주는 변수가 필요한데 이런 경우를 react에서는 state 라고 부른다. => userState (hook) 목차에 설명.

배운 내용 최종복습

import './App.css';
import React, {useState} from "react";

function Menu( props ){
  let menu_list=[]
  for(let i=0; i<props.menus.length;i++)
  menu_list.push(
    <li key={props.menus[i].id}>
      <a
      href="#"
      onClick={
        (e) => {
          e.preventDefault();
          props.onChangeMenu(props.menus[i].id)
        }
      }
      >
      {props.menus[i].title}
      </a>
    </li>
  ) 
  return <ul>{menu_list}</ul>;
}

function Item(props){
  return(
    <div>
      <h3>{props.title}</h3>
      <p>{props.content}</p>
    </div>
  )
}

function App(){
  //let menu = 0;
  const [menu, setMenu] = useState(1)
  const menus= [
    {id: 1, title:"WISH", content:"Riku"},
    {id: 2, title:"HANDS UP", content:"MaeDa"},
    {id: 3, title:"SONG BIRDS", content:"MaeDa Riku"},
    {id: 4, title:"SAIL AWAY", content:"Kuri"},
    {id: 5, title:"NASA", content:"Neko Riku"},
  ]
  return(
    <div>
      <Menu 
      menus={menus}
      onChangeMenu={
        //console.log(menu_id)
      (menu_id)=>{
        //menu = menu_id
        setMenu(menu_id)
        console.log("Call Menu Comp : " + menu_id)
      }
    }
      ></Menu>
      <hr />
      <Item
      title={menus[menu-1].title}
      content={menus[menu-1].content}
      ></Item>
      
    </div>

  )

}
export default App;
profile
오늘의 공부 기록📝

0개의 댓글