Archive

React.js Axios Package,Side Effect,HTTP Request,Interceptors

|

React.js Axios Package,Side Effect,HTTP Request,Interceptors


  1. Axios Package

    • axios 패키지는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리이다
    • 백엔드와 프론트엔드간 통신을 위해 사용되는 Ajax의 라이브러리중 하나이다
    • npm install –save axios 설치
    • GET, PUT, POST, DELETE 등 메소드로 API 요청을 할 수 있다
    • 공통된 URL을 baseURL로 지정하여 각 컴포넌트에서 URL을 귀찮게 일일이 다 안적어도 된다
    • 공통 헤더 지정도 가능
    axios.defaults.baseURL = 'http://어쩌구..'
    axios.defaults.headers.common['Authorization'] = 'AUTH_TOKEN';
    axios.defaults.headers.post['Content-Type'] = 'application/json';
    
    • 사용자 정의 인스턴스
    const instance = axios.create({
        baseURL: 'http;//어쩌구..'
    });
    
    instance.defaults.headers.common['Authorization'] = 'AUTH TOKEN';
    


  2. JSON Placeholder

    • 서버가 없을 때, API 테스트를 할 수 있는 사이트로 dummy 데이터를 제공한다
  3. Side Effect

    • 서버로부터 데이터를 가져온다던지, 수동으로 리액트 컴포넌트의 DOM을 수정한다던지 이를 리액트에서는 side effect라 한다
    • 컴포넌트가 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들이다
    • side effect는 Clean-up가 필요한 것과 그렇지 않은 것 두 가지로 구분된다
    • 리액트가 DOM을 렌더링한 뒤 추가로 코드를 실행하는 경우 : 네트워크 리퀘스트, DOM 수동 조작, 로깅 등은 Clean-up이 필요 없는 side-effect이다
    • Clean-up이 필요한 side-effect는 외부 데이터에 subscription을 설정해야하는 경우 등이 있다
  4. HTTP Request (GET)

    • 클래스 방식의 ComponentDidMount() lifecycle 메소드는 최초 렌더링 후 필요한 HTTP Request를 보내는 side effect를 설치하기 위한 최적의 장소이다
    • axios.get 메소드로 리소스 조회 요청을 보낼 수 있는데 일반적으로 데이터를 받기까지 시간이 걸리고 리액트는 다음 line의 코드를 바로 실행해버린다
    • 데이터를 다 못받았는데 다음 코드가 실행되면 예상치 못한 결과가 나오므로 primose를 사용하고 then 안에 다음 코드를 작성하도록 하자
    import axios from 'axios';
    
    componentDidMount() {
        // JSON placeholder의 dummy data
        axios.get('http://jsonplaceholder.typicode.com/posts')
        	.then((response) => {console.log(response)});
    }
    // 데이터 조회에 성공하면 HTTP 상태코드 200을 볼 수 있다
    


    • ComponentDidUpdate() lifecycle 메소드는 사용자의 입력에 따라 re-render가 되며, 그에 필요한 HTTP Request side effect를 설치하기에 좋은 곳이다
    • 이 때, promise 안의 setState로 re-render가 일어나 다시 HTTP Request를 하게되는 무한 루프에 빠지지 않도록 조심하자
    class Post extends Component {
        state = {
            loadedData: null;
        };
    	// 사용자의 원하는 데이터를 요청하여 출력
    	componentDidUpdate() {
            if(this.props.id) {
                if(!this.state.loadedData || // 최초 한 번 실행을 위하여
                  this.state.loadedData && this.state.loadedData.id !== this.props.id) { // 무한루프를 끊기 위해
                    axios.get('URL...')
                    	.then(response => {
                        this.setState({loadedData: response.data})
                    });
                };
            }
        }
    }
    


  5. HTTP Request (POST)

    import axios from 'axios';
    
    postDataHandler = () => {
    	const post = {
        	title: this.state.title,
        	body: this.state.content,
        	author: this.state.author,
    	}
    	axios.post('URL...', post) // 두 번째 인자로 데이터 전달
    		.then(response => {
        	alert('전송 성공');
    	});
    }
    


  6. HTTP Request (DELETE)

    deleteDataHandler = () => {
        axios.delete('URL...') // 두 번째 인자로 데이터
        	.then(response => {
            alert('삭제 성공');
        });
    }
    


  7. Handling HTTP Request Fail

    • 요청한 request가 항상 작동하리란 법은 없다
    • 그래서 그 때를 대비하여 무언가 처리를 하는 것이 좋다
    • axios의 promise chaining에 .catch를 추가하여 error가 발생했을 시 무언가 실행되도록 할 수 있다
    axios.get('URL...').then(response => {
        // 정상적인 실행문
    }).catch(error => {
        // error 발생시 실행문
    })
    


  8. Interceptors

    • then, catch로 요청이 처리되기 전에 axios의 interceptors로 응답을 가로챌 수 있다
    • 이를 활용하여 모든 요청에 대한 알림 팝업을 띄운다던지, 에러 발생시 공통된 메시지를 띄운다던지 등등 할 수 있다
    • 주로 axios가 사용되는 상위 컴포넌트에 많이 들어간다
    // 요청 인터셉터 추가
    axios.interceptors.request.use(config => {
        // 요청을 보내기 전에 수행할 일
        // ...
        return config; // return 필수
      },
      error => {
        // 오류 요청을 보내기전 수행할 일
        // ...
        return Promise.reject(error);
      });
    
    // 응답 인터셉터 추가
    axios.interceptors.response.use(response => {
        // 응답 데이터를 가공
        // ...
        return response;
      }, error => {
        // 오류 응답을 처리
        // ...
        return Promise.reject(error);
      });
    
    • interceptor 제거는 use 대신 eject를 사용하면 된다




참고 자료


reactjs.org - 공식홈페이지

Udemy - React The Complete Guide

Axios 러닝 가이드

axios Github

REST API란 무엇인가 + RESTful API

|

REST API란 무엇인가 + RESTful API



  1. REST API의 탄생

    • REST (Representational State Transfer)의 약자로 2000년도 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초 공개
    • 웹의 장점을 최대한 활용할 수 있는 아키텍처로서 REST를 발표
  2. REST의 구성

    • 자원(Resource) - URI
    • 행위(Verb) - HTTP Method
    • 표현(Representations)
  3. REST의 특징

    • Uniform (유니폼 인터페이스)
      • Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일
    • Stateless (무상태성)
      • REST는 stateless 성격을 갖는다
      • 세션 정보, 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청을 단순 처리
      • 서비스의 자유도가 높아지고 서버 구현이 단순해진다
    • Cacheable (캐시 가능)
      • REST의 가장 큰 특징은 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, Last-Modified, E-Tag를 이용하여 캐싱 구현이 가능하다
    • Self-descriptiveness (자체 표현 구조)
      • REST의 또 다른 큰 특징으로 REST API 메시지만 보고도 이해할 수 있는 자체 표현 구조로 되어 있다
    • Client - Server 구조
      • REST 서버는 API를 제공, 클라이언트는 사용자 인증, 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 구조로 각각 역할이 명확하여 서로간 의존성이 줄어든다
    • Layerd System (계층형 구조)
      • REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상 유연성을 확립하고 Proxy, 게이트웨이 등 네트워크 중간매체를 사용할 수 있다
  4. REST API 디자인 가이드

    • REST API 설계시 가장 중요한 항목

      • URI는 정보의 자원을 표현해야 한다 (리소스명은 명사를 사용)
      • 자원에 대한 행위는 HTTP Method (GET,POST,PUT,DELETE)로 표현한다
        1. POST : URI를 요청하면 리소스를 생성
        2. GET : 리소스를 조회, 해당 도큐먼트에 대한 자세한 정보를 가져온다
        3. PUT : 해당 리소스를 수정
        4. DELETE : 해당 리소스를 삭제
    • URI 설계시 주의할 점

      • 슬래시 구분자(/)는 계층 관계를 나타낸다
      http://zoo.com/animals/mammals/rabbits
      
      • URI 마지막 문자로 슬래시를 포함하지 않는다
      http://zoo.com/animals/mammals/rabbits/ (x)
      http://zoo.com/animals/mammals/rabbits (o)
      
      • 하이픈(-)은 가독성을 높이는데 사용
      • 언더바(_)는 사용하지 않는다
      • 대문자 사용을 피한다
      • 파일 확장자는 포함시키지 않는다
    • 리소스간 관계 표현

      GET : /users/{userid}/devices (일반적으로 소유의 관계를 표현할 때)
      
    • Collection & Document

      • 컬렉션은 도큐먼트의 집합체 (복수)
      • 도큐먼트는 하나의 문서 (단수)
      http://zoo.com/animals/mammals/rabbits/tomy
      


  5. HTTP 응답 상태 코드

    상태 코드  
    200 클라이언트의 요청을 정상적으로 수행
    201 클라이언트가 리소스 생성을 요청, 해당 리소스가 성공적으로 생성됨
    (POST를 통한 리소스 생성 작업시)
    상태 코드  
    400 클라이언트의 요청이 부적절할 경우
    401 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 시
    403 인증상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 시
    (403 보단 400, 404 사용 권고, 403은 리소스가 존재함을 뜻하기 때문)
    404 찾을 수 없는 페이지
    405 클라이언트가 요청한 리소스에서 사용 불가능한 Method가 있을 때
    408 요청 시간이 초과됨
    409 서버가 요청을 처리하는 과정에서 충돌이 발생한 경우
    (회원가입의 중복된 아이디 등)
    상태 코드  
    301 클라이언트가 요청한 리소스에 대한 URI가 변경되었을 시
    500 서버에 문제가 있을 경우


  6. RESTful API란?

    • 개발자들이 비공식적으로 의견을 제시한거라 명확한 정의는 없다
    • RESTful의 목적은 이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것
    • CRUD를 전부 POST로만 처리하거나 URI에 관계없는 정보가 들어간 경우 등을 ‘RESTful하지 못하다’ 라고 한다
  7. 결론

    • URI로 자원(Resource)을 명시하고 행위(Method)를 통해 CRUD를 적용하고 특정 표현(JSON 등)을 사용하여 요청을 보낸다



참고 자료


REST API 제대로 알고 사용하기

REST API와 RESTful API

2021-02-01 TIL

|

2021-02-01 TIL


  • 오늘 한 것
    1. 리액트 공부 - Axios 패키지를 통하여 비동기 HTTP Request를 하는 방법을 배웠다. Backend Server가 없어서 firebase로 JSON 데이터를 주고 받는 방법을 택했는데 실제 서버와 통신이 된다면 얼마나 많은 것을 할 수 있을까.
    2. 학원 비대면 수업(15:30~22:00)



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide
    2. 학원 비대면 수업(15:30~22:00)



  • 끝으로

내일은 드디어 라우팅을 바우는 날이다.

오늘의 한 줄 총평 : 천천히 한 걸음


React.js Refs, Context API

|

React.js Refs, Context API


  1. ref

    • ref는 render 메소드에서 생성된 DOM 노드나 리액트 element에 접근하는 방법을 제공한다
    • 일반적으로 상위&하위 컴포넌트간 상호작용은 props를 이용하지만 ref를 이용해서 하위 컴포넌트를 직접 수정할 수 있다
    • focus, 텍스트 선택영역, 미디어 재생, 애니메이션 실행, third party library를 사용할 때 등이 있다
    • 16.3 이후 React.createRef() 메소드로 ref를 생성한다
    • 일반적으로 클래스 컴포넌트에서만 작동을 하고 hook을 이용해 useRef() 메소드를 함수 컴포넌트 안에서 사용하는 것은 가능하다
    • React는 ref 남용을 지양하고 있다
    // 클래스 컴포넌트 안에서...
       
    componentDidMount() {
        this.inputElement.focus();
    }// 컴포넌트가 마운트되면 input에 focus
       
    render() {
        return(
        	<input 
                ref={(inputEl) => {this.inputElement = inputEl}}
            ></input>
        )
    }// 익명 Arrow func으로 참조 연결
    
    // React 16.3 이후
       
    class xxx extends Component {
        constructor(props) {
            super(props);
            this.inputRef = React.createRef(); // 내장 메소드를 이용
        }
        componentDidMount() {
            this.inputRef.current.focus();
        }// 주의: ref를 current 프로퍼티의 값으로 받기에 명시적으로 적어야한다 
        render() {
            return(
            	<input ref={this.inputRef}></input>
            )
        }
    }
    
    // function 컴포넌트 안에서...
    import React, { useRef,useEffect } from 'react'; // import 주의
       
    const xxx = (props) => {
        const inputRef = useRef(null); // 초기값은 null이다
           
        useEffect(() => {
            inputRef.current.focus();
        }, []);
        // ref를 바로 사용하는 것은 좋지 않다. nullPointerException
        // 참조연결이 된 첫 번째 렌더링이 끝나고 사용하는 것이 바람직
        return(
            <input ref={inputRef}></input>
        )
    }
    


  2. Context API

    • App이 방대해질수록 상위 컴포넌트와 그 아래 하위컴포넌트의 개수가 늘어나기마련.
    • 이때, 최상위 컴포넌트에서 최하위 컴포넌트에 props를 전달하기 위해서는 연결된 chain layer들을 다 거치고 나서 전달해야한다
    • 이런 비효율적인 방식을 해결해주는 것이 Context API이다
    // Context를 저장할 js파일을 생성한다
    import React from 'react';
       
    const authContext = React.createContext({
        isLogin: false;
        login: () => {}
    });
       
    export default context;
    
    // Context Provider (데이터를 넘겨줄 최상위 컴포넌트)
    import AuthContext from '../context/context'; // context 별도의 폴더에 관리
       
    class App extends Component {
        constructor(props){
            super(props);
            this.state = {
                isLogin: false; // 전달할 state
            }
        }
        loginHandler = () => {} // 전달할 메소드
          
        render() {
            return (
            	<AuthContext.Provider //사용처를 감싸주고 value 전달
                    value=>
                	<Person />
                </ AuthContext.Provider>
            )
        }
    }
    
    // Context Consumer (데이터를 받을 최하위 혹은 하위 컴포넌트)
    import AuthContext from '../context/context';
       
    class Person extends Component {
        render() {
            return(
            	<AuthContext.Consumer> // 사용처를 감싸고 context 사용
                	{context => context.isLogin ? 
                    	<p>hi</p>
                    	: <p>please log in</p>}
                </ AuthContext.Consumer>
               
            )
        }
    }
    


    • React 16.6 이후 새로운 방식으로 context를 이용할 수 있다 (클래스 컴포넌트)
    import AuthContext from '../context/context';
       
    // 주의 반드시 static 지시어와 지정된 name을 사용해야함
    static contextType = AuthContext;
       
    render() {
        return( // 자동으로 변환하기 때문에 context 지정어를 사용해야함
        	{this.context.isLogin ? 
            	<p>hi</p>
            	: <p>please log in</p>}
        )
    }// 위 코드와 비교
    


    • 하지만, 함수 컴포넌트에서는 static 지시어를 사용할 수 없다
    • hook을 이용해 useContext()로 위와 동일한 효과를 낼 수 있다
    import React, { useContext } from 'react'; // import 주의
    import AuthContext from '../context/context';
       
    const person = props => {
        // useContext() 메소드를 이용해 context 저장
        const authContext = useContext(AuthContext);
           
        return(
        	<button onClick={authContext.login}>Login</button>
        )
    }
    




참고 자료


reactjs.org - 공식홈페이지

Udemy - React The Complete Guide

2021-01-30 TIL

|

2021-01-30 TIL


  • 오늘 한 것
    1. 리액트 공부 - React-The Complete Guide - 햄버거 빌더 프로젝트 시작. 지금까지 배운 내용들을 응용하여 사용자가 원하는 재료를 추가하면 햄버거 UI에 추가되어 주문을 할 수 있는 간단한 미니 프로젝트를 시작했다. 간단해보여도 쉽지가 않아… 역시 array 메소드의 chaining 등 자바스크립트를 잘해야되는듯 ㅠ



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide



  • 끝으로

이론만 주구장창 파는거보다 확실히 만들면서 배우는게 낫긴하다.

더 확실한 방법은 혼자 해보는것이겠지.

리액트 수업이 끝나면 뭔가 만들어보자.

오늘의 한 줄 총평 : 리액트 프로젝트를 혼자하는 그날까지