프론트엔드와 백엔드를 연동하다 보면 API 응답(Response) 객체의 구조가 혼동될 때가 있다.

response.data.items를 써야 할 때가 있고, response.data.data를 써야 할 때가 있다.

또한 Axios를 쓸 때와 fetch를 쓸 때 데이터를 꺼내는 방식이 근본적으로 다르다.

이번 프론트 작업을 진행하면서 코드를 분석하며 정리한 API Response 처리 방식과 그 원리를 기록해 둔다.

 

1. response.data와 item의 정의

콘솔에 찍힌 객체(Object) 구조를 기준으로 명확한 정의는 다음과 같다.

  • response.data: 서버가 응답한 본문(Body) 전체를 의미한다. Axios 라이브러리는 서버 응답을 data라는 프로퍼티에 담아서 반환하기 때문이다.
  • items (혹은 data, list 등): response.data 내부에 있는 키값이다. 이는 백엔드 개발자가 정한 변수명이다.
  • item: 배열(Array) 형태의 데이터를 반복문(map, forEach)으로 처리할 때, 개별 요소를 지칭하기 위해 임의로 붙이는 변수명이다.

구조 예시

// Axios 응답 객체 구조
{
  status: 200,
  data: {               // [1] response.data (Axios가 만든 껍데기)
    total: 2,
    items: [            // [2] 실제 데이터 목록 (백엔드가 정한 이름)
      { id: 1, name: 'A' },
      { id: 2, name: 'B' }
    ]
  }
}

 

위 구조에서 데이터를 꺼내려면 response.data.items로 접근해야 하며, 이를 반복문으로 돌릴 때 각 객체({id:1...})가 item이 된다.

 

 

2. 왜 이름이 제각각인가? (Naming Convention)

response.data 뒤에 붙는 이름이 프로젝트마다 다른 이유는 **백엔드(Java Controller)**의 리턴 타입이 다르기 때문이다. Java 웹 개발자 관점에서 보면 이해가 쉽다.

Case A: response.data.items인 경우

백엔드에서 Map이나 DTO를 구성할 때 키 이름을 items로 지정한 경우다.

// Java Controller
Map<String, Object> result = new HashMap<>();
result.put("items", memberList); // 여기서 정한 키 값이 프론트엔드의 속성명이 됨
result.put("total", count);
return result;

 

 

Case B: response.data.data인 경우

공통 응답 객체(Wrapper Class)를 사용하며 필드명을 data로 쓴 경우다.

// Java Common Response Class
public class ApiResponse<T> {
    private String message;
    private T data; // 필드명을 data로 지정함
}

결국 첫 번째 data는 Axios의 규칙이고, 두 번째 이름(items, data)은 백엔드 로직에 따라 결정된다. 따라서 콘솔 로그를 확인하여 백엔드가 넘겨준 키 값을 확인하는 과정이 필수적이다.

 

 

3. Axios와 Fetch의 결정적 차이

Axios를 사용하지 않고 브라우저 표준 API인 fetch를 사용할 경우, response 객체의 성격이 완전히 달라진다.

 

Axios의 동작 방식

Axios는 응답이 오면 자동으로 JSON 파싱을 수행하여 data 프로퍼티에 결과물을 넣어준다. 즉, '택배 상자를 뜯어서 내용물을 정리해 둔 상태'로 전달한다.

const response = await axios.get('/api/url');
console.log(response.data); // JSON 데이터가 바로 보임

 

 

Fetch의 동작 방식

fetch는 HTTP 응답 스트림(ReadableStream)을 그대로 반환한다. 즉, '택배 상자만 건네준 상태'다. 상자를 뜯는 과정(JSON 파싱)을 수동으로 수행해야 한다. fetch의 response 객체에는 .data라는 프로퍼티가 존재하지 않는다.

const response = await fetch('/api/url');
// console.log(response.data); -> undefined 발생

// 수동 파싱 필요 (비동기 작업)
const jsonData = await response.json(); 
console.log(jsonData); // 파싱이 완료되어야 데이터 확인 가능

 

 

4. 결론 및 요약

  1. Axios 사용 시: response.data까지는 고정값이다. 그 뒤의 속성명은 백엔드에서 보낸 JSON의 키 값을 따라간다. (response.data.items 등)
  2. Fetch 사용 시: response 객체에 데이터가 바로 들어있지 않다. await response.json()을 통해 파싱 과정을 반드시 거쳐야 한다.
  3. 데이터 접근 순서:
    • API 호출 -> 콘솔 로그로 구조 확인 -> response.data (Axios) 또는 .json() (Fetch) -> 백엔드 키 값(items) 확인 -> 배열 반복 시 item으로 명명.

LMS 구축이나 레거시 시스템 연동 시 백엔드 응답 규격이 통일되어 있지 않은 경우가 많으므로, 무조건적으로 코드를 복사하기보다 콘솔에서 실제 데이터 구조를 확인하고 접근 경로를 작성해야 한다.

 

+ Recent posts