Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions src/api/books/getSavedBooksInMy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { apiClient } from '../index';

// 개인적으로 저장한 책 정보 타입
// 저장한 책 정보 타입
export interface SavedBookInMy {
bookId: number;
bookTitle: string;
Expand All @@ -11,22 +11,19 @@ export interface SavedBookInMy {
isSaved: boolean;
}

// API 응답 데이터 타입
export interface SavedBooksInMyData {
bookList: SavedBookInMy[];
nextCursor: string;
isLast: boolean;
}

// API 응답 타입
export interface SavedBooksInMyResponse {
isSuccess: boolean;
code: number;
message: string;
data: SavedBooksInMyData;
}

// 개인적으로 저장한 책 목록 조회 API 함수 (무한스크롤)
export const getSavedBooksInMy = async (cursor: string | null = null) => {
try {
const params: { cursor?: string | null } = {};
Expand All @@ -43,10 +40,3 @@ export const getSavedBooksInMy = async (cursor: string | null = null) => {
throw error;
}
};

/*
// 사용 예시
const savedBooksInMy = await getSavedBooksInMy();
console.log(savedBooksInMy.data.bookList); // 개인 저장 책 목록
console.log(savedBooksInMy.data.bookList[0].bookTitle); // 첫 번째 책 제목
*/
11 changes: 0 additions & 11 deletions src/api/feeds/getFeedDetail.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { apiClient } from '../index';

// 피드 상세 정보 타입 (PostData + 추가 필드들)
export interface FeedDetailData {
feedId: number;
creatorId: number;
Expand All @@ -24,24 +23,14 @@ export interface FeedDetailData {
isWriter: boolean;
}

// API 응답 타입
export interface FeedDetailResponse {
isSuccess: boolean;
code: number;
message: string;
data: FeedDetailData;
}

// 피드 상세 조회 API 함수
export const getFeedDetail = async (feedId: number) => {
const response = await apiClient.get<FeedDetailResponse>(`/feeds/${feedId}`);
return response.data;
};

/*
// 피드 상세 정보 조회
const feedDetail = await getFeedDetail(123);
console.log(feedDetail.data.feedId); // 123
console.log(feedDetail.data.tagList); // ["태그1", "태그2"]
console.log(feedDetail.data.isPublic); // true or false
*/
22 changes: 1 addition & 21 deletions src/api/feeds/getMyFeed.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import { apiClient } from '../index';
import type { PostData } from '@/types/post';

// API 응답 데이터 타입
export interface MyFeedData {
feedList: PostData[];
nextCursor: string;
isLast: boolean;
}

// API 응답 타입
export interface MyFeedResponse {
isSuccess: boolean;
code: number;
message: string;
data: MyFeedData;
}

// 요청 파라미터 타입
export interface GetMyFeedParams {
cursor?: string; // 첫 페이지는 null 또는 없음, 다음 페이지부터는 nextCursor 값 사용
cursor?: string;
}

// 내 피드 조회 API 함수
export const getMyFeeds = async (params?: GetMyFeedParams) => {
const queryParams = new URLSearchParams();

// cursor가 있을 때만 쿼리 파라미터에 추가
if (params?.cursor) {
queryParams.append('cursor', params.cursor);
}
Expand All @@ -35,18 +30,3 @@ export const getMyFeeds = async (params?: GetMyFeedParams) => {
const response = await apiClient.get<MyFeedResponse>(url);
return response.data;
};

/*
// 첫 페이지 조회
const firstPage = await getMyFeeds();

// 다음 페이지 조회 (nextCursor 사용)
const nextPage = await getMyFeeds({
cursor: firstPage.data.nextCursor
});

// 마지막 페이지인지 확인
if (firstPage.data.isLast) {
console.log('더 이상 불러올 데이터가 없습니다.');
}
*/
10 changes: 0 additions & 10 deletions src/api/feeds/getMyProfile.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import { apiClient } from '../index';
import type { MyProfileData } from '@/types/profile';

// API 응답 타입
export interface MyProfileResponse {
isSuccess: boolean;
code: number;
message: string;
data: MyProfileData;
}

// 내 프로필 조회 API 함수
export const getMyProfile = async () => {
const response = await apiClient.get<MyProfileResponse>('/feeds/mine/info');
return response.data;
};

/*
// 내 프로필 정보 조회
const myProfile = await getMyProfile();
console.log(myProfile.data.nickname); // 닉네임
console.log(myProfile.data.followerCount); // 팔로워 수
*/
10 changes: 0 additions & 10 deletions src/api/feeds/getOtherFeed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { apiClient } from '../index';

// 다른 사용자의 피드 아이템 타입
export interface OtherFeedItem {
feedId: number;
postDate: string;
Expand All @@ -14,27 +13,18 @@ export interface OtherFeedItem {
isSaved: boolean;
}

// API 응답 데이터 타입
export interface OtherFeedData {
feedList: OtherFeedItem[];
}

// API 응답 타입
export interface OtherFeedResponse {
isSuccess: boolean;
code: number;
message: string;
data: OtherFeedData;
}

// 다른 사용자 피드 조회 API 함수
export const getOtherFeed = async (userId: number) => {
const response = await apiClient.get<OtherFeedResponse>(`/feeds/users/${userId}`);
return response.data;
};

/*
다른 사용자의 피드 리스트 조회
const otherUserFeed = await getOtherFeed(123);
console.log(otherUserFeed.data.feedList); // OtherFeedItem[]
*/
17 changes: 0 additions & 17 deletions src/api/feeds/getSavedFeedsInMy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { apiClient } from '../index';

// 개인적으로 저장한 피드 정보 타입
export interface SavedFeedInMy {
feedId: number;
creatorId: number;
Expand All @@ -21,22 +20,19 @@ export interface SavedFeedInMy {
isWriter: boolean;
}

// API 응답 데이터 타입 (무한스크롤 지원)
export interface SavedFeedsInMyData {
feedList: SavedFeedInMy[];
nextCursor: string;
isLast: boolean;
}

// API 응답 타입
export interface SavedFeedsInMyResponse {
isSuccess: boolean;
code: number;
message: string;
data: SavedFeedsInMyData;
}

// 개인적으로 저장한 피드 목록 조회 API 함수 (무한스크롤)
export const getSavedFeedsInMy = async (cursor: string | null = null) => {
try {
const params: { cursor?: string | null } = {};
Expand All @@ -53,16 +49,3 @@ export const getSavedFeedsInMy = async (cursor: string | null = null) => {
throw error;
}
};

/*
// 사용 예시 (무한스크롤)
const savedFeedsInMy = await getSavedFeedsInMy();
console.log(savedFeedsInMy.data.feedList); // 저장된 피드 목록
console.log(savedFeedsInMy.data.nextCursor); // 다음 페이지 커서
console.log(savedFeedsInMy.data.isLast); // 마지막 페이지 여부

// 다음 페이지 로드
if (!savedFeedsInMy.data.isLast) {
const nextPage = await getSavedFeedsInMy(savedFeedsInMy.data.nextCursor);
}
*/
23 changes: 1 addition & 22 deletions src/api/feeds/getTotalFeed.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
import { apiClient } from '../index';
import type { PostData } from '@/types/post';

// API 응답 데이터 타입
export interface TotalFeedData {
feedList: PostData[];
nextCursor: string;
isLast: boolean;
}

// API 응답 타입
export interface TotalFeedResponse {
isSuccess: boolean;
code: number;
message: string;
data: TotalFeedData;
}

// 요청 파라미터 타입
export interface GetTotalFeedParams {
cursor?: string; // 첫 페이지는 null 또는 없음, 다음 페이지부터는 nextCursor 값 사용
cursor?: string;
}

export const getTotalFeeds = async (params?: GetTotalFeedParams) => {
const queryParams = new URLSearchParams();

// cursor가 있을 때만 쿼리 파라미터에 추가
if (params?.cursor) {
queryParams.append('cursor', params.cursor);
}
Expand All @@ -34,20 +30,3 @@ export const getTotalFeeds = async (params?: GetTotalFeedParams) => {
const response = await apiClient.get<TotalFeedResponse>(url);
return response.data;
};

/*
사용 방법:

// 첫 페이지 조회
const firstPage = await getTotalFeeds();

// 다음 페이지 조회 (nextCursor 사용)
const nextPage = await getTotalFeeds({
cursor: firstPage.data.nextCursor
});

// 마지막 페이지인지 확인
if (firstPage.data.isLast) {
console.log('더 이상 불러올 데이터가 없습니다.');
}
*/
30 changes: 3 additions & 27 deletions src/api/feeds/postSave.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,26 @@
import { apiClient } from '../index';

// 요청 바디 타입
export interface SaveFeedRequest {
type: boolean; // true: 저장, false: 저장 취소
type: boolean;
}

// 응답 데이터 타입
export interface SaveFeedData {
feedId: number;
isSaved: boolean;
}

// API 응답 타입
export interface SaveFeedResponse {
isSuccess: boolean;
code: number;
message: string;
data?: SaveFeedData; // 성공 시에만 존재
data?: SaveFeedData;
}

// 피드 저장/저장 취소 API 함수
export const postSaveFeed = async (feedId: number, isSaved: boolean) => {
const requestBody: SaveFeedRequest = {
type: isSaved, // 현재 저장 상태로 변경
type: isSaved,
};

const response = await apiClient.post<SaveFeedResponse>(`/feeds/${feedId}/saved`, requestBody);
return response.data;
};

/*
사용 방법:

// 피드 저장
const saveResult = await postSaveFeed(123, true);
if (saveResult.isSuccess) {
console.log('저장 성공:', saveResult.data?.isSaved);
} else {
console.log('저장 실패:', saveResult.message);
}

// 피드 저장 취소
const unsaveResult = await postSaveFeed(123, false);
if (unsaveResult.isSuccess) {
console.log('저장 취소 성공:', unsaveResult.data?.isSaved);
} else {
console.log('저장 취소 실패:', unsaveResult.message);
}
*/
9 changes: 0 additions & 9 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,31 @@
import axios, { type AxiosResponse, type AxiosError } from 'axios';

// API 기본 URL
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

// Axios 인스턴스 생성
export const apiClient = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
// Request 인터셉터: 토큰 부재 시 비공개 API 요청을 선제 차단(리다이렉트 + 요청 취소)
apiClient.interceptors.request.use(
config => {
const authToken = localStorage.getItem('authToken');
const preAuthToken = localStorage.getItem('preAuthToken');
// 공개 API(완전 공개)
const publicPaths = ['/auth/token'];
// 회원가입 진행 중 필요한 경로(임시 토큰 허용)
const signupPaths = ['/users/nickname', '/users/signup'];
const isPublic = publicPaths.some(path => config.url?.startsWith(path));
const isSignupPath = signupPaths.some(path => config.url?.startsWith(path));

if (!authToken && !isPublic && !(preAuthToken && isSignupPath)) {
console.log('❌ 토큰 없음: 요청을 취소하고 홈으로 이동합니다.');
window.location.href = '/';
// 요청 자체를 취소하여 불필요한 네트워크 왕복 방지
return Promise.reject(new Error('Request cancelled: missing auth token'));
}

if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
} else if (preAuthToken && isSignupPath) {
// 회원가입 경로에서는 임시 토큰을 사용
config.headers.Authorization = `Bearer ${preAuthToken}`;
}

Expand All @@ -42,7 +34,6 @@ apiClient.interceptors.request.use(
error => Promise.reject(error),
);

// Response 인터셉터: 401 에러 시 로그인 페이지로 리다이렉트
apiClient.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError) => {
Expand Down
Loading