FrontEnd Develop/Project : Wallet Guardians

본격 연동 #7. API 함수에서의 능동적인 에러 처리 (409, 404)

Frisbeen 2025. 2. 11. 22:28

제목을 아래 처럼 지을까 고민도 했었습니다만..

 

API 에러 처리를 통해 Context와 연결하여 해결하는 과정

 

각설하고,

 

1. 문제 상황

처음 회원가입한 사용자가 getBudget() API를 호출했을 때, 서버에서 409 Conflict 오류가 발생하여 예산 데이터가 없을 경우 앱이 정상적으로 작동하지 않는 문제가 발생했습니다.

이 문제를 해결하기 위해:

이때 API 함수 내부에서 에러를 처리해야하는지, 아니면 컴포넌트 핸들러에서 처리해야하는지 고민하다 글을 씁니다.

 

제가 생각한 아이디어는

  1. API 함수 내부에서 409 에러를 처리하여 null을 반환하도록 수정하고,
  2. Context에서 API 데이터를 불러올 때 null을 안전하게 처리하여 UI가 깨지지 않도록 개선했습니다.
  3. 사실 2번에 방식에서 null을 안전하게 처리할 껀덕지도 주지 않게 null이 아닌 0을 처리하는 방식이 좀 더 좋았을 것 같긴합니다만, null이 확실히 좀 더 흐름상 좋을 것 같았습니다.

2. 문제 발생 코드 분석 -> it was getBudget() !

기존 코드에서는 getBudget()을 호출했을 때, 서버가 예산 데이터를 반환하지 않으면 null이 아닌 409 에러가 발생했습니다.

 

 

첫번째 원인

아마 404가 아닌 409가 뜬 이유는 백엔드 측에서 예산 설정을 한 후 메인에 진입하게끔 강제한 흐름이 존재했었습니다.

따라서, getBudget이라는 api 함수가 실행되는 시점에는 무조건 사용자가 예산을 설정했다고 서버는 인식하지만

회원가입을 처음 하는 사람입장에서는 예산 설정이 없었던게 첫번째 원인입니다.

 

 

두번째 원인

첫번째 원인에 맞물려, 전 사용자가 로그인을 하면 (첫 회원이든 기존 회원이든) getBudget을 함수를 활용하여 

기존 사용자인지 첫 사용자인지를 판단했습니다.

 

기존 사용자는 당연히 자연스럽게 서버의 흐름을 통과하겠습니다 (getBudget)을 통과합니다.

그러나 처음 회원가입후 바로 로그인을 한 사람은 이제야 예산을 설정해야했기에 (getBudget)을 통과 못하고 409가 발생했던겁니다

 

그럼 로그인에서 그 로직을 빼면 되지않나요

안됩니다. 로그인에서 예산 검증하는 로직은 필수적입니다. (리다이렉션) 예산 설정 or 메인

 

따라서, 방법은 getBudget 함수 내부에서 적극적으로 에러를 처리했어야했습니다.

 

기존 코드

export const getBudget = async () => {
  try {
    const response = await apiClient.get('/budget');
    return response.data.data; // 예산 데이터 반환
  } catch (error) {
    console.error('🚨 예산 조회 실패:', error);
    throw error; // 여기서 409 에러가 발생하면 예외가 던져짐
  }
};

 

이렇게 되면 fetchBudget()에서 getBudget()을 호출할 때, catch 문에서 오류를 잡지 않으면 애플리케이션이 정상적으로 실행되지 않았고...

 

const fetchBudget = async () => {
  try {
    const data = await getBudget(); // 409 에러 발생 가능
    console.log('✅ 유저 예산 정보:', data.amount);
    setGoalAmount(data.amount);
  } catch (error) {
    console.error('🚨 예산 조회 실패:', error);
    setError(error);
  }
};

 

여기서 문제는 getBudget()이 409 에러를 그대로 던지면 fetchBudget()에서도 예외가 발생하여 data.amount를 읽을 수 없게 됨.


3. 해결 방법

✅ Step 1: API 내부에서 409를 null로 변환하여 처리

409 에러가 발생하면 예외를 던지지 않고 null을 반환하도록 getBudget()을 수정합니다.

export const getBudget = async () => {
  try {
    const response = await apiClient.get('/budget');
    return response.data.data;
  } catch (error) {
    if (error.response?.status === 404 || error.response?.status === 409) {
      console.warn(`⚠️ 예산 데이터가 없음 (${error.response?.status}), 기본값 반환.`);
      return null; // 예산이 없을 경우 null 반환
    } else {
      console.error('🚨 예산 조회 중 오류:', error);
      throw error;
    }
  }
};

 이제 getBudget()이 409 에러를 발생시키지 않고 null을 반환하므로 이후 코드에서 안전하게 처리 가능.


✅ Step 2: Context에서 getBudget을 하여 가져올때 API에서  return된  null을 안전하게 처리

API가 null을 반환하는 경우 goalAmount 0으로 설정하여 UI가 깨지지 않도록 수정합니다.

const fetchBudget = async () => {
  try {
    const data = await getBudget();
    
    if (!data) { // 데이터가 null이면 0으로 초기화
      console.log('예산 데이터가 없으므로 목표금액을 0으로 설정한다.');
      setGoalAmount(0);
      return 0;
    }
    
    console.log('✅ 유저 예산 정보:', data.amount);
    setGoalAmount(data.amount);
    return data.amount;
  } catch (error) {
    console.error('🚨 예산 조회 실패:', error);
    setError(error);
  }
};

 이제 data.amount를 읽을 때 null이 아님이 보장됨 → UI에서 에러 없이 작동!

 

사실 애초에 Null을 주는것 보다 0을 줬어도 코드엔 작동 없습니다만,

Null을 주는게 좀 더 말이 자연스러울 것 같다고 판단했습니다.


4. 최종 결과 및 참고사항 (409 vs 404)

 409 에러가 발생해도 UI가 깨지지 않고 정상적으로 실행됨 

 API 내부에서 409를 null로 변환하여 불필요한 예외 발생 방지

  Context에서 안전하게 null을 처리하여 UI가 일관되게 동작

 

✅ 404 Not Found (리소스 없음)

요청한 리소스(데이터, 페이지, API 엔드포인트 등)가 존재하지 않을 때 발생하는 HTTP 상태 코드.

보통 서버에서 해당 리소스를 찾을 수 없을 때 반환함.

예시:

/budget/123을 요청했지만, ID가 123인 예산 데이터가 없을 때 404 발생.

/user/999을 조회했지만, ID가 999인 사용자가 존재하지 않을 때 404 발생.

 

✅ 409 Conflict (리소스 충돌)

클라이언트의 요청이 서버의 현재 상태와 충돌할 때 발생하는 HTTP 상태 코드.

데이터의 무결성을 유지하려는 특정 비즈니스 로직이 있는 경우 발생할 가능성이 큼.

예시:

같은 사용자가 동시에 같은 예산 데이터를 수정하려 할 때 409 발생.

이미 예산 데이터가 있는데 새로운 예산을 생성하려 할 때 409 발생 (예산이 하나만 존재해야 한다는 규칙이 있는 경우).


 요약

  • API 내부에서 409를 null로 변환하여 예외를 던지지 않도록 처리
  • Context에서 null을 감지하여 기본값(0)으로 설정
  • UI가 안전하게 동작하도록 개선하여 초기 회원가입 사용자도 문제 없이 예산을 확인 가능

프론트엔드에서 API 호출 시 409 에러로 인해 앱이 깨지는 문제는 해결되었습니다. 굿굿