WEB/Front-end

React 시작하기 (React.js)

최새벽 2024. 7. 8. 15:52

# IDLE: vscode

 

#00. 리액트 사용하는/배워야하는 이유 

 

- 예전: Legacy(오래된, 예전의, 실제 돌아가고 있는) MVC, 프로젝트 하나 안에 model, controller, view가 다 존재함

 

- 변화: (없는 서비스 새로 만드는 경우에) API를 활용한 구조 (F/E: React, B/E: SpringBoot 多)

 

[모바일에서 프로그램 사용]

- AOS DB를 따로 개발해야함. Android에서는 DB직접 접근이 불가능하기 때문(외부 DB 서버 접근 불가)

- 안드로이드에서 API로 MVC 프로그램에 접근하여 DB로 접근할 수 있도록하는 방식 사용

-> 기존 존재하는 MVC구조와 별도의 API가 존재하기 때문에 비효율적.

 

=> WEB, AOS, IOS 셋 다 API로 관리 가능하도록 개발, 멀티플랫폼을 동시에 서비스 하기 위한 구조

(금융권 핵심 코어는 예전 구조지만, 새로운 기능 개발 및 마이크로사이트 개발 시에는 현재 방식 응용)

 

 

#01. Node.js

 

JAVA로 따지면 JDK같은 역할. 

 

[Node.js 환경 설정]

1. window 사용자 이름 바꾸기: 폴더명(Users)에서 한글->영어로 변경

2. https://nodejs.org/en 설치파일 다운로드 후 설치

  - 따로 설정해 줄 부분 딱히 없음.

3. cmd에서 설치 확인(만약에 안될 시 지우고 다시 설치)

  - node.js확인:  'node -v'

  - npm 확인 : 'npm -v'

* npm: node package manager

 

[vscode]

- `Ctrl` + `J` : vscode내에서 터미널 열기

- 패키지: 여러 파일을 하나의 파일 처럼 다룰 수 있게 해주는 관리 단위, 최상위 폴더인 루트 폴더 필요

 

[package.json]

- gradle,maven build 파일 같은 역할

- `npm init` → Enter 누르기(설정 값 따로X일때) 하면 파일 생성됨

- packcage.json파일에서 scripts에 start: node index.js 추가

- 터미널에서 npm run start하면 index.js 실행됨(index.js파일 별도로 존재)

 

[모듈]

- 모듈 : 독립적으로 존재하는 프로그램의 일부

- 단위별로 모듈화 잘 하는게 프로그램의 핵심

- 단위를 너무 작거나 크게 쪼개면 안됨

- 모듈 단위 : 본인이 불러서 사용할 수 있는 단위

 

[라이브러리 활용]

- npm i lodash (※ 오타나도 모듈 파일은 생성되므로 주의)

- package.json에 dependencies 추가

- lod modules는 공유할 필요X: package.json파일을 통해 npm install 하면 됨

 

 

#02. 리액트 시작하기

 

[리액트 사용 이유]

- 속도 개선: 옛날에는 인터렉션 구현 힘들었다 → 변화가 자주 일어나는 환경에서 지연을 줄이기 위해 활용

- 유연성: 컴포넌트(부품) 기반. 컴포넌트 하나당 보통 파일 하나(함수 하나). 파일이 많아져서 복잡해지긴 함. html 코드에서 import해서 사용

 

- 웹에서 페이지 업데이트 → DOM 문서 조작

- react는 이벤트가 일어나거나 데이터가 변경될 시 교체가 필요한 요소는 삭제하고 새롭게 수정 사항을 반영한 요소를 만들어 통째로 업데이트 함

 

[Create React App]

01-1. `npx create-react-app .` 실행했는데 오류남

 

01-2. `npm create react-app .`실행

02. `npm start`

 

- src/index.js에서 root라는 id가지고 와서 react에서 랜더링 시킴

 

- App으로 import해서 실행하므로 결국 열리는건 app.js

- return 한걸 index에서 <App />으로 들어가게 됨

* 소스보기 말고 개발자도구로 봐야 웹에 나타난 부분 구조 볼 수 있음

 

[App2.js에 App2 function만들어서 활용하기]

=> index.js가 App.js, App2.js를 각각 불러오고 있는 구조

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
    <App2 />
  </React.StrictMode>
);

 

* React.StrictMode 없어도 됨: Strict(엄격한), react가 실행할 때 한 번 더 실행하면서 체크를 함. 

* webpack : js파일을 html, css 등으로 해석할 수 있게 해주는 모듈 번들러

 

[리액트 앱의 동작 원리]

1. localhost: 3000으로 접속하면 public 폴더의 index.html을 반환

2. index.html은 src폴더의 index.js와 해당 파일이 가져오는 js 파일을 한데 묶어 놓은 bundle.js를 불러옴, <script>태그에서 자동으로 추가

3. bundle.js가 실행되어 index.js에서 작성한 코드 실행

4. index.js는 ReactDOM.createRoot메서드로 돔에서 리액트 앱의 루트가 될 요소 지정

5. render 메서드를 사용해 돔의 루트 아래에 자식 컴포넌트 추가, App 컴포넌트 랜더링

 

 

#03. 리액트 기본 기능 다루기 - 컴포넌트 

mkdir chapter5
cd chapter5 (or 바로npm create react-app chapter5)
npm create react-app .
npm start

- 컴포넌트 : 리액트의 기본 단위

- 클래스, 함수로 컴포넌트를 구성할 수 있으나, 요즘에는 대부분 함수로 사용

- 컴포넌트, 모듈화 시키는 하는 이유: 코드의 재사용성을 위해서

- 함수형 컴포넌트: 첫글자 대문자로 시작(태그랑 혼동될 수 있기 때문), 익명 함수로 활용하는 경우가 많다

- 보통 하나의 파일에 하나의 컴포넌트를 만든다 => 가독성을 위해서 

 

[컴포넌트 생성 및 import하기]

import './App.css'; 
import Header from './component/Header.js'; // App.js가 위치한 곳을 기준으로 상대경로
import Body from './component/Body.js'; 
import Footer from './component/Footer.js'; 

function App() {
  return (
    <div className="App">
      <Header/>
      <Body/>
      <Footer/>
    </div>
  );
}

export default App;
const Header = () => {
    return(
      <header>
        <h1>header</h1>
      </header>
    );
  } 
  // 위와 같이 익명 함수를 활용해서 사용하는 경우가 훨씬 많음

  export default Header; // default로 했기 때문에 import할 때 이름을 바꿀 수는 있음(그러나 그렇게 사용하는경우 거의 없다)
const Body = () => {
    return(
      <div>
        <h1>body</h1>
      </div>
    );
  } 
  export default Body;
const Footer = () => {
    return(
      <footer>
        <h1>footer</h1>
      </footer>
    );
  } 
  export default Footer;

 

 



#04. 리액트 기본 기능 다루기 - JSX


[JSX: JavaScript Xml]

const Body = () => {
  const numA = 1;
  const numB = 2;
    return(
      <div>
        <h1>body</h1>
        <h2>{numA+numB}</h2>
      </div>
    );
  } 
  export default Body;

- 중괄호 이용해서 js문법을 html 안에서 사용할 수 있음

- JSX는 대소문자를 구분함.

- return은 무조건 하나의 태그

- 기본 자료형(원시 자료형)을 제외한 자료형은 사용 불가능(아래와 같은 error 발생)

     "Object are not vaild as a React Child" : 객체는 리액트의 자식 요소로 적합하지 않다.

 

 

* Prettier : Formatting을 자동으로 해주는 Extensions

https://prettier.io/docs/en/configuration.html : 링크에서 json 복사후 원하는 포맷으로 수정

{
  "trailingComma": "all",
  "tabWidth": 4,
  "semi": true,
  "singleQuote": true
}

 - File - Preference - Settings 'format'검색 - Editor:format on save 체크 - Editor: default formatter를 prettier code formatter로 설정 => 수정 후 저장될 때마다 포맷팅 자동으로 해줌

 

[JSX: 스타일 적용하기]

(1) JSX: 중괄호 2개 씌워야 함. 안의 중괄호는 객체, 밖의 중괄호는 JSX 표현. 대시가 아닌 Camel표기법 사용

 return (
        <div style={{ backgroundColor: 'red', color: 'blue' }}>
            <h1>body</h1>
            <h2>{numA + numB}</h2>
            <h2>{objA.a}</h2>
            {num}은(는) {num % 2 === 0 ? '짝수' : '홀수'}입니다.
        </div>
    );

 

(2) css 파일 만들기

import './Body.css';

const Body = (props) => {
    const numA = 1;
    const numB = 2;
    const objA = {
        a: 1,
        b: 2,
    };
    console.log(props);
    // const color = { backgroundColor: 'red', color: 'blue' };
    return (
        <div className="body">
            <h1>body</h1>
            <h2>
                {numA + numB} {objA.a}
            </h2>
            <h3>{props.name}</h3>
            <h3>{props.age}</h3>
        </div>
    );
};
export default Body;
.body {
    background-color: green;
    color: blue;
}

 

[JSX: 객체 활용하기(담아서 전달)]

객체를 JSX에 담아서 js파일로 바로 넘길 수 있음. props 객체로 받아서 props.age와 같은 형식으로 사용할 수도 있지만 아래와 같이 바로 받아와서 사용할 수도 있음.

App.js에서
<Body name={name} age={age} />
Body.js에서
const Body = ({ name, age }) => {
    return (
        <div className="body">
            <h3>
                {name} {age}
            </h3>
        </div>
    );
};

 

- 객체를 받을때 보내 준 객체가 없으면 에러 발생 Cannot read properties of undefined error (reading~~~)

- 이러한 경우 삼항연산자 등으로 처리할 수도 있겠지만, 기본값을 지정해서 처리해주는 것이 좋다.

Body.defaultProps = {
    favorList: [],
};

 

[이벤트 객체 사용하기]

이벤트 객체 활용할 수 있음. 

    const handleOnClick = (e) => {
        console.log(e); // 이벤트 객체가 통째로 출력 SyntheticBaseEven...
        console.log(e.target); // 객체가 출력
        console.log(e.target.name); // 객체의 name 속성 출력
    };
            <button onClick={handleOnClick} name="A버튼"> A버튼</button>
            <button onClick={handleOnClick} name="B버튼"> B버튼</button>

 

 

#04. 리액트 기본 기능 다루기 - React Component State

 

[객체 재정의]

컴포넌트 값 변경시 그냥 값을 재정의하는 것이 아니라 state를 통한 setter를 사용해야 함

(1)

number = 1;

number = 2;

(2) 

setNumber(2); 

(1)번과 같이 바로 새로운 값을 대입하지말고 (2)번처럼 setter 함수를 사용해야함.

왜냐하면 전자는 랜더링이 다시 되어야 2로 바뀜. 대입을 해도 바로 안바뀜.

반드시 setter 함수로 값을 변경해야 바로 랜더링이 됨.

 

[useState]

- count에는 초깃값 0이 들어감, setCount에는 값을 바꿔주는 setter 함수를 넣어줌 => 구조분해할당이 일어나서 대입이 됨

- js함수도 하나의 타입이므로 변수 자리에 함수가 들어갈 수 있음

- count는 자바로 따지자면 지역변수. 해당 컴포넌트 안에서만 사용되기 때문

- 컴포넌트는 자신이 관리하는 state값이 변하면 다시 호출됨 => 리렌더, 리렌더링

- 값이 변경되면은 랜더링이 일어나야함. (단, 값 변경이 없을때 랜더링이 일어나는 것은 속도상의 문제 있음)

import { useState } from 'react';
 
const [count, setCount] = useState(0); // count에는 초깃값 0이 들어감. setCount에는 값을 바꿔주는 setter 함수를 넣어줌. -> 구조분해할당이 일어나서 대입이 됨
const onIncrease = () => {
        setCount(count + 1);
 };

 return (
        <div className="body">
            <h2>{count}</h2>
            <button onClick={onIncrease}>+</button>
        </div>
    );
};
 

 

 

 

 

* 신한DS 아카데미 부트캠프 강의를 기반으로 한 내용입니다. 

* 교재: 한 입 크기로 잘라먹는 리액트