17 KiB
17 KiB
feedback.mac.kr 커스텀 Q&A API 연동 작업 목록
목표
- 현재 사이트의 커스텀 Q&A 데이터를
feedback.mac.kr관리 서버로 전송한다. - 기존
egbim/및eng/Q&A 기능은 계속 사용할 수 있어야 한다. - 기존 데이터는 1회 백필하고, 이후 신규 등록·수정·댓글·상태 변경·삭제를 증분 동기화한다.
- 첨부파일과 댓글 이미지는 Cloudflare R2에 저장하고, 관리 서버에는 R2 객체 정보만 전달한다.
- 관리 서버에서 Q&A 본문, 답변/댓글, 첨부파일, 작성자 정보, 상태를 일관되게 조회할 수 있도록 한다.
범위
포함
- 커스텀 Q&A 게시글:
qa_posts - 게시글 첨부파일:
qa_attachments - 댓글/답변:
qa_comments - 댓글 이미지와 썸네일:
qa_comment_images - 댓글 이미지 원본과 썸네일: R2 저장 대상
- 에디터 본문에 삽입된 이미지: R2 저장 대상
- 국문 경로:
egbim/bbs/descope_qa_*.php - 영문 경로:
eng/bbs/descope_qa_*.php
제외
- 그누보드 기본 1:1 문의:
g5_qa_content,g5_qa_config - 쇼핑몰 상품 Q&A:
g5_shop_item_qa - 일반 게시판의 Q&A성 글
- FAQ 및 기타 관리자 데이터
현재 코드 기준 데이터 흐름
| 기능 | 현재 엔드포인트 | 저장 데이터 |
|---|---|---|
| 목록 조회 | bbs/descope_qa_list.php |
qa_posts, 댓글 수, 첨부 수 |
| 상세 조회 | bbs/descope_qa_detail.php |
qa_posts, qa_comments, qa_attachments, qa_comment_images |
| 글 등록/수정 | bbs/descope_qa_write.php |
qa_posts, qa_attachments |
| 댓글 등록 | bbs/descope_qa_comment.php |
qa_comments, qa_comment_images |
| 댓글 수정 | bbs/descope_qa_comment_update.php |
qa_comments |
| 댓글 삭제 | bbs/descope_qa_comment_delete.php |
qa_comments |
| 글 상태 변경 | bbs/descope_qa_status.php |
qa_posts.status |
| 글 삭제 | bbs/descope_qa_delete.php |
게시글·댓글·첨부 삭제 |
| 본문 이미지 업로드 | bbs/descope_qa_img_upload.php |
파일 시스템, 본문 URL |
1. 연동 정책 확정
feedback.mac.kr가 데이터를 받는 방식 확정: Push API 또는 관리 서버의 Pull API- 운영 API Base URL 및 환경별 URL 확정
- 인증 방식 확정: API Key, HMAC 서명, OAuth2 등
- API 버전과 리소스 경로 확정
- 전송 대상 사이트 구분값 확정:
ko,en또는egbim,eng - 관리 서버가 원본 데이터를 저장하는지, 단순 조회 프록시인지 확정
- 삭제 데이터를 실제 삭제할지
deleted상태로 보존할지 확정 - 비밀글의 본문·R2 첨부파일을 관리자 서버에서 어떻게 표시할지 확정
- 개인정보 보관 기간 및 마스킹 정책 확정
권장 동기화 방식
- 최초 1회: 커스텀 Q&A 전체 백필
- 이후: 변경 이벤트를 동기화 큐에 기록한 뒤 API로 재시도 전송
- API 전송 성공 여부는 원본 트랜잭션과 분리해 관리
- 동일 데이터 재전송이 가능하도록
source,source_id,event_id기반 멱등성 보장
2. 원본 데이터 구조 확인
저장소에는 커스텀 테이블의 정식 DDL이 없으므로 실제 운영 DB에서 컬럼, 타입, 인덱스, 기본값을 확인해야 한다.
SHOW CREATE TABLE qa_posts확보SHOW CREATE TABLE qa_comments확보SHOW CREATE TABLE qa_attachments확보SHOW CREATE TABLE qa_comment_images확보- 국문/영문 사이트가 동일 DB와 동일 테이블을 사용하는지 확인
- 각 테이블의 건수와 최대 ID 확인
- 고아 레코드 확인: 게시글 없는 댓글/첨부, 댓글 없는 이미지
- 실제 파일이 없는 첨부 레코드 확인
- DB의 시간대와 API 전송 시간 포맷을
Asia/Seoul기준으로 통일
3. API 데이터 계약 설계
게시글 기본 필드
source:egbim또는engsource_id: 원본qa_posts.post_idcategory:general,improvement,error,notice,admintitlecontentis_secretstatus:new,review,deep,patch,doneis_read_admincreated_at,updated_at
작성자 필드
user_idlogin_iduser_namephone전송 여부 및 마스킹 방식is_internalcompanyfamily_companydepartment- 관리자 표시명 변환 전 원본과 변환 후 표시명 중 무엇을 저장할지 결정
댓글/답변 필드
comment_id- 원본 게시글 ID
commenteruser_namecontentcreated_at,updated_at- 댓글 수정·삭제 여부와 삭제 시각을 보낼 수 있도록 컬럼 또는 이벤트 구조 보완
첨부파일 필드
id또는image_id- 원본 게시글/댓글 ID
ori_name또는file_name- 저장 경로
- 공개 URL 또는 관리 서버용 다운로드 URL
- 파일 크기
- MIME 타입 및 확장자
- 썸네일 URL
uploaded_at- 파일 삭제 여부와 삭제 시각
- 파일 저장소는 Cloudflare R2로 사용
- API에는 파일 자체를 보내지 않고 R2 객체 키·메타데이터를 보낼지 확정
- R2 공개 URL, 커스텀 도메인, presigned URL 중 접근 방식 확정
- 관리 서버가 R2에서 파일을 가져갈 수 있도록 할지, 원본 서버가 임시 URL을 발급할지 결정
4. API 엔드포인트 구현
공통 API 클라이언트
feedback.mac.kr전용 API 클라이언트 작성- Base URL, 인증키, timeout을 환경변수로 분리
- TLS 인증서 검증 활성화
- 요청 ID와 원본 ID를 모든 요청 헤더/본문에 포함
- 연결 실패, 4xx, 5xx, timeout을 구분해 기록
- 재시도 가능한 오류와 즉시 실패해야 하는 오류 구분
- 응답 JSON 스키마 검증
- API 인증키와 개인정보가 로그에 남지 않도록 마스킹
권장 리소스 API
POST /api/v1/qna/sync— 게시글 전체 snapshot upsertPOST /api/v1/qna/events— 등록·수정·댓글·상태·삭제 이벤트 전송POST /api/v1/qna/assets— R2 객체 키와 첨부파일 메타데이터 등록GET /api/v1/qna/sync/status— 백필/증분 동기화 상태 확인- 관리 서버의 실제 계약에 맞춰 경로와 payload 확정
5. 동기화 기록 및 재처리 구조
원본 저장 성공 후 API가 실패해도 사용자 작업이 실패하지 않도록 별도 동기화 기록이 필요하다.
qna_sync_events테이블 설계- 이벤트 종류 정의:
post.created,post.updated,post.deleted,comment.created,comment.updated,comment.deleted,status.changed,attachment.created,attachment.deleted - 원본 테이블명과 원본 ID 저장
- payload 또는 payload 생성에 필요한 snapshot 저장
event_idunique 제약으로 중복 전송 방지- 상태 정의:
pending,sending,sent,failed,dead_letter - 시도 횟수, 마지막 오류, 다음 재시도 시각 저장
- 재처리용 CLI 또는 관리자 실행 도구 작성
- 일정 시간
sending상태로 남은 이벤트 복구 처리 - 삭제 이벤트가 누락되지 않도록 soft-delete 또는 삭제 이력 보존
6. 기존 기능에 이벤트 연결
국문과 영문 코드에 같은 정책을 적용해야 한다.
egbim/bbs/descope_qa_write.php신규 등록 후 이벤트 생성egbim/bbs/descope_qa_write.php수정 후 이벤트 생성eng/bbs/descope_qa_write.php신규 등록 후 이벤트 생성eng/bbs/descope_qa_write.php수정 후 이벤트 생성- 댓글 등록 시 게시글과 댓글 이미지 이벤트 생성
- 댓글 수정 시 수정 이벤트 생성
- 댓글 삭제 시 삭제 이벤트 생성
- 게시글 상태 변경 시 상태 이벤트 생성
- 게시글 삭제 시 게시글·댓글·첨부 삭제 이벤트 순서 정의
- 에디터 이미지 업로드 시 이미지 자산 동기화 정책 적용
- 기존 화면의 저장/리다이렉트/JSON 응답 형식을 깨뜨리지 않는지 확인
트랜잭션 처리 원칙
- 게시글/댓글/첨부 DB 저장과 동기화 이벤트 기록은 동일 DB 트랜잭션으로 처리
- R2 업로드 성공 후 원본 DB에 객체 키를 저장
- 외부 API 호출은 원본 DB 트랜잭션 안에서 직접 실행하지 않음
- 이벤트 기록 성공 후 사용자에게 정상 응답
- 외부 API 실패는 백그라운드 재처리 대상으로 남김
- DB 저장 실패 시 이미 업로드된 R2 객체를 삭제하거나 orphan 정리 큐에 등록
7. 기존 데이터 백필
- 백필 기준 시각과 대상 ID 범위 확정
qa_posts전체를 페이지 단위로 추출- 게시글별
qa_comments추출 - 게시글별
qa_attachments추출 - 댓글별
qa_comment_images추출 - 본문 HTML에 포함된 이미지 URL 추출
- 파일 존재 여부와 파일 크기 검증
- 파일이 없는 레코드는 오류 목록으로 분리
- 원본 ID 보존형 upsert 적용
- 기존 로컬 파일을 R2로 대량 이전
- 대량 R2 업로드 속도 제한 및 실패 재시도 적용
- 백필 중 신규 변경분을 놓치지 않도록 기준 시각 이후 이벤트 재전송
- 백필 종료 후 원본 건수와 관리 서버 건수 대조
8. R2 첨부파일·이미지 처리
게시글 첨부파일, 댓글 이미지 원본·썸네일, 에디터 이미지를 모두 R2에 저장한다. feedback.mac.kr API에는 파일 바이너리 대신 R2 객체 식별자와 메타데이터를 전달하는 방향을 우선한다.
R2 저장 구조
- R2 버킷명과 환경별 버킷 분리 여부 확정
- R2 객체 prefix 확정: 예)
qna/{source}/{post_id}/attachments/ - 댓글 이미지 prefix 확정: 예)
qna/{source}/{post_id}/comments/{comment_id}/images/ - 댓글 썸네일 prefix 확정: 예)
qna/{source}/{post_id}/comments/{comment_id}/thumbs/ - 에디터 이미지 prefix 확정: 예)
qna/{source}/{post_id}/content/ - 동일 파일 재업로드 방지를 위한 object key 또는 content hash 정책 확정
- R2 객체에 원본 파일명, MIME, 크기, source ID를 metadata로 저장
egbim과eng파일의 prefix가 충돌하지 않는지 확인
대상별 이전·저장
- 게시글 첨부 원본 이전:
/egbim/uploads/qa/ - 영문 게시글 첨부 원본 이전:
/eng/uploads/qa/ - 댓글 이미지 원본 이전:
/egbim/uploads/comment/,/eng/uploads/comment/ - 댓글 이미지 썸네일 이전: 각
comment/thumb/경로 - 에디터 이미지 이전:
/egbim/uploads/img/,/eng/uploads/img/ - 기존 DB의
save_path,file_path,thumb_path를 R2 object key와 연결 - 이전 완료 후에도 기존 URL을 일정 기간 유지하거나 redirect 처리
- 실제 파일이 없는 DB 레코드는 오류 목록으로 분리
- R2에만 존재하거나 DB에만 존재하는 orphan 파일 정리
업로드 흐름
- 신규 게시글 첨부는 R2 업로드 성공 후
qa_attachments저장 - 댓글 이미지 원본과 썸네일 생성 후 R2 업로드
qa_comment_images에는 R2 object key와 접근 URL 정보를 저장- 에디터 이미지도 R2 업로드 후 본문에 최종 URL 저장
- R2 업로드 실패 시 Q&A 저장을 실패시키거나 임시 업로드로 분리할지 결정
- DB 저장 실패 시 R2 orphan 정리 작업 등록
- 파일 삭제 시 DB 삭제와 R2 객체 삭제 순서 및 재처리 정책 정의
접근 방식
- 공개 이미지와 비공개 첨부파일의 접근 정책 분리
- 권장안: 비밀글 첨부는 R2 비공개 저장 + 관리 서버 요청 시 짧은 presigned URL 발급
- 공개 가능한 공지 이미지 등은 R2 custom domain/CDN URL 사용 여부 결정
- API payload에는
bucket,object_key,mime_type,file_size,original_name,url또는download_token전달 - presigned URL 만료시간과 재발급 API 정의
- 관리 서버가 원본 사이트 세션 없이도 권한 검사를 통과하는 구조인지 확인
- R2 CORS 정책에 실제 사용 Origin만 등록
- R2 lifecycle 정책: orphan 파일, 임시 업로드, 삭제 보류 파일 정리
코드 정리
- R2 SDK 또는 S3 호환 클라이언트 공통 모듈 작성
- R2 endpoint, access key, secret key, bucket을 환경변수로 분리
- 게시글 첨부·댓글 이미지·에디터 이미지가 같은 업로드 모듈을 사용하도록 통합
- 상대경로와 로컬 절대경로를 R2 object key로 변환하는 마이그레이션 유틸리티 작성
- 파일명 인코딩, 한글 파일명, 특수문자 처리 확인
- 허용 확장자와 MIME 타입을 원본 서버와 R2 업로드 단계에서 검증
9. 보안 및 개인정보
- API 인증정보를 코드에 하드코딩하지 않음
- 운영/개발/로컬 API 키 분리
- API 수신 서버 allowlist 또는 IP 제한 검토
- HMAC 사용 시 timestamp와 nonce 검증
- 재전송 공격 방지
phone,login_id, 이메일 등 개인정보의 전송 범위 확정- IP 주소는 기본적으로 전송하지 않거나 별도 마스킹
- 비밀글 본문과 첨부파일이 공개 URL로 노출되지 않도록 확인
- R2 access key/secret key를 코드와 API payload에 노출하지 않음
- presigned URL이 로그·DB·브라우저에 필요 이상으로 남지 않도록 만료시간 설정
- HTML 본문을 관리 서버에서 출력할 때 XSS 정화 정책 통일
- API 요청/응답 로그에서 본문·첨부 내용·개인정보를 최소화
- API 키 교체 절차와 유출 시 폐기 절차 문서화
10. 관측성 및 운영
- 동기화 성공/실패 건수 모니터링
- 대기 이벤트 수와 가장 오래된 대기 시간을 모니터링
- 연속 실패 시 알림 기준 설정
source_id,event_id,request_id로 양쪽 로그 추적- 백필 진행률과 실패 목록 조회 기능 제공
- API 응답 지연 및 오류율 기록
- 개인정보가 포함된 원문 로그 보관 금지
- 재처리 작업의 중복 실행 방지
11. 테스트 시나리오
기능
- 신규 게시글 등록 → 관리 서버 생성 확인
- 게시글 수정 → 관리 서버 동일 레코드 갱신 확인
- 게시글 상태 변경 → 관리 서버 상태 갱신 확인
- 댓글 등록 → 관리 서버 댓글 생성 확인
- 댓글 수정 → 관리 서버 댓글 갱신 확인
- 댓글 삭제 → 관리 서버 댓글 삭제/숨김 확인
- 게시글 첨부 등록 → 파일과 메타데이터 확인
- 댓글 이미지 등록 → 원본과 썸네일 확인
- 에디터 이미지 등록 → 본문 링크와 파일 확인
- 게시글 삭제 → 관리 서버 삭제 정책 확인
- 비밀글의 본문·첨부 권한 확인
장애·재처리
- 관리 서버 timeout 후 원본 저장 성공 확인
- 500 응답 후 자동 재시도 확인
- 400 응답이 무한 재시도되지 않는지 확인
- 동일 이벤트를 여러 번 보내도 중복 레코드가 생기지 않는지 확인
- API 키 오류 시 사용자 기능과 동기화 실패가 분리되는지 확인
- 이벤트 큐가 쌓인 뒤 정상 복구되는지 확인
- 삭제 직후 재전송 시 최종 상태가 일관적인지 확인
국문/영문
egbim신규/수정/댓글/삭제 흐름 검증eng신규/수정/댓글/삭제 흐름 검증- 관리 서버에서 사이트 구분이 정확한지 확인
- 같은 DB를 공유하는 경우 중복 전송이 발생하지 않는지 확인
12. 완료 기준
- 커스텀 Q&A 전체 데이터의 게시글·댓글·첨부·이미지가 관리 서버에서 조회됨
- 최초 백필 누락 건수가 0건이거나 승인된 예외 목록으로 관리됨
- 신규 등록·수정·댓글·상태 변경·삭제가 정해진 지연시간 내 반영됨
- API 장애가 원본 Q&A 사용을 막지 않음
- 실패 이벤트를 재처리할 수 있음
- 중복 전송에도 관리 서버 데이터가 중복되지 않음
- 비밀글과 개인정보가 정책에 맞게 보호됨
- 국문/영문 양쪽의 테스트가 완료됨
- 운영 배포 및 장애 대응 절차가 문서화됨
우선순위 제안
- 관리 서버 API 계약과 인증 방식 확정
- 네 개 커스텀 테이블의 실제 DDL/건수/파일 현황 확인
- 동기화 이벤트 테이블과 공통 API 클라이언트 구현
- 게시글·댓글 저장 흐름에 이벤트 기록 연결
- R2 업로드 모듈 및 첨부파일/댓글 이미지 이전 구현
- 기존 데이터 백필
- 장애 재처리·모니터링·운영 배포
결정이 필요한 항목
feedback.mac.krAPI 명세 또는 수신 엔드포인트- Push와 Pull 중 최종 방식
- API 인증 방식 및 키 발급 방법
- 게시글·댓글·첨부 삭제 보존 정책
- 개인정보 전송 필드와 마스킹 기준
- R2 버킷, prefix, public/custom domain 정책
- R2 공개 URL과 presigned URL 사용 범위
- R2 첨부파일 전송·삭제·보존 정책
- 국문/영문 데이터가 관리 서버에서 분리되어야 하는지 여부
- API 장애 시 허용 가능한 동기화 지연시간