2025 . 오은

repo

메서드를 queryFn으로 사용시 주의점

2025.11.01

React Query에서 클래스 메서드를 queryFn으로 사용할 때 주의사항

문제 상황

React Query를 사용하다가 다음과 같은 에러를 만났습니다:

Cannot read properties of undefined (reading 'get')

코드는 다음과 같았습니다:

// queries.ts
export const useUserQuery = () => {
  return useQuery({
    queryKey: ['user'],
    queryFn: api.getUser, // 이 부분이 문제!
  });
};

// apis.ts
class ApiClient extends BaseApiClient {
  public getUser() {
    return this.get<User>("/api/auth/user");
  }
}

기본적인 문제죠..? 바로 this, 화살표함수 문제가 딱 떠올라야 하겠죠..? 하지만 저는 오늘도 바로 생각해내지 못했답니다. 헛공부ㅜㅜ

원인: JavaScript의 this 바인딩 손실

JavaScript에서 메서드를 다른 곳에 전달할 때, this 컨텍스트가 손실됩니다.

const api = new ApiClient();

// 직접 호출: this가 api 인스턴스를 가리킴
api.getUser(); // ✅ 정상 작동

// 메서드를 변수에 할당: this 컨텍스트 손실
const getUserFn = api.getUser;
getUserFn(); // ❌ this는 undefined

React Query의 queryFn에 메서드를 전달하면, React Query가 나중에 그 함수를 호출할 때 원래의 인스턴스 컨텍스트 없이 호출하게 됩니다. 따라서 this.get을 찾을 수 없게 되는 것입니다.

해결 방법 1: 화살표 함수로 변경(그냥 이렇게 하면 됨)

화살표 함수는 렉시컬 스코프를 사용하여 정의될 당시의 this를 영구적으로 바인딩합니다.

// apis.ts
class ApiClient extends BaseApiClient {
  // 일반 메서드 대신 화살표 함수로 정의
  public getUser = () => {
    return this.get<User>("/api/auth/user");
  };
  
  public logOut = () => {
    return this.get("/api/auth/logout");
  };
}

const api = new ApiClient();
export default api;
// queries.ts
export const useUserQuery = () => {
  return useQuery({
    queryKey: ['user'],
    queryFn: api.getUser, // ✅ 이제 안전하게 사용 가능!
  });
};

해결 방법 2: 래퍼 함수 사용

화살표 함수로 감싸서 명시적으로 컨텍스트를 유지할 수도 있습니다:

export const useUserQuery = () => {
  return useQuery({
    queryKey: ['user'],
    queryFn: () => api.getUser(), // 화살표 함수로 감싸기
  });
};

하지만 이 방법은 모든 사용처에서 매번 래핑해야 하므로 번거롭습니다. 그리구.. tanstack 의 client 측 공식 가이드와도 다름

해결 방법 3: bind 사용

생성자에서 메서드를 바인딩할 수도 있습니다:

class ApiClient extends BaseApiClient {
  constructor() {
    super(config);
    this.getUser = this.getUser.bind(this);
    this.logOut = this.logOut.bind(this);
  }
  
  public getUser() {
    return this.get<User>("/api/auth/user");
  }
}

하지만 메서드가 많아질수록 관리가 어려워집니다.

결론

React Query의 queryFn이나 콜백으로 클래스 메서드를 전달할 때는 화살표 함수로 정의하는 것이 가장 안전하고 깔끔한 방법이었습니다... 화살표 함수는 정의 시점의 this를 영구적으로 캡처하므로, 어디서 호출되든 항상 올바른 컨텍스트를 유지합니다.

일반 메서드 vs 화살표 함수

class Example {
  // ❌ 일반 메서드: this 컨텍스트가 호출 시점에 결정
  public method() {
    return this.something;
  }
  
  // ✅ 화살표 함수: this 컨텍스트가 정의 시점에 고정
  public arrowMethod = () => {
    return this.something;
  }
}