Skip to content

[NO-ISSUE] 어드민 관련 파일 수정#217

Merged
Develop-KIM merged 3 commits intodevelopfrom
fix/NO-ISSUE-properties
Mar 11, 2026
Merged

[NO-ISSUE] 어드민 관련 파일 수정#217
Develop-KIM merged 3 commits intodevelopfrom
fix/NO-ISSUE-properties

Conversation

@Develop-KIM
Copy link
Member

@Develop-KIM Develop-KIM commented Mar 11, 2026

Summary by CodeRabbit

릴리스 노트

  • 리팩토링
    • 도시 정보 업데이트 시 좌표(위도/경도) 정보를 함께 관리할 수 있도록 기능 개선
    • 애플리케이션 내부 아키텍처 최적화로 시스템 유지보수성 강화
    • 불필요한 오류 코드 정리

Copilot AI review requested due to automatic review settings March 11, 2026 12:40
@Develop-KIM Develop-KIM added the refactoring 외부 동작은 유지하되 코드 구조를 개선하거나 유지보수성을 높이기 위한 내부 변경에 사용합니다. label Mar 11, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7589acb5-e20b-4178-8c88-64b6994a701a

📥 Commits

Reviewing files that changed from the base of the PR and between 2d658b5 and 4a187f7.

📒 Files selected for processing (14)
  • src/main/java/com/souzip/adapter/webapi/admin/AdminLocationApi.java
  • src/main/java/com/souzip/application/admin/AdminLocationModifyService.java
  • src/main/java/com/souzip/application/admin/AdminLocationQueryService.java
  • src/main/java/com/souzip/application/admin/provided/AdminLocationFinder.java
  • src/main/java/com/souzip/application/admin/provided/AdminLocationModifier.java
  • src/main/java/com/souzip/application/admin/required/CityCommandPort.java
  • src/main/java/com/souzip/application/admin/required/CityQueryPort.java
  • src/main/java/com/souzip/application/admin/required/CountryQueryPort.java
  • src/main/java/com/souzip/domain/city/application/command/CityCommandService.java
  • src/main/java/com/souzip/domain/city/application/command/UpdateCityCommand.java
  • src/main/java/com/souzip/domain/city/entity/City.java
  • src/main/java/com/souzip/domain/country/application/query/CountryQueryService.java
  • src/main/java/com/souzip/global/exception/ErrorCode.java
  • src/test/java/com/souzip/adapter/webapi/admin/AdminLocationApiTest.java

Walkthrough

포트 기반 아키텍처에서 리포지토리 기반 아키텍처로 마이그레이션. CityCommandPort, CityQueryPort, CountryQueryPort 인터페이스 제거 후, 리포지토리 직접 사용 및 커맨드 패턴 도입으로 변경. 검색 관련 에러 코드 제거 및 도메인 모델 업데이트.

Changes

코호트 / 파일 요약
포트 인터페이스 제거
src/main/java/com/souzip/application/admin/required/CityCommandPort.java, CityQueryPort.java, CountryQueryPort.java
CityCommandPort, CityQueryPort, CountryQueryPort 인터페이스 완전 삭제. 포트 기반 계약이 제거되고 리포지토리 기반 구현으로 전환.
조회 서비스 리팩토링
src/main/java/com/souzip/application/admin/AdminLocationQueryService.java
의존성을 CityQueryPort/CountryQueryPort에서 CityRepository/CountryRepository로 변경. 키워드 기반 조건 분기로 조회 로직 수정.
명령 서비스 및 커맨드 도입
src/main/java/com/souzip/application/admin/AdminLocationModifyService.java
CityCommandPort를 CityManagementPort로 대체. createCity, updateCity, deleteCity, updateCityPriority 메서드가 이제 커맨드 객체(CreateCityCommand, UpdateCityCommand, DeleteCityCommand, UpdateCityPriorityCommand) 구성 및 전달.
제공 인터페이스 포맷팅
src/main/java/com/souzip/application/admin/provided/AdminLocationFinder.java, AdminLocationModifier.java
파일 끝 개행 추가. 인터페이스 메서드 시그니처 변화 없음.
도메인 모델 및 커맨드 확장
src/main/java/com/souzip/domain/city/entity/City.java, src/main/java/com/souzip/domain/city/application/command/UpdateCityCommand.java, src/main/java/com/souzip/domain/city/application/command/CityCommandService.java
City 엔티티의 updateName 메서드를 update로 변경하여 latitude/longitude 좌표 업데이트 포함. UpdateCityCommand에 latitude, longitude 필드 추가. CityCommandService의 updateCity 로직 조정.
국가 쿼리 서비스 인터페이스 구현
src/main/java/com/souzip/domain/country/application/query/CountryQueryService.java
CountryQueryService가 CountryAdminPort 인터페이스 구현하도록 변경. @Override 애노테이션 추가.
에러 코드 정리
src/main/java/com/souzip/global/exception/ErrorCode.java
SEARCH_INDEX_NOT_READY, SEARCH_INDEX_CREATE_FAILED, SEARCH_INDEX_DELETE_FAILED, SEARCH_SAVE_FAILED, SEARCH_SERVICE_ERROR 등 5개의 검색 관련 에러 코드 제거.
웹 API 및 테스트 정리
src/main/java/com/souzip/adapter/webapi/admin/AdminLocationApi.java, src/test/java/com/souzip/adapter/webapi/admin/AdminLocationApiTest.java
AdminLocationApi에서 여백 정리 및 개행 처리. AdminLocationApiTest에서 임포트 정리 (Mockito, RestDocumentationRequestBuilders, RequestDocumentation의 와일드카드를 명시적 멤버로 변경). BigDecimal, List 임포트 추가.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/NO-ISSUE-properties

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Develop-KIM Develop-KIM merged commit bb3c9e1 into develop Mar 11, 2026
3 of 4 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the admin location (country/city) read/write flow by removing the previous admin “required ports”, wiring admin services directly to domain repositories/ports, and extending city updates to include latitude/longitude updates.

Changes:

  • Replace CityQueryPort/CountryQueryPort/CityCommandPort usage with direct repository access (query) and CityManagementPort command dispatch (modify).
  • Extend city update command/entity behavior to update coordinates as well as names.
  • Remove unused search-related ErrorCode entries and apply import/formatting cleanups in admin API tests/controllers.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/test/java/com/souzip/adapter/webapi/admin/AdminLocationApiTest.java Import cleanups for REST Docs test.
src/main/java/com/souzip/global/exception/ErrorCode.java Removes search-related error codes.
src/main/java/com/souzip/domain/country/application/query/CountryQueryService.java Now implements CountryAdminPort (but currently has a compilation issue).
src/main/java/com/souzip/domain/city/entity/City.java City update now also updates lat/long.
src/main/java/com/souzip/domain/city/application/command/UpdateCityCommand.java Adds lat/long to update command.
src/main/java/com/souzip/domain/city/application/command/CityCommandService.java Uses new city update API (but currently has formatting + null-safety concerns).
src/main/java/com/souzip/application/admin/required/CountryQueryPort.java Deleted (admin required port removed).
src/main/java/com/souzip/application/admin/required/CityQueryPort.java Deleted (admin required port removed).
src/main/java/com/souzip/application/admin/required/CityCommandPort.java Deleted (admin required port removed).
src/main/java/com/souzip/application/admin/provided/AdminLocationModifier.java Formatting-only change.
src/main/java/com/souzip/application/admin/provided/AdminLocationFinder.java Formatting-only change.
src/main/java/com/souzip/application/admin/AdminLocationQueryService.java Implements admin queries via CityRepository/CountryRepository.
src/main/java/com/souzip/application/admin/AdminLocationModifyService.java Dispatches create/update/delete/priority via CityManagementPort + commands.
src/main/java/com/souzip/adapter/webapi/admin/AdminLocationApi.java Minor whitespace cleanup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +50 to +57
public void updateCity(UpdateCityCommand command) {
City city = findCityById(command.cityId());
city.update(
command.nameEn(),
command.nameKr(),
BigDecimal.valueOf(command.latitude()),
BigDecimal.valueOf(command.longitude())
);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CityCommandService converts boxed Double coordinates via BigDecimal.valueOf(command.latitude()) / ...longitude(). If either value is null this will throw an NPE at runtime. Add a null-validation step (or switch the command fields to non-null types like BigDecimal / primitive double) before converting.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +5
package com.souzip.domain.city.application.command;

import com.souzip.domain.city.application.port.CityManagementPort;
import com.souzip.domain.city.entity.City;
import com.souzip.domain.city.event.CityCreatedEvent;
import com.souzip.domain.city.event.CityDeletedEvent;
import com.souzip.domain.city.event.CityPriorityUpdatedEvent;
import com.souzip.domain.city.repository.CityRepository;
import com.souzip.domain.city.service.CityPriorityDomainService;
import com.souzip.domain.country.entity.Country;
import com.souzip.domain.country.repository.CountryRepository;
import com.souzip.global.exception.BusinessException;
import com.souzip.global.exception.ErrorCode;
import java.math.BigDecimal;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.souzip.domain.city.application.port.CityManagementPort;
import com.souzip.domain.city.entity.City;
import com.souzip.domain.city.event.CityCreatedEvent;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file appears to have an extra indentation prefix on the package/import lines and the rest of the code (leading spaces at the start of each line). It’s inconsistent with the rest of the Java sources and tends to create noisy diffs and formatting issues in IDEs/linters. Please reformat so package starts at column 0 and indentation is standard.

Copilot uses AI. Check for mistakes.
Comment on lines 25 to 30
public Page<City> getCities(Long countryId, String keyword, Pageable pageable) {
return cityQueryPort.getCities(countryId, keyword, pageable);
if (keyword == null || keyword.isBlank()) {
return cityRepository.findByCountryIdWithPaging(countryId, pageable);
}
return cityRepository.searchByKeyword(countryId, keyword, pageable);
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keyword is passed to cityRepository.searchByKeyword(...) without trimming, so inputs like " Seoul " will likely return no results. Note CityAdminQueryService trims the keyword before calling the same repository method. Consider applying keyword.trim() here as well to keep admin search behavior consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +27
cityManagementPort.createCity(new CreateCityCommand(
request.nameEn(),
request.nameKr(),
request.coordinate().getLatitude().doubleValue(),
request.coordinate().getLongitude().doubleValue(),
request.countryId()
));
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coordinates are converted BigDecimal -> double -> BigDecimal across the admin write path (Coordinate is BigDecimal, commands are Double, entity is BigDecimal). This can introduce precision loss and is unnecessary work. Prefer keeping coordinates as BigDecimal (or Coordinate) in the command layer so the value can be passed through without lossy conversion.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +38
cityManagementPort.updateCity(new UpdateCityCommand(
cityId,
request.nameEn(),
request.nameKr(),
request.coordinate().getLatitude().doubleValue(),
request.coordinate().getLongitude().doubleValue()
));
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as createCity(...): CityUpdateRequest coordinates are converted BigDecimal -> double -> BigDecimal, risking precision loss and adding avoidable conversions. Consider changing the command (and service) to accept BigDecimal/Coordinate so update passes validated values through directly.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to 21
@Override
public List<CountryAdminResult> getCountries(String keyword) {
if (hasNoKeyword(keyword)) {
return toResults(countryRepository.findAllByOrderByNameKrAsc());
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CountryAdminResult is a nested type in CountryAdminPort, but it’s referenced here without an import or qualification. This won’t compile after changing the import to CountryAdminPort. Import CountryAdminPort.CountryAdminResult (as done in tests) or reference it as CountryAdminPort.CountryAdminResult in the method signature/return types.

Copilot uses AI. Check for mistakes.
Comment on lines +65 to 70
public void update(String nameEn, String nameKr, BigDecimal latitude, BigDecimal longitude) {
this.nameEn = nameEn;
this.nameKr = nameKr;
this.latitude = latitude;
this.longitude = longitude;
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update(...) assigns latitude/longitude directly even though the columns are nullable = false. Since these parameters are nullable, this can lead to invalid entity state and a later persistence failure. Consider validating non-null (and ideally range, consistent with Coordinate) before assignment, or accept a validated value object like Coordinate instead of raw BigDecimals.

Copilot uses AI. Check for mistakes.
Comment on lines 3 to +8
public record UpdateCityCommand(
Long cityId,
String nameEn,
String nameKr
String nameKr,
Double latitude,
Double longitude
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UpdateCityCommand uses boxed Double for coordinates. This makes latitude/longitude nullable (risking NPEs where BigDecimal.valueOf(...) is used) and forces lossy BigDecimal -> double -> BigDecimal conversions in the admin flow. Prefer BigDecimal (or Coordinate) for these fields, or at least use primitive double if null is not allowed.

Copilot uses AI. Check for mistakes.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a187f7472

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

cityManagementPort.createCity(new CreateCityCommand(
request.nameEn(),
request.nameKr(),
request.coordinate().getLatitude().doubleValue(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 좌표 null 값을 변환하기 전에 유효성 검증하라

request.coordinate().getLatitude().doubleValue()를 바로 호출하면 coordinate 내부 필드가 비어 있는 요청(예: {"coordinate":{...}}에서 latitude/longitude 누락)에서 NullPointerException이 발생해 500으로 떨어집니다. CityCreateRequest/CityUpdateRequestcoordinate 객체 존재만 검증하고 내부 숫자 null은 막지 못하므로, 여기서 null 체크를 추가하거나 Coordinate 필드에 @NotNull 제약을 걸어 4xx로 일관되게 처리해야 합니다.

Useful? React with 👍 / 👎.

if (keyword == null || keyword.isBlank()) {
return cityRepository.findByCountryIdWithPaging(countryId, pageable);
}
return cityRepository.searchByKeyword(countryId, keyword, pageable);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 검색어를 trim 후 조회하도록 수정하라

현재는 공백 포함 키워드가 그대로 searchByKeyword로 전달되어, 사용자가 "서울 "처럼 앞뒤 공백을 포함해 입력하면 실제 데이터가 있어도 0건이 반환될 수 있습니다. 동일 도메인의 CityAdminQueryService는 조회 전에 keyword.trim()을 적용하고 있어 동작이 불일치하므로, 여기서도 trim 후 검색해야 검색 정확도 저하를 막을 수 있습니다.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoring 외부 동작은 유지하되 코드 구조를 개선하거나 유지보수성을 높이기 위한 내부 변경에 사용합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants