4계층 프로토콜

4계층에서 하는 일

  • 전송 계층(Transport Layer)는 송신자의 프로세스와 수신자의 프로세스를 연결하는 통신 서비스를 제공
  • 전송 계층은 연결 지향 데이터 스트림 지원, 신뢰성, 흐름 제어, 그리고 다중화 같은 편리한 서비스 제공
  • 종류
    • 전송 제어 프로토콜(Transmission Control Protocol):  연결 지향 전송 방식을 사용
    • 사용자 데이터그램 프로토콜(User Datagram Protocol):보다 단순한 전송에 사용

UDP(User Datagram Protocol)

안전한 연결을 지향하지 않는 UDP 프로토콜 (전송 여부 미확인)

TCP(Transmission Control Protocol)

안전한 연결을 지향하는 TCP 프로토콜 (전송 여부 확인)

6분 46초


 

포트 번호

포트 번호의 특징

  • 특정 프로세스와 특정 프로세스가 통신을 하기 위해 사용
  • 하나의 포트는 하나의 프로세스만 가능
  • 하나의 프로세스가 여러 개의 포트를 사용하는 것은 가능
  • 포트 번호는 일반적으로 정해져 있지만, 무조건 지켜야하는 것은 아님
  • 예를 들어, 일반적으로 웹 서비스는 80번 포트를 사용하지만 무조건 80번 포트를 사용해야하는 것은 아님

Well-Known 포트

서비스 이름 포트 번호
FTP 20, 21
SSH 22
TELNET 23
DNS 53
DHCP 67, 68
TFTP 69
HTTP 80
HTTPS 443

유명한 서버들이 쓰는 포트 번호

  Registered 포트

서비스 이름 포트 번호
오라클 DB 서버 1521
MySQL 서버 3306
MS 원격 데스크탑 3389

일반 사용자들이 사용하는 포트는 Dynamic 포트라고 하며 49152번 ~ 65535번 중 사용


실습

현재 포트 활성 여부를 나타내는 활성 연결 테이블 확인하기

netstat -ano

활성 연결 테이블의 PID와 작업 관리자에서 프로그램의 PID 확인해보기

작업관리자 열에서 우클릭해서 PID를 활성화하면 PID 확인 가능

Berryz WebShare 사용해보기

Berryz WebShare 다운로드

서버 컴퓨터로 만들어주는 프로그램

1. 압축 해체 후 프로그램 Webshare.exe 실행

2. 환경 설정에서 포트번호를 9999 로 변경

3. 할당된 주소(그림에서는 192.168.219.104)로 접속해보기

접속 불가능 서버는 포트를 80번이라고 생각하고 있기 때문

 

주소 뒤에 서버 포트 번호를 따로 입력해줄 경우 접속 가능


네이버 주소에 뒤에 :443 붙여서 접속해보기

정상적으로 접속되는 것을 확인할 수 있음 (https 포트 번호는 443이다)


참고자료

https://www.youtube.com/watch?v=tG0ldt4sBzY&list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi&index=16

위 강의를 보고 정리한 글입니다.

 

아래 코드에서 state가 변경될 때마다, console.log가 실행된다.

첫 번째 render할 때만 실행하고 싶다면?

import { useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("call an API");
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

 

useEffect

  • 컴포넌트 안에 딱 한 번만 실행하고 싶은 코드가 있을 경우
  • 컴포넌트 안에 특정 데이터가 변화할 때만 실행해야하는 경우
  • dependencies: React가 지켜봐야하는 것
    • dependencies가 [] (빈 리스트)이면 지켜봐야할 것이 없다 = 한 번만 실행
import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("I run all the time");
  const iRunOnlyOnce = () => {
    console.log("I run only once");
  };
  useEffect(iRunOnlyOnce, []);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

예제 - 검색창 작동 방식

import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("i run only once");
  }, []);
  console.log("SEARCH FOR", keyword);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

Problem

  • input에 있는 단어가 변경될 때마다 SEARCH FOR 실행
  • 검색과 관련 없는 button을 onClick시에도 SEARCH FOR 실행

Scratch

useEffect를 사용, 두 번째 인자에 keyword 변수 사용
useEffect(() => {
  console.log("SEARCH FOR", keyword);
}, [keyword]);
import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("i run only once");
  }, []);
  useEffect(() => {
    console.log("SEARCH FOR", keyword);
  }, [keyword]);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

Scratch 2

처음에 SEARCH FOR가 실행되는 것을 막으려면 if문으로 조건을 추가해주는  방법이 있다

useEffect(() => {
  if (keyword.length > 0) {
    console.log("SEARCH FOR", keyword);
  }
}, [keyword]);

예제 - useEffect 작동 확인

import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => {
    setKeyword(event.target.value);
  };
  console.log("I run all the time");
  useEffect(() => {
    console.log("I run only once");
  }, []);
  useEffect(() => {
    console.log("I run when 'keyword' changes.");
  }, [keyword]);
  useEffect(() => {
    console.log("I run when 'counter' changes.");
  }, [counter]);
  useEffect(() => {
    console.log("I run when 'keyword' and 'counter' changes.");
  }, [keyword, counter]);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here"
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

cleanup function

react는 컴포넌트를 destroy할 때도 함수를 사용 가능

아래 코드에서 Hello 컴포넌트가 사라질 때, useEffect 안의 함수의 return문이 실행

- Nico는 거의 사용하지 않는다고 했음

import { useEffect, useState } from "react";

function Hello() {
  useEffect(() => {
    console.log("created!");
    return () => console.log("detroyed!");
  }, []);
  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = () => setShowing((prev) => !prev);
  return (
    <div>
      {showing ? <Hello /> : null}
      <button onClick={onClick}>{showing ? "Hide" : "Show"}</button>
    </div>
  );
}

export default App;

Component Life Cycle

위의 useEffect는 React에서 Hooks라는 개념

이 이전에는 React를 class 형태로 사용했었다. 

  • Mounting
    • constructor: render 되기 전에 호출
    • componentDidMount: component가 처음 rendering되었을 때 실행, useEffect의 dependencies가 빈 리스트일 경우와 동일
  • Updating
    • componentDidUpdate: state가 변경점이 생겨, 새로 rendering된 경우에 실행
  • Unmounting
    • componentWillUnmount: component가 사라질 경우에 호출 (페이지 이동 시)
import React from "react";

class App extends React.Component {
  componentDidMount() {
    console.log("component rendered");
  }
  render() {
    console.log("I am rendering");
    return;
  }
}

export default App;
// Result
// I am rendering
// component rendered

 

'React' 카테고리의 다른 글

[React 기초] 07. 예제 - Coin tracker  (0) 2023.08.10
[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 04. create-react-app  (0) 2023.08.10
[React 기초] 03. Props  (0) 2023.08.02
[React 기초] 02. State  (0) 2023.08.02

https://create-react-app.dev/

 

Create React App

Set up a modern web app by running one command.

create-react-app.dev

실행하기 위해서는  NodeJS가 필요함

npx는 패키지 실행을 위한 도구로, 패키지의 최신버전 파일을 불러와 설치하여 실행시키고 실행된 이후에 해당 패키지를 제거하는 방식

npx create-react-app my-app
  • my-app으로 파일 생성되고 안에 패키지가 설치됨
  • package에 기본적인 명령어가 설정되어 있음
  • 개발용 server를 열게됨

package.json에서 기본적으로 설정된 명령어를 scripts에서 확인 가능

살펴보기

index.js에서 App을 랜더링하고 있음
css를 import 할 수 있음
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./style.css";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
App.js에서 컴포넌트를 불러옴
// App.js
import Button from "./Button";

function App() {
  return (
    <div>
      <h1>Wecome back!</h1>
      <Button text={"continue"} />
    </div>
  );
}

export default App;
각 컴포넌트를 사용할 시 export 해줘야 함
// Button.js
import PropTypes from "prop-types";

function Button({ text }) {
  return <button>{text}</button>;
}
Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

CSS 적용하기

1. 한 style.css 파일에 모든 내용 저장

2. 각각의 컴포넌트마다 style 지정

3. Divide & Conquer

 

각각의 컴포넌트마다 style 지정
import PropTypes from "prop-types";

function Button({ text }) {
  return (
    <button
      style={{
        color: "white",
        backgroundColor: "tomato",
      }}
    >
      {text}
    </button>
  );
}
Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;
Divide & Conquer
/* Button.module.css */
.btn {
  color: white;
  background-color: tomato;
}
// Button.js
import PropTypes from "prop-types";
import styles from "./Button.module.css";

function Button({ text }) {
  return <button className={styles.btn}>{text}</button>;
}
Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

이렇게 할 경우, 실제 브라우저에서 해당 페이지가 랜더링 될 때, class 이름은 btn-xxxx 이런 식으로 무작위로 들어감.

다른 곳에서 같은 class 이름을 사용하여도 겹치지 않음!

위에서 JSX를 사용할 때, JS에서 class는 예약어라서 className으로 속성 값 부여

마찬가지로 for도 JSX 속성값으로 줄 경우, htmlFor로 사용

'React' 카테고리의 다른 글

[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 05. effects  (0) 2023.08.10
[React 기초] 03. Props  (0) 2023.08.02
[React 기초] 02. State  (0) 2023.08.02
[React 기초] 01. Basics of React JS  (0) 2023.08.02

IPv4 프로토콜

IPv4가 하는 일

  • 네트워크 상에서 데이터를 교환하기 위한 프로토콜
  • 데이터가 정확하게 전달될 것을 보장하지 않는다
  • 중복된 패킷을 전달하거나 패킷의 순서를 잘못 전달할 가능성도 있다 (악의적으로 이용하면 DoS 공격)
  • 데이터의 정확하고 순차적인 전달은 그보다 상위 프로토콜인 TCP에서 보장

다른 네트워크의 특정 대상을 찾는 IPv4 프로토콜

  • 보통 IP Option은 거의 사용하지 않고 20 Bytes 사용
  • Header는 20 ~ 60bits인데 주어진 건 4칸? (4bit - 최대로 표현할 수 있는 수 15) => Header / 4  수를 씀
    일반적으로 5 사용
  • TOS는 현재 사용하지 않음 => 0
  • Total Length: Header + Payload의 길이
  • Identification와 IP Flags, Fragment Offset은 하나의 셋트라고 생각 
    • Identification: 잘게 잘라서 온 데이터를 알아볼 수 있도록 하는 ID
    • Flag Flags: 3bit로 이루어져 있음
      • x: 사용하지 않음
      • D: 데이터를 조각내지 않고 통으로 보낼 때 설정 (최대 전송단위보다 클 경우 데이터 전송 안됨)
      • M: 조각화가 되어있을 경우, 최대 전송단위보다 더 커서 뒤에 데이터가 있을 경우 1로 설정됨
    • Fragment Offset: 데이터 시작 부분부터 떨어진 순서 (조각난 데이터의 순서) / 8 되어 있음
  • TTL: 패킷이 살아있는 시간 (3계층 Router를 지날 때마다 1씩 차감됨)
    • 운영체제마다 다르게 설정됨, 이걸로 상대방 컴퓨터 운영체제를 유추할 수 있음
      • windows 128
      • linus 64
  • Protocol: 상위 프로토콜이 뭔지 알려줌
    • ICMP (3계층): 01
    • TCP (4계층): 06
    • UDP (4계층) 11 (십진수로 17)
  • Header Checksum: 앞 부분을 검증하는 용도


 

ICMP 프로토콜

ICMP가 하는 일

  • Internet Control Message Protocol  인터넷 제어 메세지 프로토콜
  • 네트워크 컴퓨터 위에서 돌아가는 운영체제에서 오류 메세지를 전송 받는데 주로 사용
  • 프로토콜 구조의  Type과 Code를 통해 오류 메세지를 전송 받음

특정 대상과 내가 통신이 잘되는지 확인하는 ICMP 프로토콜

  • Type: 카테고리
    • 기본
      • 0: Echo Reply (응답)
      • 8: Echo (요청)
    • 뭔가 잘못됐을 때
      • 3: Destination Unreachable (목적지까지 가지를 못함 ex 상대방 방화벽)
      • 11: Time Exceded (목적지까지는 갔는데, 응답 x)
    • 보안
      • 5: Redirect
  • Code: Type에서 분류한 것의 소분류


실습

wireshark

ICMP 확인

IPv4 확인


라우팅 테이블

어디로 보내야 하는지 설정되어 있는 라우팅 테이블

다른 네트워크 대역을 찾아가기 위한 지도

 


다른 네트워크와 통신 과정

내 컴퓨터에서 보낸 패킷이 다른 네트워크의 컴퓨터까지 이동 과정

요청 과정

요청을 받은 B는 역과정으로  A에게 응답을 보냄

 


실습

cmd에서 아래 커맨드 입력

netstat -r

 


IPv4의 조각화

조각화란?

  • 큰 IP 패킷들이 적은 Maximum Transmission Unit(MTU)(보통 1500 byte)를 갖는 링크를 통하여 전송되려면 여러개의 작은 패킷으로 쪼개어(조각화)되어 전송돼야 함
  • 목적지까지 패킷을 전달하는 과정에 통과하는 각 라우터마다 전송에 적합한 프레임으로 변환 필요
  • 일단 조각화 되면, 최종 목적지에 도달할 때까지 재조립되지 않는 것이 일반적
  • IPv4에서는 발신지 뿐만 아니라 중간 라우터에서도 IP 조각화가 가능
  • IPv6에서는 IP단편화가 발신지에서만 가능
  • 재조립은 항상 최종 수신지에서만 가능

여러 개의 패킷으로 조각화된 패킷

실제로는 보통 한 번만 조각화됨


실습

예시 문제

  • 보내려는 데이터 크기: 2379
  • MTU: 980
  • 몇개의 패킷으로 쪼개지는가?
  • 첫번째 패킷의 데이터 크기는 몇인가?
  • 마지막 패킷의 데이터의 크기는 몇인가?

예시 풀이

  • 헤더를 제외한 페이로드의 최대 크기: 980 – 20 = 960
  • 필요한 패킷의 수 = 2379 / 960 = 2/48 => 3개의 패킷 필요
  • 첫 번째 패킷의 데이터 크기: 헤더를 제외한 960 + 헤더 20 = 980
  • 마지막 패킷의 데이터 크기 = 남은 데이터 2379 - 960 - 960 = 459 + 헤더 20 => 479

참고자료

https://www.youtube.com/watch?v=_i8O_o2ozlE&list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi&index=9

위 강의를 보고 정리한 글입니다.

 

Props

  • 부모 컴포넌트로부터 자식 컴포넌트에 데이터를 보낼 수 있는 방법
  • 스타일을 저장한 컴포넌트를 재사용할 수 있다면?
  • 함수형태로 만든 컴포넌트에 인자 props를 전달 가능
  • props는 object형태로 받아서 props.property 형태로 인자 전달 가능
function Btn(props) {
  console.log(props);
  return (
    <button
      style={{
        backgroundColor: "tomato",
        color: "white",
        padding: "10px 20px",
        border: 0,
        borderRadius: "10px",
      }}
    >
      {props.potato}
    </button>
  );
}
function ConfirmBtn() {
  return <button>Confirm</button>;
}
function App() {
  return (
    <div>
      <Btn potato="Save Changes" />
      <Btn potato="Continue" />
    </div>
  );
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
JS 문법을 이용해서 props 부분 짧게 쓰는 방법
function Btn({ potato }) {
  return <button> {potato} </button>;
}
응용
function Btn({text, big})
  return (
    <button
    style={{
      fontSize: big ? 18: 10,
      }}
    >
      {text}
    </button>;
  )
function App() {
  return (
    <div>
      <Btn text="Save Changes" big={true}/>
      <Btn text="Continue" big={false}/>
    </div>
  );
}
내가 직접 만든 컴포넌트에 준 props 값은 return 값에 자동으로 들어가는 것이 아님!
내가 만든 Btn에 onClick 이벤트를 추가하려면, 실제로는 props.onClick 속성 값으로 들어감
따라서 실제 return 값에 있는 button 태그에 onClick 이벤트를 추가하고
props.onClick 값을 추가해줘야 함
function Btn({ text, onClick }) {
  return (
    <button
      onClick={onClick}
      style={{
        backgroundColor: "tomato",
        color: "white",
        padding: "10px 20px",
        border: 0,
        borderRadius: "10px",
      }}
    >
      {text}
    </button>
  );
}
function App() {
  const [value, setValue] = React.useState("Save Changes");
  const changeValue = () => setValue("Revert Changes");
  return (
    <div>
      <Btn text={value} onClick={changeValue} />
      <Btn text="Continue" />
    </div>
  );
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);

memo

바뀌는 것만 render 하기
전체를 re-render하는 것이 아니라 컴포넌트의 변경점이 있는 컴포넌트만 re-render할 수 있다
const MemorizedBtn = React.memo(Btn);
function Btn({ text, onClick }) {
  console.log(`${text} was rendered`);
  return (
    <button
      onClick={onClick}
      style={{
        backgroundColor: "tomato",
        color: "white",
        padding: "10px 20px",
        border: 0,
        borderRadius: "10px",
      }}
    >
      {text}
    </button>
  );
}
const MemorizedBtn = React.memo(Btn);
function App() {
  const [value, setValue] = React.useState("Save Changes");
  const changeValue = () => setValue("Revert Changes");
  return (
    <div>
      <MemorizedBtn text={value} onClick={changeValue} />
      <MemorizedBtn text="Continue" />
    </div>
  );
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);

PropTypes

Proptypes package는 어떤 타입의 props을 받고 있는지 체크할 수 있다
전체적인 버전에 따라서 작동 여부가 달라지는 것 같다

아래 버전으로 했을 때 정상 작동되는 것을 확인했음

<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
function Btn({ text, fontSize = 16 }) {
  return (
    <button
      style={{
        backgroundColor: "tomato",
        color: "white",
        padding: "10px 20px",
        border: 0,
        borderRadius: "10px",
        fontSize,
      }}
    >
      {text}
    </button>
  );
}
Btn.propTypes = {
  text: PropTypes.string.isRequired,
  fontSize: PropTypes.number,
};
function App() {
  return (
    <div>
      <Btn text="Save Changes" fontSize={18} />
      <Btn text={18} fontSize={"continue"} />
    </div>
  );
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);

'React' 카테고리의 다른 글

[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 05. effects  (0) 2023.08.10
[React 기초] 04. create-react-app  (0) 2023.08.10
[React 기초] 02. State  (0) 2023.08.02
[React 기초] 01. Basics of React JS  (0) 2023.08.02

State

  • state: 데이터가 저장되는 곳
  • 아래 예시에서 counter의 숫자 부분을 state로 대체 가능
  • 버튼을 누를 때 전체가 render되게 됨
  • 이렇게 구현해도 개발자 도구로 버튼을 누를 때마다 바뀌는 부분을 확인하면, 해당 부분 숫자만 바뀌는 것을 확인할 수있음 - react 짱
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Begin React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.9/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    let counter = 0;
    function countUp() {
      counter = counter + 1;
      render();
    }
    function render() {
      ReactDOM.render(<Container />, root);
    }
    const Container = () => (
      <div>
        <h3>Total clicks: {counter}</h3>
        <button onClick={countUp}>Click me</button>
      </div>
    );
    ReactDOM.render(<Container />, root);
  </script>
</html>
조금 더 rendering을 편하게 하는 방법은 없을까?

useState

[추가팁] JS 문법 
const food = ["tomato", "potato"];
const [myFavFood, mySecondFavFood] = food;
// same as myFavFood = food[0];, mySecondFavFood = food[1];
// myFavFood
// 'tomato'
useState를 사용해서 바뀐 부분과 함께 render
const [counter, setCounter] = React.useState(0);
const onClick = () => {
// modifier function은 값을 변화시킨 다음에 rerender 시켜줌
setCounter(counter + 1);
};
modifier function alpha; 변수를 통한 직접적인 값 변화보다는 함수로 처리하는 것이 더 안전
const [counter, setCounter] = React.useState(0);
const onClick = () => {
  // modifier function은 값을 변화시킨 다음에 rerender 시켜줌
  // setCounter(counter + 1);
  setCounter((current) => current + 1);
};

최종 코드

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Begin React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.9/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      const [counter, setCounter] = React.useState(0);
      const onClick = () => {
        // modifier function은 값을 변화시킨 다음에 rerender 시켜줌
        // setCounter(counter + 1);
        setCounter((current) => current + 1);
      };
      return (
        <div>
          <h3>Total clicks: {counter}</h3>
          <button onClick={onClick}>Click me</button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

유의 사항

JSX를 사용할 때는 JSX에 맞는 프로퍼티를 사용해야 함

  • class -> className
  • for -> htmlFor

React는 SyntheticBaseEvent를 발생시킴, 그 안에 nativeEvent 속성 값이 있음


분을 시간으로 환산해주는 계산기 만들어보기

  • minutes에 값을 입력하면 hour로 변환
  • input에 값을 입력 시, onChange 이벤트가 발생
  • onChange 이벤트는 setMinutes()를 작동
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Begin React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.9/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      const [minutes, setMinutes] = React.useState(0);
      const onChange = (event) => {
        // console.log(event.target.value);
        setMinutes(event.target.value);
      };
      const reset = () => setMinutes(0);
      return (
        <div>
          <h1>Super Converter</h1>
          <label htmlFor="minutes">Minutes</label>
          <input
            id="minutes"
            placeholder="Minute"
            type="number"
            value={minutes}
            onChange={onChange}
          />
          <br></br>
          <label htmlFor="hours">Hours</label>
          <input
            id="hours"
            placeholder="Hours"
            type="number"
            disabled
            value={Math.round(minutes / 60)}
          />
          <br></br>
          <button onClick={reset}>Reset</button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

시간도 분으로 계산할 수 있도록 개선해보기

  • hour input 태그에도 onChange 함수 적용
  • onFlip 이라는 변수로 현재 flipped된 상태인지 아닌지 구분
  • tenary syntax로 onFlip 변수의 상태마다 value 값이 다르게 출력될 수 있도록 함
  • tenary syntax로 onFlip 변수의 상태마다 disabled가 적용될 수 있도록 함
  • tenary syntax로 onFlip 변수의 상태마다 button의 value 값이 적용될 수 있도록 함
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Begin React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.9/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      const [amount, setAmount] = React.useState(0);
      const [flipped, setFlipped] = React.useState(false);
      const onChange = (event) => {
        // console.log(event.target.value);
        setAmount(event.target.value);
      };
      const reset = () => setAmount(0);
      // const onFlip = () => setflip(!flipped);
      const onFlip = () => {
        setFlipped((current) => !current);
        reset();
      };
      return (
        <div>
          <h1>Super Converter</h1>
          <label htmlFor="minutes">Minutes</label>
          <input
            id="minutes"
            placeholder="Minute"
            type="number"
            onChange={onChange}
            value={flipped ? amount * 60 : amount}
            disabled={flipped}
          />
          <br></br>
          <label htmlFor="hours">Hours</label>
          <input
            id="hours"
            placeholder="Hours"
            type="number"
            onChange={onChange}
            value={flipped ? amount : Math.round(amount / 60)}
            disabled={flipped === false}
          />
          <br></br>
          <button onClick={reset}>Reset</button>
          <button onClick={onFlip}>
            {flipped ? "Minutes to Hours" : "Hours to Minutes"}
          </button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

Class 사용 예시

import React from "react";

class App extends React.Component {
  state = {
    count: 0,
  };
  plus = () => {
    this.setState((current) => ({ count: current.count + 1 }));
  };
  minus = () => {
    this.setState((current) => ({ count: current.count - 1 }));
  };
  render() {
    return (
      <div>
        <h1>The number is {this.state.count}</h1>
        <button onClick={this.plus}>plus</button>
        <button onClick={this.minus}>minus</button>
      </div>
    );
  }
}

export default App;

'React' 카테고리의 다른 글

[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 05. effects  (0) 2023.08.10
[React 기초] 04. create-react-app  (0) 2023.08.10
[React 기초] 03. Props  (0) 2023.08.02
[React 기초] 01. Basics of React JS  (0) 2023.08.02

React JS를 사용하는 이유?

React JS는 UI를  interactive하게 해준다!

Vanilla JS

  • html 요소를 먼저 생성
  • 먼저 생성한 html 요소를 JS에서 지정 및 조작
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Vanilla</title>
  </head>
  <body>
    <h3>Total clicks: 0</h3>
    <button id="btn">Click me</button>
  </body>
  <script>
    let counter = 0;
    const button = document.querySelector("#btn");
    const h3 = document.querySelector("h3");
    function handdleClick() {
      counter = counter + 1;
      h3.innerText = `Total clicks: ${counter}`;
    }
    button.addEventListener("click", handdleClick);
  </script>
</html>

React JS

  • html에 직접 작성 x
  • React object를 먼저 생성, ReactDOM으로 React object를 html에 작성

얻을 수 있는 효과

  • React JS가 결과물인 html을 업데이트 가능 => 유저에게 보여질 내용을 컨트롤할 수 있다
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Begin React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
  <script>
    const root = document.getElementById("root");
    const span = React.createElement(
      "span",
      { id: "sexy-span", style: { color: "red" } },
      "Hello I am a span"
    );
    ReactDOM.render(span, root);
  </script>
</html>
addEventListner를 속성처럼 부여할 수 있음
const btn = React.createElement(
  "button",
  {
    onClick: () => console.log("im clicked"),
  },
  "Click me"
);

 


JSX

  • React 요소를 편하게, 직관적으로 작성할 수 있게 해줌
  • 코드를 브라우저가 이해할 수 있게 Babel를 사용하여 변환해줘야 함
JSX 적용 전
const span = React.createElement(
  "span",
  {
    id: "title",
    onMouseEnter: () => console.log("mouse enter"),
  },
  "Hello I am a span"
);
const btn = React.createElement(
  "button",
  {
    onClick: () => console.log("im clicked"),
    style: {
      backgroundColor: "tomato",
    },
  },
  "Click me"
);
JSX 적용 후
const Title = (
  <span id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I am a span
  </span>
);
const Button = (
  <button
    onClick={() => console.log("im clicked")}
    style={{
      backgroundColor: "tomato",
    }}
  >
    Click me
  </button>
);

Babel

  • JSX를 브라우저가 이해할 수 있도록 babel-standalone 설치
  • 기존 script 타입을 "text/babel"로 지정
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.9/babel.min.js"></script>
<script type="text/babel">
  ...
</script>

Container 안에 컴포넌트 넣기

각 컴포넌트를 모두 함수 형태로 바꿔주기 (각 컴포넌트는 대문자로 시작해야함)
const Title = () => (
  <span id="title" onMouseEnter={() => console.log("mouse enter")}>
    Hello I am a span
  </span>
);
const Button = () => (
  <button
    onClick={() => console.log("im clicked")}
    style={{
      backgroundColor: "tomato",
    }}
  >
    Click me
  </button>
);

 

아래 형태로 넣어주기 (각 컴포넌트는 대문자로 시작해야함, 소문자로 사용할 경우 기존의 태그로 인식)
const Container = () => (
  <div>
    <Title />
    <Button />
  </div>
);
ReactDOM.render(<Container />, root);

'React' 카테고리의 다른 글

[React 기초] 06. 예제 - Todo List  (0) 2023.08.10
[React 기초] 05. effects  (0) 2023.08.10
[React 기초] 04. create-react-app  (0) 2023.08.10
[React 기초] 03. Props  (0) 2023.08.02
[React 기초] 02. State  (0) 2023.08.02

ARP 프로토콜

ARP가 하는 일

IP 주소를 이용해 MAC 주소를 알아옴

  • ARP 프로토콜은 같은 네트워크 대역에서 통신을 하기 위해 필요한 MAC 주소를 IP 주소를 이용해 알아오는 프로토콜
  • 같은 네트워크 대역에 통신을 하더라도, 데이터를 보내기 위해서는 7 계층부터 캡슐화를 통해 데이터를 보내기 때문에 IP주소와 MAC 주소 모두 필요 => IP 주소는 알고 MAC 주소는 모르는 경우에도, ARP를 통해 통신 가능

ARP의 구조

ARP의 구조


 

ARP 프로토콜의 통신 과정

IP 주소로 MAC 주소를 알아오는 과정

A 컴퓨터가 MAC 주소를 모르는 C 컴퓨터로 ARP 요청을 보내려고 함

  • ARP에는 목적지의 MAC 주소가 들어가는데 어떻게 요청을 보내지?

Ethernet의 목적지 MAC 주소를 전부다 1로 하고 (FF)  (브로드캐스트) 보냄

모르는 상태로 전달

2 계층 통신 장비인 스위치는 2 계층인 ethernet만 디캡슐레이션함.

목적지 MAC주소가 브로드캐스트로 설정되어 있으므로 같은 네트워크 대역에 전부다 전달

 

목적지에 전달해서 각 컴퓨터는 2계층 신호를 디캡슐레이션하고  맞는 것을 확인 (브로드캐스트)

그 다음 3계층 신호를 디캡슐레이션하여 확인함

그 과정에서 IP 주소를 확인하게 됨

컴퓨터의 IP 주소와 목적지의 IP 주소가 같지 않을 경우 패킷을 버림

C에서 응답을 보내줌

응답이라서 두 번째줄 끝이 1로 끝나는 것을 확인할 수 있음

응답이라서 목적지와 출발지가 바뀐 것을 볼 수 있음

목적지는 출발지이기 때문에 MAC 주소를 알 수 있음

A에서는 응답을 받고, ARP 캐시 테이블에 MAC 주소를 등록함


ARP 테이블

통신했던 컴퓨터들의 주소는 ARP 테이블에 남음


실습

ARP 테이블 확인해보기

cmd 실행

arp -a

ARP 프로토콜 분석하기

wireshark 실행 후, Protocol에서 ARP만 필터

  • Who has ~ ?: 요청
  • 나머지: 응답

 

다른 IP 주소에 ping 해보고,  wireshark 확인

ping 192.168.219.100

 Ethernet의 목적지 MAC 주소에 ff:ff:ff:ff:ff:ff 인 것을 확인할 수 있다


참고자료

https://www.youtube.com/watch?v=-M_S50Ga384&list=PL0d8NnikouEWcF1jJueLdjRIC4HsUlULi&index=8

위 강의를 보고 정리한 글입니다.

 

+ Recent posts