환경 초기화 및 벤더 리포지토리 스켈레톤 도입

This commit is contained in:
JiWoong Sul
2025-09-22 17:38:51 +09:00
commit 5c9de2594a
171 changed files with 13304 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
// ignore_for_file: public_member_api_docs
import 'package:dio/dio.dart';
/// 공통 API 클라이언트 (Dio 래퍼)
/// - 모든 HTTP 호출은 이 클래스를 통해 이루어진다.
/// - BaseURL/타임아웃/인증/로깅/에러 처리 등을 중앙집중화한다.
class ApiClient {
final Dio _dio;
/// 내부에서 사용하는 Dio 인스턴스
/// 외부에서 Dio 직접 사용을 최소화하고, 가능하면 아래 헬퍼 메서드를 사용한다.
Dio get dio => _dio;
ApiClient({required Dio dio}) : _dio = dio;
/// GET 요청 헬퍼
Future<Response<T>> get<T>(
String path, {
Map<String, dynamic>? query,
Options? options,
CancelToken? cancelToken,
}) {
return _dio.get<T>(path, queryParameters: query, options: options, cancelToken: cancelToken);
}
/// POST 요청 헬퍼
Future<Response<T>> post<T>(
String path, {
dynamic data,
Map<String, dynamic>? query,
Options? options,
CancelToken? cancelToken,
}) {
return _dio.post<T>(path, data: data, queryParameters: query, options: options, cancelToken: cancelToken);
}
/// PATCH 요청 헬퍼
Future<Response<T>> patch<T>(
String path, {
dynamic data,
Map<String, dynamic>? query,
Options? options,
CancelToken? cancelToken,
}) {
return _dio.patch<T>(path, data: data, queryParameters: query, options: options, cancelToken: cancelToken);
}
/// DELETE 요청 헬퍼
Future<Response<T>> delete<T>(
String path, {
dynamic data,
Map<String, dynamic>? query,
Options? options,
CancelToken? cancelToken,
}) {
return _dio.delete<T>(path, data: data, queryParameters: query, options: options, cancelToken: cancelToken);
}
}

View File

@@ -0,0 +1,29 @@
// ignore_for_file: public_member_api_docs
import 'package:dio/dio.dart';
/// 인증 인터셉터(스켈레톤)
/// - 요청 전에 Authorization 헤더 주입
/// - 401 수신 시 토큰 갱신 및 원요청 1회 재시도 (구현 예정)
class AuthInterceptor extends Interceptor {
/// TODO: 토큰 저장/조회 서비스 주입 (예: AuthRepository)
AuthInterceptor();
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
// TODO: 저장된 토큰을 읽어 Authorization 헤더에 주입한다.
// final token = await _authRepository.getToken();
// if (token != null && token.isNotEmpty) {
// options.headers['Authorization'] = 'Bearer $token';
// }
handler.next(options);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
// TODO: 401 처리 로직(토큰 갱신 → 원요청 재시도) 구현
// if (err.response?.statusCode == 401) { ... }
handler.next(err);
}
}