Stack Building

[react] 예제 코드 분석 본문

[react] 예제 코드 분석

S00ahKim 2019. 4. 13. 12:21

출처: 권동섭 교수님 github

 

검색창에 도시 이름을 영문으로 입력하면 해당 도시의 기온, 습도 등을 그래프로 보여주고, 그 아래에 평균치를 보여주며 도시 위치를 구글맵으로 보여주는 웹사이트다. 이번 프로젝트는 미세먼지 정보를 보여주는 웹사이트 프론트를 만드는 것이라서 유사한 기능을 하고 있는 예제를 분석해 보기로 했다. 아래 분석에서 node_modules 폴더는 단순한 모듈 모음이고, css는 꾸며주는 기능이므로 제외했다.

 

public은 기본 리액트 템플릿과 똑같다. manifest.json은 웹이 안드로이드 홈에 올라갈 때 메타데이터로 쓰인다.

src 안에는 actions, components, containers, reducers 폴더가 있다.

 

actions는 액션, reducers는 리듀서를 두는 폴더. (참고) 마찬가지로 components는 컴포넌트, containers는 컨테이너를 두는 폴더다. 정확하게 이건 이거다라고 구분하는 편은 아니지만, 컨테이너는 리덕스스토어와 관련한 것을 가리킨다.

 

actions/index.js

[1] axios 라이브러리 : 외부 API에서 데이터를 가져오기 위함

[3] 키. 일부러 가려놨다. 구글맵 api를 사용하기 위한 키다.

    구글 API 키 발급받는 방법

[4] 기상 데이터 API에서 사용할 수 있는 루트 url을 제공한다. 해당 주소.

[6] type이 될 문자열 상수(const).

[8] - [16] 이 함수는 자바스크립트 객체인 action을 반환하는 action creator라고 한다. 인자 city를 받아 url을 만들고 axios를 사용해 해당 url에서 데이터를 가져온다. 이를 request로 저장한다. 타입으로는 위에서 정의한 패치_웨더를 보내고, 페이로드(*)에는 request를 보낸다.

 

 

components/chart.js

[1] lodash: 유용한 라이브러리 (함수 목록 정리) _. 하고 호출하는 경우가 많아서 이렇게 import

[2] 리액트를 불러와 JSX를 사용할 수 있게 해준다. [16]-[19] 참고.

[3]-[7] react-sparklines: 그래프를 그려주기 위한 라이브러리 (공식 문서)

[9]-[11] 평균값을 구하는 함수

[13]-[23] 차트 객체를 만든다. 컨택스트의 this의 props를 받아서 스파크라인을 사용한 그래프를 그린다. props 안에는 data, color, units 항목이 있다. 높이 120 너비 180의 그래프를 data를 받아서 그리는데, 라인 컬러는 color에서 지정한 대로 그리고, 평균치를 레퍼런스 라인으로 그려준다. 아래의 div는 그래프 밑에 표시하는 것이다. data의 평균치와 단위를 찍어준다. ex. 9 

[25] export default를 해주면 Chart를 사용하는 스크립트에서 따로 변수명을 입력하지 않으면 자동으로 default 키워드가 있는 모듈을 가져온다.

 

 

components/google_map.js

[2] component에 관련한 함수도 쓰기 때문에 함께 import 한다.

[4] 구글맵 클래스는 component를 상속한다. chart가 변수로 선언된 것에 반해 googlemap은 클래스로 선언되어 있는데, 클래스로 선언한 이유는 생성자에서 React.createRef();를 사용하고 있기 때문이다. 차트는 입력 데이터에 대해 단순히 스파크라인으로 출력만 하고 있으므로 const로 구현되어 있는 것이다. 즉, 사용하려는 대상 및 패키지에 맞게 선언해준 것.

[5]-[8] 생성자. 컴포넌트가 브라우저에 나타나기 전후에 호출됨.

[6] (super(props)를 하는 이유)

[7] createRef는 render()에서 생성된 DOM 노드나 React 엘리먼트를 액세스하는 방법을 제공한다. googleMap은 일반 이미지가 아닌 애니메이션과 같은 분류에 속하므로 Ref를 사용하여 트리거링해야 한다. createRef는 그 외에도 포커스, 문장선택 혹은 미디어 재생을 관리해야할 경우, 필수 애니메이션을 트리거링 할때, 써드 파티 DOM 라이브러리와 통합할때 쓰인다.

[9]-[18] 이것은 이 컴포넌트가 화면에 나타나게 됐을 때 호출된다. 콘솔에서 this.props를 보여주고, 구글맵을 만든다. 12 수준으로 zoom 한 지도를 보여주고, 위도와 경도 정보를 props에서 받아 가운데로 보낸다.

[20]-[23] 이후 렌더링한다. [7]에서 만든 액세스 지점을 참조하게 한다. render()는 그려질 내용을 설명한다. 컴포넌트를 그냥 함수로 작성하면 redner()를 생략할 수 있다.

 

 

containers/search_bar.js

[4] actions 폴더의 index.js에서 action type(패치웨더)를 불러온다.

[6] 검색창을 만들어주는 SearchBar 클래스는 위 구글맵과 마찬가지로 컴포넌트를 상속한다.

[10]-[13] state의 기본값을 지정한다.

[17]-[21] 서치바가 하는 일을 정의한다.

[22]-[43] 렌더링한다.

[45]-[47] state를 props로 매핑하는 함수. 컴포넌트의 props에 매핑할 state를 정의한다. 현재 리덕스 스토어의 상태를 어떻게 변형할지 그리고 어떤 속성을 통해 presentational 컴포넌트(어떻게 보여질지를 위한 컴포넌트로, 리덕스와 무관하며 props를 사용)로 넘겨줄지를 서술한다. state.weather.loading와 this.props.loading을 연결해주는 것.

[49]-[51] dispatch를 props로 매핑한다. 이 함수는 dispatcher를 컴포넌트의 props에 매핑한다. 디스패치는 액션을 보내주는 것이다. 액션을 생성하는 함수인 액션크리에이터 패치웨더와 디스패치를 함께 묶는다.

[53] connect 함수는 2개의 인자를 받아서 컴포넌트를 통과시키는 함수를 반환한다. 이를 디폴트로 export한다. 위에서 mapStateToProps로 스토어 안 값을 props로 전달한 이유가 바로 여기서 connect를 사용하기 위해서이다. connect함수는 react-redux의 내장 API 함수로 React Component와 Redux Store를 연결할때 사용한다. 좀 더 구체적으로 말하면 특정 component의 props 를 store의 데이터에 연결시켜주는 함수를 리턴한다.

 

참고

 

containers/weather_list.js

[2] connect 함수를 쓰기 위해 리액트-리덕스 패키지에서 기능을 가져온다.

[3]-[4] 미리 만들어둔 차트와 구글맵을 불러온다.

[6] 웨더리스트 역시 컴포넌트를 상속하는 클래스.

[7]-[21] 날씨를 렌더링하는 함수를 만든다. city, list를 인자로 받는다.

[22]-[30] 에러를 처리하는 함수. 존재하지 않는 도시를 검색하면 에러를 보낸다.

[31]-[51] 렌더링한다. 화면에서 여러개가 줄줄이 나오는 것이 웨더리스트 덕분이다. 그 구역 이름이 weather-list이고, 테이블을 만들어서 (마우스를 갖다대면 그 부분의 색이 바뀌도록 hover로 지정) 도시, 온도, 기압, 습도를 보여준다. 테이블 바디는 웨더리스트 클래스의 렌더웨더를 불러와 props의 weather에 매핑한다.

[53]-[58] state를 props로 매핑한다. 웨더는 스테이트의 웨더에 있는 데이터 항목으로, 에러는 스테이트의 웨더에 있는 에러 항목으로 각각 리턴하게 한다.

 

 

reducers/index.js

[1] combineReducers를 리덕스에서 가져온다. 사용법은 아래에 서술.

[2] 같은 폴더의 웨더 리듀서를 import한다.

[4]-[6] 일반적으로 폴더명만 주면 index.js가 실행되므로, 존재하는 리듀서를 묶어서 export 해준다.  여기에 weather: 이렇게 되어 있기 때문에 컨테이너의 서치바.js의 mapStateToProps에서 weather.loading으로 쓸 수 있게 되는 것이다.

 

 

reducers/weather_reducer.js

[1] 액션 타입을 보기 위해 패치 웨더를 받아온다.

[3] 이 함수를 디폴트로 export 한다. 리듀서이기 때문에 state, action을 받아서 state를 리턴하는 구조. 여기서 스테이트에 기본값을 주고 있다.

[6] 콘솔창에 액션을 찍어준다.

[7] 액션의 타입에 따라 수행하는 것이 다르다.

[8]-[29] 타입의 이름을 case로 구분한다. 만약 뒤에 Pending이 올 경우에는 return에 명시한 대로 리턴한다. ...은 배열을 함수 등에 파라미터로 넘길 때 유용하게 사용할 수 있는 전개연산자. (*) 이하동문. 여기서 받는 action.type은 actions/index.js의 [10] 실행 결과에 따라  _PENDING(진행중), _FULFILLED(성공), _REJECTED(실패)로 구분되며, 해당 경우에 맞게 다른 내용이 실행된다.

 

 

./App.js

[2] App.css로 이 파일을 꾸며준다.

[4]-[5] 서치바와 웨더리스트를 앱에 불러온다.

[7]-[16] 앱 컴포넌트는 서치바와 웨더리스트를 포함한다.

 

 

./index.js

[2] 리액트돔을 여기에 불러온다 (전 프로젝트를 통틀어 여기에 한 번만 부른다)

[3] 리덕스 패키지에서 필요한 부분을 가져온다

[4] Provider 컴포넌트는 connect() 함수를 사용하여 연결할 수 있도록 앱의 store를 제공(provide) *

[5] 미들웨어에 대한 자세한 설명은 여기

[8] index.js가 메인이므로, 앱을 여기에 불러와야 한다.

[9] 서비스워커는 PWA 개발의 필수 조건이다. 브라우저 백그라운드의 js 워커.

[10] 리듀서를 불러온다. 파일 이름을 따로 주지 않으면 index.js를 기본으로 가져온다.

[12]-[14] promiseMiddleware를 붙여서 스토어를 만든다.

[16]-[20] 리액트돔에서 렌더링. 리액트돔은 뭔가 실제로 화면에 그려준다. 리덕스에서 store를 만드는 일반적인 방법은

const store = sreateStore(reducer);

이지만, 여기에서는 리액트-리덕스를 사용하기 때문에 Provider 컴포넌트를 현재 앱에 래핑하는 방법을 사용한다. 앱 전체를 스토어로 감싸준다고 이해하면 된다. reactDom.render(element, document.getElementById('root'))의 의미는 이 element를 root 아이디 밑에 그리겠다는 의미다. 따라서 이 라인은 프로바이더로 감싸준 앱을 root 아이디 밑에 렌더링하겠다는 의미가 된다.

 

 

데이터 흐름

 

 

참고자료

1. 리액트, 리덕스, 리액트-리덕스 에 대한 과 그 번역본

2. 리액트 리덕스를 프로젝트에 사용한 예

3. 리액트 라이프 사이클

4. Ref : 일반적인 React 데이터 흐름에서, 부모 컴포넌트가 자식 컴포넌트와 소통하는 방법은 props 를 이용하는 것 뿐입니다. 그러나 일부 케이스에서 일반적인 데이터 흐름을 벗어나 자식 컴포넌트를 수정해야할 경우가 있습니다. 수정해야하는 자식 요소는 React의 컴포넌트거나 DOM 엘리먼트일 수 있습니다. 이런 경우를 위해 React가 제공하는 별도의 방법. (리액트 레퍼런스에 대한 과 그 번역본)

5. 웹앱 매니페스트와 서비스 워커에 대한 설명 PWA 개발과 관련이 있는 부분이라고 함. PWA는 앱과 웹 기술의 장점을 모은 방법으로, 여기에 자세한 설명이 있다.

6. yarn.lock: Yarn은 프로젝트의 의존성을 관리하는 JavaScript의 패키지 매니저로, 시스템간에 일관적으로 패키지 버전을 제공하기 위해 yarn.lock 파일을 프로젝트의 루트에 자동으로 생성

7. 엘리먼트 = 컴포넌트/변수값

8. 데이터 흐름 그림 출처: 리액트 리덕스

 

 

special thanks to 조우준 조교님

'' 카테고리의 다른 글

[redux] 미들웨어  (0) 2019.04.15
[react] 컴포넌트  (0) 2019.04.13
[react-redux] 리덕스 기초  (0) 2019.04.13
[react] props와 state  (0) 2019.04.11
[react] 기본 개념  (0) 2019.04.11
Comments