나의 경우는 백단 서버가 이미 존재하여, URI로 요청하는 방식이므로 axios를 사용했다
axios 사용법에 앞서, 기본적인 react 문법을 훑고 지나가자
기본 react 문법
아래는 임시로 작성한 Mypage 이다
import {NextPageWithLayout} from "@/pages/_app";
import Layout from "@/components/layout/Layout";
import {useState} from "react";
interface itemListProps {
id: string
title: string
}
const MyPage: NextPageWithLayout = () => {
//기본적인 변수 선언법
const [nickname, setNickname] = useState<string>('')
const [age, setAge] = useState<number>(0)
const [isModalOpen, setIsModalOpen] = useState(false)
const [itemList, setItemList] = useState<itemListProps[]>([])
return(
<div> mypage </div>
<div>
{itemList.map((item, index) => (
<div key={item.id}>{item.title}</div>
))}
)
}
MyPage.getLayout = function getLayout(page) {
return <Layout>{page}</Layout>
}
export default MyPage
useState
변수선언은 useState 를 이용하여 선언한다. 우측 괄호 안에 값을 넣는 것으로 초기화 가능하다
또한 List 선언의 경우 type을 정해서 itemListProps 라는 type을 정해서 리스트화 시켜줬다.
parameter type
특히 api와 통신하는 값을 받는 리스트의 경우 위와 같이 type을 interface로 선언해주고 사용하자.
n명의 개발자가 동시에 개발할때는 type이 정해져있지않다면 중구난방 난리가 날것이기 때문...
자세한 상황은 아래 api 연결할때 설명하겠다
Map
리스트의 경우 map 을 이용하여 풀어낼 수 있다.
첫번째 인자로 객체가 들어가고, 두번째는 index가 오게되는데 map 안쪽에 첫번째 요소에 key 속성이 꼭 있어야한다
만약 아래와 같이 코드를 만들경우 에러가 날것이다
return(
<div> mypage </div>
<div>
{itemList.map((item, index) => (
<div>{item.title}</div>
))}
)
key를 꼭 붙여주도록 하자
install axios
프로젝트의 루트위치에서 터미널을 실행하고 아래와 같은 커맨드를 입력한다
$ npm install axios
pakage.json, package-lock.json 파일이 자동으로 수정될것이다
axios 설정
루트폴더에 api 폴더를 생성하고 client.tsx 파일을 생성하자
이곳에 axios 의 모든 설정을 세팅할것이다
get, post, multipartfile을 같이 보낼경우 3가지의 경우를 연결하겠다
▼client.tsx
import axios from 'axios';
class Client {
async get(url: string, params?: any) {
try {
const headers = {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
}
const response = await axios.get(url, {
params: params,
headers: headers,
});
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
async post(url: string, params?: any) {
try {
const headers = {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
}
const response = await axios.post(url, params, {
headers: headers,
});
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
async postMultipartFile(url: string, params: FormData) {
try {
const headers = {
'Content-Type': 'multipart/form-data',
'X-Requested-With': 'XMLHttpRequest',
}
const response = await axios.post(url, params, {
headers: headers,
});
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
}
export const client = new Client();
이렇게 소스를 따로 뗀 이유는 api 통신이 필요한 프로젝트 내 모든 페이지에서 별도로 연결을 해주어야하기 때문이다
가독성에 안좋고 스프링시큐리티 등의 이유로 인하여 header에 특정 텍스트/쿠키 등을 태워서 보내야 하는 경우 이곳에서 한번에 처리가 가능하다.
axios 적용 테스트
자 이제 실제 페이지에서 사용해봅시다
const MyPage: NextPageWithLayout = () => {
//기본적인 변수 선언법
const [nickname, setNickname] = useState<string>('')
const [age, setAge] = useState<number>(0)
const [isModalOpen, setIsModalOpen] = useState(false)
const [itemList, setItemList] = useState<itemListProps[]>([])
useEffect(() => {
client.get("/api/어쩌고저쩌고")
.then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
})
},[])
return(
<div> mypage </div>
)
}
mypage에 진입하자마자 useEffect 가 실행되고 만들어놓은 axios get 통신을 진행하게된다
그런데 보면... 코드상에서 직접 api path 를 입력하게되는데 딱봐도..너무불안하다
실수로 오타라도 나면 url 호출이 안되면서 에러가 빡빡 생길 조짐이 보인다...
그리고 path 가 일괄변경되면 이렇게 호출한 api 로직부분을 하나하나 찾아서 고쳐줘야한다..
그래서 api 통신부분을 따로 빼기로했다
axios 실제 적용
api 폴더 안에 패키지 하나 + tsx 파일 하나 선언해주자
보통 내가 쓰는 도메인 위주로 하면된다
user 관련 api 면 user.. main 페이지 관련 api 면 main.. menu.. category..등등
import {client} from "@/api/client";
class MyPageApi {
/**
* ㅇㅇㅇ페이지 :: ㅁㅁㅁ 조회
*/
test1 = async () => {
return await client.get('/api/어쩌고주소')
}
/**
* ㅇㅇㅇ페이지 :: ㅁㅁㅁ 조회
* @param title
*/
test2 = async (title:string) => {
return await client.get('/api/어쩌고주소',title)
}
/**
* ㅇㅇㅇ페이지 :: ㅁㅁㅁ 수정
*/
test3 = async () => {
return await client.post('/api/어쩌고주소')
}
/**
* ㅇㅇㅇ페이지 :: ㅁㅁㅁ 삭제
* @param title
*/
test4 = async (title:string) => {
return await client.post('/api/어쩌고주소', title)
}
}
export const myPageApi = new MyPageApi();
이렇게 모아두면 설령 api path가 변경되는 일이 있더라도, 한번에 처리하기 쉽다!
실제 페이지 코드에서는 높은 가독성까지!
이걸 실제 코드에 적용시키면
import {NextPageWithLayout} from "@/pages/_app";
import Layout from "@/components/layout/Layout";
import {useEffect, useState} from "react";
import {myPageApi} from "@/api/myPage/myPageApi";
interface itemListProps {
id: string
title: string
}
const MyPage: NextPageWithLayout = () => {
useEffect(() => {
myPageApi.test4('test')
.then((response:itemListProps) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})
},[])
return(
<div> mypage </div>
)
}
MyPage.getLayout = function getLayout(page) {
return <Layout>{page}</Layout>
}
export default MyPage
파라미터만 url 별도입력없이 파라미터만 던지는 가독성이 깔끔한 로직이 완성된다