API 목록 펼치기

시작하기

이 문서는 샵바이 스킨에서 마키나코어 아카이브, 라운지 화면을 만드는 프론트 개발자를 위한 문서입니다. 각 API 의 [보내기]로 실제 응답을 바로 확인하십시오.

1. 기본 주소

http://localhost:4000/api/v1

다른 PC 에서는 http://192.168.17.87:4000 을 쓰십시오. 예: http://192.168.17.87:4000/api/v1/meta

2. 응답 형식

모든 API 는 JSON 으로 답합니다. HTTP 상태 코드와 ok 값을 함께 확인하십시오.

성공

{
  "ok": true,
  "data": "...",
  "meta": {
    "total": 42,
    "page": 1,
    "size": 20,
    "totalPages": 3
  }
}

실패

{
  "ok": false,
  "error": {
    "code": "VALIDATION",
    "message": "입력 값을 확인하십시오.",
    "details": [
      {
        "field": "title",
        "message": "제목을 2자 이상 쓰십시오."
      }
    ]
  }
}

목록 API 는 meta 에 페이지 정보를 줍니다. page 는 1부터 셉니다. size 기본 값은 20, 최대 값은 100 입니다.

3. 인증

  1. 회원이면 요청 헤더에 Authorization: Bearer <샵바이 accessToken> 을 넣으십시오.
  2. 로그인 직후 GET /api/v1/me 를 1번 부르십시오. 처음 온 회원이면 서버가 랜덤 닉네임으로 프로필을 만듭니다.
  3. 비회원이면 Authorization 헤더를 넣지 마십시오. 비회원 식별이 필요하면 X-Anon-Id 헤더에 브라우저에 저장한 임의 문자열을 넣으십시오.

개발 서버는 시험용 토큰을 받습니다. 예: dev-member-1001, dev-member-1002(크루 배지), dev-member-1005(작성 제한). 목록은 GET /api/v1/dev/members 로 받으십시오. 운영 서버에서는 이 토큰을 받지 않습니다.

fetch("http://192.168.17.87:4000/api/v1/me", {
  headers: { Authorization: "Bearer dev-member-1001" },
}).then((r) => r.json());

4. CORS

/api/v1/* 는 다른 출처에서 부를 수 있습니다. 허용 헤더는 Content-Type, Authorization, X-Anon-Id 입니다. 서버는 쿠키를 쓰지 않습니다.

주의: fetch 에 credentials: "include" 를 넣지 마십시오. 서버가 Access-Control-Allow-Credentials 를 보내지 않으므로 브라우저가 응답을 막습니다.

5. 오류 코드

error.codeHTTP뜻
BAD_REQUEST400요청 값이 올바르지 않습니다.
VALIDATION422입력 값을 확인하십시오. details 에 필드별 문구가 옵니다.
UNAUTHORIZED401로그인이 필요합니다. 토큰이 없거나 만료되었습니다.
FORBIDDEN403권한이 없습니다. 예: 남의 글 수정.
NOT_FOUND404대상을 찾을 수 없습니다.
CONFLICT409이미 처리된 요청입니다. 예: 이미 신고, 닉네임 변경 간격.
MEMBER_RESTRICTED403작성이 제한된 회원입니다.
BANNED_WORD422사용할 수 없는 단어가 있습니다.
POLL_CLOSED409참여 기간이 아닙니다.
ALREADY_VOTED409이미 참여했습니다.
NICKNAME_TAKEN409다른 회원이 쓰는 닉네임입니다.
RATE_LIMITED429잠시 후 다시 시도하십시오.
EXTERNAL502외부 시스템(샵바이) 호출에 실패했습니다.
INTERNAL500서버 오류가 발생했습니다.

화면에는 error.message 를 그대로 보여 주십시오. 422 VALIDATION 이면 details 의 field 별 문구를 입력란 아래에 보여 주십시오.

6. 이미지 주소

  1. 응답의 이미지 주소(thumbnailUrl, pcImageUrl, imageUrl, avatarUrl)는 절대 URL 입니다. 그대로 img src 에 넣으십시오.
  2. thumbnailUrl 이 null 이면 기본 썸네일을 그리십시오.
  3. 회원 이미지는 POST /api/v1/uploads 로 1장씩 올리십시오. 응답의 url 을 게시글 imageUrls 에 넣으십시오.
  4. 아카이브는 PC 화면에서 pcImageUrl, 모바일 화면에서 mobileImageUrl 을 쓰십시오.

7. 더 보기

공통

GET/api/v1/meta

코드표 한 번에 받기NEW

인증 없음id: meta

기능 스위치(features), 라운지 탭(loungeTabs), IP 탭, 아카이브 카테고리, 크루 말머리, 신고 사유, 닉네임 규칙을 준다. 앱 시작 때 1번 부르고 저장해 두십시오. features.lounge=false 이면 아카이브만 먼저 연 상태이므로 라운지 메뉴를 숨기십시오. 라운지 탭은 loungeTabs 순서대로 그리십시오. 마키나 랩(2027 고도화)과 건의 별도 탭은 운영 설정에 따라 들어오거나 빠집니다.

NEW 2026-10-29 바뀐 것

  • (5차) nicknameRule.pattern 에 밑줄(_) 추가, changeLimitPer12Months(3), allowedChars
  • (3차) archiveCategories: 운영자가 [IP, 운영 설정]에서 추가, 이름 변경, 삭제합니다. 삭제하면 글에서도 빠집니다. 이 값으로 필터와 말머리를 그리십시오
  • features.archiveTopicFilter: false 이면 주제별 카테고리 필터를 숨기십시오(초기 숨김)
  • archiveCategories[].count: 공개 글 수
  • ips[].iconUrl: IP 탭 동그란 아이콘(캐릭터 얼굴)
  • archiveCategories 에 COLLAB(한정판·컬래버레이션 제작기) 추가
  • defaultThumbnailUrl: 대표 이미지가 없는 글의 기본 썸네일(없으면 null)

응답 예시

{
  "ok": true,
  "data": {
    "analytics": {
      "ga4MeasurementId": "G-CNGFY7HTKQ"
    },
    "features": {
      "openScope": "ALL",
      "archive": true,
      "lounge": true,
      "lab": false,
      "suggestionMode": "CATEGORY",
      "bannedWordMode": "HIDE"
    },
    "mallBaseUrl": "https://machina-core.com",
    "loungeTabs": [
      {
        "value": "ALL",
        "label": "전체"
      },
      {
        "value": "NOTICE",
        "label": "공지"
      },
      {
        "value": "EVENT",
        "label": "이벤트"
      },
      {
        "value": "CREW",
        "label": "마키나 크루"
      }
    ],
    "crewFilterCategories": [
      {
        "value": "POSING",
        "label": "포징"
      }
    ],
    "archiveBlockTypes": [
      {
        "value": "TEXT",
        "label": "본문"
      }
    ],
    "ips": [
      {
        "id": 1,
        "code": "metalcardbot",
        "name": "메탈카드봇",
        "isOwn": true
      }
    ],
    "archiveCategories": [
      {
        "value": "DESIGN",
        "label": "설계와 구조"
      }
    ],
    "boards": [
      {
        "value": "NOTICE",
        "label": "공지"
      }
    ],
    "crewCategories": [
      {
        "value": "POSING",
        "label": "포징"
      }
    ],
    "reportReasons": [
      {
        "value": "ABUSE",
        "label": "비방, 욕설"
      }
    ],
    "nicknameRule": {
      "min": 2,
      "max": 12,
      "pattern": "^[가-힣A-Za-z0-9]+$",
      "changeIntervalDays": 30
    }
  }
}
직접 호출해 보기(Try it)

POST/api/v1/uploads

이미지 올리기(크루 게시글 첨부)

회원 토큰 필수id: upload

multipart/form-data 의 file 필드에 이미지 1장. png, jpg, webp, gif / 10MB 이하. 서버가 webp 로 바꾼다.

응답 예시

{
  "ok": true,
  "data": {
    "url": "http://192.168.17.87:4000/uploads/post/202610/uuid.webp",
    "bytes": 51234,
    "width": 1080,
    "height": 1080,
    "originalName": "pose.jpg"
  }
}

목업 화면에서 보기 (/mock/lounge/write)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/v1/track

가입 완료와 유입 경로 기록

요구사항 ST-03, EX-01선택(회원이면 토큰)id: track

샵바이 회원가입 완료 화면에서 1번 부르십시오. 가입 화면 주소에 source, place 가 있으면 보관했다가 그대로 보내십시오.

요청 본문 필드

이름형식필수설명
typeSIGNUP_COMPLETE예고정 값
sourcearchive|lounge|qr|popup|etc예유입 경로
placestring아니요팝업 QR 이 붙여 준 place 값. QR 주소 /q/{장소} 가 가입 화면 주소에 source, place 를 붙인다
contentIdnumber아니요가입 직전에 보던 아카이브 id

요청 본문 예시

{
  "type": "SIGNUP_COMPLETE",
  "source": "popup",
  "place": "seongsu"
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

회원

GET/api/v1/me

내 라운지 프로필NEW

요구사항 CM-06, LG-05회원 토큰 필수id: me

처음 부르면 서버가 랜덤 닉네임으로 프로필을 만든다. 로그인 직후 1번 부르십시오.

NEW 2026-10-29 바뀐 것

  • (5차) nicknameChange: { initial, remainingIn12Months, limitIn12Months, resetRequired }. resetRequired=true 이면 관리자가 정책 위반으로 닉네임을 바꾼 상태입니다. 닉네임 재설정 안내를 보이십시오(알림 type NICKNAME_RESET)
  • (4차) crew: 크루 이번 달 활동 진행. 크루가 아니면 null. { month, halves[{ key, label, start, end, required, current, count, met }] }. current=true 인 기간의 met=false 이면 "이번 기간 활동을 아직 하지 않았어요" 안내를 보이십시오

응답 예시

{
  "ok": true,
  "data": {
    "memberNo": "1001",
    "nickname": "용감한드라이버1001",
    "crewBadge": null,
    "canChangeNicknameAt": null,
    "restricted": false,
    "restrictedUntil": null,
    "unreadNotificationCount": 2
  }
}

오류

  • 401 UNAUTHORIZED: 토큰이 없거나 만료됨

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)

PATCH/api/v1/me/nickname

닉네임 바꾸기NEW

요구사항 LG-05회원 토큰 필수id: me-nickname

서버가 비속어, 비방어(관리자 금칙어 목록), IP 이름과 같은 닉네임, 관리자 사칭 단어를 검사합니다. 프론트는 따로 검사하지 않아도 됩니다. 어떤 단어에 걸렸는지는 알려 주지 않습니다(우회 방지).

NEW 2026-10-29 바뀐 것

  • (5차) 닉네임 운영 정책: 밑줄(_) 허용. 대소문자, 밑줄만 다른 닉네임도 중복(409 NICKNAME_TAKEN)
  • (5차) 변경 제한: 바꾼 뒤 30일, 최근 12개월 3회(409 CONFLICT, error.details.canChangeAt). 최초 설정은 세지 않음
  • (5차) IP, 캐릭터명은 단독 사용만 막음(블루캅팬은 허용). 공식, 관리자, 마키나크루 등은 조합해도 막음
  • (5차) 응답에 initial, canChangeAt, remainingIn12Months
  • (3차) 닉네임 비속어, 비방어 검사를 서버가 합니다(금칙어 8천여 개)
  • (3차) IP 이름과 같은 닉네임, 관리자로 오해할 수 있는 닉네임(관리자, 운영자, 공식, 마키나 등)은 422 NICKNAME_RESERVED

요청 본문 필드

이름형식필수설명
nicknamestring예2~12자, 한글/영문/숫자/밑줄(_). 바꾼 뒤 30일, 최근 12개월 3회(최초 설정 제외)

요청 본문 예시

{
  "nickname": "블레이드팬"
}

응답 예시

{
  "ok": true,
  "data": {
    "nickname": "블레이드팬"
  }
}

오류

  • 409 NICKNAME_TAKEN
  • 409 CONFLICT: 변경 간격 미충족
  • 422 VALIDATION
  • 422 BANNED_WORD: 비속어, 비방어
  • 422 NICKNAME_RESERVED: IP, 캐릭터명 단독, 운영진, 멤버십 사칭(NEW)
  • 409 CONFLICT: 30일, 12개월 3회 제한(details.canChangeAt)

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/v1/me/nickname

닉네임 미리 검사NEW

요구사항 LG-05회원 토큰 필수id: me-nickname-check

available=false 이면 message 를 입력창 아래에 보여 주십시오. code: VALIDATION(글자 수, 글자 종류) / BANNED_WORD(비속어, 비방어) / NICKNAME_RESERVED(IP 이름, 관리자 사칭) / NICKNAME_TAKEN(다른 회원이 씀). 변경 간격(30일)은 검사하지 않습니다.

NEW 2026-10-29 바뀐 것

  • (3차) 새 API. 닉네임 미리 검사(저장 안 함). 입력창 아래 안내에 쓰십시오

쿼리

이름형식필수설명
nicknamestring예검사할 닉네임

응답 예시

{
  "ok": true,
  "data": {
    "available": false,
    "code": "NICKNAME_RESERVED",
    "message": "IP 이름이나 운영자로 오해할 수 있는 닉네임은 쓸 수 없습니다."
  }
}

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)

GET/api/v1/me/notifications

내 알림 목록

요구사항 LB-02회원 토큰 필수id: me-notifications

link 는 화면 경로 힌트다(/lounge/posts/{id}, /me/points, /archive/{id}). 프론트 라우트에 맞게 바꾸십시오.

쿼리

이름형식필수설명
unreadOnlyboolean아니요true 이면 안 읽은 알림만
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 5,
      "type": "QNA_ANSWERED",
      "typeLabel": "질문 답변",
      "title": "마키나 랩에 내 질문의 답변이 올라왔습니다: ...",
      "link": "/lounge/posts/11",
      "read": false,
      "createdAt": "2026-10-15T08:27:33.850Z"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)

POST/api/v1/me/notifications/read

알림 읽음 처리

회원 토큰 필수id: me-notifications-read

요청 본문 필드

이름형식필수설명
idsnumber[]아니요비우면 모두 읽음

요청 본문 예시

{
  "ids": [
    5
  ]
}

응답 예시

{
  "ok": true,
  "data": {
    "updated": 1
  }
}

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/v1/me/points

내 적립 내역(라운지 보상분)

요구사항 PT-03회원 토큰 필수id: me-points

이 서버가 지급, 회수한 성공 건만 준다. 적립금 잔액은 샵바이 마이페이지 API 를 쓰십시오. meta.totalAmount 는 이 서버 지급 합계다.

쿼리

이름형식필수설명
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 5,
      "date": "2026-10-15T08:27:30.847Z",
      "amount": 500,
      "reason": "기믹 선호도 투표 참여"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)

GET/api/v1/me/questions

내 랩 질문과 처리 상태

요구사항 LB-02회원 토큰 필수id: me-questions

쿼리

이름형식필수설명
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 7,
      "title": "카드 인식 원리",
      "body": "...",
      "productName": "메탈카드봇 블레이드",
      "status": "ANSWERED",
      "statusLabel": "답변 발행",
      "qnaPostId": 11,
      "createdAt": "...",
      "answeredAt": "..."
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/lounge/lab)

직접 호출해 보기(Try it)

GET/api/v1/me/posts

내가 쓴 크루 게시글

회원 토큰 필수id: me-posts

숨김 처리된 글도 status, hiddenReason 과 함께 준다.

쿼리

이름형식필수설명
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

목업 화면에서 보기 (/mock/me)

직접 호출해 보기(Try it)

아카이브

GET/api/v1/archives

아카이브 목록NEW

요구사항 AR-01인증 없음id: archives

NEW 2026-10-29 바뀐 것

  • (3차) 인기순(sort=popular)은 조회 수(회원 + 비회원) 많은 순입니다. 댓글 수는 보지 않습니다
  • (3차) 추천순(sort=recommended)은 운영자가 정한 노출 순서입니다
  • (3차) category 값은 운영자가 관리합니다. meta.archiveCategories 로 그리십시오
  • 고정글은 목록에서 빠짐. GET /api/v1/archives/pinned 로 따로 받아 위에 그리십시오(Figma 댓글: 고정글은 필터 안함)
  • sort=recommended(추천순) 추가
  • 기본 size 10, meta.hasMore: false 이면 [더보기] 숨김
  • 대표 카테고리가 없는 글도 있음(category=null)
  • q: 제목, 요약 검색(Figma 왼쪽 검색창). 결과가 0건이면 Figma 의 "검색 결과 없음" 화면
  • category 는 추가 카테고리(tags)까지 찾음
  • categories[]: 카드 말머리 여러 개(대표 카테고리가 먼저)
  • ip.iconUrl: IP 아이콘

쿼리

이름형식필수설명
ipIdnumber아니요IP 탭(meta.ips[].id)
categoryNEWstring아니요카테고리 코드(meta.archiveCategories[].value). 대표, 추가 카테고리 모두 찾음. 운영자가 추가, 삭제하므로 값을 하드코딩하지 마십시오
sortNEWlatest|recommended|popular아니요최신순(기본) / 추천순(운영자가 정한 노출 순서, 같으면 최신순) / 인기순(조회 수 많은 순, 같으면 최신순). 기획 결정 2026-10-29
qNEWstring아니요제목, 요약 검색. 50자 이하
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 1,
      "title": "메탈카드봇 S3 블레이드, 첫 스케치부터 양산까지",
      "summary": "...",
      "category": "BEHIND",
      "categoryLabel": "제작 비하인드",
      "ip": {
        "id": 1,
        "code": "metalcardbot",
        "name": "메탈카드봇",
        "isOwn": true
      },
      "thumbnailUrl": "http://192.168.17.87:4000/uploads/seed/archive-0-thumb.webp",
      "pinned": true,
      "publishedAt": "...",
      "viewCount": 420,
      "commentCount": 1
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/archive)

직접 호출해 보기(Try it)

GET/api/v1/archives/pinned

아카이브 상단 고정글NEW

요구사항 AR-01인증 없음id: archives-pinned

목록(GET /api/v1/archives) 위에 그리십시오. 목록에는 고정글이 들어가지 않습니다. 최대 20개, 노출 순서(sortOrder) 큰 값이 먼저.

NEW 2026-10-29 바뀐 것

  • 새 API. 상단 고정글을 IP, 주제, 검색 조건과 관계없이 모두 줌(Figma 댓글: 고정글은 필터 안함)

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 1,
      "title": "렉스카이저 블랙에디션이 만들어지기까지",
      "pinned": true,
      "categories": [
        {
          "value": "BEHIND",
          "label": "제작 비하인드"
        }
      ]
    }
  ]
}

목업 화면에서 보기 (/mock/archive)

직접 호출해 보기(Try it)

GET/api/v1/archives/{id}

아카이브 상세(위지윅 본문 html, 비회원은 잠금, 상품 카드, 공유)NEW

요구사항 AR-02, AR-04선택(회원이면 토큰)id: archive-detail

html 은 백오피스 위지윅 편집기(Quill)로 쓴 본문입니다. 서버가 허용한 태그(p, h2, h3, strong, em, u, s, a, blockquote, ul, ol, li, img, iframe, hr)만 남긴 안전한 값입니다. 그대로 innerHTML 로 넣고, 태그별 글꼴과 간격은 스킨 CSS 로 정하십시오. 이미지 주소는 절대 URL 입니다. 유튜브 영상은 iframe(youtube-nocookie) 입니다. 비회원이면 회원 전용 구분선 위까지만 오고, 그 안의 영상은 <div class="mc-video-locked">회원만 재생합니다</div> 로 바뀝니다. lock.locked=true 이면 본문 아래에 잠금 안내와 [로그인] [회원가입] 버튼을 그리고, 버튼은 lock.loginUrl, lock.signupUrl(돌아올 주소 포함)로 보내십시오. relatedProducts 는 샵바이 상품 카드 값입니다(샵바이 호출이 실패하면 name 등이 null). share 는 공유 버튼 값입니다. 조회 수는 같은 회원(또는 같은 X-Anon-Id)이면 하루에 1번만 오릅니다.

NEW 2026-10-29 바뀐 것

  • moreFromIp: 같은 IP 에서 읽고 있는 글 기준 이전 글(먼저 발행한 글) 3개. 가장 오래된 글에 닿으면 최신 글부터 다시 채움(moreFromIp.wrapped=true). 기획 결정 2026-10-29
  • toc[]: 왼쪽 목차. { id, text, level, locked }. html 의 h2, h3 에 같은 id 가 붙음. 비회원에게 잠긴 소제목은 locked=true(자물쇠 표시)
  • lock.teaser: 잠금 안내 강조 문구. "무료 회원가입하고 {teaser}를 모두 볼 수 있어요!"
  • lock.loginUrl, lock.signupUrl: 돌아올 주소가 붙은 버튼 링크
  • navigation.prev, navigation.next: 하단 [이전] [다음] 버튼({ id, title } 또는 null)
  • moreFromIp: 하단 "메탈카드봇 최신 글" 영역({ ip, items[3] })
  • relatedProducts[].brandName, discountRate: 상품 카드 위 브랜드 글, 할인율(%)
  • categories[]: 말머리 여러 개

경로 값

이름형식필수설명
idnumber예콘텐츠 id

응답 예시

{
  "ok": true,
  "data": {
    "id": 1,
    "title": "...",
    "isMember": false,
    "commentEnabled": true,
    "toc": [
      {
        "id": "toc-1",
        "text": "변신의 시작은 카드를 꽂는 손끝에서",
        "level": 2,
        "locked": false
      },
      {
        "id": "toc-2",
        "text": "세 가지 슬롯 방식, 그리고 선택",
        "level": 2,
        "locked": true
      }
    ],
    "categories": [
      {
        "value": "BEHIND",
        "label": "제작 비하인드"
      },
      {
        "value": "COLLAB",
        "label": "한정판·컬래버레이션 제작기"
      }
    ],
    "navigation": {
      "prev": {
        "id": 2,
        "title": "합체 후에도 흔들리지 않는 결합부 설계 노트"
      },
      "next": null
    },
    "moreFromIp": {
      "ip": {
        "id": 1,
        "code": "metalcardbot",
        "name": "메탈카드봇",
        "isOwn": true,
        "iconUrl": "http://192.168.17.87:4000/uploads/ip/ip-metalcardbot.webp"
      },
      "items": [
        {
          "id": 4,
          "title": "...",
          "categories": [
            {
              "value": "SETTING",
              "label": "미공개 설정"
            }
          ]
        }
      ]
    },
    "html": "<h2 id=\"toc-1\">대표 이미지와 도입부</h2><p><img src=\"http://192.168.17.87:4000/uploads/real/p136690811-1.webp\" alt=\"\"></p><p>이 콘텐츠는 <strong>IP 홀더만</strong> 공개하는 자료입니다.</p>",
    "lock": {
      "locked": true,
      "message": "이어지는 내용은 회원만 볼 수 있습니다. 로그인하거나 회원가입하십시오.",
      "teaser": "초기 스케치, 설계도, 목업 비교",
      "loginUrl": "https://machina-core.com/member/login?returnUrl=https%3A%2F%2Fmachina-core.com%2Farchive%2F1",
      "signupUrl": "https://machina-core.com/member/register-term?returnUrl=https%3A%2F%2Fmachina-core.com%2Farchive%2F1&source=archive&contentId=1"
    },
    "relatedProductNos": [
      "136690811"
    ],
    "relatedProducts": [
      {
        "productNo": "136690811",
        "name": "메탈카드봇W 고스트레인",
        "imageUrl": "https://shopby-images.cdn-nhncommerce.com/...jpg",
        "salePrice": 120000,
        "discountedPrice": 95900,
        "soldOut": false,
        "brandName": "메탈카드봇",
        "discountRate": 20,
        "url": "https://machina-core.com/product/136690811"
      }
    ],
    "share": {
      "url": "http://192.168.17.87:4000/s/a/1",
      "title": "...",
      "description": "...",
      "imageUrl": "http://192.168.17.87:4000/uploads/seed/archive-0-thumb.webp"
    }
  }
}

오류

  • 404 NOT_FOUND: 없거나 발행 전

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)

POST/api/v1/archives/{id}/events

전환 측정 이벤트 보내기

요구사항 AR-05, AR-08선택(회원이면 토큰)id: archive-event

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 필드

이름형식필수설명
typeLOCK_IMPRESSION|LOGIN_CLICK|SIGNUP_CLICK|PRODUCT_CLICK|SHARE_CLICK예잠금 안내 노출(콘텐츠당 1회) / 로그인 클릭 / 회원가입 클릭 / 관련 상품 클릭 / 공유 클릭
productNostring아니요PRODUCT_CLICK 일 때 필수
anonIdstring아니요비회원 식별값(선택). X-Anon-Id 헤더로 보내도 된다

요청 본문 예시

{
  "type": "LOCK_IMPRESSION",
  "anonId": "anon-x1y2"
}

응답 예시

{
  "ok": true,
  "data": {
    "recorded": true
  }
}

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/v1/archives/{id}/comments

아카이브 댓글 목록NEW

요구사항 AR-10선택(회원이면 토큰)id: archive-comments

구조는 게시글 댓글과 같다(replies 포함).

NEW 2026-10-29 바뀐 것

  • (3차) mine=true: [내 댓글] 필터. 내가 쓴 댓글과 내가 대댓글을 단 댓글 묶음만 줍니다. 해당 댓글로 이동하는 기능은 만들지 않습니다(기획 결정)
  • 기본 size 10. 댓글은 최신순, 대댓글은 등록순
  • flat=true: 대댓글 포함 10개씩(한 줄씩 펼침, depth 0/1). Figma 댓글: 대댓글 포함 10개 노출
  • meta.totalAll: 대댓글을 포함한 전체 댓글 수(제목 "댓글 62")

경로 값

이름형식필수설명
idnumber예대상 id

쿼리

이름형식필수설명
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100
flatNEWtrue|false아니요true 이면 대댓글 포함 한 줄씩 페이지를 나눔(depth 0/1)
mineNEWtrue|false아니요true 이면 내 댓글만: 내가 쓴 댓글, 내가 대댓글을 단 댓글 묶음. 로그인 필요(없으면 401)

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)

POST/api/v1/archives/{id}/comments

아카이브 댓글 쓰기NEW

요구사항 AR-10회원 토큰 필수id: archive-comment-create

NEW 2026-10-29 바뀐 것

  • 본문 500자 이하(Figma 댓글: 500자 제한). 이미지 첨부 없음

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 예시

{
  "body": "초기 스케치가 멋집니다.",
  "parentId": null
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

PATCH/api/v1/comments/{id}

내 댓글 수정(아카이브, 라운지 공통)NEW

요구사항 AR-10, LG-04회원 토큰 필수id: comment-update

id 는 댓글 목록의 id 입니다. 내 댓글(author.isMe=true)만 고칩니다. 응답은 고친 댓글 1건입니다.

NEW 2026-10-29 바뀐 것

  • (3차) 아카이브 댓글도 이 API 로 수정합니다(아카이브, 라운지 공통)

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 필드

이름형식필수설명
bodystring예1~500자

요청 본문 예시

{
  "body": "고친 내용"
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

오류

  • 401 UNAUTHORIZED
  • 403 FORBIDDEN: 남의 댓글, 숨김된 댓글
  • 403 MEMBER_RESTRICTED
  • 404 NOT_FOUND: 없거나 삭제된 댓글
  • 422 VALIDATION: 500자 초과
  • 422 BANNED_WORD(BLOCK 모드)

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

DELETE/api/v1/comments/{id}

내 댓글 삭제(아카이브, 라운지 공통)NEW

요구사항 AR-10, LG-04회원 토큰 필수id: comment-delete

내 댓글만 지웁니다. 목록에서 '삭제된 댓글입니다.'(status=DELETED, author=null)로 바뀝니다. 대댓글은 남습니다. 대댓글이 없는 삭제 댓글은 목록에서 빠집니다.

NEW 2026-10-29 바뀐 것

  • (3차) 아카이브 댓글도 이 API 로 삭제합니다(아카이브, 라운지 공통)

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

오류

  • 401 UNAUTHORIZED
  • 403 FORBIDDEN: 남의 댓글
  • 403 MEMBER_RESTRICTED
  • 404 NOT_FOUND: 없거나 이미 삭제된 댓글

목업 화면에서 보기 (/mock/archive/1)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

라운지

GET/api/v1/lounge/pinned

라운지 위쪽 고정 게시글NEW

요구사항 LG-01선택(회원이면 토큰)id: lounge-pinned

공지, 이벤트 고정 글과 우수 크루 글(featured=true). 공지, 이벤트, 우수 크루 순서. 최대 10개.

NEW 2026-10-29 바뀐 것

  • ip.iconUrl: IP 아이콘

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

목업 화면에서 보기 (/mock/lounge)

직접 호출해 보기(Try it)

GET/api/v1/posts

게시글 목록(최신순)NEW

요구사항 LG-01, LG-02선택(회원이면 토큰)id: posts

thumbnailUrl 이 null 이면 기본 썸네일을 그리십시오(LG-02). author.type=ADMIN 이면 author.profile(답변 프로필)을 그리십시오.

NEW 2026-10-29 바뀐 것

  • (4차) fanTopic: 공식 팬 토픽 글. 카드에 [공식 팬 토픽] 표시를 붙이십시오. 이 글의 댓글은 크루 활동으로 셉니다

쿼리

이름형식필수설명
tabALL|NOTICE|EVENT|CREW|SUGGESTION|LAB아니요탭. 기본 ALL. meta.loungeTabs 의 value 를 그대로 보내십시오. 마키나 랩이 꺼져 있으면 LAB 은 404 FEATURE_OFF
boardALL|NOTICE|EVENT|LAB|CREW아니요(이전 값) tab 이 없을 때만 읽는다
categoryPOSING|REVIEW|FANART|CUSTOM|SUGGESTION아니요크루 말머리
ipIdnumber아니요IP
qstring아니요제목 검색
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 6,
      "board": "CREW",
      "boardLabel": "마키나 크루",
      "category": "POSING",
      "categoryLabel": "포징",
      "title": "블레이드 전투 포즈 3종",
      "thumbnailUrl": "...",
      "ip": null,
      "author": {
        "type": "MEMBER",
        "nickname": "강철커맨더",
        "crewBadge": "CREW",
        "isMe": false
      },
      "pinned": false,
      "featured": false,
      "hasPoll": false,
      "suggestionStatus": null,
      "likeCount": 3,
      "commentCount": 3,
      "viewCount": 45,
      "createdAt": "..."
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/lounge)

직접 호출해 보기(Try it)

GET/api/v1/posts/{id}

게시글 상세(투표, Q&A, 보상 포함)

선택(회원이면 토큰)id: post-detail

본문은 bodyHtml 을 그리십시오. 공지, 이벤트는 운영자가 위지윅 편집기로 쓴 HTML, 회원 글은 평문을 바꾼 HTML 입니다(bodyFormat=HTML|TEXT). share 는 공유 버튼 값이다(share.url = /s/p/{id} 미리보기 링크). 마키나 랩이 꺼져 있으면 LAB 게시글은 404 다. polls[]: 게시글 안의 투표 문항(2개 이상이면 설문). phase=OPEN 일 때만 참여 버튼을 켜십시오. myVote 가 있으면 참여 완료로 그리십시오. voteCount, ratio, totalVotes 는 결과 공개 시점에만 들어온다. qna 가 있으면 마키나 랩 공식 Q&A 레이아웃(질문 요약 → 답변 프로필 → 답변)으로 그리십시오.

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

{
  "ok": true,
  "data": {
    "id": 2,
    "board": "EVENT",
    "title": "[투표] 이번 주 기믹 선호도 투표",
    "body": "...",
    "images": [],
    "author": {
      "type": "ADMIN",
      "profile": {
        "displayName": "조립 연구원",
        "title": "조립 전문가",
        "avatarUrl": "http://192.168.17.87:4000/uploads/seed/avatar-assembly.webp",
        "badge": "LAB"
      }
    },
    "likedByMe": false,
    "canEdit": false,
    "polls": [
      {
        "id": 1,
        "question": "가장 보고 싶은 기믹을 고르십시오.",
        "type": "SINGLE",
        "maxChoices": null,
        "phase": "OPEN",
        "resultVisibility": "AFTER_CLOSE",
        "startsAt": "...",
        "endsAt": "...",
        "options": [
          {
            "id": 1,
            "label": "카드 슬롯 발광",
            "imageUrl": null
          }
        ],
        "totalVotes": null,
        "myVote": null
      }
    ],
    "reward": {
      "amount": 500,
      "rule": "PARTICIPATION",
      "ruleLabel": "참여",
      "mode": "INSTANT",
      "modeLabel": "즉시 지급",
      "reason": "기믹 선호도 투표 참여"
    },
    "qna": null,
    "share": {
      "url": "http://192.168.17.87:4000/s/p/2",
      "title": "[투표] 이번 주 기믹 선호도 투표",
      "description": "...",
      "imageUrl": null
    }
  }
}

목업 화면에서 보기 (/mock/lounge/2)

직접 호출해 보기(Try it)

POST/api/v1/posts

크루 게시글 쓰기

요구사항 CR-01회원 토큰 필수id: post-create

금칙어 처리 방식(meta.features.bannedWordMode)이 HIDE 이면 금칙어가 있어도 201 로 저장하고 숨긴다. 이때 응답은 { id, status: HIDDEN, moderation: { hidden: true, message } } 이다. message 를 회원에게 보여 주고 내 글 목록으로 보내십시오. BLOCK 이면 422 BANNED_WORD 다.

요청 본문 필드

이름형식필수설명
categoryPOSING|REVIEW|FANART|CUSTOM|SUGGESTION예말머리. SUGGESTION 은 건의
titlestring예2~80자
bodystring예1~5000자. 줄바꿈은 \n
ipIdnumber아니요IP(외부 IP 도 가능)
imageUrlsstring[]아니요POST /api/v1/uploads 응답 url. 최대 10장. 첫 장이 썸네일

요청 본문 예시

{
  "category": "POSING",
  "title": "블레이드 전투 포즈",
  "body": "관절 각도를 바꿔 찍었습니다.",
  "ipId": 1,
  "imageUrls": [
    "http://192.168.17.87:4000/uploads/post/202610/abc.webp"
  ]
}

응답 예시

{
  "ok": true,
  "data": {
    "id": 11,
    "status": "HIDDEN",
    "moderation": {
      "hidden": true,
      "message": "운영 정책에 맞지 않는 단어가 있어 글을 숨겼습니다. 운영자가 확인한 뒤 다시 공개합니다."
    }
  }
}

오류

  • 403 MEMBER_RESTRICTED
  • 422 BANNED_WORD(BLOCK 모드)

목업 화면에서 보기 (/mock/lounge/write)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

PATCH/api/v1/posts/{id}

내 게시글 수정

요구사항 LG-03회원 토큰 필수id: post-update

보낸 필드만 바뀐다. imageUrls 를 보내면 이미지 목록을 통째로 바꾼다.

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 예시

{
  "title": "수정한 제목"
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

DELETE/api/v1/posts/{id}

내 게시글 삭제

요구사항 LG-03회원 토큰 필수id: post-delete

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/v1/posts/{id}/like

좋아요

요구사항 LG-04회원 토큰 필수id: post-like

취소는 같은 경로에 DELETE.

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

{
  "ok": true,
  "data": {
    "liked": true,
    "likeCount": 4
  }
}

목업 화면에서 보기 (/mock/lounge/6)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

DELETE/api/v1/posts/{id}/like

좋아요 취소

요구사항 LG-04회원 토큰 필수id: post-unlike

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

{
  "ok": true,
  "data": {
    "liked": false,
    "likeCount": 3
  }
}
직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/v1/posts/{id}/comments

댓글 목록(대댓글 포함)NEW

요구사항 LG-04선택(회원이면 토큰)id: post-comments

최상위 댓글 기준으로 페이지를 나눈다. 각 댓글의 replies 에 대댓글이 모두 들어 있다. 대댓글은 1단계만 있다. 삭제, 숨김 댓글은 author=null, status 와 안내 문구로 온다.

NEW 2026-10-29 바뀐 것

  • (3차) mine=true: 내 댓글 필터(아카이브와 같음)
  • 아카이브 댓글과 같음: 최신순, flat=true, meta.totalAll

경로 값

이름형식필수설명
idnumber예대상 id

쿼리

이름형식필수설명
pagenumber아니요페이지 번호(1부터). 기본 1
sizenumber아니요페이지 크기. 기본 20, 최대 100
flattrue|false아니요true 이면 대댓글 포함 한 줄씩
mineNEWtrue|false아니요true 이면 내 댓글만(로그인 필요)

응답 예시

{
  "ok": true,
  "data": [
    {
      "id": 1,
      "parentId": null,
      "author": {
        "type": "MEMBER",
        "nickname": "용감한드라이버1001",
        "crewBadge": null,
        "isMe": false
      },
      "body": "두 번째 포즈가 제일 멋집니다.",
      "status": "PUBLISHED",
      "createdAt": "...",
      "updatedAt": "...",
      "replies": [
        {
          "id": 2,
          "parentId": 1,
          "author": {
            "type": "MEMBER",
            "nickname": "강철커맨더",
            "crewBadge": "CREW",
            "isMe": false
          },
          "body": "감사합니다.",
          "status": "PUBLISHED"
        },
        {
          "id": 3,
          "parentId": 1,
          "author": {
            "type": "ADMIN",
            "profile": {
              "displayName": "조립 연구원",
              "title": "조립 전문가",
              "avatarUrl": "http://192.168.17.87:4000/uploads/seed/avatar-assembly.webp",
              "badge": "LAB"
            }
          },
          "body": "우수 게시글 후보로 올렸습니다.",
          "status": "PUBLISHED"
        }
      ]
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "size": 20,
    "totalPages": 1
  }
}

목업 화면에서 보기 (/mock/lounge/6)

직접 호출해 보기(Try it)

POST/api/v1/posts/{id}/comments

댓글, 대댓글 쓰기NEW

요구사항 LG-04회원 토큰 필수id: post-comment-create

응답에 moderation 이 붙는다. 금칙어로 숨겼으면 moderation.hidden=true 와 안내 문구가 온다(HIDE 모드).

NEW 2026-10-29 바뀐 것

  • 본문 500자 이하

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 필드

이름형식필수설명
bodystring예1~500자(NEW: 1000자에서 줄임)
parentIdnumber아니요대댓글이면 부모 댓글 id. 대댓글에 답하면 같은 부모 아래로 붙는다

요청 본문 예시

{
  "body": "동의합니다.",
  "parentId": 1
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

오류

  • 403 MEMBER_RESTRICTED
  • 422 BANNED_WORD(BLOCK 모드)

목업 화면에서 보기 (/mock/lounge/6)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/v1/reports

게시글, 댓글 신고

요구사항 LG-06회원 토큰 필수id: report

같은 대상은 1번만 신고한다. 신고가 기준(기본 3건) 이상이면 서버가 대상을 임시 숨김한다.

요청 본문 예시

{
  "targetType": "POST",
  "targetId": 10,
  "reason": "SALES",
  "detail": "판매 글입니다."
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

오류

  • 409 CONFLICT: 이미 신고
  • 400 BAD_REQUEST: 본인 글

목업 화면에서 보기 (/mock/lounge/6)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/v1/polls/{id}/votes

투표, 설문 문항 답하기

요구사항 VT-02, PT-01회원 토큰 필수id: vote

문항마다 1번만 답한다. 설문은 문항마다 이 API 를 부른다. 즉시 지급 보상이면 모든 문항을 답한 순간 reward 에 지급 결과가 온다.

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 필드

이름형식필수설명
optionIdsnumber[]아니요SINGLE: 1개 / MULTI: 여러 개(maxChoices 이하)
textAnswerstring아니요TEXT(주관식) 문항

요청 본문 예시

{
  "optionIds": [
    3
  ]
}

응답 예시

{
  "ok": true,
  "data": {
    "pollId": 1,
    "optionIds": [
      3
    ],
    "textAnswer": null,
    "reward": {
      "status": "SUCCESS",
      "txnId": 5
    }
  }
}

오류

  • 409 ALREADY_VOTED
  • 409 POLL_CLOSED
  • 422 VALIDATION

목업 화면에서 보기 (/mock/lounge/2)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

공유

GET/s/a/{id}

아카이브 공유 미리보기 페이지(HTML)

요구사항 AR-10인증 없음id: share-archive

API 가 아니라 공유 링크다. og:title, og:image 를 서버에서 그린 HTML 을 주고, 사람은 쇼핑몰 아카이브 상세(설정 archivePath)로 바로 이동한다. 카카오톡, 페이스북 수집기가 이 주소를 열 수 있어야 하므로 운영에서는 공개 도메인(PUBLIC_BASE_URL)에 둡니다.

경로 값

이름형식필수설명
idnumber예콘텐츠 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/s/p/{id}

라운지 게시글 공유 미리보기 페이지(HTML)

요구사항 LG-10인증 없음id: share-post

아카이브 공유 링크와 같다. 쇼핑몰 라운지 상세(설정 loungePath)로 이동한다.

경로 값

이름형식필수설명
idnumber예게시글 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/q/{place}

팝업 QR 주소(장소별 집계 후 가입 화면으로 이동)

요구사항 EX-01인증 없음id: qr

QR 스캔(QR_SCAN)을 장소별로 기록하고 쇼핑몰 회원가입 화면(설정 signupPath)으로 302 이동한다. 이동 주소 뒤에 ?source=popup&place=seongsu 를 붙인다.

경로 값

이름형식필수설명
placestring예장소 값. 영문, 숫자, -, _ 로 40자 이하. 예: seongsu

쿼리

이름형식필수설명
spopup|qr아니요유입 경로. 기본 popup

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

마키나 랩

POST/api/v1/lab/questions

비공개 질문 제출(2027 고도화, 설정으로 켬)

요구사항 LB-01회원 토큰 필수id: lab-question

마키나 랩이 꺼져 있으면(meta.features.lab=false) 404 FEATURE_OFF 다.

요청 본문 필드

이름형식필수설명
titlestring예2~80자
bodystring예5~2000자
productNamestring아니요관련 제품 이름
productNostring아니요샵바이 상품번호(선택)

요청 본문 예시

{
  "title": "카드 인식 원리",
  "body": "카드를 꽂으면 어떻게 인식하나요?",
  "productName": "메탈카드봇 블레이드",
  "productNo": "1001"
}

응답 예시

{
  "ok": true,
  "data": {
    "id": 7,
    "status": "RECEIVED",
    "message": "질문이 접수되었습니다. 답변이 발행되면 알림으로 알려 드립니다."
  }
}

목업 화면에서 보기 (/mock/lounge/lab)

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

개발용

GET/api/v1/dev/members

시험용 회원 토큰 목록(DEV_AUTH=true 일 때만)

인증 없음id: dev-members

Authorization: Bearer dev-member-1001 처럼 쓰십시오. 목록에 없는 번호도 처음 호출할 때 회원이 생긴다. 운영 서버에서는 404.

응답 예시

{
  "ok": true,
  "data": [
    {
      "memberNo": "1001",
      "nickname": "용감한드라이버1001",
      "status": "ACTIVE",
      "crewBadge": null,
      "token": "dev-member-1001"
    }
  ]
}
직접 호출해 보기(Try it)
백오피스 API(참고)사용자 화면에서는 쓰지 않습니다. 백오피스 로그인 쿠키가 필요합니다.

GET/api/admin/me

로그인한 관리자와 연동 상태

백오피스 로그인id: a-me

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/dashboard

처리 대기 건, 오늘, 7일 지표

요구사항 ST-01백오피스 로그인id: a-dashboard

features.openScope=ARCHIVE_ONLY 이면 화면이 archiveToday(아카이브 오늘 지표)를 먼저 보인다.

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/archives

아카이브 목록(상태, 카테고리, IP, 검색)

요구사항 AR-09백오피스 로그인id: a-archives

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

POST/api/admin/uploads

백오피스 이미지 올리기(대표 이미지, 본문 이미지)

백오피스 운영 관리자 이상id: a-admin-upload

multipart/form-data 로 보내십시오. file = 이미지 1장(png, jpg, webp, gif, 10MB 이하), folder = archive. 서버가 webp 로 바꿉니다. 응답의 url 을 thumbnailUrl 이나 본문 HTML 의 img src 에 넣으십시오. 백오피스 편집기는 이미지 단추로 이 API 를 부릅니다.

응답 예시

{
  "ok": true,
  "data": {
    "url": "http://192.168.17.87:4000/uploads/archive/202610/uuid.webp",
    "bytes": 81234,
    "width": 1440,
    "height": 810,
    "originalName": "cover.jpg"
  }
}
직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/admin/archives

아카이브 게시글 등록(임시저장으로 만듦)

요구사항 AR-03백오피스 운영 관리자 이상id: a-archive-create

아카이브 게시글은 운영자가 백오피스 [아카이브] > [새 콘텐츠] 화면(/admin/archives/new)에서 등록합니다. 이 화면이 부르는 API 가 이것입니다. 사용자 화면(쇼핑몰)에서는 부르지 않습니다. 순서: 1) POST /api/admin/uploads 로 이미지를 올린다. 2) 이 API 로 만든다(상태 DRAFT). 3) POST /api/admin/archives/{id}/status {"action":"publish"} 로 발행한다. 발행해야 GET /api/v1/archives 목록에 보입니다. 백오피스 로그인 쿠키(mc_admin)가 필요합니다. 개발 서버는 /admin/login 의 [개발용 로그인]으로 쿠키를 받습니다.

요청 본문 필드

이름형식필수설명
titlestring예2~100자
summarystring아니요목록 카드 요약. 300자 이하
categoryNEWDESIGN|EVOLUTION|SETTING|BEHIND|COLLAB|null아니요대표 카테고리. 없어도 됨(NEW)
tagsNEWstring[]아니요추가 카테고리(말머리 2번째부터)
lockTeaserNEWstring아니요잠금 안내 강조 문구. 60자 이하
ipIdnumber아니요IP(meta.ips[].id)
thumbnailUrlstring아니요목록 대표 이미지. 발행하려면 필수
pinnedboolean아니요목록 맨 위 고정
sortOrdernumber아니요노출 순서. 클수록 앞
commentEnabledboolean아니요댓글 사용. 기본 true
bodyHtmlstring(HTML)예위지윅 본문 HTML. 이미지 묶음(그리드)은 <div class="mc-gallery" data-cols="2|3"><img>...</div>(NEW). 허용 태그만 남기고 저장합니다. <hr class="mc-lock"> = 회원 전용 구분선(1개까지). 유튜브 iframe 은 개인정보 보호 모드 주소로 바뀝니다
productNosstring[]아니요관련 샵바이 상품번호(숫자). 최대 20개

요청 본문 예시

{
  "title": "메탈카드봇 S3 블레이드, 첫 스케치부터 양산까지",
  "summary": "제작진이 직접 공개하는 개발 과정",
  "category": "BEHIND",
  "ipId": 1,
  "thumbnailUrl": "http://192.168.17.87:4000/uploads/archive/202610/cover.webp",
  "pinned": false,
  "sortOrder": 0,
  "commentEnabled": true,
  "bodyHtml": "<p><img src=\"http://192.168.17.87:4000/uploads/archive/202610/cover.webp\"></p><p>이 콘텐츠는 <strong>IP 홀더만</strong> 공개하는 자료입니다.</p><hr class=\"mc-lock\"><h2>초기 디자인과 설계</h2><iframe src=\"https://www.youtube-nocookie.com/embed/aqz-KE-bpKQ\"></iframe>",
  "productNos": [
    "136690811"
  ]
}

응답 예시

{
  "ok": true,
  "data": {
    "id": 5,
    "title": "...",
    "status": "DRAFT",
    "statusLabel": "임시저장",
    "live": false,
    "bodyHtml": "<p>...</p>",
    "productNos": [
      "136690811"
    ]
  }
}

오류

  • 401 UNAUTHORIZED: 백오피스 로그인 필요
  • 403 FORBIDDEN: 열람자 권한
  • 422 VALIDATION: 입력 값 오류(details 확인)
직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/archives/{id}

아카이브 1건(편집용, 발행 전 포함)

백오피스 로그인id: a-archive-get

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

PUT/api/admin/archives/{id}

아카이브 저장(위지윅 본문 통째로)

요구사항 AR-03백오피스 운영 관리자 이상id: a-archive-put

회원 전용 구분선은 1개까지 둡니다. 발행하려면 구분선 위에 글이나 이미지가 있어야 합니다.

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 예시

{
  "title": "...",
  "category": "BEHIND",
  "ipId": 1,
  "thumbnailUrl": "...",
  "bodyHtml": "<p>공개 부분</p><hr class=\"mc-lock\"><p>회원 전용 부분</p>",
  "productNos": [
    "136690811"
  ]
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/admin/archives/{id}/status

발행, 예약 발행, 숨김, 임시저장

요구사항 AR-09백오피스 운영 관리자 이상id: a-archive-status

발행, 예약하려면 목록 대표 이미지가 있고, 회원 전용 구분선 위에 글이나 이미지가 있어야 합니다.

경로 값

이름형식필수설명
idnumber예대상 id

요청 본문 필드

이름형식필수설명
actionpublish|schedule|hide|draft예지금 발행 / 예약 발행 / 숨김 / 임시저장으로
publishAtstring(ISO 8601)아니요schedule 일 때 필수. 예: 2026-11-30T10:00:00+09:00

요청 본문 예시

{
  "action": "publish"
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/admin/archives/bulk

일괄 숨김, 고정, 삭제

요구사항 CM-09백오피스 운영 관리자 이상id: a-archive-bulk

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/posts

라운지 게시글 목록(숨김 포함)

백오피스 로그인id: a-posts

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

POST/api/admin/posts

공지, 이벤트, 연구노트 쓰기(투표, 보상 포함)

요구사항 LG-07, VT-01백오피스 운영 관리자 이상id: a-post-create

공지, 이벤트의 body 는 위지윅 HTML 입니다(bodyFormat=HTML 로 저장). 마키나 랩 글은 평문입니다. 적립금 메뉴를 끈 동안에는 reward 를 넣으면 404 FEATURE_OFF 입니다.

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/admin/posts/{id}/action

숨김, 고정, 삭제, 건의 상태

요구사항 LG-06백오피스 운영 관리자 이상id: a-post-action

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

POST/api/admin/posts/{id}/reward

마감 후 보상 일괄 지급

요구사항 PT-02백오피스 운영 관리자 이상id: a-post-reward

경로 값

이름형식필수설명
idnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/comments

댓글 목록

백오피스 로그인id: a-comments

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

POST/api/admin/comments

관리자 댓글(답변 프로필)

백오피스 운영 관리자 이상id: a-comment-create

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/lab/questions

질문 접수함

요구사항 LB-03백오피스 로그인id: a-questions

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

POST/api/admin/lab/qna

질문 묶어 공식 Q&A 발행

요구사항 LB-04, LB-06백오피스 운영 관리자 이상id: a-qna

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/profiles

답변 프로필 목록

요구사항 LB-05백오피스 로그인id: a-profiles

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/polls

투표, 설문 현황

요구사항 VT-04백오피스 로그인id: a-polls

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/polls/{postId}/export

참여자 명단 엑셀(.xlsx). ?format=csv 이면 CSV. 회원번호 가림

요구사항 VT-04백오피스 운영 관리자 이상id: a-poll-export

경로 값

이름형식필수설명
postIdnumber예대상 id

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/banned-words

금칙어 목록(q 검색, scope ALL|NICKNAME|RESERVED, 페이지). POST 추가(scope, exact), PATCH /{id}, DELETE /{id}, POST /check 닉네임 검사해 보기NEW

요구사항 LG-06백오피스 로그인id: a-banned-words

NEW 2026-10-29 바뀐 것

  • (3차) 검색, 범위, 정확히 일치, 닉네임 검사해 보기

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/crew-activity

크루 월별 활동 현황(?month=YYYY-MM): 전반, 후반 유효 활동 수, 시스템 판정, 검토 대기, 박탈 이력. POST /judge { month } 판정 만들기(검토 대기, 매월 1일 자동). PATCH /decision { month, memberNo, decision, note } 최종 결정 바꾸기. POST /apply { month } 반영. POST /remove { memberNos, reason } 특이 사례 즉시 박탈NEW

백오피스 로그인id: a-crew-activity

NEW 2026-10-29 바뀐 것

  • (4차) 새 API. 크루 활동 기준 확인과 자격 박탈

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/reports

신고 목록(대상별 묶음)

요구사항 LG-06백오피스 로그인id: a-reports

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/members

회원 목록과 활동 수

백오피스 로그인id: a-members

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

GET/api/admin/points

적립금 원장

요구사항 PT-04백오피스 로그인id: a-points

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

POST/api/admin/points

관리자 지급, 회수

요구사항 PT-03백오피스 운영 관리자 이상id: a-points-grant

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/stats

기간 통계

요구사항 ST-02 ~ ST-05백오피스 로그인id: a-stats

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)

PUT/api/admin/settings

운영 설정 바꾸기

백오피스 슈퍼 관리자id: a-settings-put

요청 본문 예시

{
  "key": "openScope",
  "value": "ARCHIVE_ONLY"
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

PUT/api/admin/menus

메뉴 1개 켜고 끄기, 역할 바꾸기

요구사항 CM-03백오피스 슈퍼 관리자id: a-menus-put

끈 메뉴는 화면과 그 메뉴의 API 를 모두 막습니다(404 FEATURE_OFF). 역할이 없으면 403 FORBIDDEN 입니다. 슈퍼 관리자는 켠 메뉴에 항상 들어옵니다. 적립금(points) 메뉴를 끄면 투표 보상 지급과 재처리도 멈춥니다.

요청 본문 예시

{
  "key": "points",
  "enabled": false,
  "roles": [
    "SUPER",
    "OPERATOR"
  ]
}

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)
참고: 실제 데이터가 바뀝니다. 시험 뒤 npm run db:seed 로 되돌리십시오.

GET/api/admin/stats/ga

GA4 사이트 행동(페이지뷰, 사용자, 참여 시간, 이벤트)

요구사항 AR-11, ST-02백오피스 로그인id: a-stats-ga

서버가 GA4 Data API(runReport)를 불러 10분 동안 기억합니다. 아카이브, 라운지 상세 주소(운영 설정의 경로)에서 콘텐츠 id 를 꺼내 제목과 맞춥니다. GA 를 연결하지 않았으면 configured=false, 호출이 실패하면 error 에 이유가 옵니다.

쿼리

이름형식필수설명
fromYYYY-MM-DD아니요시작일(기본 30일 전)
toYYYY-MM-DD아니요종료일(기본 오늘)

응답 예시

{
  "ok": true,
  "data": {
    "configured": true,
    "propertyId": "123456789",
    "measurementId": "G-CNGFY7HTKQ",
    "auth": "OAUTH",
    "error": null,
    "data": {
      "overview": [
        {
          "date": "2026-10-18",
          "activeUsers": 320,
          "sessions": 410,
          "pageViews": 1500,
          "avgEngagementSec": 74,
          "newUsers": 120
        }
      ],
      "archives": [
        {
          "id": 1,
          "title": "...",
          "views": 230,
          "users": 180,
          "avgEngagementSec": 95
        }
      ],
      "posts": [],
      "events": [
        {
          "name": "archive_view",
          "count": 230,
          "users": 180
        }
      ]
    }
  }
}
직접 호출해 보기(Try it)

GET/api/admin/audit

관리 이력

요구사항 CM-04백오피스 운영 관리자 이상id: a-audit

응답 예시

예시가 없습니다. 아래 [보내기]로 실제 응답을 확인하십시오.

직접 호출해 보기(Try it)