Conversation
…ctor/homeCreate
- HomeCreateRequestDto, HomeUpdateRequestDto 신규 생성 - HomeCreateDTO에서 imageUrls 필드 제거 (파일 업로드만 지원) - HomeImageVO 필드명 수정 (ImageUrl → imageUrl) - Swagger 어노테이션 추가 및 예제값 설정
- selectHomeFacilitiesByHomeDetailId 중복 제거 - selectHomeMaintenanceFeesByHomeId 중복 제거 - selectFacilityCategories 중복 제거 - selectFacilityItemsByCategoryId 중복 제거 - incrementViewCount 중복 제거
- HomeController 인터페이스 정의 - HomeControllerImpl 구현 클래스 생성 - API 정의와 비즈니스 로직 분리 - 테스트 가능성 및 유지보수성 향상
- 불필요한 디버깅 로그 제거
- 이미지 업로드 로직 단순화
- S3 경로 처리 개선 (home/{homeId}/{fileName} 형식)
- 에러 처리 및 로깅 메시지 최적화
- updateHome 메서드에 이미지 파라미터 추가 - 매물 수정 시 이미지 업로드 기능 지원
- 메서드 호출 공백 일관성 개선 - 코드 포맷팅 통일
- LocalDateTime.toLocalDate() 호출 제거 - buildDate가 이미 LocalDate 타입으로 처리되도록 수정
- HomeCreateRequestDto/HomeUpdateRequestDto import 경로 수정 - buildDate 타입을 LocalDateTime에서 LocalDate로 변경 - 필드명 매핑 수정 (bathroomCount -> bathroomCnt, isParkingAvailable -> isParking) - MaintenanceFeeDTO를 MaintenanceFeeItem으로 변환하는 로직 추가 - Integer를 Long으로 변환하는 로직 추가
- multipart/form-data에서 LocalDate 타입 변환 지원 - ISO_LOCAL_DATE 포맷 (yyyy-MM-dd) 처리 - 빈 문자열 처리 지원
… into refactor/homeCreate
Walkthrough홈 도메인 전반을 DTO/VO 기반으로 재구성하고, 컨트롤러를 인터페이스+구현 클래스로 분리했습니다. 매퍼(Java/XML), 서비스(API/구현), DTO/VO, enum을 대폭 변경·추가했으며, 이미지 업로드(S3 서비스 인터페이스)·시설/유지비/좋아요·검색/카운트 기능을 통합했습니다. ServletConfig에 LocalDate 컨버터가 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant HomeControllerImpl
participant HomeService
participant HomeMapper
participant S3 as S3Service
Client->>HomeControllerImpl: POST /api/homes (multipart form)
HomeControllerImpl->>HomeService: createHome(createDTO, images, userId)
HomeService->>HomeMapper: insertHome(HomeVO)
HomeService->>HomeMapper: insertHomeDetail(HomeDetailVO)
HomeService->>HomeMapper: insertHomeFacility(...)*N
HomeService->>HomeMapper: insertHomeMaintenanceFee(...)*M
alt images present
HomeService->>S3: upload(image)*K
S3-->>HomeService: url
HomeService->>HomeMapper: insertHomeImage(url)*K
end
HomeService-->>HomeControllerImpl: homeId
HomeControllerImpl-->>Client: ApiResponse(homeId)
sequenceDiagram
autonumber
participant Client
participant HomeControllerImpl
participant HomeService
participant HomeMapper
Client->>HomeControllerImpl: GET /api/homes/search?...
HomeControllerImpl->>HomeService: searchHomes(searchDTO)
HomeService->>HomeMapper: selectHomeListByCondition(searchDTO)
HomeMapper-->>HomeService: List<HomeVO>
loop for each home
HomeService->>HomeMapper: selectHomeImagesByHomeId(homeId)
end
HomeService-->>HomeControllerImpl: List<HomeResponseDTO>
HomeControllerImpl-->>Client: PageResponse(payload, counts)
sequenceDiagram
autonumber
participant Client
participant HomeControllerImpl
participant HomeService
participant HomeMapper
Client->>HomeControllerImpl: POST /api/homes/{id}/like
HomeControllerImpl->>HomeService: toggleHomeLike(userId, homeId)
HomeService->>HomeMapper: selectHomeLikeExists(userId, homeId)
alt exists
HomeService->>HomeMapper: deleteHomeLike(userId, homeId)
else not exists
HomeService->>HomeMapper: insertHomeLike(userId, homeId)
end
HomeService-->>HomeControllerImpl: Void
HomeControllerImpl-->>Client: ApiResponse(Void)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 20
🔭 Outside diff range comments (1)
src/main/java/org/scoula/domain/fraud/service/AiFraudAnalyzerService.java (1)
310-323: home 조회 null 처리 누락: NPE 위험 (homeId null 케이스 포함)
findHomeById가 null을 반환해도 예외가 발생하지 않아, 아래의home.get...에서 NPE가 발생합니다. 또한homeId자체가 null일 수 있는 경우도 선제 차단 필요합니다.다음과 같이 방어 코드를 추가해 주세요.
Long homeId = request.getHomeId(); - HomeVO home = null; - try { - home = homeMapper.findHomeById(homeId); - } catch (Exception e) { - throw new BusinessException(FraudErrorCode.INVALID_HOME_ID); - } + if (homeId == null) { + throw new BusinessException(FraudErrorCode.INVALID_HOME_ID); + } + HomeVO home; + try { + home = homeMapper.findHomeById(homeId); + } catch (Exception e) { + throw new BusinessException(FraudErrorCode.INVALID_HOME_ID); + } + if (home == null) { + throw new BusinessException(FraudErrorCode.INVALID_HOME_ID); + } request.setAddress(home.getAddr1() + " " + home.getAddr2()); request.setPropertyPrice(home.getDepositPrice()); request.setMonthlyRent(home.getMonthlyRent() != null ? home.getMonthlyRent() : 0); request.setLeaseType(home.getLeaseType().toString()); request.setResidenceType(home.getResidenceType().toString()); request.setRegisteredUserName(home.getUserName());
🧹 Nitpick comments (32)
src/main/java/org/scoula/domain/home/enums/HomeStatus.java (1)
26-39: from(...)이 라벨만 허용 — enum 키(AVAILABLE/RESERVED/CONTRACTED)도 허용하도록 확장 제안현재는 "입주가능/예약중/계약완료" 라벨만 역직렬화됩니다. 키 문자열(예: "CONTRACTED")도 허용하면 프론트·DB·테스트 데이터의 혼용을 안전하게 흡수할 수 있습니다.
아래처럼 키 매칭(대소문자 무시)을 추가해 주세요.
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) public static HomeStatus from(String value) { - if (value == null || value.trim().isEmpty()) { - throw new IllegalArgumentException("매물 상태 값이 null이거나 비어있습니다."); - } - - String trimmedValue = value.trim(); - for (HomeStatus status : values()) { - if (status.description.equals(trimmedValue)) { - return status; - } - } - throw new IllegalArgumentException("알 수 없는 매물 상태입니다: " + value); + if (value == null || value.trim().isEmpty()) { + throw new IllegalArgumentException("매물 상태 값이 null이거나 비어있습니다."); + } + final String trimmed = value.trim(); + for (HomeStatus status : values()) { + // 1) 한글 라벨 매칭 + if (status.getDescription().equals(trimmed)) { + return status; + } + // 2) enum 키 매칭 (대소문자 무시) + if (status.name().equalsIgnoreCase(trimmed)) { + return status; + } + } + throw new IllegalArgumentException("알 수 없는 매물 상태입니다: " + value); }src/main/java/org/scoula/global/config/ServletConfig.java (1)
81-94: LocalDate 바인딩: Converter 대신 표준 Registrar 사용 권장(간결/일관)Spring 표준 Registrar를 사용하면 ISO 형식 바인딩을 일관되게 적용하고, 코드가 간결해집니다. 현재 구현도 동작은 하지만 유지보수 관점에서 Registrar가 더 낫습니다.
아래처럼 교체를 제안합니다.
@Override public void addFormatters(FormatterRegistry registry) { - // LocalDate converter for form data - registry.addConverter( - new Converter<String, LocalDate>() { - @Override - public LocalDate convert(String source) { - if (source == null || source.trim().isEmpty()) { - return null; - } - return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE); - } - }); + // LocalDate: ISO-8601 (yyyy-MM-dd) + org.springframework.format.datetime.standard.DateTimeFormatterRegistrar registrar = + new org.springframework.format.datetime.standard.DateTimeFormatterRegistrar(); + registrar.setUseIsoFormat(true); + registrar.registerFormatters(registry); }추가로, Converter 방식을 유지한다면 잘못된 날짜 형식에 대한 예외 메시지를 명확히 하여 400 Bad Request로 매핑되도록 하는 것도 좋습니다(바인딩 오류 가독성 향상).
- return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE); + try { + return LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE); + } catch (java.time.format.DateTimeParseException e) { + throw new IllegalArgumentException("유효하지 않은 날짜 형식입니다(예: 2024-12-31): " + source, e); + }참고: Registrar 사용 시에는 별도 예외 처리가 기본 바인딩 오류로 위임됩니다.
src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (1)
5-10: Lombok 중복 사용(@DaTa + @Getter/@Setter) — 불필요한 중복 제거 권장@DaTa가 이미 getter/setter/equals/hashCode/toString를 생성합니다. @Getter/@Setter는 중복이므로 제거하면 가독성과 일관성이 좋아집니다.
-@Data -@Getter -@Setter +@Data @AllArgsConstructor @NoArgsConstructor @Builder public class HomeImageVO {src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
5-10: Lombok 중복 사용(@DaTa + @Getter/@Setter) — 불필요한 중복 제거 권장여기도 @DaTa만으로 충분합니다.
-@Data -@Getter -@Setter +@Data @AllArgsConstructor @NoArgsConstructor @Builder public class FacilityCategory {src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
5-10: Lombok 중복 사용(@DaTa + @Getter/@Setter) — 불필요한 중복 제거 권장중복 어노테이션 제거로 간결화해 주세요.
-@Data -@Getter -@Setter +@Data @AllArgsConstructor @NoArgsConstructor @Builder public class FacilityItem {src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
3-10: Lombok 중복 사용 및 와일드카드 import 정리 제안@DaTa는 @Getter/@Setter를 포함하므로 중복입니다. 또한 와일드카드 import는 유지보수성 측면에서 지양하는 것이 좋습니다.
아래처럼 정리 권장:
-import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; -@Getter -@Settersrc/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
66-73: 중복 중첩 DTO 제거: MaintenanceFeeDTO 공용 클래스로 추출 권장Create/Update DTO 양쪽에 동일한 중첩 클래스가 중복 정의되어 있습니다. 상위 패키지의 공용 DTO로 추출하면 중복 제거와 스키마 일관성 유지에 유리합니다.
예시(신규 파일):
// src/main/java/org/scoula/domain/home/dto/MaintenanceFeeDTO.java package org.scoula.domain.home.dto; import lombok.*; @Data @NoArgsConstructor @AllArgsConstructor @Builder public class MaintenanceFeeDTO { private Integer maintenanceId; private Integer fee; }그 후 본 파일과 Update DTO에서는
List<MaintenanceFeeDTO>를 import 하여 사용하세요.
23-65: 유효성 검증 추가 고려주요 필드에 Bean Validation을 부여하면 조기 검증과 문서화 품질이 향상됩니다. 실제 요구사항에 따라 최소한 아래 항목 검토를 권장합니다.
src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java (1)
25-25: DTO 명명 컨벤션 통일 필요: HomeUpdateRequestDto → HomeUpdateRequestDTO아래 파일들에서 클래스명과 파일명을
HomeUpdateRequestDTO로 변경하고, 관련 import 및 사용처도 일괄 업데이트해주세요.
- src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java
• 클래스 선언(25행)
• 파일명 →HomeUpdateRequestDTO.java- src/main/java/org/scoula/domain/home/controller/HomeController.java
• import 선언(10행)
• 메서드 시그니처 내 사용(@ModelAttribute, 59행)- src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
• import 선언(12행)
• 메서드 시그니처 내 사용(150행)-public class HomeUpdateRequestDto { +public class HomeUpdateRequestDTO {src/main/java/org/scoula/domain/home/enums/HomeDirection.java (1)
27-29: from(String) 개선 제안: 키/설명 모두 허용현재 @JsonCreator는 한글 설명값만 허용합니다. 클라이언트가
E/SE...키를 보낼 가능성까지 고려해 키와 설명을 모두 수용하도록 개선하면 호환성이 좋아집니다.예시 구현(참고용):
@JsonCreator public static HomeDirection from(String value) { if (value == null) throw new IllegalArgumentException("Unknown home direction: null"); // 키 시도 try { return HomeDirection.valueOf(value.trim().toUpperCase()); } catch (IllegalArgumentException ignore) { // 설명 매칭 for (HomeDirection direction : HomeDirection.values()) { if (direction.getDescription().equals(value)) { return direction; } } } throw new IllegalArgumentException("Unknown home direction: " + value); }src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
5-12: Lombok 중복 사용 및 와일드카드 import 정리 제안@DaTa는 @Getter/@Setter를 포함합니다. 와일드카드 import도 명시 import로 정리하는 것이 좋습니다.
-import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; -@Getter -@Settersrc/main/java/org/scoula/domain/home/vo/HomeVO.java (2)
11-16: Lombok 어노테이션 중복 (@DaTa + @Getter/@Setter)@DaTa가 이미 getter/setter/toString/equals/hashCode 등을 생성하므로 @Getter/@Setter는 제거 가능합니다. 중복은 해롭진 않지만 노이즈를 줄이는 편이 좋습니다.
적용 예:
@Data -@Getter -@Setter @AllArgsConstructor @NoArgsConstructor @Builder
32-37: 면적 타입 Float 사용은 정밀도 문제 유발 가능성 (Double/BigDecimal 고려)면적(supplyArea, exclusiveArea, area)은 UI/계약서 표기에 정밀도가 중요한 경우가 많습니다. Float 보다는 Double(또는 회계적 정밀도가 필요하면 BigDecimal) 사용을 권장합니다.
적용 예:
- private Float supplyArea; + private Double supplyArea; ... - private Float exclusiveArea; + private Double exclusiveArea; ... - private Float area; + private Double area;src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (2)
9-14: Lombok 어노테이션 중복 (@DaTa + @Getter/@Setter)@DaTa로 충분하며 @Getter/@Setter는 불필요합니다.
적용 예:
@Data -@Getter -@Setter @AllArgsConstructor @NoArgsConstructor @Builder
25-27: 면적 Float 정밀도 고려 및 필드 중복 설계 점검
- 면적(area)은 Float 대신 Double/BigDecimal 고려를 권장합니다.
- area/landCategory/homeFloor 등이 HomeVO에도 존재합니다. 도메인 분리가 의도된 것인지(요약 vs 상세) 명확하면 좋겠습니다.
도메인 경계 확인: HomeVO와 HomeDetailVO 간 중복 필드가 설계적으로 의도된 것인지 확인해 주세요.
src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java (1)
98-99: 이미지 업로드 제약 검토(개수/용량/확장자)API 요청 DTO 차원에서
@Size(max = N)등 기본 제약을 두는 것이 운영 안정성에 유리합니다. 서비스 레벨의 S3 업로드 정책과 함께 정합적으로 적용을 권장합니다.@ApiModelProperty(value = "매물 이미지 목록") - private List<MultipartFile> images; + @Size(max = 10) + private List<MultipartFile> images;src/main/java/org/scoula/domain/fraud/service/AiFraudAnalyzerService.java (1)
565-571: AI 요청 전문(JSON) 디버그 로그는 PII 노출 가능성 있음전체 요청을 그대로 로그로 남기면 주소/이름 등 민감정보가 포함될 수 있습니다. 운영 환경에서는 마스킹/필드 선택 로깅 또는 로그 레벨 하향(TRACE) 전환을 권장합니다.
적용 예(요약 필드만 출력 또는 비활성화):
- String requestJson = mapper.writeValueAsString(aiRequest); - log.debug("[디버깅] AI 서버 전송 데이터: {}", requestJson); + // 민감정보 최소화: 요약 정보만 로깅 + log.debug("[디버깅] AI 서버 전송 요약 - homeId: {}, leaseType: {}, residenceType: {}", + LogSanitizerUtil.sanitizeValue(aiRequest.getHomeId()), + LogSanitizerUtil.sanitizeValue(aiRequest.getLeaseType()), + LogSanitizerUtil.sanitizeValue(aiRequest.getResidenceType()));src/main/java/org/scoula/domain/home/dto/HomeSearchDTO.java (2)
46-49: 페이지네이션 파라미터 검증 추가 제안 (@min, 상한 설정)page/size에 대한 유효성 검증이 없어 음수/과도한 값이 들어오면 성능/오류를 유발할 수 있습니다. Bean Validation으로 최소/최대 값을 제한하세요.
다음 어노테이션 추가를 제안합니다(Controller의 @validated와 함께 사용 권장):
- private Integer page = 1; - private Integer size = 21; + @javax.validation.constraints.Min(1) + private Integer page = 1; + @javax.validation.constraints.Min(1) + @javax.validation.constraints.Max(100) + private Integer size = 21;필요 시 javax.validation.constraints.* 임포트를 파일 상단에 추가하세요.
55-57: 오프셋 계산 방어 로직 추가page가 0 이하일 경우 음수 오프셋이 발생합니다. 방어적으로 0 이상으로 고정하세요.
- return (page - 1) * size; + return Math.max(0, (page - 1) * size);src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (2)
35-35: 오탈자: maintenaceFee → maintenanceFee (API/도메인 전반 오염 가능)필드명이 오탈자로 고정되어 있습니다. 외부 API/DB 매핑에 퍼지기 전에 정정하는 것을 권장합니다.
리네이밍에는 범위가 크므로 단계적 적용을 권장합니다:
- DTO 필드명을 maintenanceFee로 변경하고, Jackson 사용 시 @JsonAlias("maintenaceFee")로 하위호환 유지
- Service/VO/Mapper의 동일 오탈자도 일괄 정정
원하시면 전체 리팩터링용 변경 스크립트/PR 패치를 도와드리겠습니다.
54-59: 컬렉션 필드 null 회피를 위한 기본값 권장facilities/maintenanceFees/imageUrls가 null이면 클라이언트에서 방어 코드가 필요합니다. 빌더 기본값으로 빈 리스트를 제공하세요.
- private List<FacilityItem> facilities; + @Builder.Default + private List<FacilityItem> facilities = new java.util.ArrayList<>(); private String description; - private List<HomeMaintenanceFeeVO> maintenanceFees; + @Builder.Default + private List<HomeMaintenanceFeeVO> maintenanceFees = new java.util.ArrayList<>(); - private List<String> imageUrls; + @Builder.Default + private List<String> imageUrls = new java.util.ArrayList<>();src/main/java/org/scoula/domain/home/service/HomeService.java (2)
12-59: 서비스 네이밍 컨벤션 미준수 (Interface 접미사 누락)가이드라인에 따르면 서비스는
*ServiceInterface/*ServiceImpl패턴을 사용해야 합니다. 현재 인터페이스명이HomeService입니다.
- 인터페이스를
HomeServiceInterface로 리네임하고 구현체는HomeServiceImpl유지- 컨트롤러/구현체 의존성 주입 시 타입도 함께 수정
큰 변경이므로 범위 조정 필요 시 알려주세요.
34-36: status를 String으로 받는 인터페이스는 타입 안정성 부족 — Enum 사용 권장상태 전환은 HomeStatus로 한정하는 것이 안전합니다. 유효하지 않은 문자열 유입을 컴파일 타임에 차단하세요.
- void updateHomeStatus(Integer homeId, String status, Integer userId); + void updateHomeStatus(Integer homeId, HomeStatus status, Integer userId);컨트롤러 @RequestParam도 Enum으로 매핑하거나, 문자열 입력 시 Enum 변환/검증 로직을 추가해야 합니다.
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java (5)
31-35: Swagger 문서화 어노테이션 누락 (팀 러닝/가이드라인 불일치)컨트롤러 엔드포인트에 Swagger 어노테이션이 없습니다. 팀 가이드라인/러닝에 따라 @Tag/@operation 등을 추가해 주세요.
예시(클래스 및 한두 개 메서드에 적용, 나머지 동일 패턴으로 확장):
@Log4j2 @RestController @RequestMapping("/api/homes") @RequiredArgsConstructor +@io.swagger.v3.oas.annotations.tags.Tag(name = "Homes", description = "매물 API") public class HomeControllerImpl implements HomeController {@Override @PostMapping(consumes = "multipart/form-data") + @io.swagger.v3.oas.annotations.Operation(summary = "매물 등록", description = "매물과 이미지를 등록합니다.") public ResponseEntity<ApiResponse<Integer>> createHome( @Valid @RequestPart HomeCreateRequestDto requestDto, Authentication authentication) {@Override @GetMapping("/{homeId}") + @io.swagger.v3.oas.annotations.Operation(summary = "매물 상세 조회") public ResponseEntity<ApiResponse<HomeResponseDTO>> getHome(@PathVariable Integer homeId) {필요 시 공통 ApiResponse 스키마도 @ApiResponses로 기술해 주세요.
110-124: 페이지 응답 래퍼 불일치 — 모든 엔드포인트에서 ApiResponse 일원화 권장가이드라인상 모든 응답을 ApiResponse로 감싸야 합니다. 현재 getHomeList는 PageResponse를 직접 반환합니다.
- public ResponseEntity<PageResponse<HomeResponseDTO>> getHomeList( + public ResponseEntity<ApiResponse<PageResponse<HomeResponseDTO>>> getHomeList( @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "21") int size) { @@ - return ResponseEntity.ok(PageResponse.of(homes, pageRequest, totalCount)); + return ResponseEntity.ok(ApiResponse.success(PageResponse.of(homes, pageRequest, totalCount))); }searchHomes에도 동일하게 적용해 주세요.
126-144: searchHomes도 ApiResponse 래퍼 적용 필요위 코멘트와 동일한 이유로 ApiResponse로 래핑하여 일관성 유지하세요.
- public ResponseEntity<PageResponse<HomeResponseDTO>> searchHomes( + public ResponseEntity<ApiResponse<PageResponse<HomeResponseDTO>>> searchHomes( @ModelAttribute HomeSearchDTO searchDTO) { @@ - return ResponseEntity.ok(PageResponse.of(homes, pageRequest, totalCount)); + return ResponseEntity.ok(ApiResponse.success(PageResponse.of(homes, pageRequest, totalCount))); }
45-48: 민감/대용량 필드 로깅 레벨 하향 (PII/노이즈 방지)요청 DTO 전체와 description을 INFO로 찍으면 PII/불필요한 로그가 축적될 수 있습니다. DEBUG로 내리거나 요약 정보만 로깅하세요.
- log.info("매물 등록 요청 데이터: {}", requestDto); - log.info("컨트롤러에서 확인한 description 값: {}", requestDto.getDescription()); + log.debug("매물 등록 요청 수신: addr1={}, residenceType={}, images={}", + requestDto.getAddr1(), requestDto.getResidenceType(), + requestDto.getImages() != null ? requestDto.getImages().size() : 0);
223-236: status 파라미터 Enum 매핑 또는 검증 필요문자열 status는 유효성 문제가 있습니다. HomeStatus로 직접 매핑하거나, 문자열을 Enum으로 검증/변환 후 서비스에 전달하세요.
Enum 직접 매핑 예시:
- public ResponseEntity<ApiResponse<Void>> updateHomeStatus( - @PathVariable Integer homeId, - @RequestParam String status, + public ResponseEntity<ApiResponse<Void>> updateHomeStatus( + @PathVariable Integer homeId, + @RequestParam HomeStatus status, Authentication authentication) { @@ - homeService.updateHomeStatus(homeId, status, userId); + homeService.updateHomeStatus(homeId, status, userId);컨트롤러 상단에 HomeStatus 임포트를 추가하세요.
src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java (2)
41-43: 과도한 상세 데이터 로깅 — PII/로그 노이즈 이슈DTO/상세 VO 전체와 description을 INFO로 출력 중입니다. DEBUG로 내리거나 마스킹/요약하세요.
- log.info("서비스에서 받은 DTO: {}", createDTO); - log.info("서비스에서 확인한 description 값: {}", createDTO.getDescription()); + log.debug("서비스에서 받은 DTO 요약: addr1={}, residenceType={}, images={}", + createDTO.getAddr1(), createDTO.getResidenceType(), images != null ? images.size() : 0); @@ - log.info("DB에 저장할 HomeDetailVO 객체: {}", homeDetail); - log.info("최종 DB 저장 직전의 description 값: {}", homeDetail.getDescription()); + log.debug("DB 저장 직전 요약: homeFloor={}, isPet={}, isParking={}", + homeDetail.getHomeFloor(), homeDetail.getIsPet(), homeDetail.getIsParking());Also applies to: 89-92
137-140: 주석과 실제 S3 키 경로 불일치 (혼동 유발 가능)주석은 uploads/home/...를 언급하나 실제 코드는 home/... 경로를 사용합니다. 주석을 코드와 일치시키세요.
- // S3에 업로드 (uploads/home/{homeId}/{fileName} 형식으로 저장됨) + // S3에 업로드 (home/{homeId}/{fileName} 형식으로 저장됨)src/main/java/org/scoula/domain/home/controller/HomeController.java (1)
70-75: 매물 상태(status) 문자열 대신 Enum 사용 고려상태 값은 도메인 Enum(HomeStatus 등)으로 한정하는 것이 타입 안정성과 스키마 문서화(스웨거) 측면에서 유리합니다. 서비스/매퍼에서도 enum.name() 혹은 TypeHandler로 매핑하면 안전합니다.
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml (1)
83-86: EXISTS 서브쿼리 표기 간단화 제안(선택 사항)성능상 차이는 미미하나 관례적으로 EXISTS (SELECT 1 ...) 표기 권장입니다. 가독성 개선 목적의 제안입니다.
- WHERE h.home_status = 'AVAILABLE' AND EXISTS(select * from home_identity_verification as hiv where h.home_id = hiv.home_id) + WHERE h.home_status = 'AVAILABLE' + AND EXISTS (SELECT 1 FROM home_identity_verification hiv WHERE hiv.home_id = h.home_id)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (30)
src/main/java/org/scoula/domain/fraud/service/AiFraudAnalyzerService.java(2 hunks)src/main/java/org/scoula/domain/home/controller/HomeController.java(1 hunks)src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java(1 hunks)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java(1 hunks)src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java(1 hunks)src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java(1 hunks)src/main/java/org/scoula/domain/home/dto/HomeSearchDTO.java(1 hunks)src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java(1 hunks)src/main/java/org/scoula/domain/home/dto/request/HomeCreateRequestDto.java(0 hunks)src/main/java/org/scoula/domain/home/dto/request/HomeReportRequestDto.java(0 hunks)src/main/java/org/scoula/domain/home/dto/request/HomeUpdateRequestDto.java(0 hunks)src/main/java/org/scoula/domain/home/dto/response/FacilityResponseDto.java(0 hunks)src/main/java/org/scoula/domain/home/dto/response/HomeResponseDto.java(0 hunks)src/main/java/org/scoula/domain/home/dto/response/MaintenanceFeeItemResponseDto.java(0 hunks)src/main/java/org/scoula/domain/home/enums/HomeDirection.java(1 hunks)src/main/java/org/scoula/domain/home/enums/HomeStatus.java(2 hunks)src/main/java/org/scoula/domain/home/mapper/HomeMapper.java(1 hunks)src/main/java/org/scoula/domain/home/service/HomeService.java(1 hunks)src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java(1 hunks)src/main/java/org/scoula/domain/home/vo/FacilityCategory.java(1 hunks)src/main/java/org/scoula/domain/home/vo/FacilityItem.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeImageVO.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeMaintenanceFeeVO.java(1 hunks)src/main/java/org/scoula/domain/home/vo/HomeRegisterVO.java(0 hunks)src/main/java/org/scoula/domain/home/vo/HomeVO.java(1 hunks)src/main/java/org/scoula/global/config/ServletConfig.java(2 hunks)src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml(1 hunks)
💤 Files with no reviewable changes (7)
- src/main/java/org/scoula/domain/home/dto/request/HomeCreateRequestDto.java
- src/main/java/org/scoula/domain/home/dto/response/FacilityResponseDto.java
- src/main/java/org/scoula/domain/home/dto/response/MaintenanceFeeItemResponseDto.java
- src/main/java/org/scoula/domain/home/vo/HomeRegisterVO.java
- src/main/java/org/scoula/domain/home/dto/request/HomeReportRequestDto.java
- src/main/java/org/scoula/domain/home/dto/request/HomeUpdateRequestDto.java
- src/main/java/org/scoula/domain/home/dto/response/HomeResponseDto.java
🧰 Additional context used
📓 Path-based instructions (5)
src/main/java/org/scoula/**/controller/*Controller{,Impl}.java
📄 CodeRabbit Inference Engine (CLAUDE.md)
Use interface-implementation pattern for controllers:
*Controller.java(interface) and*ControllerImpl.java(implementation)
Files:
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.javasrc/main/java/org/scoula/domain/home/controller/HomeController.java
src/main/java/org/scoula/**/controller/**/*.java
📄 CodeRabbit Inference Engine (CLAUDE.md)
src/main/java/org/scoula/**/controller/**/*.java: All controller endpoints should return a consistentApiResponse<T>wrapper
Add Swagger annotations to controller endpoints for API documentation
Files:
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.javasrc/main/java/org/scoula/domain/home/controller/HomeController.java
src/main/java/org/scoula/**/service/*Service{Interface,Impl}.java
📄 CodeRabbit Inference Engine (CLAUDE.md)
Use interface-implementation pattern for services:
*ServiceInterface.java(interface) and*ServiceImpl.java(implementation)
Files:
src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java
src/main/java/org/scoula/domain/*/mapper/*Mapper.java
📄 CodeRabbit Inference Engine (CLAUDE.md)
src/main/java/org/scoula/domain/*/mapper/*Mapper.java: Define MyBatis mapper interfaces undersrc/main/java/org/scoula/domain/*/mapper/*Mapper.java
Annotate MyBatis mapper interfaces with@Mapper
Files:
src/main/java/org/scoula/domain/home/mapper/HomeMapper.java
src/main/resources/org/scoula/domain/*/mapper/*Mapper.xml
📄 CodeRabbit Inference Engine (CLAUDE.md)
src/main/resources/org/scoula/domain/*/mapper/*Mapper.xml: Place MyBatis XML mappers atsrc/main/resources/org/scoula/domain/*/mapper/*Mapper.xml
Name MyBatis XML mappers*Mapper.xmlto match their corresponding*Mapper.javainterfaces
Files:
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
🧠 Learnings (5)
📚 Learning: 2025-08-12T03:59:30.512Z
Learnt from: CR
PR: ITZEEP/backend#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-12T03:59:30.512Z
Learning: Applies to src/main/java/org/scoula/**/controller/*Controller{,Impl}.java : Use interface-implementation pattern for controllers: `*Controller.java` (interface) and `*ControllerImpl.java` (implementation)
Applied to files:
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
📚 Learning: 2025-08-12T03:59:30.512Z
Learnt from: CR
PR: ITZEEP/backend#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-12T03:59:30.512Z
Learning: Applies to src/main/java/org/scoula/**/controller/**/*.java : Add Swagger annotations to controller endpoints for API documentation
Applied to files:
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
📚 Learning: 2025-08-12T03:59:30.512Z
Learnt from: CR
PR: ITZEEP/backend#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-12T03:59:30.512Z
Learning: Applies to src/main/java/org/scoula/domain/*/mapper/*Mapper.java : Define MyBatis mapper interfaces under `src/main/java/org/scoula/domain/*/mapper/*Mapper.java`
Applied to files:
src/main/java/org/scoula/domain/home/mapper/HomeMapper.javasrc/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
📚 Learning: 2025-08-12T03:59:30.512Z
Learnt from: CR
PR: ITZEEP/backend#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-12T03:59:30.512Z
Learning: Applies to src/main/resources/org/scoula/domain/*/mapper/*Mapper.xml : Name MyBatis XML mappers `*Mapper.xml` to match their corresponding `*Mapper.java` interfaces
Applied to files:
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
📚 Learning: 2025-08-12T03:59:30.512Z
Learnt from: CR
PR: ITZEEP/backend#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-12T03:59:30.512Z
Learning: Applies to src/main/resources/org/scoula/domain/*/mapper/*Mapper.xml : Place MyBatis XML mappers at `src/main/resources/org/scoula/domain/*/mapper/*Mapper.xml`
Applied to files:
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
🧬 Code Graph Analysis (15)
src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (5)
src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (1)
Data(18-61)src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (1)
Data(9-28)src/main/java/org/scoula/domain/home/dto/HomeSearchDTO.java (1)
Data(13-62)src/main/java/org/scoula/domain/home/vo/HomeVO.java (1)
Data(11-40)src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (1)
Data(5-15)
src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (6)
src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (1)
Data(9-28)src/main/java/org/scoula/domain/home/vo/HomeVO.java (1)
Data(11-40)src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
Data(7-17)
src/main/java/org/scoula/domain/home/vo/HomeVO.java (3)
src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
Data(7-17)src/main/java/org/scoula/domain/home/vo/HomeMaintenanceFeeVO.java (1)
Data(5-15)
src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (8)
src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (1)
Data(9-28)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)src/main/java/org/scoula/domain/home/vo/HomeVO.java (1)
Data(11-40)src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
Data(7-17)src/main/java/org/scoula/domain/home/vo/HomeMaintenanceFeeVO.java (1)
Data(5-15)
src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java (2)
src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java (2)
ApiModel(20-128)ApiModel(113-127)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)
src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java (2)
src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java (2)
ApiModel(20-119)ApiModel(104-118)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)
src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (6)
src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (1)
Data(9-28)src/main/java/org/scoula/domain/home/vo/HomeVO.java (1)
Data(11-40)src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
Data(5-15)
src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
Data(5-14)
src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (9)
src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (1)
Data(18-61)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)src/main/java/org/scoula/domain/home/vo/HomeVO.java (1)
Data(11-40)src/main/java/org/scoula/domain/home/vo/HomeImageVO.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/FacilityItem.java (1)
Data(5-15)src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
Data(7-17)src/main/java/org/scoula/domain/home/vo/HomeMaintenanceFeeVO.java (1)
Data(5-15)
src/main/java/org/scoula/domain/home/dto/HomeSearchDTO.java (2)
src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (1)
Data(18-61)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)
src/main/java/org/scoula/domain/home/vo/FacilityItem.java (2)
src/main/java/org/scoula/domain/home/vo/FacilityCategory.java (1)
Data(5-14)src/main/java/org/scoula/domain/home/vo/HomeFacilityVO.java (1)
Data(5-14)
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java (1)
src/main/java/org/scoula/global/common/exception/BusinessException.java (1)
BusinessException(4-21)
src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (3)
src/main/java/org/scoula/domain/home/vo/HomeDetailVO.java (1)
Data(9-28)src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (2)
Data(17-74)Data(66-73)src/main/java/org/scoula/domain/home/dto/HomeSearchDTO.java (1)
Data(13-62)
src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java (2)
src/main/java/org/scoula/global/common/exception/BusinessException.java (1)
BusinessException(4-21)src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java (1)
Log4j2(31-326)
src/main/java/org/scoula/domain/home/controller/HomeController.java (1)
src/main/java/org/scoula/domain/chat/controller/AiClauseImproveTestController.java (1)
Api(24-151)
🔇 Additional comments (14)
src/main/java/org/scoula/domain/home/enums/HomeStatus.java (2)
22-24: getKey() 추가 👍 — API에서 key/label 이원화에 유용라벨(@jsonvalue)과 키(getKey)의 동시 제공으로 직렬화/표시 분리가 용이해졌습니다. 다른 enum에도 동일 패턴을 일관 적용하면 클라이언트 측 사용성이 좋아집니다.
9-9: CONTRACTED로 상수명 변경 — 자동 검색 결과 미발견, 추가 확인 필요자동화 스크립트로
HomeStatus.SOLD참조 및"SOLD"하드코딩은 발견되지 않았습니다.
다만 아래 영역에서 수동으로 한 번 더 점검해 주세요:
- DB 마이그레이션·시드 데이터(SQL)
- 매퍼/XML 파일 내 문자열
- 프론트엔드 코드(.js/.ts/.vue) 내 하드코딩
- 외부 API 연동 문서·페이로드에서 enum key 직접 사용 여부
src/main/java/org/scoula/global/config/ServletConfig.java (1)
74-79: 전역 ObjectMapper에 JavaTimeModule 및 날짜 직렬화 옵션이 이미 적용되어 있습니다
src/main/java/org/scoula/global/config/RootConfig.java
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)objectMapper.registerModule(new JavaTimeModule())ServletConfig.configureMessageConverters에서 주입된 동일한objectMapper를 사용하므로 LocalDate 직렬화/역직렬화가 올바르게 처리됩니다추가 조치 없이도 JSON에서 LocalDate가 ISO-8601 문자열로 직렬화됩니다.
src/main/java/org/scoula/domain/home/dto/HomeUpdateRequestDto.java (2)
62-76: 필드 스키마 불일치 확인 요청: area/landCategory 업데이트 필요 여부Create DTO에는
area,landCategory가 존재하지만, Update DTO에는 빠져 있습니다. 의도된 제한인지, 누락인지 확인 부탁드립니다. 누락이라면 추가 및 매퍼/서비스 로직 보강이 필요합니다.
56-58: 단일 관리비(maintenanceFee) vs 항목별 관리비(maintenanceFees) 중복 의미 명확화 필요Update DTO에 합계형
maintenanceFee와 항목별maintenanceFees가 공존합니다. 합계가 항목들의 합과 불일치할 가능성이 있으므로, 다음 중 하나로 정리하는 것이 안전합니다.
- 합계는 서버에서
maintenanceFees합으로만 계산하고, 클라이언트 입력을 받지 않는다.- 혹은 둘 다 받되, 서비스 계층에서 일관성 검증(합/일치) 로직을 추가한다.
원하시면 서비스 계층에 일관성 검증 헬퍼 추가를 제안드리겠습니다.
Also applies to: 96-97
src/main/java/org/scoula/domain/home/enums/HomeDirection.java (1)
27-29: getKey() 추가 LGTMEnum 키 문자열 접근자가 생겨서 DB/프론트 연동 시 가독성이 좋아집니다.
src/main/java/org/scoula/domain/home/vo/HomeLikeVO.java (1)
16-16: likedAt 정밀도 검토 요청정렬/중복 제어/감사 로그 등을 고려하면
LocalDate대신LocalDateTime(또는 타임스탬프)이 더 유용할 수 있습니다. 도메인 요구사항에 따라 현재 결정이 의도된 것인지 확인 부탁드립니다.src/main/java/org/scoula/domain/home/vo/HomeMaintenanceFeeVO.java (1)
11-15: 구현 깔끔: 별도 이슈 없음단순 VO로 목적에 부합하고, 타입/명명도 직관적입니다.
src/main/java/org/scoula/domain/fraud/service/AiFraudAnalyzerService.java (1)
1-1: 패키지 네이밍(‘org.scoula’ vs ‘org.scoola’) 일관성 확인 완료
전체 코드베이스에서package org.scoula…만 선언되어 있으며,package org.scoola…선언은 존재하지 않습니다.
네이밍 불일치로 인한 컴파일/빈 주입 오류 우려 없음.src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java (1)
454-458: 동적 정렬 파라미터 치환 사용 없음 확인매퍼 XML(src/main/resources)에서
${sortBy},${sortDirection}및 일반적인${...}패턴이 검색되지 않아 SQL 인젝션 위험이 없습니다. 추가 검증이나 수정은 필요 없습니다.src/main/java/org/scoula/domain/home/controller/HomeController.java (3)
81-86: 찜 토글 엔드포인트 시그니처/권한 전달 적절토글 목적의 POST + Authentication 전달 방식 일관되고 명확합니다. 나머지 계층에서 idempotency/중복 처리만 보장되면 충분합니다.
91-99: 편의시설 조회 엔드포인트 구성 적절카테고리/아이템 분리 및 명확한 경로 설계, 반환 타입 모두 적절합니다.
28-32: 파일 업로드 필드 존재 확인
HomeCreateRequestDto클래스에 이미private List<MultipartFile> images필드가 정의되어 있어,multipart/form-data요청 시 이미지 업로드가 누락되지 않습니다. 추가 조치가 필요 없습니다.src/main/java/org/scoula/domain/home/mapper/HomeMapper.java (1)
31-33: 검색/카운트 시 DTO 파라미터 네이밍 통일 적절@param("search")로 DTO를 감싸는 패턴 일관적입니다. XML의 #{search.*} 참조와도 맞습니다.
Also applies to: 37-39
| @ApiOperation(value = "매물 목록 조회", notes = "페이징된 매물 목록을 조회합니다.") | ||
| @GetMapping | ||
| public ResponseEntity<PageResponse<HomeResponseDto>> getAllHomes( | ||
| @ApiParam(value = "페이지 번호", defaultValue = "1") @RequestParam(defaultValue = "1") | ||
| String pageStr, | ||
| @ApiParam(value = "페이지 크기", defaultValue = "10") @RequestParam(defaultValue = "10") | ||
| String sizeStr) { | ||
| ResponseEntity<PageResponse<HomeResponseDTO>> getHomeList( | ||
| @ApiParam(value = "페이지 번호 (1부터 시작)", defaultValue = "1") | ||
| @RequestParam(defaultValue = "1") | ||
| int page, | ||
| @ApiParam(value = "페이지 크기", defaultValue = "21") @RequestParam(defaultValue = "21") | ||
| int size); | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
페이지 응답도 ApiResponse로 일관되게 감싸주세요
코딩 가이드라인에 따라 모든 컨트롤러 응답은 ApiResponse로 감싸져야 합니다. 현재 getHomeList, searchHomes는 PageResponse를 직접 반환하고 있어 일관성이 깨집니다.
아래처럼 반환 타입을 변경하는 것을 제안합니다.
- ResponseEntity<PageResponse<HomeResponseDTO>> getHomeList(
+ ResponseEntity<ApiResponse<PageResponse<HomeResponseDTO>>> getHomeList(
@ApiParam(value = "페이지 번호 (1부터 시작)", defaultValue = "1")
@RequestParam(defaultValue = "1")
int page,
@ApiParam(value = "페이지 크기", defaultValue = "21") @RequestParam(defaultValue = "21")
int size);
- ResponseEntity<PageResponse<HomeResponseDTO>> searchHomes(
+ ResponseEntity<ApiResponse<PageResponse<HomeResponseDTO>>> searchHomes(
@ApiParam(value = "검색 조건") @ModelAttribute HomeSearchDTO searchDTO);Also applies to: 47-51
🤖 Prompt for AI Agents
In src/main/java/org/scoula/domain/home/controller/HomeController.java around
lines 38-46 (and also 47-51), the controller methods return
PageResponse<HomeResponseDTO> directly which breaks the guideline requiring
ApiResponse<T> wrappers; change the method signatures to return
ResponseEntity<ApiResponse<PageResponse<HomeResponseDTO>>> (and update imports),
update annotations if necessary, and ensure the service/controller
implementation and any tests build and return ApiResponse.of(pageResponse) (or
the project’s standard ApiResponse factory) so all controller responses are
consistently wrapped.
| @Override | ||
| @PutMapping("/{homeId}") | ||
| public ResponseEntity<ApiResponse<Void>> updateHome( | ||
| @PathVariable Integer homeId, | ||
| @Valid @ModelAttribute HomeUpdateRequestDto updateDto, | ||
| @RequestParam(value = "newImages", required = false) List<MultipartFile> newImages, | ||
| Authentication authentication) { | ||
|
|
||
| Integer userId = getCurrentUserId(authentication); | ||
|
|
||
| log.info( | ||
| "매물 수정 요청: homeId={}, userId={}, 새 이미지 개수={}, 삭제할 이미지 개수={}", | ||
| homeId, | ||
| userId, | ||
| newImages != null ? newImages.size() : 0, | ||
| updateDto.getDeleteImageIds() != null ? updateDto.getDeleteImageIds().size() : 0); | ||
|
|
||
| // 요청 DTO의 homeId 설정 (경로 변수의 homeId 사용) | ||
| updateDto.setHomeId(homeId); | ||
|
|
||
| // HomeUpdateRequestDto를 HomeCreateDTO로 변환 | ||
| HomeCreateDTO updateDTO = | ||
| HomeCreateDTO.builder() | ||
| .addr1(updateDto.getAddr1()) | ||
| .addr2(updateDto.getAddr2()) | ||
| .residenceType(updateDto.getResidenceType()) | ||
| .leaseType(updateDto.getLeaseType()) | ||
| .depositPrice(updateDto.getDepositPrice()) | ||
| .monthlyRent(updateDto.getMonthlyRent()) | ||
| .maintenaceFee(updateDto.getMaintenanceFee()) | ||
| .roomCnt(updateDto.getRoomCnt()) | ||
| .supplyArea(updateDto.getSupplyArea()) | ||
| .exclusiveArea(updateDto.getExclusiveArea()) | ||
| .buildDate(updateDto.getBuildDate()) | ||
| .homeFloor(updateDto.getHomeFloor()) | ||
| .buildingTotalFloors(updateDto.getBuildingTotalFloors()) | ||
| .homeDirection(updateDto.getHomeDirection()) | ||
| .bathroomCnt(updateDto.getBathroomCnt()) | ||
| .isPet(updateDto.getIsPet()) | ||
| .isParking(updateDto.getIsParking()) | ||
| .facilityItemIds(updateDto.getFacilityItemIds()) | ||
| .maintenanceFees( | ||
| updateDto.getMaintenanceFees() != null | ||
| ? updateDto.getMaintenanceFees().stream() | ||
| .map( | ||
| fee -> | ||
| HomeCreateDTO.MaintenanceFeeDTO | ||
| .builder() | ||
| .maintenanceId( | ||
| fee | ||
| .getMaintenanceId()) | ||
| .fee(fee.getFee()) | ||
| .build()) | ||
| .collect(java.util.stream.Collectors.toList()) | ||
| : null) | ||
| .build(); | ||
|
|
||
| homeService.updateHome(homeId, updateDTO, newImages, userId); | ||
|
|
||
| return ResponseEntity.ok(ApiResponse.success(null, "매물이 성공적으로 수정되었습니다.")); | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
수정 API에서 삭제 이미지/시설 변경사항 반영 누락
updateDto.getDeleteImageIds()를 로깅만 하고 실제 삭제/동기화 로직이 없습니다. 서비스 계층에 반영하여 이미지/시설/관리비의 추가·삭제를 함께 처리하세요.
[suggest_optional_refactor]
필요 시 매퍼 메서드 존재 여부를 확인하는 스크립트를 실행해 주세요(존재 시 즉시 적용 가능합니다).
🏁 Script executed:
#!/bin/bash
# 매퍼/인터페이스에 업데이트/삭제 관련 메서드가 정의되어 있는지 확인
rg -n -C2 --type=java --type=xml -P '(update|delete).*Home(Image|Facility|MaintenanceFee)?' src/main/java src/main/resourcesLength of output: 19594
매물 수정 시 이미지·편의시설·관리비 동기화 로직 미구현
현재 HomeControllerImpl.updateHome에서 삭제할 이미지 ID를 로깅만 하고, HomeServiceImpl.updateHome(…)에는 실제 삭제·추가 로직이 빠져 있습니다. 아래 항목을 서비스 계층에 반드시 구현하세요.
• HomeServiceImpl.updateHome 메서드(약 335–347라인)
– 기존 이미지 중 updateDto.getDeleteImageIds()에 해당하는 항목 삭제
– 새 이미지 업로드 로직
– updateDto.getFacilityItemIds() 기반 편의시설 삭제(deleteHomeFacilitiesByHomeDetailId) 및 재등록
– updateDto.getMaintenanceFees() 기반 관리비 삭제(deleteHomeMaintenanceFeesByHomeId) 및 재등록
• 매퍼 메서드(HomeMapper.xml 및 HomeMapper 인터페이스)에 필요한 deleteXXXByHomeId, insertXXX 메서드는 이미 정의되어 있으므로 즉시 호출 가능합니다.
|
|
||
| private Integer monthlyRent; | ||
|
|
||
| private Integer maintenaceFee; |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
필드명 오탈자: maintenaceFee → maintenanceFee (전역 정리 필요)
DTO/VO/Response 간 필드명이 불일치합니다. 특히 이 DTO의 maintenaceFee 오탈자는 API 계약과 매퍼/서비스 매핑 오류를 유발할 수 있습니다. Update DTO는 maintenanceFee로 올바르게 표기되어 있어 불일치가 확실합니다.
우선 이 파일의 필드명을 수정하고, 연관된 VO/DTO/Mapper/XML/프론트 계약을 일괄 교정해 주세요.
- private Integer maintenaceFee;
+ private Integer maintenanceFee;레포 전역에서 불일치 지점을 점검하는 스크립트:
🏁 Script executed:
#!/bin/bash
# maintenaceFee 오탈자/정상 표기 모두 검색하여 영향도 확인
rg -nP -C2 --type=java '\bmaintenaceFee\b|\bmaintenanceFee\b'Length of output: 10967
필드명 오탈자 수정: ‘maintenaceFee’ → ‘maintenanceFee’
DTO/VO/Response/Service/Controller 전역에서 필드명이 일치하지 않아 API 계약 및 매퍼 오류를 유발합니다. 아래 위치를 일괄 교정해주세요.
- src/main/java/org/scoula/domain/home/vo/HomeVO.java (필드 및 getter/setter 변경)
- src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java
- src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java
- src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java
- getMaintenaceFee() → getMaintenanceFee()
- .maintenaceFee(...) → .maintenanceFee(...)
- src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
- .maintenaceFee(...) → .maintenanceFee(...)
- 기타 매퍼(XML)·프론트 API 계약 스펙
- private Integer maintenaceFee;
+ private Integer maintenanceFee;전역에서 rg -nP '\bmaintenaceFee\b'로 잔여 오타가 없는지 확인 바랍니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private Integer maintenaceFee; | |
| private Integer maintenanceFee; |
🤖 Prompt for AI Agents
In src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java around line 35,
the field name maintenaceFee is misspelled; rename the field to maintenanceFee
and update its getter/setter accordingly, then propagate the rename across the
codebase: update src/main/java/org/scoula/domain/home/vo/HomeVO.java (field and
getter/setter), src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java,
src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java
(getMaintenaceFee() → getMaintenanceFee(), builder/call sites
.maintenaceFee(...) → .maintenanceFee(...)),
src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
(.maintenaceFee(...) → .maintenanceFee(...)), any mapper XMLs and frontend API
contract/spec; after applying edits, run rg -nP '\bmaintenaceFee\b' to confirm
no remaining occurrences and run tests/compile to ensure no build breaks.
| @ApiModelProperty(value = "시/도 및 시/군/구", example = "서울특별시 강남구", required = true) | ||
| private String addr1; | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
검증 애노테이션(@Valid) 누락: 런타임 유효성 보장 필요
Swagger의 required 표시는 문서용입니다. 실제 요청 검증을 위해 JSR-303 애노테이션을 추가해 주세요. (컨트롤러에서 @Valid 적용도 필요)
다음과 같이 주요 필드에 최소한의 제약을 권장합니다:
@ApiModelProperty(value = "시/도 및 시/군/구", example = "서울특별시 강남구", required = true)
+ @NotBlank
private String addr1;
@@
private String addr2;
@@
@ApiModelProperty(
value = "거주 유형",
example = "APARTMENT",
required = true,
allowableValues = "APARTMENT, VILLA, ONEROOM, OFFICETEL, HOUSE")
+ @NotNull
private ResidenceType residenceType;
@@
@ApiModelProperty(
value = "임대 유형",
example = "WOLSE",
required = true,
allowableValues = "JEONSE, WOLSE")
+ @NotNull
private LeaseType leaseType;
@@
@ApiModelProperty(value = "보증금 (원)", example = "50000000", required = true)
- private Integer depositPrice;
+ @NotNull
+ @Min(0)
+ private Integer depositPrice;
@ApiModelProperty(value = "월세 (원)", example = "1000000", notes = "전세인 경우 0")
- private Integer monthlyRent;
+ @Min(0)
+ private Integer monthlyRent;
@ApiModelProperty(value = "관리비 (원)", example = "150000")
- private Integer maintenanceFee;
+ @Min(0)
+ private Integer maintenanceFee;
@ApiModelProperty(value = "방 개수", example = "3")
- private Integer roomCnt;
+ @NotNull
+ @Min(0)
+ private Integer roomCnt;컨트롤러 단에서의 검증 활성화도 확인해 주세요:
- 메서드 파라미터에
@Valid HomeCreateRequestDto request적용 - 클래스 레벨에
@Validated적용(필요 시)
교차 필드 검증(예: JEONSE면 monthlyRent=0, WOLSE면 monthlyRent>0)은 별도 커스텀 Validator로 확장 가능합니다. 원하시면 샘플 Validator도 제공하겠습니다.
[offer_assistance]
검증 활성화 여부 점검 스크립트:
Also applies to: 33-39, 40-46, 47-55, 56-58
🏁 Script executed:
#!/bin/bash
# 컨트롤러 계층에서 @Valid 사용 여부 확인
rg -n -C2 '@(Valid|Validated)\b' --type=javaLength of output: 19842
HomeCreateRequestDto 필드에 JSR-303 검증 애노테이션 추가 필요
컨트롤러(HomeControllerImpl)에서 이미 @Valid @RequestPart를 통해 검증이 활성화된 것을 확인했습니다. 런타임 유효성 보장을 위해 DTO 필드에 다음과 같이 JSR-303 제약 애노테이션을 추가해주세요:
@ApiModelProperty(value = "시/도 및 시/군/구", example = "서울특별시 강남구", required = true)
+ @NotBlank
private String addr1;
@@
private String addr2;
@@
@ApiModelProperty(
value = "거주 유형",
example = "APARTMENT",
required = true,
allowableValues = "APARTMENT, VILLA, ONEROOM, OFFICETEL, HOUSE")
+ @NotNull
private ResidenceType residenceType;
@@
@ApiModelProperty(
value = "임대 유형",
example = "WOLSE",
required = true,
allowableValues = "JEONSE, WOLSE")
+ @NotNull
private LeaseType leaseType;
@@
@ApiModelProperty(value = "보증금 (원)", example = "50000000", required = true)
+ @NotNull
+ @Min(0)
private Integer depositPrice;
@ApiModelProperty(value = "월세 (원)", example = "1000000", notes = "전세인 경우 0")
+ @Min(0)
private Integer monthlyRent;
@ApiModelProperty(value = "관리비 (원)", example = "150000")
+ @Min(0)
private Integer maintenanceFee;
@ApiModelProperty(value = "방 개수", example = "3")
+ @NotNull
+ @Min(0)
private Integer roomCnt;• 교차 필드 검증(예: JEONSE일 때 monthlyRent=0, WOLSE일 때 monthlyRent>0)이 필요하다면 별도 커스텀 Validator로 확장 가능합니다.
• DTO 전체에 @Validated 애노테이션은 선택 사항이며, 주로 클래스 레벨 검증이 추가로 필요할 때 사용합니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @ApiModelProperty(value = "시/도 및 시/군/구", example = "서울특별시 강남구", required = true) | |
| private String addr1; | |
| // … around line 27 in HomeCreateRequestDto.java … | |
| @ApiModelProperty(value = "시/도 및 시/군/구", example = "서울특별시 강남구", required = true) | |
| @NotBlank | |
| private String addr1; | |
| private String addr2; | |
| @ApiModelProperty( | |
| value = "거주 유형", | |
| example = "APARTMENT", | |
| required = true, | |
| allowableValues = "APARTMENT, VILLA, ONEROOM, OFFICETEL, HOUSE") | |
| @NotNull | |
| private ResidenceType residenceType; | |
| @ApiModelProperty( | |
| value = "임대 유형", | |
| example = "WOLSE", | |
| required = true, | |
| allowableValues = "JEONSE, WOLSE") | |
| @NotNull | |
| private LeaseType leaseType; | |
| @ApiModelProperty(value = "보증금 (원)", example = "50000000", required = true) | |
| @NotNull | |
| @Min(0) | |
| private Integer depositPrice; | |
| @ApiModelProperty(value = "월세 (원)", example = "1000000", notes = "전세인 경우 0") | |
| @Min(0) | |
| private Integer monthlyRent; | |
| @ApiModelProperty(value = "관리비 (원)", example = "150000") | |
| @Min(0) | |
| private Integer maintenanceFee; | |
| @ApiModelProperty(value = "방 개수", example = "3") | |
| @NotNull | |
| @Min(0) | |
| private Integer roomCnt; | |
| // … rest of the class … |
🤖 Prompt for AI Agents
In src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java around
lines 27 to 29, the DTO field validations are missing; add JSR-303 annotations
to ensure runtime validation (e.g., annotate addr1 with @NotBlank to require a
non-empty address) and similarly mark other fields appropriately
(@NotNull/@NotBlank/@Min/@Positive as applicable for numeric and required fields
such as monthlyRent, deposit, contractType, etc.); for the conditional rule
between contract type and monthlyRent (JEONSE vs WOLSE), implement a class-level
custom ConstraintValidator and companion annotation to enforce the cross-field
logic and annotate the DTO class with that custom constraint (optional: add
@Validated where class-level validation is needed).
| @ApiModelProperty(value = "관리비 (원)", example = "150000") | ||
| private Integer maintenanceFee; | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
필드명 불일치: maintenanceFee vs (다른 계층) maintenaceFee
본 DTO는 maintenanceFee로 올바르게 작성되었으나, HomeVO/HomeCreateDTO 일부에 maintenaceFee 오타가 존재합니다. 자동 매핑 실패/데이터 유실이 발생합니다.
권장 방안(정렬 우선순위):
- 도메인 전반을
maintenanceFee로 통일 (VO/DTO/Mapper XML/Service 매핑 코드 일괄 수정) - 일괄 수정이 어려우면 임시로 매핑 계층에 수동 매핑 또는 MapStruct @mapping으로 브릿지
예: MapStruct 매핑(참고용)
@Mapping(source = "maintenanceFee", target = "maintenaceFee")
HomeCreateDTO toCreateDto(HomeCreateRequestDto req);원하시면 레포 전역 리팩터링 패치 생성해 드릴게요.
[offer_assistance]
오타 필드 사용 위치 스캔:
🏁 Script executed:
#!/bin/bash
rg -n --hidden -S '\bmaintenaceFee\b' -C2Length of output: 9822
필드명 통일 필요: maintenaceFee → maintenanceFee
VO/DTO/서비스/매퍼 전반에 오타가 있어 자동 매핑·데이터 유실 위험이 있습니다.
아래 위치를 일괄 수정해주세요.
- src/main/java/org/scoula/domain/home/vo/HomeVO.java (라인 26:
private Integer maintenaceFee;) - src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (라인 35:
private Integer maintenaceFee;) - src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (라인 35:
private Integer maintenaceFee;) - src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java
- 라인 54, 233, 278:
.maintenaceFee(...)호출
- 라인 54, 233, 278:
- src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java
- 라인 63, 175:
.maintenaceFee(requestDto.getMaintenanceFee())호출
- 라인 63, 175:
- src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
- 라인 13, 54, 76, 93, 233, 248, 268:
#{maintenaceFee}및as maintenaceFee매핑
- 라인 13, 54, 76, 93, 233, 248, 268:
권장 방안:
- 도메인 전반
maintenaceFee→maintenanceFee일괄 리팩터링 - 불가 시 MapStruct로 임시 브릿지 추가
@Mapping(source = "maintenanceFee", target = "maintenaceFee") HomeCreateDTO toCreateDto(HomeCreateRequestDto req);
필요하시면 레포지토리 전역 리팩터링 패치 제공 가능합니다.
🤖 Prompt for AI Agents
In src/main/java/org/scoula/domain/home/dto/HomeCreateRequestDto.java around
lines 53-55: there's a misspelled field name maintenaceFee that must be renamed
to maintenanceFee; perform an across-repository refactor to rename maintenaceFee
→ maintenanceFee in the listed files (VO, DTOs, service calls, controller calls,
and all occurrences in
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml) and update
corresponding getters/setters, constructor usages and mapper property names to
match; if you cannot refactor everywhere at once, add a temporary MapStruct
mapping bridging maintenanceFee → maintenaceFee for DTO/VO conversions per the
suggested @Mapping until the full rename is applied.
| private LeaseType leaseType; | ||
| private Integer depositPrice; | ||
| private Integer monthlyRent; | ||
| private Integer maintenaceFee; |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
오타: maintenaceFee → maintenanceFee (매핑/직렬화/쿼리 실패 가능성 큼)
다른 DTO(예: HomeCreateRequestDto)의 필드명은 maintenanceFee로 보입니다. 현재 VO의 오타로 인해 MapStruct/수동 매핑/마이바티스 resultMap에서 필드 매칭이 누락될 수 있습니다.
다음과 같이 필드명을 즉시 정정하는 것을 권장합니다.
- private Integer maintenaceFee;
+ private Integer maintenanceFee;참고: 연쇄 영향이 큰 변경입니다. 아래 항목들도 함께 정렬해 주세요.
- HomeCreateDTO의
maintenaceFee→maintenanceFee - Mapper XML의 컬럼 alias 또는 resultMap 필드명
- 서비스/컨트롤러 매핑 코드
원하시면 전체 레퍼런스 수정 PR 패치를 만들어 드릴게요.
[offer_assistance]
레포 내 오타 사용 위치를 확인하는 스크립트입니다.
🏁 Script executed:
#!/bin/bash
rg -n --hidden -S '\bmaintenaceFee\b' -C2Length of output: 9822
오타 수정: maintenaceFee → maintenanceFee
VO, DTO, Mapper, Controller, Service 전반에서 일관된 필드명을 사용해야 매핑/직렬화/쿼리 오류를 방지할 수 있습니다.
• 수정 대상 위치
- src/main/java/org/scoula/domain/home/vo/HomeVO.java (라인 26)
- src/main/java/org/scoula/domain/home/dto/HomeCreateDTO.java (라인 35)
- src/main/java/org/scoula/domain/home/dto/HomeResponseDTO.java (라인 35)
- src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml (총 7곳:
#{maintenaceFee}→#{maintenanceFee},as maintenaceFee→as maintenanceFee,maintenance_fee = #{maintenaceFee}→#{maintenanceFee}) - src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java (2곳:
.maintenaceFee(...)→.maintenanceFee(...)) - src/main/java/org/scoula/domain/home/service/HomeServiceImpl.java (3곳:
.maintenaceFee(...)→.maintenanceFee(...))
• 예시 diff (HomeVO.java)
- private Integer maintenaceFee;
+ private Integer maintenanceFee;위 변경에 따른 연쇄 수정이 반드시 필요하니, 각 매퍼(resultMap/SQL), 매핑 코드, DTO 필드명까지 함께 정리해 주세요.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private Integer maintenaceFee; | |
| private Integer maintenanceFee; |
🤖 Prompt for AI Agents
In src/main/java/org/scoula/domain/home/vo/HomeVO.java around line 26 (and all
related files listed), there is a typo: the field maintenaceFee should be
renamed to maintenanceFee; update the field name in HomeVO and then apply the
same rename across DTOs (HomeCreateDTO.java line ~35, HomeResponseDTO.java line
~35), all usages in HomeControllerImpl.java (2 places) and HomeServiceImpl.java
(3 places), and every occurrence in the MyBatis mapper file
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml (change
#{maintenaceFee} → #{maintenanceFee}, SQL aliases "as maintenaceFee" → "as
maintenanceFee", and parameter bindings like maintenance_fee = #{maintenaceFee}
→ #{maintenanceFee}); ensure getters/setters and any builder/constructor calls
are updated, regenerate/adjust mapper resultMap and SQL statements to use the
corrected property name, and run a build/tests to catch any remaining
references.
| #{userId}, #{addr1}, #{addr2}, #{residenceType}, #{leaseType}, | ||
| #{depositPrice}, #{monthlyRent}, #{maintenaceFee}, #{homeStatus}, | ||
| #{viewCnt}, #{likeCnt}, #{chatCnt}, #{roomCnt}, #{supplyArea}, #{exclusiveArea} | ||
| ) |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
프로퍼티명 오타: maintenaceFee → maintenanceFee
VO 필드명이 maintenanceFee일 가능성이 높습니다. 현재 SQL 바인딩/별칭이 maintenaceFee(오타)로 되어 있어 런타임 바인딩 에러 또는 매핑 실패가 발생할 수 있습니다. 모든 위치를 일괄 수정하세요.
먼저 실제 VO 필드명을 확인해 주세요.
수정 예시:
- #{depositPrice}, #{monthlyRent}, #{maintenaceFee}, #{homeStatus},
+ #{depositPrice}, #{monthlyRent}, #{maintenanceFee}, #{homeStatus},
- h.maintenance_fee as maintenaceFee, h.home_status as homeStatus,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
- h.maintenance_fee as maintenaceFee, h.home_status as homeStatus,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
- h.maintenance_fee as maintenaceFee, h.home_status as homeStatus,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
- h.maintenance_fee as maintenaceFee, h.home_status as homeStatus,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
- maintenance_fee = #{maintenaceFee},
+ maintenance_fee = #{maintenanceFee},Also applies to: 54-58, 76-80, 92-96, 231-236, 268-269
🏁 Script executed:
#!/bin/bash
# VO와 XML에서 maintenaceFee/maintenanceFee 사용 여부 확인
fd -a HomeVO.java | xargs -I{} rg -n -C2 -P 'maintenaceFee|maintenanceFee' {}
rg -n -C2 -P 'maintenaceFee|maintenanceFee' src/main/resourcesLength of output: 5314
VO 필드명 및 매퍼 XML 오타 수정 (maintenaceFee → maintenanceFee)
VO(HomeVO.java)에 maintenaceFee 필드명 오타가 있어, 이를 maintenanceFee로 변경하고 관련 getter/setter를 모두 수정해야 합니다. 그 후 매퍼 XML의 바인딩·별칭·업데이트 절에서도 #{maintenaceFee} 및 as maintenaceFee를 maintenanceFee로 일괄 교체하세요.
• 수정 대상
- src/main/java/**/HomeVO.java
- src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
• 예시 diff
--- a/src/main/java/org/scoula/domain/home/vo/HomeVO.java
+++ b/src/main/java/org/scoula/domain/home/vo/HomeVO.java
@@ -23,7 +23,7 @@ public class HomeVO {
- private Integer maintenaceFee;
+ private Integer maintenanceFee;
- public Integer getMaintenaceFee() {
- return maintenaceFee;
- }
+ public Integer getMaintenanceFee() {
+ return maintenanceFee;
+ }
- public void setMaintenaceFee(Integer maintenaceFee) {
- this.maintenaceFee = maintenaceFee;
+ public void setMaintenanceFee(Integer maintenanceFee) {
+ this.maintenanceFee = maintenanceFee;
}
}--- a/src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
+++ b/src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml
@@ -12,7 +12,7 @@
- #{depositPrice}, #{monthlyRent}, #{maintenaceFee}, #{homeStatus},
+ #{depositPrice}, #{monthlyRent}, #{maintenanceFee}, #{homeStatus},
@@ -53,7 +53,7 @@
- h.maintenance_fee as maintenaceFee, h.home_status as homeStatus,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
@@ -268,7 +268,7 @@
- maintenance_fee = #{maintenaceFee},
+ maintenance_fee = #{maintenanceFee},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #{userId}, #{addr1}, #{addr2}, #{residenceType}, #{leaseType}, | |
| #{depositPrice}, #{monthlyRent}, #{maintenaceFee}, #{homeStatus}, | |
| #{viewCnt}, #{likeCnt}, #{chatCnt}, #{roomCnt}, #{supplyArea}, #{exclusiveArea} | |
| ) | |
| #{userId}, #{addr1}, #{addr2}, #{residenceType}, #{leaseType}, | |
| #{depositPrice}, #{monthlyRent}, #{maintenanceFee}, #{homeStatus}, | |
| #{viewCnt}, #{likeCnt}, #{chatCnt}, #{roomCnt}, #{supplyArea}, #{exclusiveArea} | |
| ) |
🤖 Prompt for AI Agents
In src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml around lines
12 to 15, the field name maintenaceFee is misspelled; update all occurrences of
#{maintenaceFee} and any "as maintenaceFee" to #{maintenanceFee} / "as
maintenanceFee". Also fix the VO: open src/main/java/**/HomeVO.java and rename
the field maintenaceFee → maintenanceFee, update the getter/setter names and
references, and then update any mapper resultMap, SQL insert/update parameter
bindings, aliases, and unit tests or usages to use the corrected maintenanceFee
name consistently.
| <select id="selectHomeDetailByHomeId" parameterType="int" resultType="org.scoula.domain.home.vo.HomeDetailVO"> | ||
| SELECT | ||
| home_detail_id, home_id, build_date, home_floor, building_total_floors, | ||
| home_direction, bathroom_count as bathroomCnt, is_pet as isPet, is_parking_available as isParking, description as description | ||
| FROM home_detail | ||
| WHERE home_id = #{homeId} | ||
| </select> |
There was a problem hiding this comment.
home_detail 조회에 area/land_category 필드 누락
insert 시에는 area, land_category, description을 넣지만 selectHomeDetailByHomeId에는 area와 land_category가 누락되어 조회 결과가 불완전합니다. 컬럼을 추가 선택하세요.
- SELECT
- home_detail_id, home_id, build_date, home_floor, building_total_floors,
- home_direction, bathroom_count as bathroomCnt, is_pet as isPet, is_parking_available as isParking, description as description
+ SELECT
+ home_detail_id, home_id, build_date, home_floor, building_total_floors,
+ home_direction, bathroom_count as bathroomCnt, is_pet as isPet, is_parking_available as isParking,
+ area as area, land_category as landCategory, description as description📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <select id="selectHomeDetailByHomeId" parameterType="int" resultType="org.scoula.domain.home.vo.HomeDetailVO"> | |
| SELECT | |
| home_detail_id, home_id, build_date, home_floor, building_total_floors, | |
| home_direction, bathroom_count as bathroomCnt, is_pet as isPet, is_parking_available as isParking, description as description | |
| FROM home_detail | |
| WHERE home_id = #{homeId} | |
| </select> | |
| <select id="selectHomeDetailByHomeId" parameterType="int" resultType="org.scoula.domain.home.vo.HomeDetailVO"> | |
| SELECT | |
| home_detail_id, home_id, build_date, home_floor, building_total_floors, | |
| home_direction, bathroom_count as bathroomCnt, is_pet as isPet, is_parking_available as isParking, | |
| area as area, land_category as landCategory, description as description | |
| FROM home_detail | |
| WHERE home_id = #{homeId} | |
| </select> |
🤖 Prompt for AI Agents
In src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml around lines
63 to 69, the selectHomeDetailByHomeId query omits the area and land_category
columns causing incomplete HomeDetailVO results; modify the SELECT projection to
include area and land_category and alias them to match the HomeDetailVO property
names (e.g., area and landCategory or whatever the VO expects) so the mapper
returns the same fields that insert populates.
| <select id="findHomeById" resultType="org.scoula.domain.home.vo.HomeVO"> | ||
| SELECT * FROM home WHERE home_id=#{id} | ||
| </select> | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
SELECT * 사용 및 중복 쿼리: findHomeById 정리
- SELECT *는 컬럼/alias 일관성을 깨고 MyBatis 전역 설정(mapUnderscoreToCamelCase)에 의존하게 만듭니다.
- 이미 selectHomeById가 존재하므로 중복입니다. 하나로 통일하세요.
옵션 A: XML에서 해당 쿼리 제거하고 자바 매퍼도 정리
- <select id="findHomeById" resultType="org.scoula.domain.home.vo.HomeVO">
- SELECT * FROM home WHERE home_id=#{id}
- </select>옵션 B: 동일한 컬럼 alias를 사용하는 쿼리로 교체(중복은 남지만 안전)
- <select id="findHomeById" resultType="org.scoula.domain.home.vo.HomeVO">
- SELECT * FROM home WHERE home_id=#{id}
- </select>
+ <select id="findHomeById" parameterType="int" resultType="org.scoula.domain.home.vo.HomeVO">
+ SELECT
+ h.home_id as homeId, h.user_id as userId, h.addr1, h.addr2,
+ h.residence_type as residenceType, h.lease_type as leaseType,
+ h.deposit_price as depositPrice, h.monthly_rent as monthlyRent,
+ h.maintenance_fee as maintenanceFee, h.home_status as homeStatus,
+ h.view_cnt as viewCnt, h.like_cnt as likeCnt, h.chat_cnt as chatCnt,
+ h.room_cnt as roomCnt, h.supply_area as supplyArea, h.exclusive_area as exclusiveArea,
+ h.created_at as createdAt, h.updated_at as updatedAt
+ FROM home h
+ WHERE h.home_id = #{id}
+ </select>중복된 selectHomeById 쿼리의 존재 여부를 확인하기 위해 다음 스크립트를 실행해주세요:
🏁 Script executed:
#!/bin/bash
rg -nP --type=xml '<select\s+id="selectHomeById"' -C2 src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xmlLength of output: 335
중복된 쿼리 제거 및 명시적 컬럼 매핑 통일
이미 selectHomeById(lines 49–57)에서 컬럼을 명시적으로 alias 처리한 쿼리가 존재하므로, 아래 중 하나를 선택하세요:
• 옵션 A: findHomeById 매퍼 및 사용부 제거
- 파일:
src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml(256–259줄) - 연관 자바 인터페이스 메소드(
findHomeById)도 삭제 - 호출부(service/DAO)에서
findHomeById→selectHomeById로 변경
• 옵션 B: findHomeById 쿼리를 selectHomeById와 동일한 컬럼·alias 구조로 교체
- <select id="findHomeById" resultType="org.scoula.domain.home.vo.HomeVO">
- SELECT * FROM home WHERE home_id=#{id}
- </select>
+ <select id="findHomeById" parameterType="int" resultType="org.scoula.domain.home.vo.HomeVO">
+ SELECT
+ h.home_id AS homeId, h.user_id AS userId,
+ h.addr1, h.addr2,
+ h.residence_type AS residenceType,
+ h.lease_type AS leaseType,
+ h.deposit_price AS depositPrice,
+ h.monthly_rent AS monthlyRent,
+ h.maintenance_fee AS maintenanceFee,
+ h.home_status AS homeStatus,
+ h.view_cnt AS viewCnt,
+ h.like_cnt AS likeCnt,
+ h.chat_cnt AS chatCnt,
+ h.room_cnt AS roomCnt,
+ h.supply_area AS supplyArea,
+ h.exclusive_area AS exclusiveArea,
+ h.created_at AS createdAt,
+ h.updated_at AS updatedAt
+ FROM home h
+ WHERE h.home_id = #{id}
+ </select>위 변경을 통해
SELECT *의 불명확성 해소- MyBatis 전역 설정 의존성 축소
- 중복 매퍼 정리 가 동시에 이루어집니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <select id="findHomeById" resultType="org.scoula.domain.home.vo.HomeVO"> | |
| SELECT * FROM home WHERE home_id=#{id} | |
| </select> | |
| <select id="findHomeById" parameterType="int" resultType="org.scoula.domain.home.vo.HomeVO"> | |
| SELECT | |
| h.home_id AS homeId, | |
| h.user_id AS userId, | |
| h.addr1, | |
| h.addr2, | |
| h.residence_type AS residenceType, | |
| h.lease_type AS leaseType, | |
| h.deposit_price AS depositPrice, | |
| h.monthly_rent AS monthlyRent, | |
| h.maintenance_fee AS maintenanceFee, | |
| h.home_status AS homeStatus, | |
| h.view_cnt AS viewCnt, | |
| h.like_cnt AS likeCnt, | |
| h.chat_cnt AS chatCnt, | |
| h.room_cnt AS roomCnt, | |
| h.supply_area AS supplyArea, | |
| h.exclusive_area AS exclusiveArea, | |
| h.created_at AS createdAt, | |
| h.updated_at AS updatedAt | |
| FROM home h | |
| WHERE h.home_id = #{id} | |
| </select> |
🤖 Prompt for AI Agents
In src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml around lines
256–259 there is a duplicate SELECT * mapper (findHomeById) that conflicts with
the existing selectHomeById (lines 49–57) which uses explicit column aliases;
either remove findHomeById entirely (delete this mapper, remove the
corresponding method from the Java mapper interface, and update all callers to
use selectHomeById) or replace the findHomeById SQL so it lists the same
explicit columns and aliases as selectHomeById (keep signature same) to ensure
consistent column mapping and remove SELECT * usage.
| <update id="updateHomeDetail" parameterType="org.scoula.domain.home.vo.HomeDetailVO"> | ||
| UPDATE home_detail SET | ||
| build_date = #{buildDate}, | ||
| home_floor = #{homeFloor}, | ||
| building_total_floors = #{buildingTotalFloors}, | ||
| home_direction = #{homeDirection}, | ||
| bathroom_count = #{bathroomCnt}, | ||
| is_pet = #{isPet}, | ||
| is_parking_available = #{isParking} | ||
| WHERE home_detail_id = #{homeDetailId} | ||
| </update> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
home_detail 갱신 시 area/land_category/description 누락
updateHomeDetail에서 insert된 필드(area, land_category, description)가 갱신되지 않습니다. 필드 추가가 필요합니다.
<update id="updateHomeDetail" parameterType="org.scoula.domain.home.vo.HomeDetailVO">
UPDATE home_detail SET
build_date = #{buildDate},
home_floor = #{homeFloor},
building_total_floors = #{buildingTotalFloors},
home_direction = #{homeDirection},
bathroom_count = #{bathroomCnt},
is_pet = #{isPet},
- is_parking_available = #{isParking}
+ is_parking_available = #{isParking},
+ area = #{area},
+ land_category = #{landCategory},
+ description = #{description}
WHERE home_detail_id = #{homeDetailId}
</update>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <update id="updateHomeDetail" parameterType="org.scoula.domain.home.vo.HomeDetailVO"> | |
| UPDATE home_detail SET | |
| build_date = #{buildDate}, | |
| home_floor = #{homeFloor}, | |
| building_total_floors = #{buildingTotalFloors}, | |
| home_direction = #{homeDirection}, | |
| bathroom_count = #{bathroomCnt}, | |
| is_pet = #{isPet}, | |
| is_parking_available = #{isParking} | |
| WHERE home_detail_id = #{homeDetailId} | |
| </update> | |
| <update id="updateHomeDetail" parameterType="org.scoula.domain.home.vo.HomeDetailVO"> | |
| UPDATE home_detail SET | |
| build_date = #{buildDate}, | |
| home_floor = #{homeFloor}, | |
| building_total_floors = #{buildingTotalFloors}, | |
| home_direction = #{homeDirection}, | |
| bathroom_count = #{bathroomCnt}, | |
| is_pet = #{isPet}, | |
| is_parking_available = #{isParking}, | |
| area = #{area}, | |
| land_category = #{landCategory}, | |
| description = #{description} | |
| WHERE home_detail_id = #{homeDetailId} | |
| </update> |
🤖 Prompt for AI Agents
In src/main/resources/org/scoula/domain/home/mapper/HomeMapper.xml around lines
276 to 286, the UPDATE statement for updateHomeDetail is missing the area,
land_category and description columns that were inserted earlier; add these
three columns to the SET clause mapping to the corresponding HomeDetailVO
properties (map DB columns area, land_category, description to the VO
properties, e.g., area, landCategory, description), ensure proper comma
separation and that the parameter names exactly match the VO getters so MyBatis
can bind them.
| @Valid @RequestPart HomeCreateRequestDto requestDto, Authentication authentication) { | ||
|
|
||
| // ✨ 매물 등록 요청 데이터와 description 값을 로그로 확인 | ||
| log.info("매물 등록 요청 데이터: {}", requestDto); |
Check failure
Code scanning / CodeQL
Log Injection High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 6 months ago
To fix this log injection vulnerability, we should sanitize all user-provided fields before logging them. The best approach is to avoid logging the entire requestDto object directly. Instead, log only the fields that are necessary for debugging, and sanitize each field to remove newline characters and other potentially dangerous content. For string fields, replace any newline (\n, \r) characters with spaces or remove them entirely. For collections or nested objects, sanitize each string element. This can be done by creating a helper method to sanitize strings and applying it to each field before logging. The fix should be applied to line 46 in src/main/java/org/scoula/domain/home/controller/HomeControllerImpl.java. We may need to add a private helper method in the controller to perform the sanitization.
| @@ -34,6 +34,14 @@ | ||
| @RequiredArgsConstructor | ||
| public class HomeControllerImpl implements HomeController { | ||
|
|
||
| /** | ||
| * Sanitizes a string for safe logging by removing newlines and carriage returns. | ||
| */ | ||
| private String sanitize(String input) { | ||
| if (input == null) return null; | ||
| return input.replaceAll("[\\r\\n]", " "); | ||
| } | ||
|
|
||
| private final HomeService homeService; | ||
| private final UserServiceInterface userService; | ||
|
|
||
| @@ -43,8 +51,30 @@ | ||
| @Valid @RequestPart HomeCreateRequestDto requestDto, Authentication authentication) { | ||
|
|
||
| // ✨ 매물 등록 요청 데이터와 description 값을 로그로 확인 | ||
| log.info("매물 등록 요청 데이터: {}", requestDto); | ||
| log.info("컨트롤러에서 확인한 description 값: {}", requestDto.getDescription()); | ||
| log.info("매물 등록 요청 데이터: addr1={}, addr2={}, residenceType={}, leaseType={}, depositPrice={}, monthlyRent={}, maintenanceFee={}, roomCnt={}, supplyArea={}, exclusiveArea={}, buildDate={}, homeFloor={}, buildingTotalFloors={}, homeDirection={}, area={}, landCategory={}, bathroomCnt={}, isPet={}, isParking={}, facilityItemIds={}, description={}", | ||
| sanitize(requestDto.getAddr1()), | ||
| sanitize(requestDto.getAddr2()), | ||
| sanitize(String.valueOf(requestDto.getResidenceType())), | ||
| sanitize(String.valueOf(requestDto.getLeaseType())), | ||
| sanitize(String.valueOf(requestDto.getDepositPrice())), | ||
| sanitize(String.valueOf(requestDto.getMonthlyRent())), | ||
| sanitize(String.valueOf(requestDto.getMaintenanceFee())), | ||
| sanitize(String.valueOf(requestDto.getRoomCnt())), | ||
| sanitize(String.valueOf(requestDto.getSupplyArea())), | ||
| sanitize(String.valueOf(requestDto.getExclusiveArea())), | ||
| sanitize(String.valueOf(requestDto.getBuildDate())), | ||
| sanitize(String.valueOf(requestDto.getHomeFloor())), | ||
| sanitize(String.valueOf(requestDto.getBuildingTotalFloors())), | ||
| sanitize(String.valueOf(requestDto.getHomeDirection())), | ||
| sanitize(String.valueOf(requestDto.getArea())), | ||
| sanitize(String.valueOf(requestDto.getLandCategory())), | ||
| sanitize(String.valueOf(requestDto.getBathroomCnt())), | ||
| sanitize(String.valueOf(requestDto.getIsPet())), | ||
| sanitize(String.valueOf(requestDto.getIsParking())), | ||
| sanitize(String.valueOf(requestDto.getFacilityItemIds())), | ||
| sanitize(requestDto.getDescription()) | ||
| ); | ||
| log.info("컨트롤러에서 확인한 description 값: {}", sanitize(requestDto.getDescription())); | ||
|
|
||
| Integer userId = getCurrentUserId(authentication); | ||
|
|
|
|
||
| // ✨ 매물 등록 요청 데이터와 description 값을 로그로 확인 | ||
| log.info("매물 등록 요청 데이터: {}", requestDto); | ||
| log.info("컨트롤러에서 확인한 description 값: {}", requestDto.getDescription()); |
Check failure
Code scanning / CodeQL
Log Injection High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 6 months ago
To fix the log injection vulnerability, we should sanitize the user-provided description before logging it. The most straightforward and effective way is to remove or replace newline (\n, \r) and other control characters from the string before logging. This can be done using String.replaceAll() with a regular expression that matches all line breaks and control characters. The fix should be applied directly in the logging statement in HomeControllerImpl.java on line 47, ensuring that only sanitized data is logged. No changes to the DTO or other files are required. If the project does not already have a utility method for sanitizing log input, we can implement the sanitization inline.
| @@ -44,7 +44,8 @@ | ||
|
|
||
| // ✨ 매물 등록 요청 데이터와 description 값을 로그로 확인 | ||
| log.info("매물 등록 요청 데이터: {}", requestDto); | ||
| log.info("컨트롤러에서 확인한 description 값: {}", requestDto.getDescription()); | ||
| String sanitizedDescription = requestDto.getDescription() == null ? "" : requestDto.getDescription().replaceAll("[\\r\\n]", ""); | ||
| log.info("컨트롤러에서 확인한 description 값: {}", sanitizedDescription); | ||
|
|
||
| Integer userId = getCurrentUserId(authentication); | ||
|
|
|
|
||
| // ✨ 서비스에서 받은 DTO와 description 값 확인 | ||
| log.info("서비스에서 받은 DTO: {}", createDTO); | ||
| log.info("서비스에서 확인한 description 값: {}", createDTO.getDescription()); |
Check failure
Code scanning / CodeQL
Log Injection High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 6 months ago
To fix this log injection vulnerability, we need to sanitize the user-provided description field before logging it. The best approach is to remove or escape newline (\n, \r) and other control characters from the string before passing it to the logger. This can be done by creating a utility method (e.g., sanitizeForLog(String input)) that replaces or removes these characters. The fix should be applied in HomeServiceImpl.java on line 42, where the log entry is made. We should also add the utility method within the same file (since we cannot edit other files), and use it to sanitize the description before logging.
| @@ -29,6 +29,15 @@ | ||
| private final HomeMapper homeMapper; | ||
| private final S3ServiceInterface s3Service; | ||
|
|
||
| /** | ||
| * Sanitizes user input for safe logging by removing newlines and carriage returns. | ||
| */ | ||
| private static String sanitizeForLog(String input) { | ||
| if (input == null) return null; | ||
| // Remove newlines, carriage returns, and other control characters | ||
| return input.replaceAll("[\\r\\n\\t\\f\\b]", ""); | ||
| } | ||
|
|
||
| @Override | ||
| public Integer createHome(HomeCreateDTO createDTO, List<MultipartFile> images, Integer userId) { | ||
| log.info( | ||
| @@ -39,7 +48,7 @@ | ||
|
|
||
| // ✨ 서비스에서 받은 DTO와 description 값 확인 | ||
| log.info("서비스에서 받은 DTO: {}", createDTO); | ||
| log.info("서비스에서 확인한 description 값: {}", createDTO.getDescription()); | ||
| log.info("서비스에서 확인한 description 값: {}", sanitizeForLog(createDTO.getDescription())); | ||
|
|
||
| try { | ||
| HomeVO home = |
|
|
||
| // ✨ DB에 저장할 객체의 description 값 최종 확인 | ||
| log.info("DB에 저장할 HomeDetailVO 객체: {}", homeDetail); | ||
| log.info("최종 DB 저장 직전의 description 값: {}", homeDetail.getDescription()); |
Check failure
Code scanning / CodeQL
Log Injection High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 6 months ago
To fix this log injection vulnerability, we need to sanitize the user-provided description before logging it. The best approach is to remove or replace newline (\n, \r) and other control characters from the string before it is logged. This can be done by creating a helper method (e.g., sanitizeForLog(String input)) that replaces all newline and carriage return characters with spaces or removes them entirely. We should apply this sanitization in all log statements that output the description, specifically in HomeServiceImpl.java on lines 42 and 91. The helper method can be private and static within the service class, or placed in a utility class if available. Only the log output needs to be sanitized; the value stored in the database can remain unchanged.
| @@ -26,6 +26,15 @@ | ||
| @Transactional | ||
| public class HomeServiceImpl implements HomeService { | ||
|
|
||
| /** | ||
| * Sanitizes a string for safe logging by removing newlines and carriage returns. | ||
| */ | ||
| private static String sanitizeForLog(String input) { | ||
| if (input == null) return null; | ||
| // Remove newlines and carriage returns | ||
| return input.replaceAll("[\\r\\n]", " "); | ||
| } | ||
|
|
||
| private final HomeMapper homeMapper; | ||
| private final S3ServiceInterface s3Service; | ||
|
|
||
| @@ -39,7 +48,7 @@ | ||
|
|
||
| // ✨ 서비스에서 받은 DTO와 description 값 확인 | ||
| log.info("서비스에서 받은 DTO: {}", createDTO); | ||
| log.info("서비스에서 확인한 description 값: {}", createDTO.getDescription()); | ||
| log.info("서비스에서 확인한 description 값: {}", sanitizeForLog(createDTO.getDescription())); | ||
|
|
||
| try { | ||
| HomeVO home = | ||
| @@ -88,7 +97,7 @@ | ||
|
|
||
| // ✨ DB에 저장할 객체의 description 값 최종 확인 | ||
| log.info("DB에 저장할 HomeDetailVO 객체: {}", homeDetail); | ||
| log.info("최종 DB 저장 직전의 description 값: {}", homeDetail.getDescription()); | ||
| log.info("최종 DB 저장 직전의 description 값: {}", sanitizeForLog(homeDetail.getDescription())); | ||
|
|
||
| int detailResult = homeMapper.insertHomeDetail(homeDetail); | ||
| if (detailResult != 1) { |
🚀 관련 이슈
🔑 주요 변경사항
✔️ 체크 리스트
mainbranch에 실수로 PR 생성 금지)📢 To Reviewers
📸 스크린샷 or 실행영상
Summary by CodeRabbit