[LG CNS AM CAMP 1기] 프론트엔드 4 | JavaScript, React

letthem·2024년 12월 30일
0

LG CNS AM CAMP 1기

목록 보기
4/16
post-thumbnail

axios

JSON Formatter

ajax: JS에서 제공해주는 비동기 통신방식
JSON: 객체 표현식
모든 입출력 데이터는 문자열이다 !

chrome 확장 프로그램 JSON Formatter 설치

axios

JavaScript 환경에서 HTTP 요청을 보내고 응답을 처리하는 데 사용되는 Promise 기반의 HTTP 클라이언트 라이브러리
요청 데이터를 JSON으로 직렬화하거나, 응답 데이터를 JSON으로 자동 파싱
간단한 사용법과 강력한 기능을 제공하여 RESTful API와의 상호작용에 널리 활용

cdn 복사


GET 요청

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> // cdn
  <script>
    axios
    .get("https://jsonplaceholder.typicode.com/posts")
    .then(res => {
	  // 성공했을 때
      console.log(res.data);
      // title만 콘솔에 출력
      res.data.forEach(d => console.log(d.title));
      console.log("----------------------");
      res.data.map(d => console.log(d.title));
    })
    .catch(err => {
	  // 실패했을 때
      console.log(err);
    })
  </script>
</head>
<body>
  
</body>
</html>

POST 요청 => 요청 본문을 통해서 서버로 정보(요청 파라미터)를 전달

axios
.post("https://jsonplaceholder.typicode.com/posts", {
  title: "axios post test",
  body: "axios is fun!!!",
  userName: "홍길동"
})
.then(res => {
  console.log(res.data);
})
.catch(err => {
  console.log(err);
})

요청 본문에 적은 건 객체로 보냈는데 네트워크 탭 > 페이로드 > 파싱된 데이터 보면

이렇게 axios가 자동으로 JSON으로 파싱해주었다!


인터셉터란?

모든 요청 전에 선실행되는 것 !!

요청 인터셉터 설정

요청할 때마다 서버는 Authorization 헤더값을 보고 판단한다.
매번 붙여서 서버에 요청하기엔 번거로우니 인터셉터를 사용해 편하게 쓰자!

axios.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer MY_ACCESS_TOKEN`;
  return config;
}, error => {
  return Promise.reject(error);
});

이런식으로 axios 요청하기 전에 인터셉터를 만들어두면

이런식으로 헤더에 자동으로 들어간다.

응답 인터셉터 설정

위 코드에서 request 대신 response 로 바꿔주면 된다.

axios.interceptors.response.use(response => {
  console.log('Interceptor response data', response.data);
  return Promise.resolve(response);
}, error => {
  return Promise.reject(error);
});

전체

// 요청 인터셉터
axios.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer MY_ACCESS_TOKEN`;
  return config;
}, error => {
  return Promise.reject(error);
});

// 응답 인터셉터
axios.interceptors.response.use(response => {
  console.log('Interceptor response data', response.data);
  return Promise.resolve(response);
}, error => {
  return Promise.reject(error);
});


// post
axios
.post("https://jsonplaceholder.typicode.com/posts", {
  title: "axios post test",
  body: "axios is fun!!!",
  userName: "홍길동"
})
.then(res => {
  console.log(res.data);
})
.catch(err => {
  console.log(err);
});

// get
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then(res => {
  // 성공했을 때
  console.log(res.data);
})
.catch(err => {
	// 실패했을 때
  console.log(err);
})

  • xhr: xml http request - ajax 통신 하는 Type

GET: 200 OK
POST: 201 Created


국가 정보를 가져와서 화면에 출력

국가명, 국기 이미지, 지도 링크 등을 출력해보자 !!

1. 국가 정보를 제공하는 REST API

국가 정보를 제공하는 REST API
필드 설명

2. 실행에 필요한 JS 라이브러리를 추가

<!-- axios, jquery 라이브러리 추가 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.js" 
  integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous">
</script>

3. axiox를 이용해서 국가 데이터를 조회

axios.get("https://restcountries.com/v3.1/all")
.then(res => {
  console.log(res);
})
.catch(err => {
  console.log(err);
});

4. 가져온 데이터를 <li> 요소로 출력

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- axios, jquery 라이브러리 추가 -->
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.7.1.js" 
    integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous">
  </script>
  <script>
  axios.get("https://restcountries.com/v3.1/all")
  .then(res => {
    console.log(res);
    res.data.forEach(country => {
      // console.log(country.name.official);
      // console.log(country.flags.png);
      // console.log(country.maps.googleMaps);
      // console.log(country.maps.openStreetMaps);
      // console.log("---------------------");

      const li = `
        <li>
          <img src="${country.flags.png}" alt="${country.flags.alt}" />
          <p>${country.name.common} (${country.name.official})</p>
        </li>
        `;
        $('ul').append(li);
      
    });
  })
  .catch(err => {
    console.log(err);
  });
  </script>
  <style>
    img { width: 100px; height: auto; }
    p { display: inline; }
  </style>
</head>
<body>
  <h1>국가 정보를 가져와서 출력</h1>

  <ul>
    <!-- 
    <li>
      <img src="" alt="국기설명" />
      <p>일반국가명 (공식국가명)</p>
    </li> 
    -->
  </ul>
</body>
</html>

5. 부트스트랩 적용

cf_1

  • 디자인 쉽게 적용하기 위해 만들어 놓은 것
  • 빠르고 간편한 반응형 웹 디자인(responsive web design)을 위한 open-source front-end framework

bootstrap cdn

<!-- Bootstrap JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" 
  integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous">
</script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

container 는 기본 레이아웃 중앙으로 잡아주는 것 !

row row-cols-1 row-cols-md-2 row-cols-lg-3 ← 반응형 된다,, 대박

g-3 는 gap 이다.

img-fluid ⬇️
Bootstrap의 이미지는 .img-fluid를 통해서 반응형으로 만들어집니다. 이렇게 하면 이미지에 max-width: 100%; 및 height: auto;가 적용되어 부모 요소와 함께 크기가 조정됩니다.

ms(margin-start) 는 margin-left
me(margin-end) 는 margin-right
ms/me cf

부트스트랩 말로만 들어보고 처음 써보는데 되게 간편한 것 같다!!!


여기까지 전체 (국가 정보 GET 및 부트스트랩으로 디자인 적용)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- axios, jquery 라이브러리 추가 -->
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.7.1.js" 
    integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous">
  </script>
  <!-- Bootstrap JavaScript -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" 
    integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous">
  </script>
  <script>
    axios.get("https://restcountries.com/v3.1/all")
    .then(res => {
      console.log(res);
      res.data.forEach(country => {

        const li = `
          <li class="d-flex align-items-center border p-3 bg-white rounded shadow-sm">
            <img src="${country.flags.png}" alt="${country.flags.alt}" class="img-fluid rounded" />
            <p class="mb-0 ms-3">${country.name.common} (${country.name.official})</p>
          </li>
          `;
          $('ul').append(li);

      });
    })
    .catch(err => {
      console.log(err);
    });
  </script>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
  <style>
    img { width: 100px; height: auto; margin-right: 10px; }
    ul { padding: 0; }
    li { list-style-type: none; margin-bottom: 20px; }
  </style>
</head>
<body class="bg-light">
  <div class="container my-5">
    <h1 class="text-center text-primary mb-4">국가 정보를 가져와서 출력</h1>
    <ul class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-3"></ul>
  </div>
</body>
</html>

6. 특정 단어가 들어간 국가만 필터링해서 출력되도록 수정

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- axios, jquery 라이브러리 추가 -->
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.7.1.js" 
    integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous">
  </script>
  <!-- Bootstrap JavaScript -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" 
    integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous">
  </script>
  <script>
    // 서버로 부터 가져온 전체 국가 정보를 저장할 배열
    let datas = [];


    // 국가 정보를 담고 있는 배열을 출력
    const showCountryInfo = countryInfos => {
      $('ul').empty();
      countryInfos.forEach(country => {
        const li = `
          <li class="d-flex align-items-center border p-3 bg-white rounded shadow-sm">
            <img src="${country.flags.png}" alt="${country.flags.alt}" class="img-fluid rounded" />
            <p class="mb-0 ms-3">${country.name.common} (${country.name.official})</p>
          </li>
        `;
        $('ul').append(li);
      });    
    };


    axios.get("https://restcountries.com/v3.1/all")
    .then(res => {
      datas = [...res.data];
      showCountryInfo(res.data);
    })
    .catch(err => {
      console.log(err);
    });
  </script>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
  <style>
    img { width: 100px; height: auto; margin-right: 10px; }
    ul { padding: 0; }
    li { list-style-type: none; margin-bottom: 20px; }
  </style>
</head>
<body class="bg-light">
  <div class="container my-5">
    <h1 class="text-center text-primary mb-4">국가 정보를 가져와서 출력</h1>
    <div class="d-flex justify-content-center mb-4">
      <input type="text" class="form-control" placeholder="검색할 국가명을 입력하세요." />
    </div>
    <ul class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-3"></ul>
  </div>

  <script>
      $('input').on('keyup', e => {
        const inputText = $(e.currentTarget).val().toLowerCase();
        console.log(inputText); // 현재 입력창에 입력된 내용(글자)
        // 서버로부터 가져온 국가 정보에서 국가명에 입력창의 내용이 포함된 건만 추출해서 출력
        // ~~~~~~~~~~~~~~~~~~~~    ~~~~   ~~~~~~~~~~  ~~~~~~~~~~~~~   ~~~
        //        datas     datas[*].name.common inputText |     showCountryInfo()
        //                 datas[*].name.official          <-- Array.filter()
        
        const filteredData = datas.filter(data =>
          data.name.common.toLowerCase().indexOf(inputText) >= 0 ||
          data.name.official.toLowerCase().indexOf(inputText) >= 0
        );
        showCountryInfo(filteredData);
      })
  </script>
</body>

</html>

TODO

  1. 검색 결과로 조회된 국가 개수를 출력하는 코드를 추가
  2. 국가명 아래에 구글 지도와 Open Street Map 지도를 보여주는 링크를 추가
    (링크를 클릭하면 지도가 새창에서 열리도록)

모듈

소프트웨어를 구성하는 하나의 독립적인 단위로, 특정 기능을 캡슐화하여 다른 코드와 분리한 코드의 집합
모듈을 사용하면 코드 재사용성을 높이고, 관리와 유지보수를 쉽게 하며, 복잡한 시스템을 더 작은 단위로 나누어 개발하는 것이 가능

꼭 읽어보기 ! ⬇️

모듈 cf_1
모듈 cf_2
모듈 cf_3

모듈 생성 및 사용

math.js (모듈 파일)

export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

main.js (모듈을 사용하는 파일)

import { add, subtract } from './math.js';

console.log(add(5, 3));        // 8
console.log(subtract(5, 3));   // 2

기본(default) 내보내기

math.js

export default function multiply(a, b) {
  return a * b;
}

main.js

import multiply from './math.js'; // 중괄호 X

console.log(multiply(5, 3));   // 15

React

정의

The library for web and native user interfaces = 사용자 인터페이스를 만들기 위한 자바스크립트 라이브러리
라이브러리 ⇒ 자주 사용되는 기능을 정래해 모아 놓은 것

  • 대표적인 자바스크립트 UI 라이브러리 : Angular, React, Vue.js
  • 프레임워크 vs 라이브러리
    • 프레임워크는 흐름의 제어 권한을 개발자가 아닌 프레임워크가 갖고 있는 반면 (기본적인 틀이 있고, 개발자가 코드를 추가해주는 것)
    • 라이브러리는 흐름에 대한 제어를 하지 않고 개발자가 필요한 부분만 필요할 때 가져다 사용하는 형태 (개발에 대한 흐름을 개발자가 만들어나가는 것)

SPA(Single Page Application)를 쉽고 빠르게 만들수 있도록 해 주는 도구

😇 장점

  • 빠른 업데이트와 렌더링 속도
  • 컴포넌트 기반 구조
  • 재사용성
  • 메타(페이스북) 지원
  • 활발한 지식 공유와 커뮤니티
  • 모바일 앱 개발 기능 지원 (React Native)

😭 단점

  • 방대한 학습량
  • 높은 상태(state) 관리 복잡도

리액트 앱 개발

일반 웹 페이지에 react.js 파일을 추가해서 기능을 구현

sample.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- #1 HTML 파일에 DOM 컨테이너를 추가
                    ~~~~~~~~~~
                    Root DOM Node => Virtual DOM의 시작점
   -->
  <div id="root"></div>

  <!-- #2 리액트 파일(react.js, react-dom.js)을 추가
   https://ko.legacy.reactjs.org/docs/cdn-links.html
  -->
  <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

  <!-- #3 리액트 컴포넌트 코드를 추가 -->
  <script src="MyButton.js"></script>
</body>
</html>

MyButton.js

function MyButton(props) {
  const [isClicked, setIsClicked] = React.useState(false);

  // <button>Clicked</button>
  return React.createElement(
    "button",
    { onClick: () => setIsClicked(!isClicked) },
    isClicked ? "Clicked" : "Click here"
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(React.createElement(MyButton));

너무 복잡슨 ,, JSX 로 쓰자 !!

JSX = JavaScript + XML

                HTML => XML
                ~~~~~~~~~~~~~~~~~~~~~
const element = <h1>Hello, World!</h1>; 😇
~~~~~~~~~~~~~~~                       ~
        |                             |
        <-----  JavaScript ----------->
    
const element = React.creatElement('h1', {}, "Hello, World!"); 😭

CRA, CNA

리액트 기반 웹 애플리케이션 개발에 필요한 모든 설정 상태의 프로젝트를 만들어 주는 도구

CRA(create-react-app) / CNA(create-next-app)

CRA

npx create-react-app my-cra-app
해당 폴더로 들어가서
npm start
하니까 무슨 리액트19가 CRA 이제 지원 안 한다고 해서 (한 달도 안 된듯ㅜ)
에러가 떠서 여기 참고해서 해결했다

버전을 낮추고 npm install react@18 react-dom@18
npm i web-vitals 이것까지 설치해주면
npm start
드디어 실행이 잘된당 !!

접속하면 뜨는 페이지 : public/index.html
그곳에 <div id="root"></div> <= root는 시작되는 위치!

index.js 에서 root id 를 ReactDOM의 Root 로 만들어주는 코드가 있다! ⬇️
const root = ReactDOM.createRoot(document.getElementById('root'));

그리고 root.render 에 App 을 넣어주고 있다. ⬇️

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

그래서 App.js 에 그려준 MyButton 이 보이는 것이다 ! ⬇️

import MyButton from './MyButton';

function App() {
  return (
    <MyButton />
  );
}

export default App;

MyButton.js ⬇️

import { useState } from "react";

function MyButton() {
  const [isClicked, setIsClicked] = useState(false);

  /*
  return React.createElement(
    "button",
    { onClick: () => setIsClicked(!isClicked) },
    isClicked ? "Clicked" : "Click here"
  );
  */

  // 훨씬 보기 좋아졌다!
  return (
    <button onClick={() => setIsClicked(!isClicked)}>
      {isClicked ? "Clicked" : "Click here"}
    </button>
  );
}

export default MyButton;

CNA

npx create-next-app 하고
해당 폴더로 들어가서

CNA 에서도 마찬가지로 파일을 넣고 npm run dev 하면 똑같이 뜬다.


Vite

차세대 빌드 도구
JavaScript, TypeScript 기반 웹 애플리케이션을 더 빠르고 효율적으로 개발하기 위해 설계

프로젝트 생성

c:\react> npm create vite my-app

                      ~~~~~~
                      프로젝트 이름

npx
create-vite my-app

√ Select a framework: » React ⇐ 화살표 키를 이용해서 이동 후 선택
√ Select a variant: » JavaScript

의존 모듈 설치 및 개발 서버 실행

c:\react> cd my-app ⇐ 프로젝트 디렉터리로 이동

c:\react\my-app> npm install ⇐ 의존 모듈 설치

c:\react\my-app> npm run dev ⇐ 개발 서버 실행

my-app@0.0.0 dev
vite

VITE v6.0.7 ready in 246 ms

➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help

🚨 파일 확장자를 jsx로 설정


XSS(Cross-Site Scripting, 크로스 사이트 스크립팅)

공격자가 전달한 스크립트 코드가 사용자 브라우저를 통해서 실행되는 공격 기법

희생자 브라우저에서 공격자가 전달한 스크립트 코드가 실행되면,

☠️

  1. 희생자 브라우저 정보를 탈취 => 대표적으로 Cookie(쿠키는 브라우저가 아니라 서버 사이드에서 만드는 것이다.)
    XSS를 사용해서 쿠키를 탈취해서 서버를 속일 수 있다.

http는 stateless 하다.
예를 들어 클라이언트-서버 간 요청-응답을 하고 시간이 지나고 나서 동일한 요청을 했을 때 서버가 같은 클라이언트로부터 왔다는 것을 알 수 없다.
그것을 알 수 있게 해주는 메커니즘이 쿠키이다!

서버가 Set-Cookie: role = user; 를 응답 헤더에 담아서 보내준다. 다음에 올 때는 이 값을 가지고 와! 라고 시킨다.
그럼 클라이언트가 저장해놓고 있다가 Cookie: role = user; 를 자동으로 갖고 요청을 보내서 그 때 왔던 클라이언트라는 것을 인식시킨다 !!

공격자가 이 저장된 쿠키를 탈취하면 ,,!! 공격자 PC 에서 이 탈취한 쿠키를 가지고 서버에 접근해서 → 서버 망할 수 있다 ☠️☠️☠️☠️☠️

  1. 가짜 페이지를 만들어 사용자 입력을 유도해서 입력한 정보를 탈취

  2. 해당 PC의 제어권을 탈취해서 원격에서 제어 => BeEf 와 공격 프레임워크를 활용해서 가능

홍길동
글쓰기 페이지 ----------------------------> 글저장

             이렇게 하면 텍스트로 인식됨! => &lt;script&gt; alert('xss') &lt;/script&gt;
                                           |

고길동 |
글읽기 페이지 <-----------------------------------+

<script> alert('xss') </script>

방어 기법 ⬇️

스크립트 코드가 실행되지 않도록 안전한 형태로 변경(인코딩)해서 저장하거나 응답
이걸 공격자 것만 막는 게 어렵다. 어떻게 구분할까? 내려보내주는 정보를 믿을 수 있나? -> CSP (컨텐츠 보안 정책) ⭐️⭐️⭐️ (브라우저에서 제공)

cf) CORS (교차 출처 리소스 공유) : sop(Same-origin policy: 동일 출처 정책)를 완화해주는 정책


JSX 사용법

1. 반드시 부모 요소 하나로 감싸야 한다.


function App() {
  return (
    <h1>리액트 앱</h1>
    <h2>react app</h2> <= JSX 식에는 부모 요소가 하나 있어야 한다.
  );
}

export default App;

방법 1. 다른 태그를 추가
근데 필요없는 div 태그 추가로 쓰기 좀 그렇다..

방법 2. Fragment 컴포넌트를 이용 => 불필요한 태그 추가를 방지
<Fragment> 를 사용하면 된다. 근데 import 도 해야하고,, 치기 귀찮다.

방법 3. Fragment를 축약 방식으로 사용 ⭐️
<>~~~~</>

2. JSX 안에서는 자바스크립트 표현식을 { }로 감싸서 작성

function App() {

  const name = "홍길동";
  const age = 23;

  return (
    <>
      <h1>{`안녕, ${name}`}</h1>
      <h1>안녕, {name}</h1>
      <h2>{age + 2}</h2>
    </>
  );
}

export default App;

3. JSX 내부에서 자바스크립트의 if 문을 사용할 수 없으므로, 삼항 연산자를 사용해야 한다.

<h2>{name === "홍길동" ? "환영합니다." : "환영하지 않습니다."}</h2>

4. 조건을 만족할 때만 내용을 보여주는 경우 => 조건부 렌더링

방법 1. 삼항 연산자를 이용하는 방법 => 조건을 만족하지 않는 경우 null을 반환

<h2>{name === "홍길동" ? "환영합니다." : null}</h2>

방법 2. && 연산자를 이용

  • && : 단락 연산자 (short circuiting operator)
  • (1 > 2) & (2 > 3) = false & false => false
    두 연산을 다 보고 최종 false 를 결론 낸다.

  • (1 > 2) && (2 > 3) => false
    앞 연산만 보고 최종 결론을 낸다. => 뒤 연산이 생략(단락)된다.
    => 빠르게 연산 가능

  • (1 < 2) | (2 < 3) => true | false => true

  • (1 < 2) || (2 < 3) => true
<h2>{name === "홍길동" && "환영합니다."}</h2>
                        ~~~~~~~~~
                  조건을 만족했을 때 출력할 내용

name === "홍길동"이 true면 환영합니다를 보여주고, false면 띄우지 않는다.

⭐️⭐️⭐️

&& 는 앞에 것이 true면 뒤에 것을 적용!
|| 는 앞에 것이 false면 뒤에 것을 적용!

5. 인라인 스타일

태그 내에서 style 속성을 이용해서 스타일을 지정하는 방법

  • DOM 요소에 스타일을 지정할 때는 { 객체 형태 }로 적용해야 한다.
  • 스타일 이름은 카멜 표현식을 사용한다.
  • 숫자 타입의 경우 단위를 생략하면 기본값이 px로 사용된다.
  • 단위를 포함할 때는 문자열로 표현해야 한다.
<h1 style={{ backgroundColor: "black", color: "yellow", fontSize: 28, padding: '16px' }}>{`안녕, ${name}`}</h1>

바깥 중괄호 : 표현식을 의미
안쪽 중괄호 : 객체를 의미

이렇게도 사용 가능! ⬇️

const myStyle = { backgroundColor: "black", color: "yellow", fontSize: 28, padding: '16px' }

return (<h1 style={myStyle}>{`안녕, ${name}`}</h1>)

function App() {

  const name = "홍길동";
  const age = 23;
  const myStyle = { 
    h1Style: { backgroundColor: "black", color: "yellow", fontSize: 28, padding: '16px' },
    h2Style: { color: 'red' }
  };
  
  return (
    <>
      <h1 style={myStyle.h1Style}>{`안녕, ${name}`}</h1>
      <h1>안녕, {name}</h1>
      <h2>{age + 2}</h2> 
      <h2 style={myStyle.h2Style}>{name === "홍길동" && "환영합니다."}</h2>
    </>
  );
}

export default App;

6. 함수가 undefined를 반환하지 않도록 기본값을 설정

function Name() {
  let name; // undefined
  return name || "아무개";
}
function App() {
  return (
    <>
      안녕, <Name />!
    </>
  );
}

export default App;

7. CSS 클래스를 사용할 때 class가 아닌 className으로 설정

App.css ⬇️

.react {
  background-color: black;
  color: yellow;
  font-size: 40px;
  padding: 10px;
}

App.js에 App.css import하고 클래스 속성 추가 ⬇️

import './App.css'

function App() {
  return (
    <div className="react">
      홍길동
    </div>
  );
}

export default App;

8. 모든 태그는 반드시 닫는 태그를 사용

내용이 없는 태그의 경우에는 self-closing 태그를 사용
~~~~~~~~~~~~         ~~~~~~~~~~~~~~~~
|                    +-- <input /> <img /> <hr /> <br /> ...
+-- <input> <img> <hr> <br> ...
import './App.css'

function App() {
  return (
    <input type="text" />
	<input type="text"></input>
  );
}

export default App;

9. 주석(comment)

import './App.css'

// 자바스크립트 주석
/*
  자바스크립트 주석
*/

function App() {
  // 자바스크립트 주석
  /*
    자바스크립트 주석
  */

  return (
    // 태그가 시작되기 전에는 자바스크립트 주석 사용이 가능
    /*
      자바스크립트 주석
    */

    <>
      // 태그가 시작되면 주석이 아닌 일반 문자열로 인식
      /*
        일반 문자열로 해석되어 화면에서 출력
      */

      {/* 자바스크립트 표현식으로 주석을 처리 */}
      { // 인라인 주석을 사용할 때는 유의해야 함 (표현식 끝에 }을 사용하면 주석 처리되어 버림)
      }
      <input type="text" />
      <input type="text"></input>
    </>
  );
}

export default App;

그냥 태그 시작 이후에는 {/* ~~ */} 이거 쓰자


컴포넌트

클래스형 컴포넌트와 함수형 컴포넌트 구조⭐️

클래스형 컴포넌트

부모(Component)로부터 상속받은 MyApp에서 render()를 재정의해야한다.

import { Component } from "react";

class **MyApp** extends Component {
  render() {
  	return (
      <></>
    );
  }
}
export default **MyApp**;

함수형 컴포넌트

상속의 개념이 없다.
단순 반환 값이 화면에 출력된다.

function MyApp() {
  return (
    <></>
  );
}
export default MyApp;

함수 표현식으로 변경

const MyApp = function() {
  return (
    <></>
  );
}
export default MyApp;

화살표 함수로 변경

const MyApp = () => {
  return (
    <></>
  );
}
export default MyApp;

0개의 댓글