별도리 Dev Docs
연동 가이드

커뮤니티 API

게시글, 댓글, 좋아요 CRUD 및 구현 상세

게시글 타입

type 파라미터: FREE / REVIEW / EDUCATION

게시글 엔드포인트

메서드경로설명
POST/community/{type}/posts작성
GET/community/{type}/posts목록 조회
GET/community/posts/{id}상세 조회 (조회수 +1)
PATCH/community/posts/{id}수정
DELETE/community/posts/{id}삭제
POST/community/posts/{id}/likes/toggle좋아요 토글

목록 조회 파라미터

파라미터기본값설명
page0페이지 번호 (0부터 시작)
size20페이지 크기
sortByLATESTLATEST / VIEWS / LIKES
keyword-검색어
searchByTITLETITLE / CONTENT / NICKNAME

검색 구현: TITLE, CONTENT는 MySQL FULLTEXT 인덱스 기반 자연어 검색입니다. NICKNAME은 LIKE 검색입니다.

홈 화면 API

GET /community/home/reviews       — 최신 관측 후기 (최대 20개)
GET /community/home/educations    — 신규 교육 콘텐츠 (최대 20개)
GET /community/home/free-posts    — 인기 자유게시글, 조회수 기준 (최대 20개)

게시글 타입별 추가 필드

REVIEW (관측 후기)

{
  "title": "...",
  "content": "...",
  "review": {
    "location": "강원도 인제",
    "observationSiteId": 1,
    "equipment": "망원경 80mm",
    "observationDate": "2024-01-01",
    "score": 5,
    "targets": ["M42", "M45"]
  },
  "imageUrls": ["https://..."]
}

EDUCATION (교육 콘텐츠)

{
  "title": "...",
  "content": "...",
  "education": {
    "difficulty": "BEGINNER",
    "tags": "천문,별자리",
    "status": "PUBLISHED",
    "contentUrl": "https://.../content.json",
    "targets": ["오리온자리"]
  }
}

contentUrl/files/json으로 업로드한 JSON 파일 URL입니다. 서버에서 PUBLIC_BASE_URL로 시작하는 URL만 허용합니다.


댓글

메서드경로설명
POST/community/posts/{id}/comments작성
GET/community/posts/{id}/comments?page=1&size=15목록
PATCH/community/posts/{id}/comments/{cid}수정
DELETE/community/posts/{id}/comments/{cid}삭제
POST/community/posts/{id}/comments/{cid}/likes-toggle댓글 좋아요

대댓글은 parentId 필드를 포함합니다.

POST /community/posts/{id}/comments
{
  "content": "댓글 내용",
  "parentId": 123  // 대댓글인 경우만
}

댓글 수 — 댓글 작성/삭제 시 서버가 community_posts.comment_count를 자동 갱신합니다. 별도 카운트 조회 API 없이 게시글 상세의 commentCount 필드를 사용하세요.


좋아요 구현 상세

POST /community/posts/{id}/likes/toggle          — 게시글 좋아요
POST /community/posts/{id}/comments/{cid}/likes-toggle  — 댓글 좋아요

응답:

{
  "data": {
    "liked": true,
    "likeCount": 5
  }
}

서버 구현: 좋아요 토글 시 like_count를 직접 UPDATE합니다. 낙관적 락을 사용하지 않으므로 동시 요청 시 count가 틀릴 수 있지만, 소규모 서비스에서는 허용 가능한 수준입니다.


이미지 첨부 플로우

1. POST /files/image → url 반환
2. 게시글 작성 시 imageUrls 배열에 포함
3. 게시글 수정 시 imageUrls로 최종 목록 전달 (없는 URL은 삭제)

게시글 삭제 시 서버가 트랜잭션 커밋 후 스토리지에서 이미지 파일도 삭제합니다.


⚠️ 미구현 항목

  • 내가 쓴 글 목록 — 서버 엔드포인트 없음, 구현 전 서버 작업 필요
  • 내가 좋아요한 글 목록 — 서버 엔드포인트 없음
  • 교육 콘텐츠 평가 조회 — 작성은 가능하나 내 평가 조회 API 없음

API 직접 테스트

타입별 목록 조회

GET
/community/{type}/posts

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

type*string
Value in"REVIEW" | "FREE" | "EDUCATION"

Query Parameters

page?integer
Default0
Formatint32
size?integer
Default20
Formatint32
sortBy?string
Default"LATEST"
Value in"LATEST" | "VIEWS" | "LIKES"
keyword?string
searchBy?string
Default"TITLE"
Value in"TITLE" | "CONTENT" | "NICKNAME"

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/REVIEW/posts"
{
  "content": [
    {
      "id": 0,
      "type": "REVIEW",
      "title": "string",
      "authorId": 0,
      "authorNickname": "string",
      "authorProfileImageUrl": "string",
      "observationSiteId": 0,
      "contentSummary": "string",
      "viewCount": 0,
      "likeCount": 0,
      "commentCount": 0,
      "createdAt": "2019-08-24T14:15:22Z",
      "liked": true,
      "score": 0.1,
      "thumbnailUrl": "string"
    }
  ],
  "page": 0,
  "size": 0,
  "totalElements": 0,
  "totalPages": 0
}

게시글 생성

POST
/community/{type}/posts

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

type*string
Value in"REVIEW" | "FREE" | "EDUCATION"

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

*/*

curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/REVIEW/posts" \  -H "Content-Type: application/json" \  -d '{    "title": "string",    "content": "string"  }'
{
  "id": 0
}

상세 조회

GET
/community/posts/{postId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0"
{
  "id": 0,
  "type": "REVIEW",
  "title": "string",
  "content": "string",
  "authorId": 0,
  "authorNickname": "string",
  "authorProfileImageUrl": "string",
  "images": [
    "string"
  ],
  "review": {
    "location": "string",
    "observationSiteId": 0,
    "targets": [
      "string"
    ],
    "equipment": "string",
    "observationDate": "2019-08-24",
    "score": 1
  },
  "education": {
    "difficulty": "BEGINNER",
    "targets": [
      "string"
    ],
    "tags": "string",
    "status": "DRAFT",
    "averageScore": 0.1,
    "contentUrl": "string"
  },
  "viewCount": 0,
  "likeCount": 0,
  "commentCount": 0,
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z",
  "liked": true
}

수정

PATCH
/community/posts/{postId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

*/*

curl -X PATCH "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0" \  -H "Content-Type: application/json" \  -d '{}'
{
  "success": true,
  "message": "string",
  "data": {}
}

삭제

DELETE
/community/posts/{postId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Response Body

*/*

curl -X DELETE "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0"
{
  "success": true,
  "message": "string",
  "data": {}
}

좋아요 토글

POST
/community/posts/{postId}/likes/toggle

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Response Body

*/*

curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/likes/toggle"
{
  "liked": true,
  "likes": 0
}

교육 콘텐츠 평가

POST
/community/posts/{postId}/evaluations

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

*/*

curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/evaluations" \  -H "Content-Type: application/json" \  -d '{    "score": 1  }'
{
  "success": true,
  "message": "string",
  "data": {}
}

댓글 목록

GET
/community/posts/{postId}/comments

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Query Parameters

page?integer
Default1
Formatint32
size?integer
Default15
Formatint32

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments"
{
  "content": [
    {
      "id": 0,
      "authorId": 0,
      "authorNickname": "string",
      "authorProfileImageUrl": "string",
      "content": "string",
      "createdAt": "2019-08-24T14:15:22Z",
      "parentId": 0,
      "depth": 0,
      "deleted": true,
      "likeCount": 0,
      "liked": true
    }
  ],
  "page": 0,
  "size": 0,
  "totalElements": 0,
  "totalPages": 0
}

댓글/대댓글 작성

POST
/community/posts/{postId}/comments

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

*/*

curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments" \  -H "Content-Type: application/json" \  -d '{    "content": "string"  }'
{
  "id": 0,
  "authorId": 0,
  "authorNickname": "string",
  "authorProfileImageUrl": "string",
  "content": "string",
  "createdAt": "2019-08-24T14:15:22Z",
  "parentId": 0,
  "depth": 0,
  "deleted": true,
  "likeCount": 0,
  "liked": true
}

댓글 수정

PATCH
/community/posts/{postId}/comments/{commentId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64
commentId*integer
Formatint64

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

content*string

Response Body

*/*

curl -X PATCH "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments/0" \  -H "Content-Type: application/json" \  -d '{    "content": "string"  }'
{
  "id": 0,
  "authorId": 0,
  "authorNickname": "string",
  "authorProfileImageUrl": "string",
  "content": "string",
  "createdAt": "2019-08-24T14:15:22Z",
  "parentId": 0,
  "depth": 0,
  "deleted": true,
  "likeCount": 0,
  "liked": true
}

댓글 삭제

DELETE
/community/posts/{postId}/comments/{commentId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64
commentId*integer
Formatint64

Response Body

*/*

curl -X DELETE "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments/0"
{
  "success": true,
  "message": "string",
  "data": {}
}

댓글 좋아요 토글

POST
/community/posts/{postId}/comments/{commentId}/likes-toggle

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

postId*integer
Formatint64
commentId*integer
Formatint64

Response Body

*/*

curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments/0/likes-toggle"
{
  "liked": true,
  "likes": 0
}

인기 자유게시글 목록 조회

GET
/community/home/free-posts

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/home/free-posts"
[
  {
    "id": 0,
    "type": "REVIEW",
    "title": "string",
    "authorId": 0,
    "authorNickname": "string",
    "authorProfileImageUrl": "string",
    "observationSiteId": 0,
    "contentSummary": "string",
    "viewCount": 0,
    "likeCount": 0,
    "commentCount": 0,
    "createdAt": "2019-08-24T14:15:22Z",
    "liked": true,
    "score": 0.1,
    "thumbnailUrl": "string"
  }
]

최신 관측 후기 게시글 홈 화면 조회

GET
/community/home/reviews

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/home/reviews"
[
  {
    "id": 0,
    "type": "REVIEW",
    "title": "string",
    "authorId": 0,
    "authorNickname": "string",
    "authorProfileImageUrl": "string",
    "observationSiteId": 0,
    "contentSummary": "string",
    "viewCount": 0,
    "likeCount": 0,
    "commentCount": 0,
    "createdAt": "2019-08-24T14:15:22Z",
    "liked": true,
    "score": 0.1,
    "thumbnailUrl": "string"
  }
]

최신 교육 게시글 홈 화면 조회

GET
/community/home/educations

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Response Body

*/*

curl -X GET "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/home/educations"
[
  {
    "id": 0,
    "type": "REVIEW",
    "title": "string",
    "authorId": 0,
    "authorNickname": "string",
    "authorProfileImageUrl": "string",
    "observationSiteId": 0,
    "contentSummary": "string",
    "viewCount": 0,
    "likeCount": 0,
    "commentCount": 0,
    "createdAt": "2019-08-24T14:15:22Z",
    "liked": true,
    "score": 0.1,
    "thumbnailUrl": "string"
  }
]

On this page