React와 연결하기
api
- 고객이 접하는 애플리케이션을 만들기 위해 React 애플리케이션을 만들어보자.
- 만들어질 React애플리케이션이 gc-coffee 스프링부트 애플리케이션의 API를 호출하도록 연결해주자.
리액트 서버에서 스프링부트를 호출할 수 있도록 설정해준다.
- 컨트롤러에 api 패키지를 만들고 그 안에
ProductRestController
클래스를 넣어 꾸며주자.
- 전체 제품을 조회할 수 있는 컨트롤러 메서드를 만들어보자.
@GetMaping
의 URL은 api에 v1을 주고 products
복수의 형태로 표현함으로 다건의 제품이 반환된다는 것을 알려줄 수 있다.
- 필요하다면 products에 RequestParam을 사용해서 카테고리별로 조회하게 할수도 있다.
Optional
로 카테고리를 받고, map
처리를 한다. 카테고리가 존재하면 map의 언더펑션이 동작.
카테고리별 제품, 혹은 모든 제품을 반환한다.
Post
- configuration 패키지를 만들고
MvcConfiguration
클래스를 생성해준다.
WebMvcConfigurer
를 이용하면 원하는 Mvc설정을 확장할 수 있다.
addCorsMappings
을 통해 cors레지스트리에서 addMapping
으로 api에 대한 cors 설정을 할 수 있다.
@Configuration
추가.
React 사용해보기
node.js 다운로드
- 왼쪽 것을 다운로드 받자.
Long Term Support. 오랜 기간 지원한다는 의미로, 안정적이다.
- node.js도 환경변수 설정을 해줘야한다. 자바의 환경변수 설정을 한 것과 비슷하게 하면 된다.
내 PC → 속성 → 고급 시스템 설정 → 환경변수
로 들어가준다.
두 가지를 설정해주어야 한다.
NODE_HOME
변수를 생성해준다. 특별히 지정해주지 않는다면 C드라이브의 Program 폴더 안에 위치한다.
- 다음은
Path
변수에서 %NODE_HOME%
을 추가해준다.
React
- npx : 노드 패키지를 실행시킬 수 있게 해주는 명령어.
create-react-app
을 실행시키며 my-app
이라는 폴더를 만들고 해당 폴더에 기본적 설정이 되어 있는 리액트 애플리케이션이 생성됨.
- 빌드 완료.
지정해놓은 경로로 가면 설정해놓은 프로젝트 명으로 생성된 폴더가 있다.
package.json
에 가면 "start"
명령어를 사용할 수 있는 것을 확인할 수 있다.
package.json
은 노드 프로젝트에서 노드 패키지 모듈이라는 것을 알려주는 명세서 같은 것.
start
: 리액트 스크립트를 실행시켜, 리액트 애플리케이션을 실행시킨다.
- 리액트 애플리케이션이 실행된 모습.
localhost:3000
으로 접속하면 볼 수 있다.
- 리액트 애플리케이션을 만들어보자.
리액트란?
- 프로젝트를 진행하다보면 HTML과 CSS는 퍼블리셔가 제공한다.
디자이너가 이미지 제공 > 이 이미지를 바탕으로 HTML, CSS 작성. > 프론트엔드 개발자가 HTML, CSS를 리액트 애플리케이션으로 전환함.
사용자 인터페이스를 만들기 위한 JavaScript 라이브러리
JS 라이브러리를 이용해서 JS 애플리케이션을 만들 수 있고, 이 JS 애플리케이션이 사용자 인터페이스를 제공한다.
- 대부분 웹 브라우저 인터페이스를 제공하지만, React Native를 이용해서 앱 개발도 가능.
- JSX : 리액트가 개발한 문법으로 개발자가 리액트 코드를 전달하면, 그것을 JS 코드로 변환해서 전달함.
- 리액트는
Element
혹은 Component
의 묶음으로 구성된다.
이런 컴포넌트를 정의하고, 이 컴포넌트로 하나의 애플리케이션을 구성하게 된다.
HTML 가져오기
- 이 웹 페이지에서 HTML 파일을 어떻게 저장할까?
- 먼저, 웹 페이지에서
ctrl + s
눌러 저장해준다.
- 이런 창이 뜨는데 맨 위의,
웹페이지, HTML만
을 체크해준다.
경로를 설정하고 저장을 눌러주면 된다.
- HTML 파일을 인텔리제이에 바로 집어넣으면 HTML 파일의 구조를 알 수 있다.
- 빨간 밑줄을 쳐놓은 부분에서 브라우저를 골라 실행볼수도 있다.
React App
- 리액트 애플리케이션은 src > index.js가 시작지점이 된다.
- APP이라는 애플리케이션을 root에다 구현한다고 볼 수 있다.
- 즉,
App
을 바꾸면 화면 구성을 바꿀 수 있다는 뜻.
- App 안의 스크립트를 모두 지우면 리액트 애플리케이션의 웹 화면도 텅 비는 것을 확인할 수 있다.
- 파일이 변경되면 화면을 실시간으로 업데이트해준다.
React 애플리케이션 구성
- sample.html의 body부분을 복사해서
App.js
에 넣어준다.
- body를 div로 바꿔주고
ctrl + alt + L
을 사용해서 자동으로 포맷팅을 해준다.
- 안닫힌 이미지 태그들을
/
를 사용해서 닫아주자.
- hr 태그를 닫아주면 오류를 모두 수정했다고 나오고, 그 순간 React App 페이지가 변한다.
- 지금은 세부설정이 전혀 안되어 있어서 그리 보기 좋은 모습은 아니다.
CSS를 적용해주자.
- sample.html의 style 부분 복사 → App.css에 붙여넣기 → App.js에서 import 설정을 해주면 된다.
- 아까보다는 조금 보기 좋아졌다.
- 더해서, bootstrap을 사용하고 있기 때문에 bootstrap을 추가해주어야 한다.
npm install bootstrap
- 이전에 설치해서 그런지 딱히 출력되는 메시지는 없다.
- bootstrap의 css를 사용할 수 있도록 import를 해줬고, 모양이 얼추 갖춰졌다.
컴포넌트로 쪼개기
- 상품 목록과 Summary의 큰 영역으로 구분된다.
상품 목록 안에는 제품군이 있고 Summary안에는 선택한 아이템들을 보여준다.
- 이들을 컴포넌트로 분리해주자.
ProductList 컴포넌트 만들기
- 리액트에서는 클래스 컴포넌트도 생성할 수 있지만, function컴포넌트로 생성해주자.
일반적으로 JS는 소문자로 시작하지만, 컴포넌트라는 것을 알려주기 위해서 대문자로 생성한다.
- return 값으로 나와야하는 것은 element 코드들.
리액트 컴포넌트는 무조건 하나의 엘리멘트만 리턴되어야 한다.
- 두개를 하나로 묶어 div를 할수도 있지만,
React.Fragment
를 사용해보자.
- 상품목록에 해당하는 부분의 코드를
function ProductList
에 삽입.
→ function App
에서 사라졌기 때문에 리액트 애플리케이션에 출력이 되지 않음.
→ function App
의 기존 상품목록 부분에 <ProductList/>
추가
→ 상품목록 제대로 출력됨.
- 컴포넌트를 구분한 후 다시 애플리케이션에 출력시키는 일련의 과정.
Summary 컴포넌트 만들기
- Summary 도 마찬가지 방법으로 만들어준다.
Product 컴포넌트 만들기
- Product의 컴포넌트도 만들어주자.
- 여기서 잠깐. Product의 각 값 : 커피콩, Columbia Nariñó, 5000원 등의 정보들이 데이터를 받아 출력된다.
이것은 argument로 전달되는데, 리액트에서는 props
에 argument를 객체로 전달해주게 된다.
props
를 이용해 코드를 바꿨다.
const
상수를 선언하는 함수로 productName 등을 함수로 선언한 것.
props를 통해 객체, 파라미터 형태로 값을 전달받게 된다.
각 데이터에는 { }
표현식을 사용해서 데이터에 접근하게 된다.
- props에 빈 객체가 들어가기 때문에 값이 비어있다.
- props를 이용해 바꾼 Product 컴포넌트를 이용해 코드를 추가했다.
ProductList props 이용해서 바꾸기
- ProductList 역시 props로 처리해줄수 있다.
JS에서는 객체를 디스트럭쳐 할 수 있다.
function ProductList({ products }) {
props 안에 products가 존재한다고 보는 것.
products.map(v => )
프로덕트만큼 매핑을 해서 전체 프로덕트 안에 있는 배열의 요소만큼 변환하는 코드를 작성할 수 있다.
- 각 변수도 하드코딩 된 값이 아닌
v.
의 값으로 변경.
- 디폴트 값을 전달해줘야한다.
- 루프를 돌때는 키를 전달해주어야한다.
- 상품 목록이 비었고, product는 App에서 전달해주어야한다.
App과 ProductList 컴포넌트 연계하기
- App에 상태를 만들어보자.
클래스형 컴포넌트로 만들었을 때는 this.state로 상태에 접근할 수 있다.
함수형 컴포넌트에서는 useState();
라는 훅을 이용해야한다.
useState();
는 인자가 두개인 배열을 반환한다.
const [product, setProduct] = useState();
두번째는 상태값을 바꾸는 함수, 첫번째는 상태에 접근할 수 있는 변수명.
SummaryItem 컴포넌트 만들고 Summary와 연계하기
- Summary에서 반복되고 있는 부분을 처리하기 위해서
SummaryItem
컴포넌트를 만든다.
- ProductList를 작성한 것과 비슷한 방식으로 만들어주면 된다.
- 추가된 제품들이 사라졌다. 디폴트 값이기 때문.
- 총 금액은 전체 목록 아이템에 price를 곱한 가격이기 때문에 함수를 작성해주자.
- totalPrice 메서드 작성.
reduce
함수를 이용해 items에서 prev 값과 curr 값을 받아온다.
prev + (curr.price * curr.count)
: 이전 값 + (현재값 * 현재개수).
default
값은 0으로 설정