[TIL-0517] Axios 메서드

jiny·2025년 6월 5일

캡스톤2

목록 보기
20/22

axios는 HTTP 메서드에 따라 데이터를 전달하는 방식이 조금씩 다르다.
앞으로 axios를 사용할 일이 많을 것 같아서, 메서드별 사용법을 완벽하게 정리해보기로 했다.

🌟 GET

get 메서드는 HTTP GET 요청을 보내기 위한 함수이며, 서버에서 데이터를 가져올 때 주로 사용된다.

  1. 기본 개념

    axios.get(url[, config])

    📥 url (필수 인자)

    • 요청할 서버 주소
    • 문자열로 된 주소 (REST API의 endpoint)
    • 예: "https://api.example.com/users"

    📥 config (선택 인자)

    • 헤더, 쿼리 파라미터, 응답 설정 등 세부 설정 객체
      {
        params?: object; // 쿼리 파라미터
        headers?: object; // 요청 헤더
        timeout?: number; // 요청 제한 시간(ms)
        withCredentials?: boolean; // 쿠키 포함 여부
        responseType?: string; // 응답 형식 (예: 'json', 'blob')
        signal?: AbortSignal; // 요청 취소용 AbortController
      }

    ⚠️ 주의사항

    • get 메서드는 두 번째 인자로 객체 이외의 값(예: 문자열, 숫자 등)을 받을 수 없다.
    • 비객체 타입을 전달하면 에러는 아니지만 무시되거나, 잘못 동작할 수 있다.
  2. 사용법

    axios.get("https://api.example.com/users", {
      params: { page: 2, limit: 10 },
      headers: { Authorization: "Bearer TOKEN" },
      timeout: 5000,
    });

    결과적으로 요청은 다음과 같이 전송된다.

    GET https://api.example.com/users?page=2&limit=10
  3. 반환값
    axios.get()Promise를 반환한다. (Promise<AxiosResponse> 타입)

    axios.get(...).then(response => {
      console.log(response.data); // 실제 데이터
      console.log(response.status); // HTTP 상태 코드 (200, 404 등)
      console.log(response.headers); // 응답 헤더
      console.log(response.config); // 요청에 사용된 config
      console.log(response.request); // 원본 요청 객체
    });

    💡 response.data에 들어 있는 데이터는 백엔드가 응답에 넣은 JSON, 객체, 문자열 등이다.

    • 예시
      • 백엔드 응답 JSON
        {
          "code": 200,
          "message": "성공",
          "data": {
            "userId": 1,
            "nickname": "Jiny"
          }
        }
      • 이걸 axios.get()으로 받으면
        axios.get("/api/user").then((res) => console.log(res.data))
      • console.log(res.data)의 결과
        {
          "code": 200,
          "message": "성공",
          "data": {
            "userId": 1,
            "nickname": "Jiny"
          }
        }
  4. 실제 예제

    • 장바구니 조회 (basket.api.ts)

      // basket.api.ts
      export const readBasket = async ({
        countryName,
        regionName,
      }: CountryAndRegion): Promise<InsertBasketDataType> => {
        const path = "/account/basket/read";
        
        try {
          const response = await api.get(path, {
            params: {
              countryName,
              regionName,
            },
          });
          const data = response.data;
          return data;
        } catch (error) {
          if (axios.isAxiosError(error)) {
            console.error("[readBasket] Axios 에러: ", error);
          } else {
            console.error("[readBasket] 일반 에러: ", error);
          }
          throw error;
        }
      };

      🧩 전체 동작 흐름

      1. 사용자가 특정 국가와 지역을 선택함
      2. readBasket({ countryName: "대한민국", regionName: "부산" })을 호출함
      3. Axios가 다음 주소로 GET 요청을 전송함:
        GET /account/basket/read?countryName=대한민국&regionName=부산
      4. 응답이 오면 .data를 추출하여 return함
      5. 에러 발생 시 콘솔에 로그 출력 후 에러를 전파함
    • 장소 세부정보 요청 (place.api.ts)

      // place.api.ts
      export const readPlaceDetail = async ({
        placeId,
      }: PlaceId): Promise<ReadPlaceDetailResponse> => {
        const path = `/discovery/details/${placeId}`;
        
        try {
          const response = await api.get(path);
          const data = response.data;
          return data;
        } catch (error) {
          if (axios.isAxiosError(error)) {
            console.error("[readPlaceDetail] Axios 에러: ", error);
          } else {
            console.error("[readPlaceDetail] 일반 에러: ", error);
          }
          throw error;
        }
      };

      🧩 전체 동작 흐름

      1. readPlaceDetail({ placeId: "abc123" })을 호출함
      2. Axios가 GET /discovery/details/abc123 요청을 보냄
      3. 서버에서 해당 장소의 상세 정보를 반환함
      4. response.data를 추출해 return함
      5. 에러 발생 시 콘솔에 로그 출력 후 에러를 전파함

🌟 POST

post 메서드는 HTTP POST 요청을 보내기 위한 함수이며, 서버에 데이터를 생성하거나 전달할 때 주로 사용된다.

  1. 기본 개념

    axios.post(url[, data[, config]])

    📥 url (필수 인자)

    • 요청할 서버 주소
    • 문자열로 된 주소 (REST API의 endpoint)
    • 예: "https://api.example.com/users"

    📥 data (선택 인자)

    • 서버에 전달할 본문 데이터
    • 일반적으로 JSON 형식을 사용함
    • 자동으로 JSON.stringify(data) 처리
    • Content-Type: application/json 헤더가 기본으로 설정됨

    📥 config (선택 인자)

    • 헤더, 쿼리 파라미터, 응답 설정 등 세부 설정 객체
      {
        params?: object; // 쿼리 파라미터
        headers?: object; // 요청 헤더
        timeout?: number; // 요청 제한 시간(ms)
        withCredentials?: boolean; // 쿠키 포함 여부
        responseType?: string; // 응답 형식 (예: 'json', 'blob')
        signal?: AbortSignal; // 요청 취소용 AbortController
      }

    🧐 JSON.stringify(data) 자동 처리란?

    🔍 Fetch를 사용하면

    fetch("/api/data", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ name: "Jiny" }),
    });
    • fetch()를 사용할 때는 본문 데이터를 직접 JSON.stringify()로 문자열로 바꿔줘야 함
    • 그렇지 않으면 서버는 정상적인 JSON이 아닌 "객체 그대로의 값"을 받아서 파싱 실패할 수 있음

    🔍 하지만, Axios를 사용하면

    axios.post("/api/data", { name: "Jiny" });

    위 코드만 작성해도 내부적으로 아래처럼 처리됨

    fetch("/api/data", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ name: "Jiny" }),
    });
    • 즉, data 객체를 자동으로 JSON 문자열로 변환해 주고,
    • "Content-Type": "application/json" 헤더도 자동으로 붙여줌
  2. 사용법

    axios.post(
      "/api/login",
      {
        email: "hyunjin@naver.com",
        password: "1234"
      },
      {
        headers: {
          Authorization: "Bearer ACCESS_TOKEN",
        },
        timeout: 5000,
      }
    );

    결과적으로 요청은 다음과 같이 전송된다. (요약 형태)

    POST /api/login HTTP/1.1
    Host: example.com
    Content-Type: application/json
    Authorization: Bearer ACCESS_TOKEN
    Content-Length: 52
    
    {
      "email": "hyunjin@naver.com",
      "password": "1234"
    }
  3. 반환값
    axios.post()Promise를 반환한다. (Promise<AxiosResponse> 타입)

    axios.post(...).then(response => {
      console.log(response.data); // 실제 데이터 (백엔드 응답 데이터)
      console.log(response.status); // HTTP 상태 코드 (200, 404 등)
      console.log(response.headers); // 응답 헤더
      console.log(response.config); // 요청에 사용된 config
      console.log(response.request); // 원본 요청 객체
    });
  4. POST와 GET의 차이 요약

    항목GETPOST
    목적데이터 조회데이터 생성/전송
    데이터 위치URL 쿼리 (params)요청 본문 (data)
    보안URL 노출 가능성 ↑상대적으로 안전 (본문에 포함됨)
    캐싱브라우저가 캐싱할 수 있음기본적으로 캐싱 안 됨

    GET 요청: 데이터는 URL에 붙음 (params)

    axios.get("/api/search", {
      params: { keyword: "제주도", sort: "popular" }
    });

    실제 전송되는 HTTP 요청은 다음과 같음 👇

    GET /api/search?keyword=%EC%A0%9C%EC%A3%BC%EB%8F%84&sort=popular HTTP/1.1
    • params 객체URL에 쿼리스트링으로 변환되어 붙음
    • axios가 자동으로 인코딩 처리를 해줌
    • 브라우저 주소창에도 그대로 노출됨 → 즐겨찾기나 공유에 좋음
    • 쿼리스트링이 주소창에 그대로 노출되므로 민감 정보 노출 위험에 주의해야 함

    POST 요청: 데이터는 요청 본문에 담김 (data)

    axios.post("/api/login", {
      username: "hyunjin",
      password: "test123"
    });

    실제 전송되는 HTTP 요청은 다음과 같음 👇

    POST /api/login HTTP/1.1
    Content-Type: application/json
    {
      "username": "hyunjin",
      "password": "test123"
    }
    • data 객체HTTP 본문(body)에 담김
    • 주소창에는 전혀 보이지 않음
    • 민감한 정보(비밀번호, 토큰 등)에 적합함
    • JSON 형식으로 자동 변환됨 (JSON.stringify())
    • 본문에 담기므로 상대적으로 안전하지만, HTTPS를 반드시 사용해야 암호화됨

    🤔 왜 GET은 캐싱이 되고, POST는 기본적으로 안 되는가?

    ➡️ HTTP 표준 때문

    • GET"읽기 전용"이므로, 동일한 요청은 항상 동일한 결과여야 함 → 캐시 가능
    • POST"서버 상태 변경"이 목적이라서, 같은 요청이라도 결과가 다를 수 있음 → 캐싱하면 데이터 일관성 문제가 생김

    🤔 캐싱을 의도적으로 조절하고 싶다면?

    🔍 GET 요청에서 캐싱 방지

    • HTTP 응답 헤더에 캐시 관련 지시를 내림
      Cache-Control: no-cache, no-store, must-revalidate
      지시어의미
      no-cache브라우저는 캐시된 응답을 사용하기 전에 항상 서버에 검증 요청해야 함 (즉, 무조건 fresh한지 확인해야 함)
      no-store아예 캐시에 저장하지 마라 (메모리, 디스크 모두 포함)
      must-revalidate캐시된 응답이 만료되면, 반드시 서버에 검증 요청을 보내야 함. 만료된 후 재사용하지 않음
    • 또는 요청 URL에 현재 시각(timestamp)을 붙여, URL을 매번 다르게 만들어 캐시를 우회
      axios.get(`/api/data?ts=${Date.now()}`);

    🔍 POST 요청에서도 강제로 캐싱할 수는 있지만, 거의 하지 않음

    • 브라우저는 캐싱하려 하지 않지만, 캐시 서버/프록시가 응답을 저장할 수는 있음
    • 다만 이건 위험하고, 특수한 경우(예: idempotent POST)에만 고려
  5. 실제 예제

    • 자체 로그인 (login.api.ts)

      // login.api.ts
      export const selfLogin = async ({ id, pw }: LoginType) => {
        const path = "/account/login";
        
        try {
          const response = await api.post(path, {
            memberId: id,
            password: pw,
          });
          return response;
        } catch (error) {
          if (axios.isAxiosError(error)) {
            if (error.response?.data.code === "CLT010") {
              console.error("[login] 회원정보 불일치");
              throw new Error("회원정보가 일치하지 않습니다.");
            } else {
              console.error("[login] Axios 에러: ", error);
            }
          } else {
            console.error("[login] 일반 에러: ", error);
          }
          throw error;
        }
      };

      🧩 전체 동작 흐름

      1. 사용자 입력 수집: id, pw를 사용자가 입력함
      2. 로그인 요청: Axios post()memberId, password를 서버에 보냄
      3. 성공 응답 처리
        • 응답 전체를 반환함 (response.data, response.status 등 포함)
        • 로그인 성공 시 토큰, 사용자 정보 등을 받아올 수 있음
      4. 에러 발생 시 분기 처리
        • 서버에서 응답한 code"CLT010"이면 → 회원정보 불일치
        • 사용자는 "회원정보가 일치하지 않습니다."라는 에러 메시지를 받게 됨
        • 기타 Axios 에러나 일반 에러도 콘솔에 출력하고 다시 throw
    • 이메일 인증코드 전송 (signup.api.ts)

      // signup.api.ts
      export const checkEmail = async ({ email }: CheckEmailType) => {
        const path = "/account/email/verification";
        
        try {
          const response = await api.post(path, {
            email,
          });
          return response;
        } catch (error) {
          if (axios.isAxiosError(error)) {
            if (error.response?.data.code === "CLT001") {
                console.error("[checkEmail] 이미 존재하는 이메일", error);
                throw new Error("이미 존재하는 이메일입니다.");
            } else if (error.response?.data.code === "SYS001") {
              console.error("[checkEmail] 이메일 전종 실패", error);
              throw new Error("이메일 전송에 실패했습니다.");
            } else {
              console.error("[checkEmail] Axios 에러: ", error);
            }
          } else {
            console.error("[checkEmail] 일반 에러: ", error);
          }
          throw error;
        }
      };

      🧩 전체 동작 흐름

      1. 사용자 입력 수집: email 값을 사용자가 입력함
      2. 이메일 인증 요청: Axios post()email을 서버에 전송함
      3. 성공 응답 처리
        • 인증코드 전송 성공 시 응답 전체를 반환함
        • 이후에 사용자에게 "인증코드 전송 완료" 안내 가능
      4. 에러 발생 시 분기 처리
        • 응답에 code가 포함된 경우 코드별로 처리
        • 그 외 Axios 에러는 콘솔 출력, 일반 에러도 throw 처리

🌟 PUT

put 메서드는 HTTP PUT 요청을 보내기 위한 함수이며, 서버에 있는 데이터를 완전히 수정(대체)할 때 주로 사용된다.

  1. 기본 개념

    axios.put(url[, data[, config]])

    📥 url (필수 인자)

    • 요청할 서버 주소
    • 문자열로 된 주소 (REST API의 endpoint)
    • 예: "https://api.example.com/users"

    📥 data (선택 인자)

    • 서버에 전달할 수정 대상 데이터
    • 일반적으로 JSON 형식을 사용함
    • 자동으로 JSON.stringify(data) 처리
    • Content-Type: application/json 헤더가 기본으로 설정됨

    📥 config (선택 인자)

    • 헤더, 쿼리 파라미터, 응답 설정 등 세부 설정 객체
      {
        params?: object; // 쿼리 파라미터
        headers?: object; // 요청 헤더
        timeout?: number; // 요청 제한 시간(ms)
        withCredentials?: boolean; // 쿠키 포함 여부
        responseType?: string; // 응답 형식 (예: 'json', 'blob')
        signal?: AbortSignal; // 요청 취소용 AbortController
      }
  2. 사용법

    axios.put("/api/user/1", {
      name: "hyunjin",
      email: "jiny@example.com"
    });

    결과적으로 요청은 다음과 같이 전송된다.

    PUT /api/user/1
    Content-Type: application/json
    
    {
      "name": "hyunjin",
      "email": "jiny@example.com"
    }
  3. 반환값
    axios.put()Promise를 반환한다. (Promise<AxiosResponse> 타입)

    axios.put(...).then(response => {
      console.log(response.data); // 실제 데이터 (백엔드 응답 데이터)
      console.log(response.status); // HTTP 상태 코드 (200, 404 등)
      console.log(response.headers); // 응답 헤더
      console.log(response.config); // 요청에 사용된 config
      console.log(response.request); // 원본 요청 객체
    });
  4. PUT 메서드의 특징

    항목내용
    목적기존 자원의 전체 수정/대체
    멱등성있음 (같은 요청 여러 번 보내도 결과 동일)
    데이터 위치요청 본문(body)
    사용 예회원 정보 수정, 게시글 수정, 설정 업데이트 등
  5. 예제: 회원정보 수정 API
    진행하는 프로젝트에 put() 예제가 없어서, 임의로 실무 예제를 만들어 보았다.

    export const updateProfile = async ({
      userId,
      name,
      email
    }: {
      userId: string;
      name: string;
      email: string;
    }) => {
      try {
        const res = await api.put(`/account/profile/${userId}`, {
          name,
          email,
        });
        return res.data;
      } catch (err: any) {
        if (axios.isAxiosError(err)) {
          console.error("[updateProfile] 에러: ", err.response?.data);
        }
        throw err;
      }
    };

    🧩 전체 동작 흐름

    1. 사용자로부터 수정할 정보 입력 받기
      • UI 폼 등에서 사용자로부터 입력을 수집함
      • 이 값이 updateProfile({ userId, name, email })의 인자로 전달됨
    2. PUT 요청 준비
      • 요청 경로를 userId로 동적으로 구성함
      • 서버에 전송할 데이터를 JSON 형태로 준비함
    3. 서버에 요청 전송: PUT /account/profile/1234 요청을 전송함
    4. 서버 응답 수신: 서버가 수정 결과를 응답으로 반환함
    5. 응답 데이터 반환
      • 호출한 쪽에서는 await updateProfile(...) 결과로 res.data를 받음
      • 이 데이터를 UI에 반영하거나 성공 메시지 표시 가능
    6. 에러 발생 시 처리 (실패 시)
      • 서버가 오류 코드(예: 400, 404, 500 등)를 보낼 경우, catch 블록으로 이동함
      • Axios 에러인지 확인 후 콘솔 출력
      • throw로 다시 던져서 상위에서 onError 등으로 처리

🌟 PATCH

patch 메서드는 HTTP PATCH 요청을 보내기 위한 함수이며, 서버에서 자원의 일부만 수정할 때 주로 사용된다.

  1. 기본 개념

    axios.patch(url[, data[, config]])

    📥 url (필수 인자)

    • 요청할 서버 주소
    • 문자열로 된 주소 (REST API의 endpoint)
    • 예: "https://api.example.com/users"

    📥 data (선택 인자)

    • 서버에 전달할 수정할 필드만 담긴 데이터 객체
    • 일반적으로 JSON 형식을 사용함
    • 자동으로 JSON.stringify(data) 처리
    • Content-Type: application/json 헤더가 기본으로 설정됨

    📥 config (선택 인자)

    • 헤더, 쿼리 파라미터, 응답 설정 등 세부 설정 객체
      {
        params?: object; // 쿼리 파라미터
        headers?: object; // 요청 헤더
        timeout?: number; // 요청 제한 시간(ms)
        withCredentials?: boolean; // 쿠키 포함 여부
        responseType?: string; // 응답 형식 (예: 'json', 'blob')
        signal?: AbortSignal; // 요청 취소용 AbortController
      }
  2. 사용법

    axios.patch("/api/user/1234", {
      nickname: "Jinny",
    });

    결과적으로 요청은 다음과 같이 전송된다.

    PATCH /api/user/1234 HTTP/1.1
    Content-Type: application/json
    
    {
      "nickname": "Jinny"
    }
  3. 반환값
    axios.patch()Promise를 반환한다. (Promise<AxiosResponse> 타입)

    axios.patch(...).then(response => {
      console.log(response.data); // 실제 데이터 (백엔드 응답 데이터)
      console.log(response.status); // HTTP 상태 코드 (200, 404 등)
      console.log(response.headers); // 응답 헤더
      console.log(response.config); // 요청에 사용된 config
      console.log(response.request); // 원본 요청 객체
    });
  4. PATCH 메서드의 특징

    항목내용
    목적자원의 일부만 수정
    멱등성보장되지 않음 (같은 요청 여러 번 보내면 서버 상태가 달라질 수 있음)
    데이터 위치요청 본문(body)
    사용 예닉네임만 변경, 비밀번호만 변경 등 필드 단위 업데이트
  5. PUT과 PATCH 차이 요약

    항목PUTPATCH
    목적리소스 전체를 완전히 교체리소스의 일부 필드만 수정
    사용 예사용자 정보 전체 변경닉네임만 변경, 비밀번호만 변경
    전송 데이터변경 대상의 모든 필드 포함 (전체 구조)변경할 필드만 포함
    요청 크기큼 (전체 리소스를 보내야 하므로)작음 (수정 필드만 보내므로)
    멱등성✅ 같은 요청을 반복해도 결과가 동일함❌ 같은 요청을 여러 번 보내면 결과가 다르게 나올 수 있음
    생략된 필드 처리생략된 필드는 삭제되거나 기본값으로 대체생략된 필드는 유지
    서버 구현 복잡도상대적으로 단순함 (전체 덮어쓰기)약간 높음 (부분 병합 구현 필요)
    의미상 구분대체(replace) → 전체 구조를 새로 보내서 덮어씀변경(change) → 수정할 부분만 보냄
    주로 사용하는 곳게시글 전체 수정, 리소스 상태 초기화 등 전체 갱신이 필요한 경우마이페이지 수정, 비밀번호 변경, 설정 토글 등
    실무에서의 빈도전체 상태를 명시적으로 덮어쓸 필요 있을 때 사용자주 사용됨 (성능 & UX 고려해 필드 단위 수정)
  • PATCH 예시: 일부 필드만 수정
    axios.patch("/api/user/1234", {
      nickname: "Jiny"
    });
    • 서버는 nickname만 바꾸고 나머지 필드는 그대로 유지함
  • PUT 예시: 전체 교체
    axios.put("/api/user/1234", {
      nickname: "Jiny",
      email: "jiny@naver.com"
    });
    • 서버는 기존 user 데이터를 전체 교체함 (nickname, email 둘 다 필요)
    • 예전 값이 누락되면 해당 필드는 사라질 수 있음
  1. 예제: 비밀번호 변경 API
    진행하는 프로젝트에 patch() 예제가 없어서, 임의로 실무 예제를 만들어 보았다.
    export const updatePassword = async ({
      userId,
      newPassword,
    }: {
      userId: string;
      newPassword: string;
    }) => {
      try {
        const res = await api.patch(`/account/password/${userId}`, {
          password: newPassword,
        });
        return res.data;
      } catch (err: any) {
        if (axios.isAxiosError(err)) {
          console.error("[updatePassword] 에러: ", err.response?.data);
        }
        throw err;
      }
    };

    🧩 전체 동작 흐름

    1. 사용자 입력
      • 사용자가 새 비밀번호를 입력함
      • userId는 로그인 중인 사용자의 ID 또는 관리자 수정 대상 ID임
    2. PATCH 요청 준비
      • userId를 경로에 포함하여 해당 사용자의 비밀번호만 변경하도록 함
      • 요청 body에는 변경할 비밀번호만 포함함
    3. 서버에 PATCH 요청 전송: PATCH /account/password/1234 요청을 전송함
    4. 서버 응답 수신: 비밀번호 변경에 성공하면 응답이 도착함
    5. 응답 데이터 반환: 호출한 쪽에서 await updatePassword(...)로 이 응답 데이터를 받아 사용 가능함
    6. 에러 발생 시 처리
      • 서버 응답 오류(예: 잘못된 형식, 인증 실패 등) 발생 시
      • Axios 전용 에러인지 판별 후 로그 출력
      • 에러는 다시 throw 되어 상위 onError, try...catch, catch()에서 처리 가능

🌟 DELETE

delete 메서드는 HTTP DELETE 요청을 보내기 위한 함수이며, 서버에 있는 데이터를 삭제할 때 주로 사용된다.

  1. 기본 개념

    axios.delete(url[, config])

    📥 url (필수 인자)

    • 삭제할 자원의 경로
    • 문자열로 된 주소 (REST API의 endpoint)
    • 예: "https://api.example.com/users"

    📥 config (선택 인자)

    • 헤더, 쿼리 파라미터, 응답 설정 등 세부 설정 객체
      {
        data?: {
          [key: string]: any; // ⭐ get 메서드와의 차이점!!
       };
        params?: object; // 쿼리 파라미터
        headers?: object; // 요청 헤더
        timeout?: number; // 요청 제한 시간(ms)
        withCredentials?: boolean; // 쿠키 포함 여부
        responseType?: string; // 응답 형식 (예: 'json', 'blob')
        signal?: AbortSignal; // 요청 취소용 AbortController
      }

    ⚠️ 주의사항

    • delete 메서드는 post, put, patch와 달리 기본적으로 data를 두 번째 인자로 받지 않는다.
    • 그러나 일부 서버에서는 data를 요청 본문에 필요로 하기도 하므로, 그럴 경우 config 안에 data를 넣어야 한다.
  2. 사용법

    axios.delete("/api/favorite", {
      data: {
        userId: "abc123",
        placeId: "p001"
      }
    });

    결과적으로 요청은 다음과 같이 전송된다.

    DELETE /api/favorite HTTP/1.1
    Host: example.com
    Content-Type: application/json
    Content-Length: 46
    
    {
      "userId": "abc123",
      "placeId": "p001"
    }
    • HTTP 표준상 DELETE 요청은 보통 body를 가지지 않지만, 일부 백엔드 API(예: NestJS, Express 등)는 본문 데이터를 허용하기도 한다.
    • 이럴 땐 dataconfig 객체 안에 포함시켜야 한다.
    • delete(url, data)는 잘못된 사용이다. 반드시 config.data로 감싸야 한다.
  3. 반환값
    axios.delete()Promise를 반환한다. (Promise<AxiosResponse> 타입)

    axios.delete(...).then(response => {
      console.log(response.data); // 실제 데이터 (백엔드 응답 데이터)
      console.log(response.status); // HTTP 상태 코드 (200, 404 등)
      console.log(response.headers); // 응답 헤더
      console.log(response.config); // 요청에 사용된 config
      console.log(response.request); // 원본 요청 객체
    });
  4. 실제 예제

    • 여행 계획 삭제 (travelPlan.api.ts)
      // travelPlan.api.ts
      export const deleteTravelPlan = async ({ id }: TravelPlanId) => {
        const path = "/account/plan/delete";
        
        try {
          const response = await api.delete(path, {
            data: { id },
          });
          return response;
        } catch (error) {
          if (axios.isAxiosError(error)) {
            console.error("[deleteTravelPlan] Axios 에러: ", error);
          } else {
            console.error("[deleteTravelPlan] 일반 에러: ", error);
          }
          throw error;
        }
      };

      🧩 전체 동작 흐름

      1. deleteTravelPlan 함수 호출: id는 삭제할 여행 계획의 고유 식별자
      2. path 정의: 삭제 요청을 보낼 API 경로
      3. axios.delete()로 DELETE 요청 실행
        • DELETE 요청이 path로 전송됨
        • 본문(body)에는 { id: "plan1234" }가 JSON 형태로 포함됨
        • 여기서 config 객체 안에 data를 넣는 건 DELETE 메서드의 특별한 사용법임
      4. 서버 응답 받기
        • 서버는 해당 id를 기준으로 여행 계획을 삭제함
        • 삭제 성공 시, 일반적으로 200 OK 또는 204 No Content 상태 코드를 반환함
        • 응답 본문에 삭제 결과 메시지나 상태 정보가 포함될 수 있음
      5. 응답 처리
        • 응답 전체(AxiosResponse 객체)를 반환함
        • 필요한 경우, 호출부에서 .data로 실제 데이터를 추출할 수 있음
      6. 예외 처리
        • 요청 실패 시 오류 로그를 출력함
        • axios.isAxiosError()로 Axios에서 발생한 오류인지 구분함
        • 오류를 다시 throw 하므로, 호출부에서도 .catch() 또는 try...catch로 처리해야 함

🌟 HTTP 표준에 따른 메서드별 요청 구조 차이

메서드데이터를 어디에 담아야 하는가?이유
GETconfig.params (URL 쿼리스트링)GET은 HTTP 표준상 본문(body)을 가질 수 없음
DELETEconfig.params 또는 config.data보통은 쿼리로 식별자를 전달하지만, 일부 API는 본문(body)도 허용함
POST, PUT, PATCHdata (body에 포함됨)본문(body) 전송이 표준 방식

🤔 GET은 절대 body(data)를 가질 수 없는가?

  • HTTP 명세(RFC 7231)에 따르면:
    • GET 요청은 리소스를 가져오는 목적이며,
    • 요청 본문(body)을 갖지 않아야 함
  • 대부분의 브라우저와 서버는 GET의 body를 무시하거나 거부
  • 그래서 GET 요청에서는 아래와 같이 params에 데이터를 담아 URL 쿼리로 전송
    axios.get("/api/items", {
      params: { category: "fruit", page: 2 }
    });
    // 전송 URL: /api/items?category=fruit&page=2

🤔 DELETE는 왜 data에 담을 수 있는가?

  • DELETE는 일부 서버에서 요청 본문(body)을 받아들이도록 허용
  • 하지만 HTTP 표준상 반드시 보장되는 건 아님
  • Axios는 이를 지원하기 위해 아래와 같이 config.data를 통해 본문 전송을 허용
    axios.delete("/api/favorite", {
      data: {
        userId: "abc",
        placeId: "p001"
      }
    });
  • 즉, DELETE는 config.params로도 가능하고, 서버가 지원한다면 config.data로도 가능

🤔 그럼 DELETE에서 params를 사용하면 안 되는가?

✅ 사용할 수 있음!

axios.delete("/api/favorite", {
  params: {
    userId: "abc",
    placeId: "p001"
  }
});

이때, 전송 URL은 다음과 같음

DELETE /api/favorite?userId=abc&placeId=p001
  • 이건 RESTful하게 자원 식별자로 삭제 요청을 보낼 때 많이 사용됨
  • 만약 데이터가 민감하거나, 길거나, 구조화된 형태라면 body(data)에 담는 것이 더 적절할 수 있음

REST(Representational State Transfer)란?

2000년에 로이 필딩(Roy Fielding)이 자신의 박사 논문에서 제안한 웹 아키텍처 스타일로, HTTP의 기본 원칙에 따라 클라이언트와 서버가 통신하는 방식을 정의한다.

RESTful이란?

REST의 원칙을 지키는 방식으로 API를 설계한 상태"RESTful하다"고 말한다.

🔍 RESTful한 DELETE 요청 예시

  • RESTful하지 않은 방식
    DELETE /deleteUser
    Body: { userId: "1234" }
    • URL만 봐서는 어떤 자원을 삭제하는지 알기 어려움
    • 삭제할 대상을 본문에 넣음 → REST 원칙 위반
  • RESTful한 방식
    DELETE /users/1234
    • /users/1234삭제 대상 자원(Resource)을 URL에서 명확하게 표현
    • 행위(DELETE)는 HTTP 메서드로 표현됨
    • 본문 없음 → REST 스타일에 맞음

🤔 GET 요청에 data를 넣으면 어떻게 되나?

axios.get("/api/test", {
  data: { foo: "bar" }
});
  • 이건 전혀 효과 없음 → Axios는 내부적으로 data를 무시
  • 브라우저도 GET 요청에 body가 있으면 무시하거나 경고를 발생시킴
  • 따라서 GET에서는 params만 사용해야 함

0개의 댓글