프로젝트/커넥팅칩스

[커넥팅칩스] 프로젝트 3주차(09.18 ~ 09.24)

pizzaYami 2023. 10. 6.

서버가 완성되고 api명세서를 기준으로 코드를 작성하기 시작하였다.

더미데이터로 코딩을 하다가 실제로 데이터를 받아서 코드를 작성하니깐. 너무 구조가 달라져서 시간이 오래 걸리고 버그도 많았다.

그리고 처음으로 typescript를 적용하였는데 원시타입만 하는줄 알았는데 useState나 event마다 다른 type을 지정해주어야 해서 너무 짜증 나고 스트레스받았다. 에러코드를 읽어도 이게 뭔 소리지?라는 게 대부분이라 더욱더 어려웠다.

 

1. axios로 데이터 받아오기

axios를 오랜만에 사용해서 다 까먹고 효율적으로 사용하는 방법이 있다고해서 정리를 해보았다.

 

axiosConfig (GET, POST, PUT, DELETE)

서버에 요청을 보낼 때 GET, POST, PUT, DELETE를 사용하게 되는데 이 4가지를 미리 만들어두어서 편의성을 높였다.

 

전체코드

더보기

 

import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios';

axios.defaults.baseURL = '기본URL';

const client: AxiosInstance = axios.create();

// 인스턴스를 만든 후 기본값 변경하기
client.defaults.headers.common['withCredentials'] = true;

/** Axios Response 데이터 형식
 *  config : 요청에 대한 axios 구성 설정
 *  data 서버가 제공한 응답 데이터
 *  headers : 헤더 정보
 *  request : 요청
 *  status : 응답 HTTP 상태 코드
 *  statusText : 응답 HTTP 상태 메시지
 */

// 본인 서버에서 내려주는 응답 구조
interface APIResponse<T> {
  statusCode: number; // 상태코드 (보인 서버상태코드)
  errorCode: number; // 에러코드 (본인 서버에러코드)
  message: string; // 메시지
  data: T; // 데이터 내용
  timestamp: Date; // 시간
}

//TODO: GET 메서드
export const getData = async <T>(
  url: string,
  config?: AxiosRequestConfig,
): Promise<APIResponse<T>> => {
  try {
    const response = await client.get<APIResponse<T>>(url, config);
    return response.data;
  } catch (error: any) {
    return Promise.reject(error);
  }
};

//TODO: POST 메서드
export const postData = async <T>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig,
): Promise<APIResponse<T>> => {
  try {
    const response = await client.post<APIResponse<T>>(url, data, config);
    return response.data;
  } catch (error: any) {
    return Promise.reject(error);
  }
};

//TODO: PUT 메서드
export const putData = async <T>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig,
): Promise<APIResponse<T>> => {
  try {
    const response = await client.put<APIResponse<T>>(url, data, config);
    return response.data;
  } catch (error: any) {
    throw new Error(error.message);
  }
};

//TODO: Delete 메서드
export const deleteData = async <T>(
  url: string,
  config?: AxiosRequestConfig,
): Promise<APIResponse<T>> => {
  try {
    const response = await client.delete<APIResponse<T>>(url, config);
    return response.data;
  } catch (error: any) {
    throw new Error(error.message);
  }
};

 

전체코드에서 일부분을 분석을 해보자.

 

import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';

axios.defaults.baseURL = '기본 URL';

const client: AxiosInstance = axios.create();

// 인스턴스를 만든 후 기본값 변경하기
client.defaults.headers.common['withCredentials'] = true;

/** Axios Response 데이터 형식
 *  config : 요청에 대한 axios 구성 설정
 *  data 서버가 제공한 응답 데이터
 *  headers : 헤더 정보
 *  request : 요청
 *  status : 응답 HTTP 상태 코드
 *  statusText : 응답 HTTP 상태 메시지
 */
 
 // 본인 서버에서 내려주는 응답 구조
interface APIResponse<T> {
  statusCode: number; // 상태코드 (보인 서버상태코드)
  errorCode: number; // 에러코드 (본인 서버에러코드)
  message: string; // 메시지
  data: T; // 데이터 내용
  timestamp: Date; // 시간
}

 

1. axios.defaults.baseURL = '기본 URL'

이부분이 없다면 url을 요청 보낼 때 모든 url를 다 작성해야 한다.

예를 들어 https://www.naver.com/mail로 요청을 보내야 한다면 axios.defaults.baseURL = 'https://www.naver.com'로 설정하면 url에 "/mail"만 적으면 제대로 된 요청이 보내진다.

 

2. client.defaults.headers.common ['withCredentials'] = true;

withCredentials는 서로 다른 도메인(크로스 도메인)에 요청을 보낼 때 요청에 credential 정보 정보를 담아서 보낼지를 결정하는 항목이다. 

여기서, credential 정보가 포함되어 있는 요청은 아래 두 가지 경우를 의미합니다.

  1) 쿠키를 첨부해서 보내는 요청 헤더에 Authorization 항목이 있는 요청

  2) 헤더에 Authorization 항목이 있는 요청

나는 헤더에 Authorizaion 항목이 있는 요청이 생겨서 이 옵션을 넣었다.

 

3. interface APIResponse <T>

이거는 응답을 받을 때 데이터들의 타입들인데 여기서 T(제네릭 타입)이 뭔지 몰라서 엄청 헤맸었다.

https://cho9407.tistory.com/65

 

그다음으로 여러 가지 Method가 있는데 그중 put에 대해서 분석해 보자.

 

//TODO: PUT 메서드
export const putData = async <T>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig,
): Promise<APIResponse<T>> => {
  try {
    const response = await client.put<APIResponse<T>>(url, data, config);
    return response.data;
  } catch (error: any) {
    throw new Error(error.message);
  }
};

 

1. data?: any ? 는 무엇인가

?는 데이터가 들어올 수도 안 들어올 수도 있다는 걸 의미한다.

실제로 put을 사용하다 보면 url만 보내는 경우가 있고 data와 config를 함께 보내야 하는 경우도 있다.

이럴 경우 타입에서 에러는 발생시키는 것을 방지하기 위해서?를 사용한다.

 

2. Promise <APIResponse <T>>

이거는 응답으로 받아오는 데이터의 타입을 말한다. 내가 아까 지정해 놓은 interface APIResponse <T> 가져와 사용한 것이다.

 

3. async await

요거는 비동기와 관련되어 있는데 간단히 말하면 await부분을 완전히 끝내고 나서 다음코드를 실행하라는 뜻이다.

 

4. <T>에 타입지정해서 넣어야 되는 거 아닌가?

이건 나중에 put을 편하게 사용하기 위해 함수를 만든 것이기 때문에 putData함수를 사용할 때 넣으면 된다.

ex) putData <string {}>("url", {date : "20.12.12"})

 

실제로 사용할 때 

게시글을 수정할 때 putData함수를 이용해서 요청, 응답을 하는 함수를 만들었다.

이걸 분석해 보면서 어떻게 사용했는지 알아보자.

export interface RsEditBoard {
  // boardId: number;
  content: string;
}

//게시글 수정 -> put요청
export const putEditBoard = async (boardId: number, content: RsEditBoard): Promise<RsEditBoard> => {
  try {
    const { tockenHeader } = getToken();
    const response = await putData<RsEditBoard>(`/boards/${boardId}`, content, tockenHeader);
    return response.data;
  } catch (error) {
    console.error(error);
    throw new Error('게시글 수정 에러');
  }
};

 

2. Public, src 중 어디에서 이미지를 저장해서 가져와야 할지

 

이미지를 가져오는 여러가지 방법

프로젝트를 진행하면서 이미지를 어디에 보관하고 어떻게 가져오는게 좋은지에 대한 궁금증으로 인해서 블로그를 작성하게 되었다. 1. 어느 폴더에서 관리하는게 좋지? 📂 public webpack에 의해

cho9407.tistory.com

이미지 파일을 어디에 저장해서 가져와야 할지 고민이 되어서 따로 블로깅을 하였다.

근데 결론은 서버에서 이미지 응답 보내는 걸로 됐다. ㅋㅋㅋ

 

3. 개발자도구에서 키보드 뜨게 하기 

나는 웹에서만 개발을 하여서 실제로 모바일에서 input을 클릭하면 키보드가 뜬다던가 dvw, dvh가 제대로 적용이 되는지 확인이 불가능하였다. 

하지만 개발자도구에서도 확인이 가능한 방법이 있다고 하여서 적용해 보았다.

개발자도구에서 크기 - 수정 -Nexus 5, Nexus5 X 체크 - 핸드폰 돌아가는 아이콘 클릭 - keyboard

 

 

이렇게 세팅을 하면 키보드가 나와서 확인가능하다.

 

4. 이번주를 마무리하며

이번주는 너무 바쁜 주였다. 이것 말고도 많은 것들을 했지만 아쉽게도 양이 너무 많아져서 생략을 했다.

특히 QA를 진행하면서 많은 버그를 발견하여서 실시간으로 바로바로 고치느냐 필기를 못 한 게 너무 아쉽다.

 

 

댓글