안녕하세요
이번 시간에는 React의 Routing과 Form에 대해서 배웠습니다.
참,,,,리액트는 알 것 같다가도 모를 것 같은 친구네여
0. Routing(라우팅)
라우팅의 개념을 알기 전에, SPA(Single Page Application)과
MPA(Multi Page Application)에 대해 짚고 넘어가도록 하겠습니다!
SPA = Single Page Application
웹 페이지 딱 하나로 돌아가는 애플리케이션
- 단 하나의 HTML 페이지를 로드한 후,
나머지 사용자 업데이트에 필요한 리소스와 데이터를 동적으로 로드하는 형태
- React는 SPA를 구현하기 위해 최적화되어 있음
- 동적으로 필요한 부분만 부르기 때문에 빠른 속도와 부드러운 UX 제공
- 초기 로딩 속도가 느림 (모든 자원들을 불러와야하기 때문)
- 검색 엔진 최적화(SEO)에 적합하지 않고, 콘텐츠 크롤링이 어려움
MPA = Muti Page Application
여러 개의 독립적인 웹 페이지를 구성하고, 사용자가 새로운 페이지로 이동할 때마다 새로운 웹 페이지를 불러옴
- SEO 친화적이고, 검색 엔진이 크롤링하기에 용이함
- 방식이 전통적이고 간단한 사이트를 구현하는데 용이함
- SPA와 반대로 페이지 하나하나 로딩해오기 때문에 페이지 전환 속도가 느림
- UX가 부드럽지 않음
여기서 React를 사용하여 SPA 방식을 채택하는 경우가 많습니다.
이때, 이 SPA방식이 가능하도록 도와주는 모듈이 바로 Routing입니다.
Routing이란 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것입니다.
예를 들어, 저희가 웹 페이지에서 로그인 버튼을 누르면
[ https://****/login ] URL로 이동하고, 로그인 화면이 나오잖아요?
그 URL경로를 지정해 주고 맞는 페이지를 사용자에게 보여주는 것이 ROUTING입니다.
1. Routing 사용
Routing을 사용하기 위해서는 모듈 설치를 아래와 같은 명령어로 설치해주어야 합니다.
npm install react-router-dom
일단, react-router-dom을 설치한 후 App.js에서 사용한 제 예시코드는 이렇습니다.

전체적인 구성과 한 줄씩 구체적으로 보도록 하겠습니다.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
설치했던 react-router-dom 모듈에서 각각의 기능들을 import 해줍니다.
여기서 사용하는 기능들은 아래와 같은 역할을 가집니다.
BrowserRouter
- URL과 UI 동기화 : URL의 변화를 감지하고 URL의 변화에 맞는 UI를 찰떡같이 렌더링 해주는 역할
- 중첩된 Routing지원: 한 페이지가 여러 개의 하위 페이지를 가졌을 때에도 처리 쌉가능
- 더 나은 UX: 브라우저의 뒤로 가기, 앞으로 가기 등의 기능도 지원
React의 version 6부터 Routes와 Route라는 새로운 구성 요소가 생겼습니다.

Routes
- Route 컴포넌트를 중첩하고 관리하는 역할
Route
- 특정 경로에 대해 렌더링 할 컴포넌트를 지정함
- path와 element라는 prop을 사용함
- path: URL경로지정
- element: 렌더링할 컴포넌트 지정
이 App.js에서는
각 URL에 맞게 MainPage, ProductPage, ProductDetail, Photos, NotFound라는
컴포넌트 JSX를 렌더링 하고 있습니다.
2. Component
저희가 앞서 보았던 App.js에서 Router 내 element들은
path 경로에 맞추어 렌더링 될 component라고 했습니다.
하여, Page component와 요소 compoent와 css를 위해 src 내 폴더를 components, pages, styles로 구성하였습니다.

그리고 이 pages 폴더 내에 각각의 url에 맞는 렌더링 될 페이지들을 만들어줄 겁니다.
먼저, Mainpage를 보겠습니다.

위에 있는 핑크색 부분이 App.js에서 넣었던 header입니다.
그리고 노란색 바탕을 차지하고 있는 부분이 MainPage.js에서 렌더링 하고 있는 부분입니다.
localhost:3000번에 App.js에서 정했던 path대로 MainPage 컴포넌트가 렌더링 되었습니다.
여기서 쿼리 파라미터를 붙여서 페이지에 변화를 주어 보도록 하겠습니다.

이 페이지에서 특별히 react-router-dom모듈의 useSearchParams를 불러오고 있습니다.
useSearchParams 훅
- 현재 URL의 쿼리 파라미터를 읽고 변경하게 해 줍니다.
- 현재 위에서는 searchParams에 useSearchParams()를 설정해 주었습니다.
(useState처럼 초기값과 setter함수가 정의됨 / 그러나 초기값 설정은 useState와 약간 다름)
button onClick={() => {setSearchParams({ mode: 'Dark' });}}>Dark Mode</button>
이 중에서 button을 누르게 되면 searchParams가 setter함수에 의해 { mode : "Dark" }라는
값 변경이 들어가고 있습니다.
그럼 localhost:3000에? mode=Dark라는 쿼리 파라미터가 붙음과 동시에
제가 CSS에 정의했던 대로 MainPage의 배경이 까맣게 바뀝니다.


className에 join으로 searchParams함수를 넣어주어서. Main.Dark css가 적용되었습니다.
다음은, ProductPage 컴포넌트를 보도록 하겠습니다.
앞서, App.js에서 썼던 BrowserRouter 내에서 중첩된 요소도 가능하다고 했었죠?
여기서 사용해 볼 겁니다.

저희의 ProductPage 컴포넌트는 ProductList라는 하위 컴포넌트를 부르고 있습니다.

ProductList 페이지는 productInofs라는 프로덕트의 전체 리스트를 가지고 있고,
map함수를 통해 하나하나 돌면서 다시 ProductItem이라는 컴포넌트를 부르고 있습니다.
여기서 부를 때 map함수에서 얻은 ProductInfos의 요소들을 props로 보내고 있습니다.

이 컴포넌트에서 드디어 상품명, 상세 설명을 뜯어서 보여주고 있습니다.
이 product 페이지는 하나의 Route안에 세 개의 컴포넌트가 엮여서
최종적으로 아래와 같은 화면을 보여주고 있습니다.

이 상세 설명들이 전부 <a> 태그처럼 마치 누르면 다른 URL로 가는 것처럼 되어있습니다.
이유는 ProductItem 컴포넌트에서 Link를 사용했기 때문입니다.


Link 컴포넌트
- a태그처럼 url을 제공하고 변경된 URL로 이동하게 해주는 역할
- a태그와 다른 점은 모든 페이지가 다시 렌더링 되는 것이 아닌, 컴포넌트만 바꿔치기함
- " to " prop 사용하여 이동할 경로 지정
제가 사용한 Link에서는 `/products/${product.id}`로 이동하기 때문에, id가 1인 상품의
상품명, 상세설명 중 아무거나 누르게 된다면 /products/1 URL로 이동하게 되겠죠.

그럼 저희가 App.js에서 정의한 url대로 ProductDetail 컴포넌트로 렌더링 하게 됩니다.

이 컴포넌트에서 특이한 점은 저희가 URL에서 param을 통해 이 컴포넌트에 들어왔기 때문에,
useParam훅을 사용합니다.

Router 모듈로부터 useParams와 useNavigate 컴포넌트를 불러오고 있습니다.
useParams 훅
- 동적으로 들어오는 경로를 추출할 수 있음
- ex) /product/ :id 이렇게 들어온다면 이 id값을 추출할 수 있음
지금은 product의 id값을 동적으로 넘겨주고 있어서, id값을 useParams로 추출한 후,
productInfo배열에서 [ id-1 ]에 해당하는 상품의 디테일을 가져오고 있는 것입니다.
(배열의 index는 0부터 시작하지만, 상품은 1부터 시작하기 때문)
useNavigate 훅
- 함수를 반환하고 그 함수를 사용하여 페이지 이동, 변경시킬 수 있음
- 안에 경로를 넣어서 주로 사용
- ex) navigate('/home')
제가 예제에서 사용한 navigate(-1)은 뒤로 가는 역할 버튼입니다.
자기가 조회한 바로 전 컴포넌트를 렌더링 해줍니다. 신기하죠?

이로써, React의 Routing은 전체적으로 보았습니다.
많은 컴포넌트와 훅이 나왔지만 전체적으로 구성을 잘 이해한다면 어렵지 않은 개념입니다.
3. React Hook Form
React의 라이브러리 중 React Hook Form이라는 라이브러리가 있습니다.
React에서 폼을 쉽게 관리하고 폼 상태 관리와 유효성 검사를 간단하게 만들어 주며,
필요한 인풋 컴포넌트만 리렌더링 되고, 폼 유효성 검사와 에러메시지를 폼 안에서 처리할 수 있습니다.
이러한 다양한 장점으로 현업에서도 많이 쓰인다고 합니다
먼저, 라이브러리 설치는 다음 명령어로 진행할 수 있습니다.
npm install react-hook-form
그리고 사용하고 싶은 컴포넌트 안에서 import 해야 합니다.

이 useForm 컴포넌트는 굉장히 많은 기능을 제공하기 때문에
다음과 같은 네 가지 분해로 사용하도록 하겠습니다.

[ register ]
- Form의 인풋 요소를 등록하고, 인풋 요소의 값 변경을 감지함
<input {...register('fieldName', {'option'})} />
... register부분은 생소한 모양이었지만,
ref요소를 사용해서 Dom에 직접 닿을 수 있게 생성한 패턴이라고 합니다.
첫 번째 인자로 네임값을 받아 이를 통해 ref로 Dom에 직접 관여하고,
두 번째 인자로 input을 받을 조건? 옵션을 넣습니다.

여기서 'username'이라는 input을 등록하고 감지하는데,
이때 옵션은 required와 minLength인 것입니다.
여기서 자주 올 수 있는 옵션들에 대해 정리하겠습니다.
1. required (boolean 또는 문자열):
- 인풋 필드가 반드시 채워져 있어야 하는지 여부를 나타내는 옵션
- 문자열로 설정하면 해당 문자열이 필드가 비어있을 때 나타나는 에러 메시지로 사용함
{...register('fieldName', { required: '이름을 입력해주세요' })}
2. minLength 및 maxLength (객체):
- 최소 길이와 최대 길이를 설정할 수 있는 옵션입니다.
- minLength에는 value( 최소 길이 ) 속성과 message ( 에러 메시지 ) 속성이 포함된 객체를 전달
{...register('fieldName', {
minLength: { value: 2, message: '이름은 최소 2글자 이상이어야 합니다' },
maxLength: { value: 10, message: '이름은 최대 10글자까지 허용됩니다' }
})}
3. pattern (객체):
- 정규식 패턴을 사용하여 입력 값을 검증할 수 있는 옵션
- value에 정규식 패턴을, message에 에러 메시지를 설정
{...register('fieldName', {
pattern: {
value: /^[A-Za-z]+$/, // 알파벳만 허용
message: '영문자만 입력 가능합니다'
}
})}
4. validate (함수):
- 사용자 정의 유효성 검사 함수를 설정할 수 있는 옵션
- 사용자 정의 함수를 정의하고, 그 함수에서 유효성을 검사한 후 에러 메시지를 반환
{...register('fieldName', {
validate: (value) => {
// 유효성 검사 로직
// 유효하다면 아무 값도 반환하지 않음
// 유효하지 않다면 에러 메시지 반환
return value.length > 5 ? undefined : '최소 6글자 이상 입력해주세요';
}
})}
[ handleSubmit ]
- 폼이 제출될 때 실행하는 함수를 호출하는 역할

onValid 함수는 폼이 성공적으로 제출될 때 실행되는 함수이고,
onInvalid함수는 폼의 제출이 실패되었을 때 실행되는 함수입니다.
둘 다 data를 인자로 받으며 console.log로 찍어보면 어떤 데이터가 제출되었고,
어떤 데이터가 실패되었는지 알려줍니다.
[ formState ]
- 이 객체는 폼의 상태 정보를 제공함
- 이 중 errors 속성은 유효성 검사 에러에 대한 정보를 포함함

이 맨 밑 로그에서 formState의 errors가 쓰이고 있습니다.
옵셔널 체이닝으로 errors 객체에 username이 있다면 errors.message를 보여주라는 뜻입니다.
(error객체에 usename이 있다는 것은 required에서 걸렸거나, minLength에서 걸린 것이겠죠)
[ watch ]
- 특정 필드의 값을 실시간으로 감시하는 함수
- 필드 값에 따라 동적으로 상호작용할 수 있음
이상,,,,,,,자러가야겠어요,,,,,,,,,,,,,,,,
'개발 공부한 것들 > SeSSAC 웹 풀스텍 과정 회고록' 카테고리의 다른 글
| SeSSAC 웹 풀스텍 과정 회고록[SeSSAC] 웹 풀스택 영등포 5기 과정_2차 프로젝트 회고록 (0) | 2023.11.14 |
|---|---|
| [SeSSAC] 웹 풀스택 영등포 5기 과정_REACT(7)_Redux (0) | 2023.10.22 |
| [Sessac] 프로젝트 회고록_CRUD (0) | 2023.10.14 |
| [SeSSAC] 웹 풀스택 영등포 5기 과정_REACT(5)_Sass (0) | 2023.10.12 |
| [SeSSAC] 웹 풀스택 영등포 5기 과정_REACT(4)_hooks (2) | 2023.10.12 |