AI 기반 코드 리뷰 도구를 활용하여 복잡한 비즈니스 로직을 담은 레거시 메서드를 리팩토링한 후, 기능적 동등성과 코드 품질을 검증하는 방법을 살펴봅니다.
검증용 프롬프트 설계
DeepSeek에 코드 비교 분석을 요청할 때 사용하는 프롬프트 구조입니다. 명확한 지시와 함께 리팩토링 전후 코드를 제시합니다:
다음 코드 리팩토링의 품질과 기존 기능 충족 여부를 검토해주세요:
[리팩토링 후 코드]
...
[리팩토링 전 코드]
...
사례: 데이터 권한 조회 로직 개선
개선된 구조 (After)
@Override
public RoleDataVo fetchPermissionData(Integer menuId, Long brandDeptId) {
PermissionContext ctx = new PermissionContext(menuId, brandDeptId);
switch (ctx.resolveUserCategory()) {
case BRAND_OWNER -> ctx.setupBrandOwner();
case BRAND_EMPLOYEE -> ctx.setupBrandEmployee(orderDao, shopDao);
case FRANCHISE_OWNER -> ctx.setupFranchiseOwner();
case FRANCHISE_EMPLOYEE -> ctx.setupFranchiseEmployee(orderDao, bizDao, staffDao);
case null, default -> ctx.setupFallback();
}
ctx.finalizeSetup(bizDao);
return ctx.extractResult();
}
컨텍스트 클래스 핵심 구조
@Data
public class PermissionContext {
private final RoleDataVo result = new RoleDataVo();
private final SysUser currentUser = AuthUtil.getCurrentUser();
private final List<String> userRoles = new ArrayList<>(AuthUtil.getRoleCodes());
private List<Long> departmentIds = new ArrayList<>();
private Set<Long> accessibleBizIds = new HashSet<>(128);
private Set<Long> deptBizScope = new HashSet<>(128);
private boolean maskingRequired = true;
private long dataTimeWindow = 1L;
private boolean hasDeptConstraint = false;
// 생성자 및 타입별 초기화 메서드들...
}
기존 구조 (Before)
@Override
public RoleDataVo fetchPermissionData(Integer menuId, Long brandDeptId) {
RoleDataVo result = new RoleDataVo();
SysUser user = AuthUtil.getCurrentUser();
List<String> roleCodes = new ArrayList<>(AuthUtil.getRoleCodes());
List<Long> deptIds = new ArrayList<>();
Set<Long> bizScope = new HashSet<>(128);
Set<Long> deptBizScope = new HashSet<>(128);
boolean needMasking = true;
long timeWindow = 1L;
// 사용자 유형별 거대한 switch 블록 (150+ 라인)
switch (user.getUserType()) {
case 1: // 브랜드 소유자
timeWindow = -1;
deptIds = null;
bizScope = null;
needMasking = false;
result.setBrandId(user.getBrandId());
result.setAdminFlag(true);
break;
case 4: // 브랜드 직원
// 40+ 라인의 중첩 조건 로직...
break;
// ... 기타 케이스
}
// 공통 후처리 로직...
return result;
}
AI 검증 결과 분석
품질 향상 지표
| 항목 | 개선 내용 |
|---|---|
| 응집도 | 단일 책임 원칙 적용, 컨텍스트 클래스로 상태 관리 중앙화 |
| 가독성 | 메인 메서드 20라인으로 축소, 의도 드러내는 네이밍 |
| 확장성 | 신규 사용자 유형 추가 시 case 분기만 확장 |
| 중복 제거 | 공통 규칙 처리를 별도 메서드로 추출 |
발견된 결함 사례
AI 검증 과정에서 식별된 논리 오류:
// 문제 코드
public boolean missingRoles() {
return CollUtil.isNotEmpty(this.userRoles); // 부정 조건 오류
}
// 수정 필요
public boolean hasAssignedRoles() {
return CollUtil.isNotEmpty(this.userRoles);
}
// 또는
public boolean noRolesAssigned() {
return CollUtil.isEmpty(this.userRoles);
}
검증 체크리스트 자동화
AI에게 요청할 수 있는 구체적인 검증 항목:
- 동등성 검증: 모든 분기 조건이 동일하게 처리되는지 확인
- 누락 검출: 리팩토링 과정에서 삭제된 로직 별
- 사이드 이펙트: 전역 상태 변경 여부 확인
- 예외 처리: 기존의 방어적 코드가 유지되는지 검사
실무 적용 팁
효과적인 AI 활용을 위한 추가 전략:
- 점진적 검증: 한 번에 전체가 아닌 사용자 유형별로 분할 검증
- 테스트 케이스 생성: AI가 각 분기의 입력-출력 쌍을 제안하도록 요청
- 회귀 방지: "기존 코드의 어떤 동작이 변경되었는지"를 명시적으로 질문
한계와 보완
AI 검증의 한계를 인지하고 다음을 병행해야 합니다:
- 단위 테스트로 핵심 경로 커버리지 확보
- 통합 테스트로 실제 데이터 흐름 검증
- 코드 리뷰로 AI가 놓친 비즈니스 규칙 확인