커뮤니티 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 | 좋아요 토글 |
목록 조회 파라미터
| 파라미터 | 기본값 | 설명 |
|---|---|---|
page | 0 | 페이지 번호 (0부터 시작) |
size | 20 | 페이지 크기 |
sortBy | LATEST | LATEST / VIEWS / LIKES |
keyword | - | 검색어 |
searchBy | TITLE | TITLE / 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 직접 테스트
타입별 목록 조회
Authorization
bearerAuth In: header
Path Parameters
"REVIEW" | "FREE" | "EDUCATION"Query Parameters
0int3220int32"LATEST""LATEST" | "VIEWS" | "LIKES""TITLE""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
}게시글 생성
Authorization
bearerAuth In: header
Path Parameters
"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
}상세 조회
Authorization
bearerAuth In: header
Path Parameters
int64Response 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
}수정
Authorization
bearerAuth In: header
Path Parameters
int64Request 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": {}
}삭제
Authorization
bearerAuth In: header
Path Parameters
int64Response Body
*/*
curl -X DELETE "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0"{
"success": true,
"message": "string",
"data": {}
}좋아요 토글
Authorization
bearerAuth In: header
Path Parameters
int64Response Body
*/*
curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/likes/toggle"{
"liked": true,
"likes": 0
}교육 콘텐츠 평가
Authorization
bearerAuth In: header
Path Parameters
int64Request 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": {}
}댓글 목록
Authorization
bearerAuth In: header
Path Parameters
int64Query Parameters
1int3215int32Response 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
}댓글/대댓글 작성
Authorization
bearerAuth In: header
Path Parameters
int64Request 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
}댓글 수정
Authorization
bearerAuth In: header
Path Parameters
int64int64Request 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/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
}댓글 삭제
Authorization
bearerAuth In: header
Path Parameters
int64int64Response Body
*/*
curl -X DELETE "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments/0"{
"success": true,
"message": "string",
"data": {}
}댓글 좋아요 토글
Authorization
bearerAuth In: header
Path Parameters
int64int64Response Body
*/*
curl -X POST "https://byeoldori-server-hbxnfn4woa-du.a.run.app/community/posts/0/comments/0/likes-toggle"{
"liked": true,
"likes": 0
}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"
}
]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"
}
]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"
}
]