Skip to content

Latest commit

 

History

History
1192 lines (979 loc) · 32.2 KB

File metadata and controls

1192 lines (979 loc) · 32.2 KB

Taba API 명세서

기본 정보

  • 개발 환경 Base URL: https://dev.taba.asia/api/v1
  • 프로덕션 Base URL: https://www.taba.asia/api/v1
  • 인증 방식: JWT Bearer Token
  • Content-Type: application/json
  • API 버전: v1

참고: 이 문서는 개발/프로덕션 환경 공통 API 명세입니다.
예시 URL은 개발 환경(dev.taba.asia)을 기준으로 작성되었으며, 프로덕션 환경에서는 www.taba.asia로 변경하여 사용하세요.

공통 응답 형식

모든 API는 다음 형식으로 응답합니다:

{
  "success": true,
  "data": { ... },
  "message": "성공 메시지 (선택사항)"
}

에러 응답:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "에러 메시지"
  }
}

인증

대부분의 API는 JWT 토큰 인증이 필요합니다. 요청 헤더에 다음을 포함하세요:

Authorization: Bearer {token}

1. 인증 API (/auth)

1.1 회원가입

POST /auth/signup

인증: 불필요

Content-Type: multipart/form-data

Request:

  • email: 이메일 (필수)
  • password: 비밀번호 (필수, 최소 8자)
  • nickname: 닉네임 (필수, 2-50자)
  • agreeTerms: 이용약관 동의 (필수, boolean)
  • agreePrivacy: 개인정보처리방침 동의 (필수, boolean)
  • profileImage: 프로필 이미지 파일 (선택사항)

Request Body 예시 (multipart/form-data):

email: user@example.com
password: password123
nickname: 사용자
agreeTerms: true
agreePrivacy: true
profileImage: [파일]

Response (201 Created):

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "user": {
        "id": "uuid",
        "email": "user@example.com",
        "nickname": "사용자"
      }
  },
  "message": "회원가입이 완료되었습니다."
}

1.2 로그인

POST /auth/login

인증: 불필요

Request Body:

{
  "email": "user@example.com",
  "password": "password123"
}

Response (200 OK):

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": "uuid",
      "email": "user@example.com",
      "nickname": "사용자"
    }
  },
  "message": "로그인에 성공했습니다."
}

2. 사용자 API (/users)

2.1 내 프로필 조회

GET /users/{userId}

인증: 필요

Response (200 OK):

{
  "success": true,
  "data": {
    "id": "uuid",
    "email": "user@example.com",
    "nickname": "사용자",
    "profileImageUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
    "createdAt": "2024-01-01T00:00:00"
  }
}

2.2 프로필 수정

PUT /users/{userId}

인증: 필요

Content-Type: multipart/form-data

Request:

  • nickname: 닉네임 (선택사항, 2-50자)
  • avatarUrl: 아바타 URL (선택사항)
  • profileImage: 프로필 이미지 파일 (선택사항)

참고사항:

  • 프로필 수정 후, 다른 API에서 유저 정보를 조회할 때 변경된 닉네임과 프로필 이미지가 즉시 반영됩니다.
  • 예: 편지 목록, 친구 목록, 알림 등에서 표시되는 유저 정보는 항상 최신 데이터를 반영합니다.

Response (200 OK):

{
  "success": true,
  "data": {
    "id": "uuid",
    "email": "user@example.com",
    "nickname": "수정된 닉네임",
    "profileImageUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
  },
  "message": "프로필이 수정되었습니다."
}

2.3 FCM 토큰 업데이트

PUT /users/{userId}/fcm-token

인증: 필요

Request Body:

{
  "fcmToken": "fcm_token_string"
}

Response (200 OK):

{
  "success": true,
  "data": null,
  "message": "FCM 토큰이 등록되었습니다."
}

2.4 회원탈퇴

DELETE /users/{userId}

인증: 필요

참고사항:

  • 본인만 탈퇴할 수 있습니다.
  • 회원탈퇴 시 사용자 정보는 소프트 삭제됩니다.
  • 탈퇴 후 해당 계정으로 로그인할 수 없습니다.

Response (200 OK):

{
  "success": true,
  "data": null,
  "message": "회원탈퇴가 완료되었습니다."
}

3. 친구 API (/friends)

3.1 친구 목록 조회

GET /friends

인증: 필요

Response (200 OK):

{
  "success": true,
  "data": {
    "friends": [
      {
        "id": "uuid",
        "email": "friend@example.com",
        "nickname": "친구1",
        "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
        "joinedAt": "2024-01-01T00:00:00",
        "friendCount": 5,
        "sentLetters": 10,
        "unreadLetterCount": 3
      }
    ]
  }
}

참고사항:

  • unreadLetterCount: 해당 친구로부터 받은 안 읽은 개인편지(DIRECT) 개수
  • 공개편지는 안 읽은 개수에 포함되지 않습니다.

3.2 친구 추가 (초대 코드 사용)

POST /friends/invite

인증: 필요

Request Body:

{
  "inviteCode": "ABC123"
}

참고사항:

  • 올바르지 않은 초대 코드인 경우: INVALID_INVITE_CODE 에러 반환
  • 만료된 초대 코드인 경우: INVITE_CODE_EXPIRED 에러 반환
  • 이미 사용된 초대 코드인 경우: INVITE_CODE_ALREADY_USED 에러 반환
  • 자신의 초대 코드를 사용한 경우: 본인 정보와 함께 "본인은 친구 추가할 수 없습니다." 메시지 반환 (201 Created)
  • 이미 친구인 경우: 친구 정보와 함께 "이미 친구입니다." 메시지 반환 (201 Created)
  • 새로운 친구인 경우: 친구 정보와 함께 "친구가 추가되었습니다." 메시지 반환 (201 Created)

Response (201 Created) - 새로운 친구 추가 성공:

{
  "success": true,
  "data": {
    "friend": {
      "id": "uuid",
      "email": "friend@example.com",
      "nickname": "친구1",
      "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
      "joinedAt": "2024-01-01T00:00:00",
      "friendCount": 5,
      "sentLetters": 10
    },
    "alreadyFriends": false,
    "isOwnCode": false
  },
  "message": "친구가 추가되었습니다."
}

Response (201 Created) - 자신의 초대 코드를 사용한 경우:

{
  "success": true,
  "data": {
    "friend": {
      "id": "uuid",
      "email": "user@example.com",
      "nickname": "본인",
      "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
      "joinedAt": "2024-01-01T00:00:00",
      "friendCount": 5,
      "sentLetters": 10
    },
    "alreadyFriends": false,
    "isOwnCode": true
  },
  "message": "본인은 친구 추가할 수 없습니다."
}

Response (201 Created) - 이미 친구인 경우:

{
  "success": true,
  "data": {
    "friend": {
      "id": "uuid",
      "email": "friend@example.com",
      "nickname": "친구1",
      "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
      "joinedAt": "2024-01-01T00:00:00",
      "friendCount": 5,
      "sentLetters": 10
    },
    "alreadyFriends": true,
    "isOwnCode": false
  },
  "message": "이미 친구입니다."
}

3.3 친구 삭제

DELETE /friends/{friendId}

인증: 필요

참고사항:

  • 친구 관계가 존재하지 않는 경우 FRIENDSHIP_NOT_FOUND 에러를 반환합니다.
  • 친구 ID가 유효하지 않은 경우 USER_NOT_FOUND 에러를 반환합니다.
  • 자기 자신을 친구 삭제 대상으로 지정할 수 없습니다.
  • 양방향 친구 관계가 모두 소프트 삭제됩니다.

Response (200 OK):

{
  "success": true,
  "data": null,
  "message": "친구가 삭제되었습니다."
}

에러 응답 (404 Not Found) - 친구 관계가 없는 경우:

{
  "success": false,
  "error": {
    "code": "FRIENDSHIP_NOT_FOUND",
    "message": "친구 관계를 찾을 수 없습니다."
  }
}

3.4 친구 편지 목록 조회

GET /friends/{friendId}/letters

인증: 필요

Response (200 OK):

{
  "success": true,
  "data": {
    "content": [
      {
        "id": "uuid",
        "letter": {
          "id": "uuid",
          "title": "편지 제목",
          "preview": "편지 미리보기",
          "fontFamily": "Jua"
        },
        "sentAt": "2024-01-01T00:00:00",
        "sentByMe": false,
        "isRead": true,
        "fontFamily": "Jua"
      }
    ],
    "pageable": { ... },
    "totalElements": 10,
    "totalPages": 1
  }
}

참고사항:

  • 친구 간 주고받은 편지 목록을 반환합니다 (양방향).
  • 공개편지 포함: 친구가 작성한 공개편지 중 내가 답장을 보낸 공개편지만 목록에 포함됩니다.
    • 공개편지에 답장한 경우, 공개편지의 sentAt이 답장 시간 바로 전(1초 전)으로 조정되어 표시됩니다.
    • 이를 통해 공개편지가 답장보다 시간상 앞서 표시되어 대화 흐름이 자연스럽게 유지됩니다.
  • 예약전송 편지 포함: 예약전송 편지도 목록에 포함됩니다.
    • 예약전송 편지의 경우 sentAtscheduledAt으로 표시됩니다
    • 받는 사람은 예약 시간 전까지 편지를 열람할 수 없지만, 목록에는 표시됩니다
  • sentByMe: 내가 보낸 편지인지 여부 (true: 내가 보낸 편지, false: 친구가 보낸 편지 또는 공개편지)
  • isRead:
    • DIRECT 편지: 내가 받은 편지인 경우 읽음 상태 (내가 보낸 편지인 경우 null)
    • PUBLIC 편지: 공개편지에 답장을 보내면 자동으로 읽음 처리되며, 이후 읽음 상태가 표시됩니다 (아직 읽지 않은 경우 false)
  • letter: 편지 요약 정보 (id, title, preview, fontFamily)
  • 시간순 정렬: sentAt(또는 scheduledAt) 기준 오름차순 정렬 (오래된 편지부터 최신 편지 순서)
  • 페이지네이션 정보가 포함됩니다.

4. 편지 API (/letters)

4.1 편지 작성

POST /letters

인증: 필요

Content-Type: application/json

Request Body:

{
  "title": "편지 제목",
  "content": "편지 내용",
  "preview": "편지 미리보기",
  "visibility": "PUBLIC",
  "template": {
    "background": "#1D1433",
    "textColor": "#FFFFFF",
    "fontFamily": "Jua",
    "fontSize": 16.0
  },
  "attachedImages": ["https://dev.taba.asia/api/v1/files/{fileId}"],
  "scheduledAt": "2024-01-01T12:00:00",
  "recipientId": "uuid",
  "language": "ko"
}

참고사항:

  • visibility: PUBLIC, DIRECT 중 하나 (필수)
  • 익명 기능은 제거되었습니다. 모든 편지는 작성자 정보가 표시됩니다.
  • recipientId: 직접 전송(DIRECT) 편지인 경우 필수, 공개 편지인 경우 선택사항
  • scheduledAt: 예약전송 시간 (선택사항). 미래 시간을 지정하면 해당 시간에 자동으로 발송됩니다.
    • 예약전송 제한사항:
      • 예약전송은 친구에게만 보낼 수 있습니다 (DIRECT 타입만 가능, PUBLIC 불가)
      • 수신자(recipientId)가 필수입니다
      • 친구 관계가 있어야 합니다
    • 예약전송 시간이 현재 시간보다 이전이거나 같으면 즉시 발송됩니다
  • language: 편지 언어 (선택사항). ko (한국어), en (영어), ja (일본어) 중 하나
  • attachedImages: 첨부 이미지 URL 배열 (선택사항). 여러 이미지를 첨부할 수 있으며, 순서대로 저장됩니다.
    • 이미지 업로드는 /files API를 통해 먼저 수행하고, 반환된 URL을 사용합니다.
    • 예: ["https://dev.taba.asia/api/v1/files/{fileId1}", "https://dev.taba.asia/api/v1/files/{fileId2}"]

Response (201 Created):

{
  "success": true,
  "data": {
    "letter": {
      "id": "uuid",
      "title": "편지 제목",
      "content": "편지 내용",
      "preview": "편지 미리보기",
      "sender": {
        "id": "uuid",
        "nickname": "작성자",
        "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
      },
      "visibility": "PUBLIC",
      "sentAt": "2024-01-01T00:00:00",
      "views": 0,
      "attachedImages": ["https://dev.taba.asia/api/v1/files/{fileId}"],
      "template": {
        "background": "#1D1433",
        "textColor": "#FFFFFF",
        "fontFamily": "Jua",
        "fontSize": 16.0
      },
      "language": "ko"
    }
  },
  "message": "편지가 작성되었습니다."
}

4.2 편지 조회

GET /letters/{letterId}

인증: 필요

참고사항:

  • 편지의 접근 권한을 확인합니다 (PUBLIC, DIRECT)
  • 예약전송 편지 접근 제한:
    • 예약전송 편지(scheduledAt이 있고 sentAt이 null인 경우)는 받는 사람이 예약 시간 전까지 열람할 수 없습니다
    • 보낸 사람은 언제든지 열람 가능합니다
    • 예약 시간이 지나면 자동으로 발송되며, 이후 받는 사람도 열람할 수 있습니다
  • 읽음 처리 (작성자가 아닌 경우에만 자동 처리):
    • 공개 편지(PUBLIC): LetterRecipient 테이블을 통해 읽음 상태가 자동으로 기록됩니다. 여러 사용자가 읽을 수 있으므로 사용자별로 읽음 상태를 관리합니다.
    • 직접 전송 편지(DIRECT): 수신자가 조회하면 Letter 엔티티의 isRead 필드가 자동으로 업데이트됩니다. 1:1 편지이므로 편지 자체의 읽음 상태로 관리합니다.
  • 편지를 조회하면 조회수(views)가 증가합니다.
  • isRead: 읽음 상태 (작성자가 아닌 경우에만 표시)
    • true: 읽음
    • false: 읽지 않음
    • null: 작성자인 경우

Response (200 OK):

{
  "success": true,
  "data": {
    "letter": {
      "id": "uuid",
      "title": "편지 제목",
      "content": "편지 내용",
      "preview": "편지 미리보기",
      "sender": {
        "id": "uuid",
        "nickname": "작성자",
        "profileImageUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
      },
      "visibility": "PUBLIC",
      "sentAt": "2024-01-01T00:00:00",
      "views": 10,
      "attachedImages": [
        "https://dev.taba.asia/api/v1/files/{fileId1}",
        "https://dev.taba.asia/api/v1/files/{fileId2}"
      ],
      "template": {
        "background": "#1D1433",
        "textColor": "#FFFFFF",
        "fontFamily": "Jua",
        "fontSize": 16.0
      },
      "language": "ko",
      "isRead": true
    }
  }
}

4.3 공개 편지 목록 조회

GET /letters/public

인증: 선택사항

Query Parameters:

  • languages (선택사항): 언어 필터링. 여러 언어를 선택하려면 같은 파라미터를 여러 번 사용하세요.
    • 예: ?languages=ko&languages=en (한국어와 영어)
    • 가능한 값: ko (한국어), en (영어), ja (일본어)
    • 생략 시 모든 언어의 편지를 조회합니다.

참고사항:

  • 모든 편지는 작성자 정보가 표시됩니다 (익명 기능 제거)
  • 로그인한 사용자의 경우 자신이 작성한 편지는 목록에서 제외됩니다
  • 언어 필터링은 여러 언어를 동시에 선택할 수 있습니다 (예: 한국어와 영어)
  • 읽음 처리: 목록 조회 시에는 읽음 처리가 되지 않습니다. 실제 편지 상세 조회(GET /letters/{letterId}) 시에만 읽음 처리가 됩니다.
  • 조회수: 목록 조회 시에는 조회수가 증가하지 않습니다. 실제 편지 상세 조회 시에만 조회수가 증가합니다.
  • isRead: 읽음 상태 (로그인한 사용자이고 작성자가 아닌 경우에만 표시)
    • true: 읽음
    • false: 읽지 않음
    • null: 작성자인 경우 또는 비로그인 사용자

Request 예시:

GET /letters/public?languages=ko&languages=en&page=0&size=20

Response (200 OK):

{
  "success": true,
  "data": {
    "content": [
      {
        "id": "uuid",
        "title": "편지 제목",
        "content": "편지 내용",
        "preview": "편지 미리보기",
        "sender": {
          "id": "uuid",
          "nickname": "작성자",
          "profileImageUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
        },
        "visibility": "PUBLIC",
        "sentAt": "2024-01-01T00:00:00",
        "views": 10,
        "attachedImages": ["https://dev.taba.asia/api/v1/files/{fileId}"],
        "template": {
          "background": "#1D1433",
          "textColor": "#FFFFFF",
          "fontFamily": "Jua",
          "fontSize": 16.0
        },
        "language": "ko",
        "isRead": true
      }
    ],
    "pageable": { ... },
    "totalElements": 100,
    "totalPages": 5
  }
}

4.4 내가 작성한 편지 목록 조회

GET /letters/my

인증: 필요

Query Parameters:

  • page: 페이지 번호 (기본값: 0)
  • size: 페이지 크기 (기본값: 20)
  • sort: 정렬 기준 (기본값: createdAt,desc)

참고사항:

  • 현재 로그인한 사용자가 작성한 모든 편지를 조회합니다.
  • 삭제되지 않은 편지만 조회됩니다 (소프트 삭제).
  • 작성일 기준 내림차순으로 정렬됩니다 (최신 편지부터).
  • 본인이 작성한 편지이므로 읽음 처리는 수행되지 않습니다.

Response (200 OK):

{
  "success": true,
  "data": {
    "content": [
      {
        "id": "uuid",
        "title": "편지 제목",
        "content": "편지 내용",
        "preview": "편지 미리보기",
        "sender": {
          "id": "uuid",
          "nickname": "작성자",
          "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
        },
        "visibility": "PUBLIC",
        "sentAt": "2024-01-01T00:00:00",
        "views": 10,
        "attachedImages": ["https://dev.taba.asia/api/v1/files/{fileId}"],
        "template": {
          "background": "#1D1433",
          "textColor": "#FFFFFF",
          "fontFamily": "Jua",
          "fontSize": 16.0
        },
        "language": "ko"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20
    },
    "totalElements": 1,
    "totalPages": 1
  }
}

4.5 편지 답장

POST /letters/{letterId}/reply

인증: 필요

Request Body:

{
  "title": "답장 제목",
  "content": "답장 내용",
  "preview": "답장 미리보기",
  "template": {
    "background": "#1D1433",
    "textColor": "#FFFFFF",
    "fontFamily": "Jua",
    "fontSize": 16.0
  },
  "attachedImages": ["https://dev.taba.asia/api/v1/files/{fileId}"],
  "scheduledAt": "2024-01-01T12:00:00"
}

참고사항:

  • recipientId는 필요하지 않습니다. 원본 편지의 작성자가 자동으로 수신자가 됩니다.
  • 공개 편지, 직접 전송 편지 모두에 답장 가능합니다.
  • 답장은 항상 DIRECT 타입으로 생성됩니다.
  • 친구가 아닌 사용자에게 답장을 보내면 자동으로 양방향 친구 관계가 생성됩니다.
  • 자기 자신에게 답장할 수 없습니다.
  • scheduledAt: 예약전송 시간 (선택사항). 답장도 예약전송 가능하며, 예약전송인 경우 친구 관계가 있어야 합니다.
  • 공개 편지(PUBLIC)에 답장하는 경우:
    • 원본 편지 ID(originalLetterId)가 답장 편지에 저장되어, 친구와의 편지 목록에서 해당 공개편지만 표시됩니다.
    • 공개 편지에 답장을 보내면 자동으로 해당 공개 편지가 읽음 처리됩니다 (LetterRecipient를 통해).
  • attachedImages: 첨부 이미지 URL 배열 (선택사항). 여러 이미지를 첨부할 수 있으며, 순서대로 저장됩니다.
    • 이미지 업로드는 /files API를 통해 먼저 수행하고, 반환된 URL을 사용합니다.

Response (201 Created):

{
  "success": true,
  "data": {
    "letter": {
      "id": "uuid",
      "title": "답장 제목",
      "content": "답장 내용",
      "preview": "답장 미리보기",
      "sender": {
        "id": "uuid",
        "nickname": "작성자",
        "profileImageUrl": "https://dev.taba.asia/api/v1/files/{fileId}"
      },
      "visibility": "DIRECT",
      "sentAt": "2024-01-01T00:00:00",
      "views": 0,
      "attachedImages": [
        "https://dev.taba.asia/api/v1/files/{fileId1}",
        "https://dev.taba.asia/api/v1/files/{fileId2}"
      ],
      "template": {
        "background": "#1D1433",
        "textColor": "#FFFFFF",
        "fontFamily": "Jua",
        "fontSize": 16.0
      },
      "language": "ko"
    }
  },
  "message": "답장이 전송되었습니다. 친구가 자동으로 추가되었습니다."
}

4.6 편지 삭제

DELETE /letters/{letterId}

인증: 필요

참고사항:

  • 자신이 작성한 편지만 삭제할 수 있습니다.
  • 편지는 소프트 삭제됩니다 (실제로 삭제되지 않고 deletedAt 필드에 타임스탬프가 기록됩니다).
  • 삭제된 편지는 조회되지 않습니다.

Response (200 OK):

{
  "success": true,
  "message": "편지가 삭제되었습니다."
}

에러 응답:

  • 403 Forbidden: 자신이 작성한 편지가 아닌 경우
  • 404 Not Found: 편지를 찾을 수 없는 경우

5. 초대 코드 API (/invite-codes)

5.1 초대 코드 생성

POST /invite-codes/generate

인증: 필요

참고사항:

  • 기존에 유효한 초대 코드가 있으면 새로 생성하지 않고 기존 코드를 반환합니다.
  • 초대 코드는 생성 후 3분간 유효합니다.

Response (201 Created):

{
  "success": true,
  "data": {
    "code": "ABC123",
    "expiresAt": "2024-01-01T00:03:00",
    "remainingMinutes": 3
  },
  "message": "초대 코드가 생성되었습니다."
}

5.2 현재 초대 코드 조회

GET /invite-codes/current

인증: 필요

참고사항:

  • 현재 유효한 초대 코드가 없거나 만료된 경우 null을 반환합니다.

Response (200 OK) - 유효한 코드가 있는 경우:

{
  "success": true,
  "data": {
    "code": "ABC123",
    "expiresAt": "2024-01-01T00:03:00",
    "remainingMinutes": 2
  }
}

Response (200 OK) - 유효한 코드가 없는 경우:

{
  "success": true,
  "data": null
}

6. 알림 API (/notifications)

6.1 알림 목록 조회

GET /notifications

인증: 필요

Query Parameters:

  • category (선택사항): 알림 카테고리 필터링
    • 가능한 값: LETTER, REACTION, FRIEND, SYSTEM
    • 생략 시 모든 카테고리의 알림을 조회합니다.
  • page (선택사항): 페이지 번호 (기본값: 0)
  • size (선택사항): 페이지 크기 (기본값: 20)

참고사항:

  • 알림 목록은 생성일시(time) 기준 내림차순으로 정렬됩니다 (최신 알림부터).
  • isUnread: 읽지 않은 알림 여부
    • true: 읽지 않은 알림
    • false: 읽은 알림
  • 페이지네이션 정보가 포함됩니다.

Response (200 OK):

{
  "success": true,
  "data": {
    "content": [
      {
        "id": "uuid",
        "title": "새 편지를 받았습니다",
        "subtitle": "친구가 편지를 보냈습니다",
        "time": "2024-01-01T00:00:00",
        "category": "LETTER",
        "isUnread": true,
        "relatedId": "letter-uuid"
      }
    ],
    "pageable": { ... },
    "totalElements": 10,
    "totalPages": 1
  }
}

6.2 알림 읽음 처리

PUT /notifications/{notificationId}/read

인증: 필요

참고사항:

  • 특정 알림을 읽음 처리합니다.
  • 읽음 처리된 알림의 isUnread 값이 false로 변경됩니다.
  • 읽지 않은 알림을 읽음 처리한 경우, 업데이트된 뱃지 숫자가 FCM 푸시 알림으로 자동 전송됩니다 (iOS/Android 모두 지원).

Response (200 OK):

{
  "success": true,
  "data": {
    "id": "uuid",
    "title": "새 편지를 받았습니다",
    "subtitle": "친구가 편지를 보냈습니다",
    "time": "2024-01-01T00:00:00",
    "category": "LETTER",
    "isUnread": false,
    "relatedId": "letter-uuid"
  }
}

6.3 모든 알림 읽음 처리

PUT /notifications/read-all

인증: 필요

참고사항:

  • 현재 사용자의 모든 읽지 않은 알림을 일괄 읽음 처리합니다.
  • 읽음 처리된 알림 개수를 반환합니다.
  • 읽음 처리한 알림이 있는 경우, 업데이트된 뱃지 숫자가 FCM 푸시 알림으로 자동 전송됩니다 (iOS/Android 모두 지원).

Response (200 OK):

{
  "success": true,
  "data": {
    "readCount": 5,
    "message": "모든 알림이 읽음 처리되었습니다."
  }
}

6.4 알림 삭제

DELETE /notifications/{notificationId}

인증: 필요

참고사항:

  • 본인의 알림만 삭제할 수 있습니다.
  • 알림 삭제 시 읽지 않은 알림 개수(/notifications/unread-count)에 즉시 반영됩니다.
  • 읽지 않은 알림을 삭제한 경우, 업데이트된 뱃지 숫자가 FCM 푸시 알림으로 자동 전송됩니다 (iOS/Android 모두 지원).

Response (200 OK):

{
  "success": true,
  "data": "알림이 삭제되었습니다.",
  "message": "알림이 삭제되었습니다."
}

6.5 읽지 않은 알림 개수 조회

GET /notifications/unread-count

인증: 필요

참고사항:

  • 현재 사용자의 읽지 않은 편지 개수를 반환합니다.
  • 앱 뱃지 숫자 표시용으로 사용됩니다.
  • FCM 푸시 알림 발송 시에도 이 개수가 뱃지 숫자로 전송됩니다.
  • 편지 읽음 처리 시 즉시 반영됩니다.
  • 뱃지 계산 기준: 내가 받은 읽지 않은 DIRECT 편지만 카운트됩니다.
    • 내가 보낸 편지는 카운트되지 않습니다.
    • 공개편지(PUBLIC)는 카운트되지 않습니다.
    • 친구 추가 알림이나 답장 알림 등은 뱃지에 포함되지 않습니다.

6.6 FCM 푸시 알림 및 뱃지

FCM 푸시 알림 뱃지 지원:

  • iOS: APNs의 badge 필드를 통해 읽지 않은 알림 개수가 자동으로 설정됩니다.
  • Android: FCM data payload의 badge 필드에 읽지 않은 알림 개수가 포함됩니다. 앱에서 이 값을 받아 뱃지를 업데이트할 수 있습니다.

뱃지 업데이트 시점:

  • 편지 수신 시: 새 편지를 받으면 읽지 않은 편지 개수를 계산하여 뱃지 숫자로 전송합니다.
  • 편지 읽음 처리 시: 편지를 읽으면 업데이트된 뱃지 숫자가 silent push로 전송됩니다.
  • 뱃지 동기화 시: 앱이 포그라운드로 올라오거나 알림 목록 화면 진입 시 현재 읽지 않은 편지 개수로 뱃지를 동기화합니다.

뱃지 계산 기준:

  • 뱃지 숫자는 내가 받은 읽지 않은 DIRECT 편지 개수를 기준으로 합니다.
  • 카운트되는 편지:
    • DIRECT 편지 중 수신자가 현재 사용자이고 읽지 않은 편지
  • 카운트되지 않는 항목:
    • 내가 보낸 편지 (수신자가 나인 경우에도 내가 보낸 편지는 카운트되지 않음)
    • 공개편지(PUBLIC) - 공개편지는 뱃지에 포함되지 않습니다
    • 친구 추가 알림, 답장 알림 등 - 내가 한 액션에 대한 알림은 뱃지에 포함되지 않습니다

FCM Data Payload 구조 (알림 생성 시):

{
  "notificationId": "uuid",
  "category": "LETTER",
  "relatedId": "letter-uuid",
  "deepLink": "/letter/letter-uuid",
  "badge": "3"
}

FCM Data Payload 구조 (뱃지 업데이트만):

{
  "type": "badge_update",
  "badge": "2"
}

Response (200 OK):

{
  "success": true,
  "data": {
    "unreadCount": 3
  }
}

6.7 뱃지 동기화

POST /notifications/badge/sync

인증: 필요

참고사항:

  • 현재 읽지 않은 편지 개수를 계산하여 뱃지 숫자를 동기화합니다.
  • 앱이 포그라운드로 올라오거나 알림 목록 화면 진입 시 호출하는 것을 권장합니다.
  • 읽지 않은 편지 개수를 반환하며, 동시에 FCM 푸시 알림으로 뱃지 숫자를 업데이트합니다.
  • iOS와 Android 모두 지원합니다.
  • 뱃지 계산 기준: 내가 받은 읽지 않은 DIRECT 편지만 카운트됩니다.
    • 내가 보낸 편지나 내가 한 액션(친구 추가, 답장 등)은 뱃지에 포함되지 않습니다.

Response (200 OK):

{
  "success": true,
  "data": {
    "unreadCount": 3
  }
}

7. 파일 API (/files)

7.1 파일 업로드

POST /files

인증: 필요

Content-Type: multipart/form-data

Request:

  • file: 파일 (필수, 이미지 파일만 가능)

Response (201 Created):

{
  "success": true,
  "data": {
    "fileId": "uuid",
    "url": "https://dev.taba.asia/api/v1/files/{fileId}"
  }
}

7.2 파일 조회

GET /files/{fileId}

인증: 필요

Response: 이미지 파일 반환


8. 차단 API (/blocks)

8.1 사용자 차단

POST /blocks/{userId}

인증: 필요

참고사항:

  • 차단하면 친구 관계가 자동으로 삭제됩니다 (양방향).
  • 차단한 사용자의 공개 편지는 목록에서 제외됩니다.
  • 자기 자신은 차단할 수 없습니다.
  • 이미 차단한 사용자는 다시 차단할 수 없습니다.

Response (201 Created):

{
  "success": true,
  "data": "사용자를 차단했습니다.",
  "message": "사용자를 차단했습니다."
}

에러 응답:

  • 400 Bad Request: 자기 자신을 차단하려는 경우 또는 이미 차단한 사용자인 경우
  • 404 Not Found: 차단할 사용자를 찾을 수 없는 경우

8.2 차단 해제

DELETE /blocks/{userId}

인증: 필요

참고사항:

  • 차단 해제 후에도 친구 관계는 자동으로 복구되지 않습니다.
  • 친구가 되려면 다시 초대 코드를 사용하거나 편지 답장을 통해 친구가 되어야 합니다.

Response (200 OK):

{
  "success": true,
  "data": "차단이 해제되었습니다.",
  "message": "차단이 해제되었습니다."
}

에러 응답:

  • 400 Bad Request: 차단하지 않은 사용자를 해제하려는 경우

8.3 차단한 사용자 목록 조회

GET /blocks

인증: 필요

Response (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "nickname": "차단한사용자",
      "avatarUrl": "https://dev.taba.asia/api/v1/files/{fileId}",
      "blockedAt": "2024-01-01T00:00:00"
    }
  ]
}

참고사항:

  • 차단한 사용자 목록을 반환합니다.
  • 차단한 사용자가 없으면 빈 배열을 반환합니다.
  • blockedAt: 차단한 시간

Swagger UI

다음 URL에서 인터랙티브 API 문서를 확인할 수 있습니다:


참고사항

유저 정보 최신 데이터 반영

  • 모든 API에서 반환되는 유저 정보(닉네임, 프로필 이미지 등)는 항상 최신 데이터를 반영합니다.
  • 프로필을 수정하면, 편지 목록, 친구 목록, 알림 등 다른 API에서 조회되는 유저 정보에도 즉시 반영됩니다.
  • 캐싱으로 인한 오래된 데이터가 표시되지 않도록 보장됩니다.

초대 코드

  • 유효 시간: 3분
  • 형식: 정확히 6자리 숫자+영문 조합 (예: A1B2C3, 9X7Y2Z, ABC123)
  • 대문자 영문(A-Z)과 숫자(0-9) 조합만 사용

편지 답장 시 자동 친구 추가

  • 친구가 아닌 사용자에게 답장을 보내면 자동으로 양방향 친구 관계가 생성됩니다

알림 뱃지 숫자

  • 뱃지 숫자는 내가 받은 읽지 않은 DIRECT 편지 개수로 표시됩니다.
  • iOS와 Android 모두 지원합니다.
  • 편지 수신, 읽음 처리 시 뱃지 숫자가 자동으로 업데이트됩니다.
  • FCM 푸시 알림을 통해 뱃지 숫자가 실시간으로 동기화됩니다.
  • 중요: 내가 보낸 편지나 내가 한 액션(친구 추가, 답장 등)은 뱃지에 포함되지 않습니다.
    • 예: 내가 친구를 추가하거나 공개편지에 답장을 보낼 때, 상대방에게는 알림과 뱃지가 추가되지만 나 자신에게는 뱃지가 카운트되지 않습니다.

사용자 차단

  • 사용자를 차단하면 친구 관계가 자동으로 삭제됩니다 (양방향).
  • 차단한 사용자의 공개 편지는 목록에서 제외됩니다.
  • 차단 해제 후에도 친구 관계는 자동으로 복구되지 않습니다.
  • 친구가 되려면 다시 초대 코드를 사용하거나 편지 답장을 통해 친구가 되어야 합니다.

편지 자동 삭제 (신고)

  • 편지가 5건 이상 신고되면 자동으로 삭제됩니다 (soft delete).
  • 삭제된 편지는 목록에서 제외되며 조회할 수 없습니다.