bootstrap 으로 화면 구성

화면을 구성해야 하므로 화면 구성을 도와줄 CSS 프레임웍인 bootstrap을 설치한다. bootstrap과 bootstrap을 리액트 컴포넌트로 구성한 react-bootstrap 두개를 모두 설치한다.

index.tsx에 bootstrap css를 적용한다.

components 폴더를 만들고 BoardList.tsx 컴포넌트를 생성한다. BoardList.tsx에 커서를 위치시키고 rsc + tab 을 누르자. 그러면 펑션 컴포넌트가 자동으로 생성될것이다. 이것은 react live template이 webstorm에 기본 탑재되어있기 때문이다. rsc는 react stateless component의 약자이다. live template에 대한 내용은 여기를 참고하자.

p-3은 padding을 1rem 만큼 적용하라는 boostrap의 유틸리티 클래스이다. 자세한 설명은여기에서 확인하자.

App.tsx에서 이 컴포넌트를 로딩한다.

Container 컴포넌트는 bootstrap의 container 클래스를 react-bootstrap에서 컴포넌트로 래핑한 것이다. bootstrap을 접해보지 못했다면 먼저 bootstrap의 container 클래스를 먼저 공부해야 한다. 여기를 살펴보자.

아직 구현한게 없으므로 브라우저에는 빈화면으로 나올것이다. 게시판 목록 가져오기 REST API를 호출해서 먼저 로그만 찍어보자.

Http 클라이언트 axios 사용

우선 HTTP 를 호출할 http 클라이언트 라이브러리가 필요한데 axios를 사용할 것이다. 아래 명령으로 모듈을 설치한다.

화면이 렌더링된 직후에 REST API를 호출하기 위해서 useEffect 훅을 사용한다. useEffect 훅을 이해하기 위해서는 먼저 클래스 component 의 componentDidmount 라이프 사이클을 이해해야 한다. 이 사이클은 화면이 렌더링된 직후에 호출되는 라이프 사이클이고 이것이 useEffect 훅으로 구현할 수 있게 되었다. sideEffect란 의미가 개발에서는 부작용이라는 의미가 아니라 어떤것이 일어난 후에 부가적으로 일어난다는 의미로 사용된다. 그래서 useEffect의 의미는 화면이 렌더링된 다음에 부가적으로 실행된다는 의미로 생각하면 된다.

useEffect의 첫번째 파라메터는 함수이고 두번째 파라메터는 watch할 대상을 배열에 넣어둔다. 두번째 파라메터가 빈 배열로 되어있으면 watch할 대상이 없으므로 화면이 렌더링 된 후 한번만 실행되게 된다.

axios의 간단 설명은 여기에서 확인하자. get 방식으로 호출하면 Promise가 호출되므로 Promise 패턴을 ES7 패턴인 async-await 방식으로 바꾸었다. 자바스크립트는 싱글쓰레드이기 때문에 비동기 패턴인 콜백패턴, Promise 패턴, async-await 패턴은 반드시 알아야 한다.

앞에서 만든 게시판 목록 보기 API를 호출하고 그 결과를 콘솔로 출력해보자.

F12번을 누르고 개발자툴을 띄운다음 network 탭을 보면 CORS error가 발생할것이다.

CORS에 대한 이해와 proxy 설정

브라우저가 http://localhost:3000 번으로 접속하다가 이 도메인외 다른 도메인인 http://localhost:8080 으로 접속하게 되면 브라우저는 options 메서드로 해당 도메인에 먼저 허가 여부를 물어보게 된다. 서버에서 만일 CORS 설정을 했다면 통과하겠지만 만일 서버에서 CORS 설정을 하지 않았다면 CORS 에러가 발생하게 된다.

이것을 해결하기 위해서 서버에서 CORS 설정을 해주는 방법이 있겠지만 클라이언트에서도 이것을 해결해 줄수있다. package.json에 아래와 같이 proxy 설정을 추가한다.

그리고, axios에서 호출시 도메인은 제외하고 호출한다.

package.json을 수정하면 서버를 다시 재시작해야 한다. 왜냐하면 package.json은 watch 의 대상이 아니라서 그렇다. 재시작후 console 창을 보면 아래와 같다.

데이터 바인딩

리턴되는 res에는 http response의 헤더와 body에 해당하는 모든 값이 담겨져 온다. 현재 지금 필요한 것은 http response의 data 이다. data는 콘솔에서 보다시피 데이터 타입이 object 배열이고 서버에서 board 테이블에 해당하는 값들이 담겨져 있다.

서버에서 넘어오는 게시판 데이터인 object를 정의하는 Board.ts 라는 interface를 dto 폴더안에 먼저 만든다.

서버에서 받아온 배열 데이터를 useState 훅에 정의한다. useState 훅은 상태를 정의하는 클래스 컴포넌트를 리액트 훅으로 가져온 것이다. 리액트는 자바스크립트 변수로 상태를 정의하고 상태를 변경하면 상태에 따라서 뷰가 렌더링 된다.

boardList라는 상태 변수는 typescript를 사용하여 useState에 제네릭 타입으로 Board 타입의 Array라고 정의하였다. 따라서 코드가 더 명확해졌고 읽기 쉬워졌다.

상태변수를 바인딩하면 뷰가 렌더링 되어야 하므로 return 문에 부트스트랩을 사용해서 렌더링한다.

xs 는 574 보다 작은 경우, sm은 574 보다 큰 경우의 break point 이다. bootstrap의 grid 시스템은 12칸이므로 8칸은 제목에 날짜에 4칸을 할당하라는 뜻이다. bootstrap의 break point 는 여기서 확인하자. 하지만 이렇게 하면 날짜 부분의 오른쪽 부분에 공백이 생긴다. 왜냐하면 4칸을 차지하고 왼쪽 정렬이 되었기 때문이다.

SCSS 적용

SCSS를 적용하기 위해서 node-sass 를 추가로 설치해야 한다.

동일한 폴더에 BoardList.scss화일을 추가한다.

추가한 scss를 BoardList.tsx 컴포넌트에서 로딩한다.

날짜 컬럼은 auto로 설정하면 컨텐츠 넓이 만큼 차지하게 된다.