Skip to content

[3주차] 강지훈/[feat] User, Post, Comment, Report 도메인 API 구현#121

Open
theSnackOverflow wants to merge 7 commits intoLeets-Official:강지훈/mainfrom
theSnackOverflow:강지훈/3주차

Hidden character warning

The head ref may contain hidden characters: "\uac15\uc9c0\ud6c8/3\uc8fc\ucc28"
Open

[3주차] 강지훈/[feat] User, Post, Comment, Report 도메인 API 구현#121
theSnackOverflow wants to merge 7 commits intoLeets-Official:강지훈/mainfrom
theSnackOverflow:강지훈/3주차

Conversation

@theSnackOverflow
Copy link
Copy Markdown
Member

@theSnackOverflow theSnackOverflow commented Apr 7, 2026

1. 과제 요구사항 중 구현한 내용

  • 프로젝트 구조 구성 (도메인별 Controller/Service/Repository 레이어 분리)
  • RESTful API 설계 원칙 적용 (자원 중심 URL, HTTP 메서드로 동작 표현)
  • 요청 데이터 처리 (@RequestParam, @PathVariable, @RequestBody, @RequestHeader)
  • Entity/DTO 분리 및 공통 응답 포맷 (ApiResponse<T>) 적용
  • Bean Validation + 전역 예외처리 (GlobalExceptionHandler) 구현
  • Swagger UI (/swagger-ui.html) 연동

2. 핵심 변경 사항

패키지 구조 개편

  • 기존 평탄 구조(controller/, service/, dto/)를 도메인별 구조(domain/{user,post,comment,report}/)로 전환
  • 공통 모듈을 global/response/, global/exception/으로 분리

공통 인프라

  • global/response/ApiResponse<T>: 공통 응답 래퍼 (success, error 정적 팩토리)
  • global/exception/ErrorCode (enum): HTTP 상태 + 에러 코드 + 메시지 일원화
  • global/exception/GlobalExceptionHandler: BusinessException, Validation, TypeMismatch, MissingHeader, 500 안전망 핸들러 추가

도메인별 API (/api/v1/...)

  • User: POST /users, GET /users/{userId}, PATCH /users/{userId}, DELETE /users/{userId}
  • Post: POST /posts, GET /posts?status=&page=&size=, GET /posts/{postId}, PATCH /posts/{postId}, DELETE /posts/{postId}
  • Comment: POST /posts/{postId}/comments, GET /posts/{postId}/comments, PATCH /comments/{commentId}, DELETE /comments/{commentId}
  • Report: POST /reports, GET /reports

인증 처리: Spring Security 미도입 상태로 작성자 식별은 X-User-Id 헤더로 임시 처리

Jackson snake_case 전역 설정으로 응답 필드 자동 변환

3. 실행 및 검증 결과

로컬에서 H2 인메모리 DB 기반으로 동작 확인 (./gradlew bootRun)

사용자 생성 POST /api/v1/users

// 요청
{ "username": "테스트유저", "email": "test@test.com", "password": "pw1234" }

// 응답
{
  "status": "success",
  "message": "요청이 성공적으로 처리되었습니다.",
  "data": { "user_id": 1, "username": "테스트유저", "email": "test@test.com", "created_at": "..." }
}

게시글 작성 POST /api/v1/posts (X-User-Id: 1)

// 요청
{ "title": "첫 번째 게시글", "content": "내용입니다" }

// 응답
{ "status": "success", "data": { "post_id": 1, "status": "PUBLISHED", ... } }

댓글 + 대댓글 조회 GET /api/v1/posts/1/comments

{
  "data": [{
    "comment_id": 1, "content": "첫 댓글",
    "replies": [{ "comment_id": 2, "content": "대댓글", "parent_comment_id": 1 }]
  }]
}

권한 없는 게시글 수정 → 403

{ "status": "error", "message": "접근 권한이 없습니다." }

빈 제목으로 게시글 작성 → 400

{ "status": "error", "message": "제목은 필수입니다." }
스크린샷 2026-04-07 오후 11 40 59 스크린샷 2026-04-07 오후 11 41 06

4. 완료 사항

  1. 도메인 패키지 구조 전환 및 불필요한 더미 파일 제거
  2. 공통 응답/예외처리 모듈 (global/response, global/exception) 분리
  3. User/Post/Comment/Report 도메인 Repository, Service, Controller, DTO 구현
  4. 각 엔티티에 정적 팩토리 메서드 및 도메인 변경 메서드 추가 (Setter 미사용)
  5. Bean Validation + ErrorCode 기반 전역 예외처리 연동
  6. Jackson snake_case 전역 설정 및 Swagger UI 연동

5. 추가 사항

  • 인증/인가는 현재 X-User-Id 헤더 기반 임시 처리이며, Spring Security 도입 시 교체 예정
  • 신고(Report) 대상 구분은 target_type (POST/COMMENT) 필드로 처리
  • 대댓글은 1뎁스로 제한 (부모 댓글의 대댓글에는 답글 불가)

제출 체크리스트

  • PR 제목이 규칙에 맞다
  • base가 강지훈/main 브랜치다
  • compare가 강지훈/3주차 브랜치다
  • 프로젝트가 정상 실행된다
  • 본인을 Assignee로 지정했다
  • 파트 담당 Reviewer를 지정했다
  • 리뷰 피드백을 반영한 뒤 머지/PR close를 진행한다

- ApiResponse를 dto에서 global/response로 이동
- ErrorCode enum 기반 BusinessException 도입
- BusinessException, MissingRequestHeader, TypeMismatch 등 핸들러 추가
- User 엔티티에 정적 팩토리/update 메서드 추가
- UserRepository, UserService, UserController 작성
- 이메일 중복 검사, Bean Validation 적용
- Post 엔티티에 정적 팩토리/update 메서드 추가
- PostRepository, PostService, PostController 작성
- status/페이지네이션 필터, 작성자 권한 검증
- Comment 엔티티에 정적 팩토리/update 메서드 추가
- CommentRepository, CommentService, CommentController 작성
- 1뎁스 대댓글 제한, 작성자 권한 검증
- Report 엔티티에 정적 팩토리 메서드 추가
- ReportRepository, ReportService, ReportController 작성
- POST/COMMENT 대상 분기 처리 및 검증
@theSnackOverflow theSnackOverflow requested a review from a team April 7, 2026 14:39
@theSnackOverflow theSnackOverflow self-assigned this Apr 7, 2026
@theSnackOverflow theSnackOverflow added the enhancement New feature or request label Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant