Elastic Compute Cloud

ECC -> EC2

 

유동적인(탄력적인) 컴퓨터 클라우드

 

EC2 사용시 지불방법

1. on-demand : 시간단위로 가격이 고정되어 있음. 개발 초기단계, 유연한 크기 설정 가능

개발 시작 시간, 개발 끝나는 시간을 알수 없는 경우, 단기간에 개발을 할 수 있는경우, 개발 초기단계에서 EC2인스턴스에 테스트를 해볼때 적합함

 

2. reserved : 한정된 EC2 용량 사용가능, 지정석, 크기를 늘이고 줄이는 기능 없음, on-demand 보다 가격이 저렴함.

개발의 시작과 끝을 미리 알 수 있는 경우에 적합. 예상가능한 워크로드시 지정해두고 할인받아 사용가능

 

3. spot : 입찰 가격 적용, 가장 큰 할인률을 적용받을 수 있음. 

 

 

EC2는 어떻게 작동되는가? 무엇으로 구성되어있는가?

EBS : EC2 안에 부착되어있는 가상 디스크 

 

다양한 볼륨이 존재하므로 적절한 선택이 필요함

EBS 란? Elastic Block Storage

저장공간이 생성되어지며 EC2 인스턴스에 부착된다

디스크 볼륨 위에 File System이 생성된다

EBS는 특정 Availability Zone에 생성된다

 

Availability Zone(AZ)는 뭘까?

일명 가용 영역 = 데이터 센터 = IDC

하나의 Region(aws 제공 인프라 위치, 서울, 도쿄, 미국 등) 안에 여러개의 AZ가 존재할 수 있다.

일종의 DR(Disaster Recovery) 

 

다시 EBS로 돌아와서 볼륨 타입

<SSD군>

1) General Purpose SSD(GP2) : 최대 10K IOPS 지원, 1GB당 3IOPS 속도가 나옴

2) Provisioned IOPS SSD(IO1) : 극도의 I/O률을 요구(매우 큰 DB관리) 환경에서 주로 사용. 10K이상의 IOPS를 지원

 

<Magnetic/HDD군>

1) Throughput Optimized HDD(ST1) : 빅데이터, 로그 프로세싱시 주로 사용, boot 볼륨으로 사용 불가(os없음)

2) CDD HDD(SC1) : 파일서버와 같이 빈번한 입출력 없이 오랫동안 데이터 보관용, boot 볼륨으로 사용 불가

3) Magnetic (Sandard) : 가장 저렴, boot 볼륨으로 사용 가능

 

 

ELB(Elastic Load Balancers)

수많은 서버의 흐름을 균형있게 흘려보내주는 역할

병목현상 방지

 EC2 인스턴스가 unhealty 인스턴스가 되는경우 healty 인스턴스로 보내주는 역할

 

ELB종류

특정상황 - 어떤 ELB를 적절하게 사용해야 하는지

1) Application Load Balancer : OSI 7에서 작동됨,

HTTP, HTTPS같은 트래픽의 로드밸런싱 역할

라우팅설정을 따로 할 수 있어서, 특정 서버로 트래픽을 보내줄수 있다 (커스터마이징 가능)

 

2) Network Load Balancer : OSI 4에서 작동됨

극도의 퍼포먼스가 요구되는 TCP 트래픽에 적합함

구글이나 네이버같은 큰 서버에서 적합함

 

3) Classic Load Balancer : 현재 legacy로 간주됨, 따라서 거의 쓰이지 않음.

Layer7의 HTTP. HTTPS 라우팅 기능 지원

Layer4의 TCP 트래픽 라우팅 기능 지원

 

에러 처리

Load Balancer Error : 504 Error

주로 웹서버/데이터베이스 레이어에서 에러처리

 

X-Forwarded-For 헤더

public IP 주소로 접속(152.12.3.225)

DNS 를 통해

ELB에 도달 (private IP 10.0.0.23)

EC2(10.0.0.23) 으로 요청 보냄

 

-> EC2는 private IP 만 알수 있다. 즉 DNS에서 변환된 Private IP만 알수있으므로, 실제 요청의 원천은 알 수 없다

-> 이를 위해 X-Forwarded-For 헤더를 사용

 

Route53

AWS에서 제공하는 DNS 서비스

EC2 인스턴스/S3 Bucket / Load Balancer 서비스들에게 이름을 부여해주는 서비스

도메인 주소를 구매하여 연결

 

1. 도메인 등록(유료) 또는 타 사이트에서 도메인 생성

IAM 이란?

클라우드 사용자(유저)를 관리(권한 등)

 

1. 유저별로 다른 권한 부여기능(A: 데이터베이스 읽기 권한만 부여/ B: 데이터베이스 테이블 생성 권한만 부여)

2. 모든 유저들에게 비밀번호를 강제로 변경하도록 기한 설정 가능

3. MFA 다중인증 기능 : 루트유저는 필수

 

루트 유저로 생성할 수 있는 것

1) 그룹 : 유저 묶음

2) 유저

3) 역할

4) 정책 : json 형태로 되어있는 document를 가리킨다. 세밀한 접근권한을 일일히 설정하여 하나의 정책 document 생성

 

IAM 은 universal 하다 

universal (전역적) <-> regional (지역적)

 

IAM 정책 시뮬레이터(IAM과 관련 문제 디버깅하기 위한 툴)

1. 개발환경(Staging or Develop)에서 실제환경(Production)으로 빌드하기 전 IAM 정책이 잘 작동되는지 테스트하기 위함

2. IAM과 관련된 문제들을 디버깅하기에 최적화된 툴(이미 실제로 유저에 부여된 다양한 정책들도 테스트 가능)

 

 

[실습]

aws 콘솔에 로그인 - IAM 서비스

사용자 추가

1. 사용자(유저) 클릭 

2. 사용자 추가

3. 사용자 이름 설정

4. AWS 액세스 유형 선택

- 프로그래밍 방식 액세스 : 처음 유저를 생성할 때 액세스키/시크릿키 부여하고 그 키를 통해 접근

- 암호 : 콘솔에 로그인할 수 있도록 비밀번호 부여

두가지 다 선택, 또는 한가지만 선택 가능

 

5. 나머지 모두 디폴트 선택으로 진행

6. 사용자 추가 완료

 

그룹 추가

1. 그룹이름 지정

2. 디폴트로 진행

3. 그룹 추가 완료

 

사용자 그룹 지정

1. 그룹 클릭

2. 사용자 추가

3. 그룹에 사용자 추가 완료

 

정책

정책생성방법

1. GUI방법

2. json 도큐먼트 직접 작성

json 예시

 

유저에게 정책 추가 전 IAM 정책 시뮬레이터

: 유저별로 어떤 기능이 허용인지, 거절인지 바로 돌려볼 수 있다.

aws_user1은 아무런 정책을 갖고 있지 않기 때문에 모두 denied 거절 당한다.

 

유저에 정책 추가

 

유저에게 정책 추가 후 정책 시뮬레이터

 

'programming > Web' 카테고리의 다른 글

HMAC : API 통신 클라이언트 무결성 검증 방법  (0) 2022.06.28
AWS - EC2(EBS/AZ/ELB)  (0) 2022.04.06
API, SDK, Library, Framework  (0) 2022.03.10
CSS3 특성 선택자(Selector)  (0) 2022.03.05
REST Service에 대하여  (0) 2022.03.05

1. 명령어로 구분

package.json에 script : start/build/test 각각의 스크립트가 있음

-> 배포시 build.gradle에 npm build 명령어가 들어있음

 

2. .env 파일에서 환경변수 사용

두개의 분리된 dotEnv 파일 생성

.env.development : 개발용 환경변수

.env.production : 상용 환경변수

 

원리) Creact-React-App으로 리액트를 만들고 npm 스크립트를 실행할 때 스크립트 명령어별로 env 파일의 적용 우선순위가 있다.

 

script 명령어 별 env 파일 우선순위

  • npm start : .env.development.local, .env.local, .env.development, .env
  • npm build : .env.production.local, .env.local, .env.production, .env
  • npm test : .env.test.local, .env.test, .env

 

3. 각각의 파일에서 REACT_APP으로 시작하는 baseURL 설정

//.env.development
REACT_APP_BASE_URL = http://localhost:3000
//.env.production
REACT_APP_BASE_URL = http:hello.com

 

5. axios config 또는 rootSaga 에서 설정한 환경변수 사용

baseURL : process.env.REACT_APP_BASE_URL

// rootSaga.js
axios.defaults.baseURL = process.env.REACT_APP_BASE_URL;

 

데이터타입

 

원시값

String, Number, Boolean, Null, Undefined

-> 자동 깊은 복사, 다른 메모리에 값 자체를 할당

 

참조값

Object, Symbol

-> 얕은 복사, 가리키는 주소를 복사

 

얕은 복사

객체를 가리키는 주소를 같이쓰는것

바꾸면 같이 따라서 바뀌어 버린다

 

깊은 복사

  • spread 연산자 사용 (1 depth 까지만)
  • Object.assign() 메소드 사용 (1 depth 까지만)

 

완벽한 깊은 복사 방법

  • 재귀적으로 깊은 복사 수행
  • Lodash의 cloneDeep 함수 사용 (라이브러리)
  • JSON.parse()와 JSON.Stringify() 함수 사용
    • JSON.stringify()는 객체를 json문자열로 변환한다. 이 과정에서 원본객체와 참조가 모두 끊어진다.
    • JSON.stringify()로 관계를 끊어버리고, 다시 JSON.parse()하여 객체형태로 만든다.
    • 단점 ; 느림
const obj = {
  a: 1,
  b: {
    c: 2,
  },
};

const copiedObj = JSON.parse(JSON.stringify(obj));

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false

Javascript 에서는 객체를 상속하기 위해 프로토타입이라는 방식을 사용한다.

이미 존재하는 생성자에게 메소드를 추가하기 위해 프로토타입 속성을 사용하는 법을 알아보자

 

자바스크립트는 프로토타입기반 언어라고도 불리운다

모든 객체들이 그들의 프로토타입으로 부터 메소드와 속성들을 상속받는다.

모든 객체들은 최소한 하나 이상의 다른 객체로부터 상속을 받는데, 이때 상속되는 정보를 제공하는 객체를 프로토타입이라고 한다.

 

 

동작 순서 : 프로토타입 체인

person 객체가 자체적으로 valueOf() 메소드를 가지고 있는지 체크

person의 프로토타입 객체 Person()의 생성자의 프로토타입에 valueOf() 메소드가 있는지 체크

여전히 없으므로 Person()의 생성자의 프로토타입 객체의 프로토타입 Object() 생성자의 프로토타입이 valueOf()가 있는지 체크

 

Person 자체의 prototype은 따로 지정한게없어서 내용이 없음

하지만 Person의 부모 Object의 Prototype은 내용이 많다

이를 상속 받는다

 

 

생성자의 프로토타입에 메소드를 추가하면 생성한 인스턴스들에서 모두 사용할 수 있다

 

 

일반적으로 속성은 생성자에서, 메소드는 프로토타입에서 정의한다

 

 

프로토타입 = { 프로토타입 오브젝트 + 프로토타입 링크}

 

1. 프로토타입 오브젝트

객체는 항상 함수로 만들어진다 

var person = new Person()

 

함수가 정의될 때는 2가지 일이 동시에 일어난다

1) 해당 함수에 Constructor(생성자) 자격부여

2) 해당 함수의 "Prototype Object" 생성 및 연결 => prototype 속성이 생긴다

 

2. 프로토타입 링크

__proto__ : 객체가 생성될때 조상이었던 함수의 Prototype Object를 가리킨다.

프로토타입 체인 : 연결 연결 조상까지 올라가서 필요한 값을 찾는것

 

자바스크립트는 느슨한 타입언어, 동적 타입언어, 변수의 타입을 미리 선언할 필요가 없다.

프로그램이 처리되는 과정에서 자동으로 파악되고, 같은 변수라도 상황에 따라 타입이 바뀔 수도 있다.

 

자바스크립트는 컴파일 과정 없이 실행과 동시에 해석을 하는 인터프리터 언어

 

자바스크립트의 형변환은 2가지로 일어난다 (명시적형변환/암시적 형변환)

 

1. 명시적 형변환 

string, number, boolean 타입으로 이루어진다

의도적으로 형태를 변형해서 사용하겠다는 것

String(123)
String(NaN)
Number('') //0
Number('123') //123
ParseInt('123a') //123
Boolean("") //false

 

2. 암시적 형변환

연산할 때 일어난다.

문자열이 하나라도 포함되면 문자열 연산이된다

 

// string
console.log('문자' + 1234); // 문자1234
console.log('문자' + true); // 문자true

// number
console.log(1234 + '1234'); //12341234
console.log(1234 + true); // 1235
console.log(1234 + undefined); // NaN

// boolean
console.log(true + 123); // 124
console.log(false + undefined); // NaN

// null
console.log(null + 1234); // 1234


// undefined
console.log(undefined + 1234); // NaN

 

null, undefined 차이

둘다 자료형이면서 동시에 값이다

빈값이냐, 값을 할당하지 않았냐

 

화장실에 휴지걸이가 있으면 undefined

휴지걸이에 휴지심만 있으면 null

 

null 은 명시적,

undefined는 암시적,

 

null은 코드를 작성할 때 의도적으로 명확하게 비어있다고 하는 것,

undefined 는 할당이 안된 것

 

캡처링과 버블링을 간단히 정의하면 다음과 같다.

 

  • 캡처링 - window 로부터 이벤트가 발생한 요소까지 이벤트를 전파한다.
  • 버블링 - 이벤트가 발생한 요소부터 window 까지 이벤트를 전파한다.

 

버블링

 

버블링과 캡처링

 

ko.javascript.info

버블링(bubbling)의 원리는 간단합니다.

한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작합니다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작합니다.

3개의 요소가 FORM > DIV > P 형태로 중첩된 구조를 살펴봅시다. 요소 각각에 핸들러가 할당되어 있습니다.

 

사례)

테이블의 경우에 테이블 전체(event.currentTarget)에 이벤트를 걸고 내부의 td(evnet.target)를 클릭해도 이벤트가 동작하게 할 수 있다.

 

 

버블링 중단하기

이벤트 버블링은 타깃 이벤트에서 시작해서 <html> 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생합니다. 몇몇 이벤트는 window 객체까지 거슬러 올라가기도 합니다. 이 때도 모든 핸들러가 호출됩니다.

그런데 핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 명령할 수도 있습니다.

이벤트 객체의 메서드인 event.stopPropagation()를 사용하면 됩니다.

아래 예시에서 <button>을 클릭해도 body.onclick은 동작하지 않습니다.

 

 

둘의 차이점은 단순히 방향이다.

하위 => 상위, 상위 => 하위 개념으로 보면 된다.

위의 예제의 경우는 버블링이라고 볼 수 있다.

WC3 에서 명시한 스펙의 그림을 보면 쉽게 이해할 수 있다.



 

 

제어방법

캡처링

addEventListener 메소드 세번째 인자 useCapture값을 설정

 

버블링

단순히 e.stopPropagation() 메소드를 사용하면 된다.

뭐가 좋은가?

프로그램이 종료될때 removeEventListner 확실히 제거 에러방지

 

 

API

API : Application Program Interface

all about communication : 다른서비스끼리의 의사소통 방법

응용프로그램에서 운영체제나 프로그래밍언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스

연결, 다리

/naver-map/jamsil

구현과 독립적으로 사양만 정의되어있다

API에 따라 접근권한이 필요할 수 있다

open API : 노출된 API

구성 : 요청, 

 

Library

응용 프로그램 개발을 위해 필요한 기능(함수)를 모아놓은 소프트웨어

독립성을 가진다

응용프로그램이 능동적으로 라이브러리를 사용한다

library와 API의 차이점은 구현 로직의 유무이다

 

SDK 

SDK : Software Development Kit

소스코드의 모음과 유틸리티

Tool Box

실제로 API를 호출하는 코드

java, node, go, python -> 각각의 SDK 있다

java SDK, 안드로이드 SDK,

라이브러리와 프레임워크의 중간쯤?

목적에 맞게 라이브러리들을 모아놓은거

라이브러리 -> SDK -> 프레임워크

컴퓨터가 제공하는 기본적인 명령어 -> 반복 적인 작업이 있다면, 순서대로 나열하여 이름을 붙이면 프로그램이 된다 -> 명령어의 세트

 

Framework

틀 안에서 작업

응용프로그램이나 소프트웨어의 솔루션 개발을 수월하게 하기위해 제공된 소프트웨어 환경

상호협력하는 클래스와 인터페이스의 집합이다

응용프로그램이 수동적으로 프레임워크에 의해 사용된다.

 

 

'programming > Web' 카테고리의 다른 글

AWS - EC2(EBS/AZ/ELB)  (0) 2022.04.06
[AWS] IAM 이란? (개념과 실습)  (0) 2022.04.05
CSS3 특성 선택자(Selector)  (0) 2022.03.05
REST Service에 대하여  (0) 2022.03.05
HTTP 헤더 총정리  (0) 2022.03.04

CI

Continuous Integration

 

CD

Continuous Deploy

 

github action

컨테이너를 띄워서 일련의 작업들을 할 수 있도록 해줌,

그 외 여러가지도 가능

 

github pages

github에서 제공하는 호스팅

 

TODO : vue.js를 스터디한 내용을 github에 push 하고, github action과 github pages를 사용하여 호스팅을 해보려 한다.

 

1. github push

 

생략 (add-commit-push)

 

2. github action

1) 폴더만들고 그안에 main.yaml 생성

폴더 트리 구조와 파일명을 준수해야한다

.github/workflows/main.yaml

 

2) main.yaml 파일내용

주의점은 [main] -> 배포할 브랜치를 명시, 처음에 master로 했다가 안나와서 당황

name: Deploy

on:
  push:
    branches: [main] 
  pull_request:
    branches: [main]
jobs:
  myProfile:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup nodejs
        uses: actions/setup-node@v2
        with:
          node-version: "16"
      - name: Install packages
        run: npm install
      - name: Build Vue application
        run: npm run build
      - name: Deploy Github page
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          PUBLISH_BRANCH: heros
          publish_dir: ./dist

위 코드에서 가장 아래부분이 실제 배포를 원하는 부분에 대한 설정이다

현재는 github pages를 사용하기 때문에 github pages로 배포하는 설정으로 되어있다.

만약 aws나 다른 곳으로 배포를 하고 싶다면, 이 부분을 수정하면 된다.

secret 에 대한 부분은 (github를 믿고) github - settings - secret 에 등록해두면, deploy 시 적절하게 키값을 가져와서 사용할 수 있다.

 

3) 작성한 main.yaml 이 github에 올린다

add-commit-push

 

4) github 레포지터리에서 Actions 탭에서 workflows 확인

실수 없이 잘 했으면 두번째 줄 pages build and deployment 하나만 나와서 주황동그라미가 돌아가면서 deploy를 하고 있을 것이다.

나는 처음에 branch를 잘못 표기해서 다시 올려서 2개가 올라왔고, 뒤에 두개는 이후에 할 작업이다.

일단은 pages build and deployment  잘 나오는지 확인

 

5) deploy 성공 후 Code 탭으로 가서 npm run build 결과물이 모여진 브랜치(heros) 가 생성 되었는지 확인

 

3. github Pages

1) settings - pages - source 브랜치 선택 : 최초 None 으로 되어있는 거를 위에서 만든 heros로 변경한다.

변경하고 Save 하면 다음과 같이 주소가 만들어진다.

이 주소로 들어가보자

 

하지만 404가 나올것! 

 

2) 다시 로컬에서 작업하는 프로젝트 공간으로 와서 추가 작업을 해주어야한다.

github pages에서 만들어준 호스팅 주소에 default 로 github 자체의 레포지토리 이름이 들어가 있기 때문에, 이를 설정해 주어야 한다.

 

2-1) main.js 파일에 history 경로 추가

아래는 main.js 소스 전문

import { createApp } from 'vue'
import { createWebHistory, createRouter } from 'vue-router';
import App from './App.vue'
// router 쓰일 Component
import Home from './views/Home.vue';
import About from './views/About.vue';
import User from './views/User.vue';
import UserDetail from './views/UserDetail.vue';

//routes 정하기
const routes = [    
  { path : '/', component: Home, name:"home"},
  { path : '/about', component: About, name:'about2' },
  { path : '/user', component: User },
  { path : '/user/:id', component: UserDetail, props: true },
]

const router = createRouter({
  history: createWebHistory('/vue-study/'),
  routes
})

const app = createApp(App)
app.use(router)
app.mount('#app')

 

2-2) vite.config.js 파일에도 base 추가

아래는 vite.config.js 소스 전문

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: '/vue-study/'
})

 

3) 이렇게 바꾼 소스의 내용을 다시 github에 올려준다

add - commit - push

 

 

4) 다시 github로 와서 Actions 탭으로 가면 새로 push 한 내용에 대해서 deploy 를 하고 있는 것을 확인할 수 있다.

 

5) deploy가 다 될때 까지 기다렸다가, 다시 github pages에서 줬던 페이지로 접속해보자.

혹시라도 아무것도 안뜨고, console창에 404에러가 뜬다면, 다른문제가 있을 수도 있지만, 몇번 새로고침이나, 브라우저를 끄고 다시 접속해보자.

 

TODO

  • Router 아무 path 없을 때는 layout 구현, 그 안에 Route 구현
  • notFound 페이지 예외 처리 예정
  • Layout 에서 NavLink로 링크 구현
  • Outlet으로 랜더할 내용 받아줌
  • useParams로 parameter 받기

 

1. 사용할 페이지 간략 내용 views들 생성

  • /views/About.js
  • /views/About.js
  • /views/NotFound.js
  • /views/UserDetail.js
  • /views/Users.js
  • Layout은 조금 이따가

 

 

 

2. 레이아웃 담당할 Layout.js 작성

  • react-router-dom이 제공하는 NavLink, Outlet 사용
  • NavLink는 a태그 역할 링크 역할
  • Outlet은 Content가 담길 곳 명시하는 것 (react-router-dom내부 규칙)
// views/Layout.js

import { NavLink, Outlet } from 'react-router-dom';
import styled from 'styled-components';

const Nav = styled.nav`
    height : 100px;
    background-color : skyblue;
`

const Main = styled.main`
    display: flex;
`

const SideMenu = styled.div`
    min-width : 300px;
    min-height : 400px;
    border : 1px solid grey;
`

const Content = styled.div``

export default function Layout() {
    return (
        <>
            <Nav>
                <NavLink to="/">Home</NavLink>
                <NavLink to="/about">About</NavLink>
                <NavLink to="/user">Users</NavLink>
            </Nav>
            <Main>
                <SideMenu>사이드 메뉴</SideMenu>
                <Content>
                    {/* 각각 컴포넌트들이 보여질 곳 Outlet으로 받아줌 */}
                    <Outlet/>
                </Content>
            </Main>
        </>
    )
}

 

3. 위의 페이지들을 랜더링할 최상위 컴포넌트 App.js 작성

  • BrowserRouter로 전체라우팅 감싸기
  • Routes로 라우트들 감싸기
  • <Route element={<Layout/>}로 전체 레이아웃 설정
  • 전체 레이아웃 안에 이제, 랜더링될 페이지들이 Route 태그로 설정
  • 여기서 내부에 랜더링되는 페이지들이 위의 Layout.js 코드 속 Outlet에 표현된다.
  • user/3 과 같이 뒤에 파라미터로 id를 받는 경우는 user/:id로 표현
//App.js

import './App.css';
import { BrowserRouter, Route, Routes } from "react-router-dom";

import About from './views/About';
import Home from './views/Home';
import Users from './views/Users';
import UserDetail from './views/UserDetail';
import NotFound from './views/NotFound'
import Layout from './views/Layout';


function App() {
  return (
    <BrowserRouter>
      <Routes>
        {/* 아무 path 없으면 레이아웃 자동 만들어줌 */}
        <Route element={<Layout/>}>
          {/* 최초 슬래시로 갔을 때 */}
          <Route index element={<Home/>}/> 
          <Route path="about" element={<About/>}/>
          <Route path="user" element={<Users/>}/>
          <Route path="user/:id" element={<UserDetail/>}/>
          {/* 예외페이지 처리 */}
          <Route path="*" element={<NotFound/>}/>
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default App;

 

4. UserDetail.js 에서 useParams를 사용하여 파라미터 받기

// views/UserDetail.js

import { useParams } from "react-router-dom"


export default function UserDetail() {
    let params = useParams();

    return <h1>UserDetail: { params.id }</h1>
}

 

[실행결과]

+ Recent posts