1. API 목록
2. POST: 제출물 피드백 작성 (Upsert)
외부멘토가 특정 제출물에 본인 피드백을 작성하여 저장합니다. 본인 피드백이 없으면 생성, 있으면 수정합니다. 첨부파일은 추가(files) / 삭제(removeFileIds)를 함께 처리합니다. (multipart/form-data)
| Parameter | Description |
|---|---|
|
대회 ID |
|
제출물 ID |
| Name | Description |
|---|---|
|
Bearer {accessToken} |
PUT /contests/1/submissions/12/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Authorization: Bearer mentor.access.token
Host: localhost:8080
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=files; filename=피드백.pdf
Content-Type: application/pdf
feedback-content
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--
| Part | Description |
|---|---|
|
신규 추가 첨부파일 (선택, 다중 업로드 허용) |
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
2.1. ⚠️ 실패 케이스
❌ Case 1: 존재하지 않는 제출물
PUT /contests/1/submissions/999/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 59
{
"message" : "존재하지 않는 제출물입니다."
}
❌ Case 2: 본문이 비어있음
PUT /contests/1/submissions/12/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 73
{
"message" : "[description] : 피드백 본문은 필수입니다."
}
❌ Case 3: 존재하지 않는 대회
PUT /contests/999/submissions/12/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 56
{
"message" : "존재하지 않는 대회입니다."
}
❌ Case 4: 빈 파일 첨부
PUT /contests/1/submissions/12/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Authorization: Bearer mentor.access.token
Host: localhost:8080
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=files; filename=빈파일.pdf
Content-Type: application/pdf
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 85
{
"message" : "업로드할 파일이 비어 있거나 존재하지 않습니다"
}
❌ Case 5: 삭제할 첨부파일을 찾을 수 없음
PUT /contests/1/submissions/12/feedbacks HTTP/1.1
Content-Type: multipart/form-data;charset=UTF-8
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 53
{
"message" : "파일을 찾을 수 없습니다"
}
3. GET: 내 피드백 단건 조회
외부멘토가 특정 제출물에 본인이 작성한 피드백 단건을 조회합니다. (작성 폼 프리필용)
| Parameter | Description |
|---|---|
|
대회 ID |
|
제출물 ID |
| Name | Description |
|---|---|
|
Bearer {accessToken} |
GET /contests/1/submissions/12/feedbacks/me HTTP/1.1
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 299
{
"feedbackId" : 50,
"description" : "발표 흐름이 좋네요. 데모 영상 길이만 조금 줄여보세요.",
"createdAt" : "2026-06-02T11:00:00",
"updatedAt" : "2026-06-02T11:00:00",
"files" : [ {
"fileId" : 201,
"fileName" : "피드백.pdf",
"fileSize" : 524288
} ]
}
| Path | Type | Description |
|---|---|---|
|
|
피드백 ID |
|
|
피드백 본문 |
|
|
작성 시각 (ISO-8601) |
|
|
마지막 수정 시각 (ISO-8601) |
|
|
첨부파일 목록 |
|
|
첨부파일 ID |
|
|
첨부파일명 |
|
|
첨부파일 용량 (byte) |
3.1. ⚠️ 실패 케이스
❌ Case 1: 작성한 피드백 없음
GET /contests/1/submissions/12/feedbacks/me HTTP/1.1
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 59
{
"message" : "존재하지 않는 피드백입니다."
}
❌ Case 2: 존재하지 않는 대회
GET /contests/999/submissions/12/feedbacks/me HTTP/1.1
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 56
{
"message" : "존재하지 않는 대회입니다."
}
❌ Case 3: 존재하지 않는 제출물
GET /contests/1/submissions/999/feedbacks/me HTTP/1.1
Authorization: Bearer mentor.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 59
{
"message" : "존재하지 않는 제출물입니다."
}
4. GET: 제출물 피드백 목록 조회 (관리자)
관리자 제출 자료 관리 페이지에서 특정 제출물에 달린 모든 멘토의 피드백 목록을 조회합니다.
| Parameter | Description |
|---|---|
|
대회 ID |
|
제출물 ID |
| Name | Description |
|---|---|
|
Bearer {accessToken} |
GET /contests/1/submissions/12/feedbacks HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 351
[ {
"feedbackId" : 50,
"memberId" : 5,
"memberName" : "이지민",
"description" : "발표 흐름이 좋네요. 데모 영상 길이만 조금 줄여보세요.",
"createdAt" : "2026-06-02T11:00:00",
"updatedAt" : "2026-06-02T11:00:00",
"files" : [ {
"fileId" : 201,
"fileName" : "피드백.pdf",
"fileSize" : 524288
} ]
} ]
| Path | Type | Description |
|---|---|---|
|
|
피드백 목록 |
|
|
피드백 ID |
|
|
작성자 ID |
|
|
작성자 이름 |
|
|
피드백 본문 |
|
|
작성 시각 (ISO-8601) |
|
|
마지막 수정 시각 (ISO-8601) |
|
|
첨부파일 목록 |
|
|
첨부파일 ID |
|
|
첨부파일명 |
|
|
첨부파일 용량 (byte) |
4.1. ⚠️ 실패 케이스
❌ Case 1: 존재하지 않는 대회
GET /contests/999/submissions/12/feedbacks HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 56
{
"message" : "존재하지 않는 대회입니다."
}
❌ Case 2: 존재하지 않는 제출물
GET /contests/1/submissions/999/feedbacks HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 59
{
"message" : "존재하지 않는 제출물입니다."
}
5. GET: 피드백 첨부파일 다운로드 (관리자)
관리자 페이지에서 특정 피드백에 첨부된 파일을 개별 다운로드합니다. `fileId`가 `feedbackId`에, `feedbackId`가 `submissionId`에 속하는지 계층 검증합니다.
| Parameter | Description |
|---|---|
|
대회 ID |
|
제출물 ID |
|
피드백 ID |
|
첨부파일 ID |
| Name | Description |
|---|---|
|
Bearer {accessToken} |
GET /contests/1/submissions/12/feedbacks/50/files/201 HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Disposition: attachment; filename="=?UTF-8?Q?=ED=94=BC=EB=93=9C=EB=B0=B1.pdf?="; filename*=UTF-8''%ED%94%BC%EB%93%9C%EB%B0%B1.pdf
Content-Type: application/pdf;charset=UTF-8
Accept-Ranges: bytes
Content-Length: 13
feedback-file
5.1. ⚠️ 실패 케이스
❌ Case 1: 존재하지 않는 피드백
GET /contests/1/submissions/12/feedbacks/999/files/201 HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 59
{
"message" : "존재하지 않는 피드백입니다."
}
❌ Case 2: 피드백에 속하지 않은 파일
GET /contests/1/submissions/12/feedbacks/50/files/999 HTTP/1.1
Authorization: Bearer admin.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 53
{
"message" : "파일을 찾을 수 없습니다"
}