Restful API에 대해 설명해주세요. GET,POST 외에 알고 있는 메소드와 그 기준을 설명해주세요. RESTful API 가 아닌 것들은 어떤 게 있나요?

RESTful API ?

: 웹 기반 시스템에서 자원(데이터나 서비스)을 명시하고 해당 자원에 접근하기 위한 규약을 제공하는 아키텍처 패턴이다. RESTful API는 "REST" (Representational State Transfer)의 원칙에 따라 설계되며, 웹의 장점을 최대한 활용할 수 있도록 특정 원칙을 따른다.

 

RESTful API의 핵심 원칙 ?

  1. Stateless (무상태성): 각 요청은 서버에서 클라이언트의 상태 정보를 저장하지 않아야 한다. 필요한 정보는 요청 내에 포함되어야 하며, 서버는 각 요청을 완전히 분리된 것으로 처리해야 한다.
  2. Client-Server (클라이언트-서버 구조): 클라이언트와 서버는 각각 분리되어 있어야 한다. 이렇게 함으로써 각각을 독립적으로 발전시킬 수 있다.
  3. Cacheable (캐시 가능): 응답은 캐시 가능하거나 캐시 불가능하다는 정보를 포함해야 한다. 캐시된 응답은, 클라이언트에 의해 재사용될 수 있어야 한다.
  4. Uniform Interface (일관된 인터페이스): REST의 가장 중요한 원칙 중 하나로, URL과 HTTP 메소드(GET, POST, PUT, DELETE 등)를 사용하여 리소스에 접근하고 작업을 수행한다.
  5. Layered System (계층화 시스템): 클라이언트는 중간 계층(예: 로드 밸런서)의 존재 여부를 알 수 없어야 한다. 중간 계층은 앱의 확장성을 향상시키는 데 도움을 준다.
  6. Code on Demand (optional): 필요한 경우 서버는 코드를 클라이언트에게 전송할 수 있다. 이는 일반적으로 JavaScript를 통해 구현된다.

HTTP 메소드는 RESTful API에서 매우 중요한 부분을 차지하며, 각 메소드는 다음과 같은 의미와 기준을 가지고 있다.

  1. GET:
    • 목적: 특정 리소스를 조회
    • 비고: GET 요청은 일반적으로 데이터를 변경시키지 않아야 한다.
  2. POST:
    • 목적: 새로운 리소스를 생성
    • 비고: POST 요청은 서버에 새로운 데이터를 제공하여 리소스를 생성하는 데 사용된다.
  3. PUT:
    • 목적: 특정 리소스를 수정하거나 덮어쓰기
    • 비고: 만약 지정된 리소스가 존재하지 않으면 새로운 리소스를 생성할 수 있다. 하지만 이는 서버 구현에 따라 다를 수 있다.
  4. PATCH:
    • 목적: 리소스의 일부분만을 수정
    • 비고: PUT 메소드와 달리, PATCH는 리소스의 일부 데이터만 변경하는 데 사용된다.
  5. DELETE:
    • 목적: 특정 리소스를 삭제
    • 비고: 해당 리소스를 서버에서 제거합니다.
  6. HEAD:
    • 목적: 리소스의 헤더만을 가져오기
    • 비고: GET과 비슷하지만, 응답 본문(body) 없이 헤더 정보만 반환한다.
  7. OPTIONS:
    • 목적: 대상 리소스에 대한 통신을 위해 사용할 수 있는 메소드를 설명하는 응답을 반환
    • 비고: 주로 CORS(Cross-Origin Resource Sharing) 환경에서 사용된다.

REST 외에도 여러 가지 다른 통신 및 서비스 아키텍처 스타일이 있다. 예를 들면 다음과 같다.

  1. WebSocket
    • 단일 TCP 연결을 통해 실시간 양방향 통신을 가능하게 하는 프로토콜이다.
    • 주로 실시간 애플리케이션(채팅, 온라인 게임 등)에서 사용된다.
  2. Server-sent Events (SSE)
    • 서버에서 클라이언트로 단방향 실시간 데이터를 스트리밍하는 기술이다.
    • 주로 실시간 알림이나 라이브 피드 업데이트에 사용된다.

HTTP 메소드들은 리소스에 대한 다양한 작업을 수행할 수 있게 해주며, RESTful API는 이러한 메소드를 활용하여 표준적이고 일관된 방법으로 리소스를 처리할 수 있도록 한다.

RESTful API는 많은 웹 애플리케이션에서 널리 사용되지만, 특정 상황과 요구 사항에 따라 다른 대안들이 더 적합할 수 있다.

'CS' 카테고리의 다른 글

웹페이지가 브라우저에 렌더링  (0) 2023.07.19

웹페이지가 브라우저에 렌더링되는 과정

파싱과 렌더링?

파싱(parsing)

:  프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽고, 실행하기 위해 텍스트의 문자열을 분해하고 구조를 생성하는 일련의 과정

렌더링(rendering)

:  HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 사용자가 눈으로 볼 수 있도록 시각적으로 출력하는 것

 

브라우저의 렌더링 과정은 요청 및 응답, HTML과 CSS 파싱, 렌더 트리 생성, 레이아웃, 페인트, 그리고 JavaScript의 실행과 같은 여러 단계로 나뉜다.

 

요청 및 응답

브라우저는 웹 서버에 페이지 요청을 시작하고, 서버는 HTML, CSS, JS, 이미지 등의 자원을 반환한다.

HTML, CSS 파싱 -> DOM, CSSOM 생성

반환된 HTML은 파싱되어 DOM 트리로 변환된다. DOM은 웹 페이지의 구조적 표현이다.

반환된 CSS도 파싱되어 CSSOM 트리로 변환된다. 이 트리는 스타일 정보를 포함한다.

렌더 트리 생성

DOM과 CSSOM 트리는 합쳐져 실제 화면에 표시될 요소와 스타일 정보를 포함하는 렌더 트리를 생성한다.

레이아웃

렌더 트리를 바탕으로 브라우저는 각 요소의 크기와 위치를 결정합니다. 이 단계에서는 요소의 크기와 화면에서의 위치가 계산된다.

페인트

렌더 트리와 레이아웃 정보를 활용해 실제 픽셀로 변환되어 화면에 그려진다.

JavaScript

JavaScript는 파싱되고 실행되며, 필요에 따라 DOM을 조작하거나 스타일 변경 등의 작업을 수행한다.

'CS' 카테고리의 다른 글

Restful API  (0) 2023.07.20

중복코드 줄여보자~~~

input을 만들었을 경우

 

App.jsx

import React from "react";
import { useState } from "react";

function App() {
	const [name, setName] = useState('')
    const [password, setPassword] = useState('')
    
    const onChangeNameHandler = (e) => {
    	setName(e.target.vaule)
    }
    
    const onChangePasswordHandler = (e) => {
    	setPassword(e.target.vaule)
    }
    
    return <div>
    	<input type="text" value={name} onChange={onChangeNameHandler} />
        <input type="text" value={name} onChange={onChangePasswordHandler} />

hooks > useInput.js

cosnt useInput = () => {
	// state
    const [value, setValue] = useState('')
    
    // handler
    const handler = (e) => {
    	setValue(e.target.value)
    }
    
    return [value, handler];
}

export default useInput;

useInput 커스텀 훅 불러오기!

import React from "react";
// import { useState } from "react";
import useInput from "./fooks/useInput";

function App() {
	// 이렇게만 만들어도 밑에서 다 쓸 수 있다.
	const [name, onChangeNameHandler] = useInput('')
    const [name, onChangePasswordHandler] = useInput('')
    
    // const [name, setName] = useState('')
    // const [password, setPassword] = useState('')
    
    // const onChangeNameHandler = (e) => {
    //	   setName(e.target.vaule)
    // }
    
    // const onChangePasswordHandler = (e) => {
    //	   setPassword(e.target.vaule)
    // }
    
    return <div>
    	<input type="text" value={name} onChange={onChangeNameHandler} />
        <input type="text" value={name} onChange={onChangePasswordHandler} />

'React' 카테고리의 다른 글

Redux-thunk (미들웨어)  (0) 2023.04.29
axios interceptor  (0) 2023.04.29
비동기 통신 - axios(get)  (0) 2023.04.28
React Hooks - 최적화(React.memo, useCallback, useMemo)  (1) 2023.04.19
React Hooks - useRef  (0) 2023.04.19

생명주기(LifeCycle)

컴포넌트 중심 라이브러리의 집합체라고 보면 된다. 모든 컴포넌트는 여러 종류의 “생명주기 메서드”를 가지며, 이 메서드를 오버라이딩하여 특정 시점에 코드가 실행되도록 설정할 수 있다.

모든 컴포넌트에는 각각의 생명주기가 존재하고 각 생명주기에 맞는 메서드들이 있다.

  • 구성요소는 화면에 추가될 때 마운트(컴포넌트 생성 될 때)된다 . 
  • 구성 요소는 일반적으로 상호 작용에 대한 응답으로 새 속성 또는 상태를 수신할 때 업데이트(컴포넌트가 갱신될 때, 리렌더링)된다 .
  • 구성 요소는 화면에서 제거될 때 마운트(컴포넌트가 DOM에서 제거되는 시점) 해제된다 .

자주 사용되는 생명주기 메서드

render()

클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드이다. 이 메서드가 호출되면 this.props this.state의 값을 활용하여 아래의 것 중 하나를 반환해야 한다.

constructor()

메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 생성자를 구현하지 않아도 된다. React 컴포넌트의 생성자는 해당 컴포넌트가 마운트되기 전에 호출된다. React.Component를 상속한 컴포넌트의 생성자를 구현할 때에는 다른 구문에 앞서 super(props)를 호출해야 한다. 그렇지 않으면 this.props가 생성자 내에서 정의되지 않아 버그로 이어질 수 있다.

componentDidMount()

componentDidMount()는 컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출된다. DOM 노드가 있어야 하는 초기화 작업은 이 메서드에서 이루어지면 된다. 외부에서 데이터를 불러와야 한다면, 네트워크 요청을 보내기 적절한 위치이다.

이 메서드는 데이터 구독을 설정하기 좋은 위치이며, 데이터 구독이 이루어졌다면, componentWillUnmount()에서 구독 해제 작업을 반드시 수행해야한다.

componentDidUpdate()

componentDidUpdate()는 갱신이 일어난 직후에 호출된다. 이 메서드는 최초 렌더링에서는 호출되지 않는다.

컴포넌트가 갱신되었을 때 DOM을 조작하기 위하여 이 메서드를 활용하면 좋다. 또한, 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업도 이 메서드에서 이루어지면 된다

componentWillUnmount()

componentWillUnmount()는 컴포넌트가 마운트 해제되어 제거되기 직전에 호출된다. 이 메서드 내에서 타이머 제거, 네트워크 요청 취소, componentDidMount() 내에서 생성된 구독 해제 등 필요한 모든 정리 작업을 수행한다.

이제 컴포넌트는 다시 렌더링되지 않으므로, componentWillUnmount() 내에서 setState()를 호출하면 안 된다. 컴포넌트 인스턴스가 마운트 해제되고 나면, 절대로 다시 마운트되지 않는다.


참고문서 : https://ko.legacy.reactjs.org/docs/react-component.html#render

 

React.Component – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

시간되면 정독하기!

'메모장' 카테고리의 다른 글

react stomp 실시간 채팅 오류..  (0) 2023.06.16
클론 코딩 피드백  (0) 2023.05.18
리액트 설치 명령어  (0) 2023.04.29
props 객체에 따라 동적으로 스타일링 적용하기  (0) 2023.04.26
UUID(범용 고유 식별자)  (0) 2023.04.24

미들웨어란?

리덕스에서 dispatch를 하면 action 이 리듀서로 전달이 되고, 리듀서는 새로운 state를 반환한다. 근데 미들웨어를 사용하면 이 과정 사이에 우리가 하고 싶은 작업들을 넣어서 할 수 있다.

카운트 프로그램에서 더하기 또는 빼기 버튼을 바로 하지 않고 3초를 기다렸다가 더하는 것, 3초를 기다리는 작업이 미들웨어가 해주는 것이다.

Thunk

리덕스에서 많이 사용하고 있는 미들웨어중에 하나이다. thunk를 사용하면 우리가 dispatch를 할때 객체가 아닌 함수를 dispatch 할 수 있게 해준다. 즉 dispatch(객체) 가 아니라 dispatch(함수)를 할 수 있게 되는 것이다!

중간에 우리가 하고자 하는 작업을 함수를 통해 넣을 수 있고, 그것이 중간에 실행이 되는 것 이다. 그래서 아래 흐름과 같이 실행이 되며, 이 함수를 thunk 함수라고 부른다.

dispatch(함수) → 함수실행 → 함수안에서 dispatch(객체)

Thunk 사용하기

1. 우리의 첫 thunk 함수 만들기 : createAsyncThunk
    - reduxToolkit 내장 API
2. creatSlice => extraReducer에 thunk 등록하기
3. dispatch(thunk 함수) 하기
4. 테스트

 

😎3초를 기다리게 해보자!

redux > modules > counter.js

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
// 2개의 INPUT이 들어감
// (1) 이름 : 의미는 크게 없음
// (2) 함수
export const __addNumber = createAsyncThunk(
    'ADD_NUMBER_WAIT',
    (payload, thunkAPI) => {
        // 수행하고싶은 동작: 3초를 기다리게 할 예정
        setTimeout(() => {
            thunkAPI.dispatch(addNumber(payload))
        }, 3000)

    }
)

여기서 Thunk의 기능은 3초를 기다리게 한다.

 

App.js

import { __addNumber } from './redux/modules/counter';
  const addNumberBtn = () => {
    // dispatch(addNumber(+number))
    dispatch(__addNumber(+number))
  }

 

동작

+number로 addNumber가 들어오면 counter.js에 있는 payload로

(payload, thunkAPI)

addNumber에 넣어줬던 +number값이 들어오게 된다.

예를들어 100이라고 한다면,

그 값이 payload로 들어온다.

thunkAPI.dispatch(addNumber(payload))

들어와서 3초후에 밑에 있는 디스패치의 action.payload에 100이라는 값이 들어가면서 state가 업데이트 된다.

const counterSlice = createSlice({
    name: "counter",
    initialState,
    reducers: {
      addNumber: (state, action) => {
        state.number = state.number + action.payload;
      },

정리

  • 리덕스 미들웨어를 사용하면, 액션이 리듀서로 전달되기전에 중간에 어떤 작업을 더 할 수있다.
  • Thunk를 사용하면, 객체가 아닌 함수를 dispatch 할 수 있게 해준다. [thunk의 핵심]
  • 리덕스 툴킷에서 Thunk 함수를 생성할 때는 **createAsyncThunk 를 이용한다.**
  • **createAsyncThunk() 의 첫번째 자리에는 action value, 두번째에는 함수가 들어간다.**
  • 두번째로 들어가는 함수에서 2개의 인자를 꺼내 사용할 수 있는데, 첫번째 인자는 컴포넌트에서 보내준 payload이고, 두번째 인자는 thunk에서 제공하는 여러가지 기능이다.

'React' 카테고리의 다른 글

Custom Hooks  (1) 2023.05.01
axios interceptor  (0) 2023.04.29
비동기 통신 - axios(get)  (0) 2023.04.28
React Hooks - 최적화(React.memo, useCallback, useMemo)  (1) 2023.04.19
React Hooks - useRef  (0) 2023.04.19

Git Bash파일 만들기

pwd #현재 내가 위치하고 있는 곳이 어디인지 확인해보세요.

cd 폴더이름 #리액트 프로젝트를 생성하고 싶은 폴더로 들어갑니다.

yarn create react-app nminyfile #프로젝트 생성!

yarn 에서 styled-components 설치

yarn add styled-components

리덕스 설치

yarn add redux react-redux

# 아래와 같은 의미
yarn add redux
yarn add react-redux

react-router-dom 설치하기

yarn add react-router-dom

툴킷 설치하기

yarn add react-redux @reduxjs/toolkit

 

axios 설치

yarn add axios

json-server 설치

yarn add json-server

json-server --watch db.json --port 4000(번호) 입력
bash: json-server: command not found 뜨면

npm install -g json-server 하고 다시

json-server --watch db.json --port 번호 입력

Lodash라이브러리 설치

yarn add lodash

폴더 구조 생성하기

글로 정리하기..

환경정보로 빼기

.env파일 만들고 저장!

REACT_APP_SERVER_URL=http://localhost:주소번호(ex.4005)

 원래 있던 URL대신 (`${process.env.REACT_APP_SERVER_URL}/todos`) 입력한다.

// 조회 함수
  // 비동기 함수 : 서버(json-server)에 todos를 요청하는 함수
  const fatchTodos = async () => {
    //const {data} = await axios.get("http://localhost:번호/todos")
    //console.log('data', data)
    const {data} = await axios.get(`${process.env.REACT_APP_SERVER_URL}/todos`)
    setTodos(data)
  };

 

 

axios폴더 > api.js파일 만들고 저장!

import axios from "axios";

const instence = axios.create({
    baseURL: process.env.REACT_APP_SERVER_URL,
})

export default instence;

axios를 api로  바꾸고 괄호안에 ("/todos")로 변경하면 된다.

const fatchTodos = async () => {
    // 1. const {data} = await axios.get("http://localhost:번호/todos")
    // console.log('data', data)
    // 2. const {data} = await axios.get(`${process.env.REACT_APP_SERVER_URL}/todos`)
    // setTodos(data)
    const {data} = await api.get("/todos")
    setTodos(data)
  };

이제는 가공한 인스턴스를 조금 더 interceptor를 이용해서 좀 더 요청과 응답 사이에 관여해보자~~

request와 response 사이에 어떤 로직들을 넣겠다.

instence.interceptors.request.use(

    // 요청을 보내기 전 수행되는 함수
    function(config){
        console.log('인터셉터 요청 성공!')
        return config;
    },

    // 오류 요청을 보내기 전 수행되는 함수
    function(error){
        console.log('인터셉트 요청 오류!')
        return Promise.reject(error);
    },
)

instence.interceptors.request.use(

    // 응답을 내보내기 전 수행되는 함수
    function(response){
        console.log('인터셉터 응답 받았습니다!')
        return response;
    },

    // 오류 응답을 내보내기 전 수행되는 함수
    function(error){
        console.log('인터셉터 응답 오류 발생!')
        return Promise.reject(error);
    },
)

인자는 항상 (config)라는 인자를 받는다. 매개변수로 들어오는 이름은 상관없다.

오류 함수 return에 Promise.reject를 꼭 해줘야 한다.

인터셉터 요청, 응답 성공

컴포넌트가 렌더링 되면서 fetchTodos가 실행이 되면서 axios를 콜 한다. 그러면서 requset를 하게 됩니다.

이렇게 중간에서 어떤 인터셉터가 HTTP 요청을 가로채서 어떠한 작업을 하는 것이다.

강제로 실패시키기

timeout이란?

axios 콜을 했을 때, 서버에 통신을 요청하면 '나는 언제까지 기다린다'라는 초(ms)를 말한다.

예를 들면 '2초까지 기다릴거야'라고 했을 때 2(0.002ms->2000을 적어줘야 2초가 됨)초를 기다렸는데도 안오면 오류를 내버리는 기준을 말한다.

const instence = axios.create({
    baseURL: process.env.REACT_APP_SERVER_URL,
    timeout: 1,
})

이렇게 변경하면, 요청 타임아웃이 1ms이다. 엄청 짧은 시간,,

뭐야 응답받으면 안되는데;;  왜 오류메세지는 떠...?

 

'React' 카테고리의 다른 글

Custom Hooks  (1) 2023.05.01
Redux-thunk (미들웨어)  (0) 2023.04.29
비동기 통신 - axios(get)  (0) 2023.04.28
React Hooks - 최적화(React.memo, useCallback, useMemo)  (1) 2023.04.19
React Hooks - useRef  (0) 2023.04.19

*설치할 것

yarn add axios
yarn add json-server

json-server --watch db.json --port 4000를 입력했더니
bash: json-server: command not found
떠서
npm install -g json-server 하고 다시

json-server --watch db.json --port 4000
썻더니 적용됐다
머여,,,; 이유는 모르겠다..

그럼 인사해준다 ㅋ.ㅋ

db.json 폴더를 하나 만들고 넣어준다.

{
    "todos": [
        {
            "id": 1,
            "title": "react"
        },
        {
            "id": 2,
            "title": "node"
        },
        {
            "id": 3,
            "title": "spring"
        }
        
    ] 
}
function App() {

  const fatchTodos = async () => {
    const response =  axios.get('http://localhost:4000/todos')
    console.log('response', response)
  }

  useEffect(() => {
    // db로부터 값을 가져올 것이다.
    fatchTodos()
  }, [])
  

  return (
    <div>
      axios
    </div>
  );
}

export default App;

여기서 consloe.log 확인을 하면 

pending이 찍힌 이유는 axious 요청을 한 직후에 찍혀 버리기 때문에 axious앞에 await문법 쓰면 async블록 안에서 

const {data} = await axios.get("http://localhost:4000/todos")

줄이 끝날 때까지 기다려준다 -> 정상적으로 값을 받을 수 있다.

여기서 data를 빼오자~~~~!

컴포넌트가 렌더링이 됐을 때 비동기함수가 실행되기 전에 return부분이 호출이 된다.

렌더링이 되고 나서 비동기함수가 async니까 타이밍이 더 늦다.

코드는 위에서부터 돌아가지만 async이기 때문에 fatchTodos 이 부분이 돌아갈 때까지 return이 기다리지 않는다.

그래서 todos는 없을수도 있는 현재 null일 수 있다. 그래서 todos? 해주면 된다!

'React' 카테고리의 다른 글

Redux-thunk (미들웨어)  (0) 2023.04.29
axios interceptor  (0) 2023.04.29
React Hooks - 최적화(React.memo, useCallback, useMemo)  (1) 2023.04.19
React Hooks - useRef  (0) 2023.04.19
React Hooks - useEffect  (0) 2023.04.19

+ Recent posts