예전엔 프론트 두려워하고 자신도 없었는데요,, 그래도 풀스택 교육 들으면서 React-TypeScript 조합으로 프론트 개발도 해보고, API 연동도 해보니 이제 어느정도는 할 수 있게 되었답니다.
물론 디자인까진 많이 신경을 못쓰지만요..
원할한 프론트엔드와의 협업과 백엔드를 맡아도 간단한 프론트 개발할 일이 분명히 있을 것 같아서 까먹지 않도록 API 연동 순서를 정리해봅니다.
React-TypeScript 환경에서 Spring Boot로 개발했던 REST API 연동입니다.
1. 엔티티별 DTO 타입 정의
1-1. 백엔드 API 만들 때 dto 클래스 작성했던 것을 모두 타입 정의를 해줘야 한다.
엔티티클래스명+Request/ReponseDto.d.ts 파일 생성
1-2. 각 엔티티별로 만들어둔 Request, Response Dto 클래스 필드들을 모두 타입 정의를 해준다.
Request, Response 로만 나눠서 파일 생성하고, 해당 파일안에 모두 작성하면 됨.
↓
- type 종류
- boolean
- number
- 소수점 포함
- string
- 작은 따옴표, 큰 따옴표 포함
- array
- 다중 타입 가능 (string | number)[]
- tuple
- 고정된 길이 배열
- enum
- any
- API 같이 외부 자원을 사용할 때 타입을 단언할 수 없을 경우
- unknown
- object
- null, undefined
- void
- 값을 반환하지 않는 함수에서 사용
- union
- 2개 이상의 타입을 허용하는 경우 (string | number)
- function
2. urlFactory.ts에 각 API마다 URL 등록
urlFactory.ts라는 파일은 API를 한눈에 볼 수 있고, 매개변수와 경로를 적어서 Fetch 함수 작성시 사용할 수 있다.
2-1. 각 API 별로 URL을 등록한다.
주석으로 HTTP 메소드 종류와 간단한 설명, Req/Res 받는 데이터나 상태 코드에 대해서 적어두면 좋다.
예시)
const BASE_URL = import.meta.env.VITE_API_URL;
//--------------- 메인 ---------------//
// POST - 간편 로그인: LoginReqDto -> LoginResDto
export const LoginURL = () => `${BASE_URL}/login`;
//--------------- 모임원 ---------------//
// POST - 모임원 전체 출력: TeamMembersReqDto -> TeamMembersResDto
export const TeamMembersPostURL = () => `${BASE_URL}/team`;
// POST - 모임 초대하기 (초대링크 생성): InviteTeamReqDto -> String
export const GenerateInviteLinkPostURL = () => `${BASE_URL}/team/invite-team`;
// PUT - 총무 변경: ChangeOwnerReqDto -> 200 OK
export const ChangeOwnerPutURL = () => `${BASE_URL}/team/change-owner`;
3. 각 페이지에 Fetch 함수 사용해서 API 연동하기
아마 프론트랑 협업할 때는 useFetch나 모달, 토글 등 이미 작성된 커스텀 Hook이 있을거다. 그 Hook을 사용해서 API 연동작업을 하면 된다.
예로 모임원 전체 출력 기능을 연동한다면,
해당 API는 List<TeamMembersResDto> teamMembers(Long teamIdx); 의 형태이다.
team 아이디를 전달하고, ResDto 리스트를 받는 형태이다.
3-1. 프론트에서 먼저 전달할 값을 변수로 받는다.
const requestData: TeamMembersReqDto = { teamIdx: teamIdx };
3-2. fetch 함수를 사용하여 API 연동 코드를 작성한다.
// 모임원 전체 정보 가져오기
const {
data: teamMemersData,
isLoading: isTeamMembersLoading,
refetch,
} = useFetch<TeamMembersReqDto, TeamMembersResDto[]>(
TeamMembersPostURL(),
"POST",
requestData
);
Response 받을 데이터는 data: 에 작성하면 된다.
useFetch 함수 부분은 아까 형태처럼 teamIdx를 전달하고(ReqDto), ResDto 리스트를 받는 형태로 작성한다.
그리고 아까 등록한 해당 API에 맞는 URL과 HTTP 방식을 작성해주면 된다.
3-3. return 부분에 response된 값을 출력할 코드를 작성한다.
return (
... 생략 ...
<span>{teamMemersData?.length}명 참여 중</span>
... 생략 ...
<VStack className="w-full gap-4">
<span className="text-sm"> 총무 </span>
{teamMemersData?.map(
(member) =>
member.teamMemberState === "총무" && (
<HStack
key={member.teamMemberIdx}
className="items-center gap-4"
>
Response 받은 데이터를 사용하여 출력할 데이터를 작성하면 된다.
참고로 커스텀 Hook을 따로 만들어서 쓰지않고, fetch 함수를 썼을땐 이런 형태였답니다.
// 카테고리 별 메뉴 출력
const fetchData = () => {
fetch('<http://localhost:8080/order>', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
category: category,
page: page,
}),
})
.then((res) => {
return res.json();
})
.then((json) => {
const message: Message = json;
const { status, result: products } = message;
if (status == 'PRODUCT_CHECK_SUCCESS') {
setProducts(products.content);
setTotalPage(products.totalPages);
}
})
.catch((err) => console.error(err));
};
fetch 함수 사용하는 것 보단 확실히 커스텀 Hook을 따로 만들어서 사용하는 것이 코드도 줄고 편한 것 같아요.
'JS & TS > TypeScript' 카테고리의 다른 글
[TypeScript] Utility Types (0) | 2024.02.15 |
---|---|
[TypeScript] 선언 파일과 구성 및 옵션, 타입 운영 (0) | 2024.02.15 |
[TypeScript] Generic (0) | 2024.02.15 |
[TypeScript] 타입 제한자 (0) | 2024.02.15 |
[TypeScript] Class (0) | 2024.02.13 |