[정다운] sprint5#87
Hidden character warning
Conversation
hagyutae
left a comment
There was a problem hiding this comment.
리뷰 요약
중요
- 현재 스프린트 미션 마다 구현을 mission_# 방식으로 추가하고 있습니다. 이렇게 미션 마다 새로 구현을 추가하는 것이 아니라,
src/하위에 내용을 수정해가면서 진행해야합니다. 팀 내 다른 사람들 진행 방식 참고하셔서 다음 스프린트 미션 때 꼭 적용해주세요.
요구사항 충족 여부
- RESTful API 재설계: 전체적인 REST 구조(리소스 기반 URL, HTTP 메서드 활용, 상태 코드 반환)는 잘 구현되어 있으나, API 스펙과 비교했을 때 HTTP 메서드(PUT vs PATCH), 엔드포인트 경로, 쿼리 파라미터 이름 등에서 불일치가 다수 존재합니다.
- Postman 테스트: PR에 Postman collection JSON이 첨부되어 있어 충족됩니다.
- springdoc-openapi / Swagger:
build.gradle에springdoc-openapi-starter-webmvc-ui의존성이 추가되어 Swagger UI 자동 생성은 가능하나, 컨트롤러에@Operation,@ApiResponse,@Tag등의 Swagger 어노테이션이 전혀 없어 API 문서의 품질이 낮습니다. - 프론트엔드 통합(심화): 정적 리소스 파일이 포함되어 있어 충족됩니다.
- Railway 배포(심화): 미구현 (PR 설명에 명시됨).
주요 문제점
- API 스펙 불일치가 다수 — 수정/업데이트 엔드포인트에서 PUT 대신 PATCH를 사용해야 하고, 경로명과 쿼리 파라미터명이 스펙과 다릅니다. 프론트엔드 연동 시 문제가 됩니다.
- 보안 이슈 — User 엔티티를 그대로 응답하여 password가 JSON에 노출됩니다.
- 빌드 아티팩트/IDE 설정 파일 커밋 —
.gradle/,build/,.idea/,.discodeit/*.ser파일들이 커밋되어 있어 저장소가 불필요하게 비대해집니다. - Swagger 어노테이션 부재 — springdoc 의존성만 추가하고 실제 API 문서화 어노테이션이 없습니다.
| .body(createdUser); | ||
| } | ||
|
|
||
| @PutMapping(value = "/{userId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) |
There was a problem hiding this comment.
API 스펙에서 User 수정은 PATCH /api/users/{userId}로 정의되어 있지만, 여기서는 @PutMapping을 사용하고 있습니다. PUT은 리소스 전체를 교체하는 의미이고, PATCH는 부분 수정입니다. UserUpdateRequest에 newUsername, newEmail, newPassword 등 선택적 필드를 사용하므로 의미상으로도 PATCH가 맞습니다.
@PatchMapping(value = "/{userId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)같은 이유로 UserStatus 업데이트(76번 줄)도 @PatchMapping으로 변경해야 합니다.
| return ResponseEntity.ok(userService.findAll()); | ||
| } | ||
|
|
||
| @PutMapping(value = "/{userId}/status") |
There was a problem hiding this comment.
API 스펙에서는 UserStatus 업데이트 경로가 /api/users/{userId}/userStatus이지만, 현재 구현은 /{userId}/status로 되어 있습니다. 프론트엔드 연동 시 경로 불일치로 동작하지 않을 수 있습니다.
@PatchMapping(value = "/{userId}/userStatus")로 수정하세요.
| import java.util.UUID; | ||
|
|
||
| @Getter | ||
| public class User implements Serializable { |
There was a problem hiding this comment.
보안 이슈: User 엔티티가 password 필드를 포함한 채로 API 응답에 그대로 직렬화됩니다. AuthController.login(), UserController.create(), UserController.update() 모두 User 객체를 반환하므로 비밀번호가 JSON 응답에 노출됩니다.
최소한 password 필드에 @JsonIgnore를 추가하거나, 응답 전용 DTO를 사용하는 것이 좋습니다.
@JsonIgnore
private String password;| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<List<BinaryContent>> findAllByIdIn( |
There was a problem hiding this comment.
API 스펙에서 여러 BinaryContent 조회 시 쿼리 파라미터 이름이 binaryContentIds이지만, 현재 구현은 ids로 되어 있습니다. 프론트엔드와 스펙 준수를 위해 파라미터 이름을 맞춰야 합니다.
@GetMapping
public ResponseEntity<List<BinaryContent>> findAllByIdIn(
@RequestParam("binaryContentIds") List<UUID> binaryContentIds) {| .body(createdMessage); | ||
| } | ||
|
|
||
| @PutMapping("/{messageId}") |
There was a problem hiding this comment.
API 스펙에서 Message 수정은 PATCH /api/messages/{messageId}로 정의되어 있습니다. 현재 @PutMapping으로 되어 있으므로 @PatchMapping으로 변경해야 합니다. 이미 PatchMapping import가 있는 것으로 보아 인지는 하고 계신 것 같은데, 실제 적용이 안 되어 있습니다.
ReadStatusController(37번 줄)와 ChannelController(49번 줄)의 update 메서드도 동일하게 @PatchMapping으로 변경이 필요합니다.
| import org.springframework.web.bind.annotation.RestController; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
||
| @RequiredArgsConstructor |
There was a problem hiding this comment.
[전체] springdoc-openapi 의존성은 추가되어 있지만, 컨트롤러에 @Tag, @Operation, @ApiResponse 등의 Swagger 어노테이션이 전혀 없습니다. 기본 자동 생성 문서만으로는 API 문서의 품질이 낮습니다. 최소한 각 컨트롤러에 @Tag를, 각 엔드포인트에 @Operation(summary = "...")을 추가하여 API 문서를 보강하세요.
@Tag(name = "User", description = "User API")
@RestController
@RequestMapping("/api/users")
public class UserController {
@Operation(summary = "User 등록")
@ApiResponse(responseCode = "201", description = "User가 성공적으로 생성됨")
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<User> create(...) { ... }
}| @@ -0,0 +1,10 @@ | |||
| # Default ignored files | |||
There was a problem hiding this comment.
[전체] mission_4/ 디렉토리에 .gradle/, build/ (컴파일된 .class 파일), .idea/, .discodeit/*.ser (직렬화된 데이터 파일) 등 버전 관리에 포함되면 안 되는 파일들이 대량으로 커밋되어 있습니다. 이들은 .gitignore에 추가하고 Git 추적에서 제거해야 합니다.
특히 .ser 파일은 테스트 중 생성된 로컬 데이터이고, build/ 디렉토리는 빌드 아티팩트이며, .idea/는 IDE 설정 파일입니다. 저장소 용량을 불필요하게 차지하고 다른 개발자 환경과 충돌할 수 있습니다.
| ); | ||
| return Optional.of(binaryContentCreateRequest); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException(e); |
There was a problem hiding this comment.
resolveProfileRequest 메서드에서 IOException 발생 시 RuntimeException으로 감싸서 던지고 있습니다. 이 경우 GlobalExceptionHandler의 Exception 핸들러에 걸려 500 에러가 반환됩니다. 파일 업로드 실패는 클라이언트 입력 문제일 수 있으므로, 좀 더 구체적인 예외(예: IllegalArgumentException)로 변환하거나 적절한 에러 메시지를 포함하는 것이 좋습니다.
MessageController의 84번 줄에도 동일한 패턴이 있습니다.
요구사항
기본
Postman API 테스트 결과를 export하여 PR에 첨부해주세요.
심화
Railway.app은 애플리케이션을 쉽게 배포할 수 있도록 도와주는 PaaS입니다.
[ ] Railway.app에 가입하고, 배포할 GitHub 레포지토리를 연결하세요.
[ ] Settings > Network 섹션에서 Generate Domain 버튼을 통해 도메인을 생성하세요.
[ ] 생성된 도메인에 접속해 배포된 애플리케이션을 테스트해보세요.
주요 변경사항
Mission_5.postman_collection.json
스크린샷
-Postman 결과 일부


-Swagger-UI 활용 결과 일부



-심화 요구사항 : 화면 가이드



멘토에게