오늘 배운 것
1. Apollo-Client의 여러가지 쿼리 방식
Apollo-Client의 useQuery는 페이지가 렌더링 될 때 data라는 고정된 형태로 데이터를 fetch해온다. 실행함수에 담아서 내가 원하는 시점에 Mutation을 요청할 수 있는 useMutation보다 훨씬 유연성이 떨어진다고 볼 수 있다. 이러한 점을 보완하기 위해 Apollo Client에서도 다양한 쿼리 방식을 지원하는데, 오늘은 그 중 두 가지를 배웠다.
useQuery | useLazyQuery | useApolloClient |
컴포넌트 열리면 바로 실행 | 원하는 시점에 실행 | 원하는 시점에 실행 |
useQuery를 내가 원하는 만큼 지연시키는 방식이다. (원하는 시점에 useQuery를 실행하는 것과 동일) | 내가 원하는 시점에 실행 가능하고, 요청에 대한 결과물도 내가 원하는 상자(함수, 변수 등)에 담을 수 있다. |
이 중 가장 활용도가 높은(=유연한) 것은 useApolloClient로 보인다.
그래서 useQuery와 useApolloClient를 사용해서 동일한 유저 정보를 받아오는 방법을 비교해보았다.
// useQuery를 사용하여 유저 정보 받아오기
const { data } = await useQuery(FETCH_USER_LOGGED_IN);
// useApolloClient를 사용하여 유저 정보 받아오기
const client = useApolloClient();
const resultUserInfo = await client.query({
query: FETCH_USER_LOGGED_IN,
context: {
headers: { Authorization: `Bearer ${accessToken}` },
}
});
useQuery를 사용하는 경우
- data라는 고정된 형태의 상자에 useQuery의 결과물을 담는다.
- useQuery하는 시점을 내가 지정하는 것이 불가능하다.
- useEffect등에 담아 fetch 시점 조작을 시도하면 아예 작동이 안 됨.
useApolloClient를 사용하는 경우
- 내가 원하는 실행 함수 내에 이 구문을 넣어주면 된다. 즉, fetch 시점 컨트롤이 가능하다는 뜻
- axios랑 비슷하다. (진짜 비슷함)
2. React hook form / Yup
React form 라이브러리, 그 중에서도 React hook이 도입된 이후 가장 많이 사용되고 있는 라이브러리 중 하나인 React-hook-form을 다루는 방법을 배웠다. (그 외의 React form 라이브러리 : React-form / Redux-form / Formik 등등..)
form 이란?
<form></form>
웹페이지에서 사용자로부터 값을 전달받을 수 있는 HTML 입력 폼(form)을 정의할 때 사용한다. form 안에는 한 개 이상의 input, textarea, select, option, fieldset 등이 들어갈 수 있다. 일반적으로 사용하는 회원가입 폼, 문의 폼 등의 단어에 들어가있는 폼(form)이 바로 이것.
form을 사용하면 input에 들어가는 정보를 개별적으로 처리하지 않고 하나의 데이터로 묶어서 처리할 수 있다. 국소적으로는 별 차이 없어 보일 수 있지만, 서비스가 커질수록 데이터 처리에 있어서 여러가지 장점이 있음. 어지간하면 입력 양식에는 반드시 form을 쓰도록 하자. 심지어 리액트에는 이 form을 간단하게 만들 수 있는 라이브러리도 많이 있고 말이다.
거기다가 Yup이라는 검증(Validation) 라이브러리까지 더하면, 각각의 input에 입력되는 값을 검증하는 작업도 간편하게 처리할 수 있다. (물론 yup 단독 사용도 가능함!)
React-hook-form 과 yup 사용 예를 보자.
import { useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import styled from "@emotion/styled";
interface IMyButtonProps {
isValid: boolean;
}
const MyButton = styled.button`
background: ${(props: IMyButtonProps) => (props.isValid ? "yellow" : "")};
`;
const schema = yup.object().shape({
myEmail: yup
.string()
.email("이메일 형식이 적합하지 않습니다.")
.required("이메일은 필수 입력 사항입니다."),
myPassword: yup
.string()
.min(4, "비밀번호는 최소 4자리 이상 입력해 주세요.")
.max(16, "비밀번호는 최대 16자리 이상 입력해 주세요.")
.required("비밀번호는 필수 입력 사항입니다."),
});
interface FormValues {
myEmail?: string;
myPassword?: string;
}
export default function ReactHookFormPage() {
const { register, handleSubmit, formState } = useForm({
resolver: yupResolver(schema),
});
const onClickSubmit = (data: FormValues) => {
console.log(data);
};
// console.log("리렌더링 체크👻");
return (
<form onSubmit={handleSubmit(onClickSubmit)}>
이메일 : <input type="text" {...register("myEmail")} />
<br />
<div>{formState.errors.myEmail?.message}</div>
<br />
비밀번호 : <input type="password" {...register("myPassword")} />
<br />
<div>{formState.errors.myPassword?.message}</div>
<br />
<MyButton isValid={formState.isValid}>로그인</MyButton>
</form>
);
}
타입스크립트 포함 약 50줄 가량의 코드로 아래 프로세스를 전부 처리할 수 있다.
- 각각의 input에 입력되는 값을 받아서 data에 모은다.
- 검증 조건 (문자열의 길이, 필수 요소 여부 등) 을 확인하여 문제가 있을 경우 에러 문구를 출력한다.
- submit 버튼을 눌렀을때 data를 활용한 함수를 실행한다.
- 원한다면 reset이나 기타 기능을 하는 버튼도 간단하게 넣을 수 있다. (button의 type만 지정해주면 됨)
React-hook-form과 yup의 공식 페이지들을 링크해둔다. 데모를 확인하며 라이브러리 사용 연습을 해보자.
https://www.npmjs.com/package/yup
3. Global State의 활용🤔
javascript에서 전역 변수 / 지역 함수를 선언할 때와 결을 공유하는 문제인데, 글로벌 스테이트로 선언한 값과 로컬 스테이트로 선언할 데이터를 잘 구분해야겠다. 글로벌 스테이트를 남발하면 서비스 전체의 성능이 너무너무 떨어질 것 같음. accessToken처럼 도메인 전체에서 일정 값을 공유하여 사용해야 하는 경우, 혹은 서로 동떨어져있는 컴포넌트에서 동일한 fetch Data를 사용해야 할 경우처럼 '반드시 필요한 경우'에만 글로벌 스테이트를 쓰도록 하자.
4. 개인 포트폴리오 프로젝트
오늘 배운 React hook form을 이용해서 제품 등록 페이지를 만들고, string 배열로 db에 들어가는 태그 기능을 구현했다. 리뷰 게시판 목록페이지까지 만들려고 했는데 그건 못했고. 그날그날의 과제 뿐 아니라 프로젝트 리셋의 업보인 게시판 재제작 작업도 같이 하려니 정말.. 눈이 돌아간다.. 🤩 그래도 지금까지 배운 내용을 바탕으로 조금 더 정돈된 코드를 짤 수 있는 점은 좋다. 몸은 피곤하지만 속은 시원함.
앞으로 할 것
- 리뷰 게시판 등록 페이지 다시 만들기 (게시글 수정처럼 손이 많이 가는 작업은 주말에 집중해서 처리하기)
- 메인 랜딩 페이지 제작하기 : 양이 많아서 매일매일 조금씩 하고 있다. 어제는 레이아웃을 잡았으니, 이제는 위에서부터 한 섹션씩 차근차근 만들어나갈 예정..
- 운동하기! 요즘은 날이 추워서 러닝 나가기 너무 귀찮고.. 대신 땅끄부부 칼소폭을 하고 있음. 주 3회 이상이 목표다.
'Journal > Today I Learned' 카테고리의 다른 글
TIL - 2022.02.18 금요일 (0) | 2022.02.18 |
---|---|
TIL - 2022.02.17 목요일 (0) | 2022.02.17 |
TIL - 2022.02.15 화요일 (0) | 2022.02.15 |
TIL - 2022.02.14 월요일 (0) | 2022.02.14 |
TIL - 2022.02.10 목요일 (0) | 2022.02.10 |