AI 리팩토링, 레거시 코드를 안전하게 바꾸는 질문법

profile_image
작성자 레거시개선연구가 강예준
댓글 0건 조회 4회

AI에게 오래된 코드를 건넨 뒤 “깔끔하게 고쳐 줘”라고 요청했는데, 겉모습만 현대적으로 바뀌고 핵심 기능은 오히려 망가진 경험이 있으신가요? AI 리팩토링의 성패는 모델의 코딩 능력보다 사용자가 변경 범위와 보존 조건을 얼마나 정확히 설명했는지에 따라 크게 달라집니다.

이번 인터뷰에서는 레거시 시스템 개선을 맡아 온 소프트웨어 아키텍트 강예준에게 AI 코딩 프롬프트 작성법, 안전한 작업 순서, 비용과 도구 선택, 결과 검증 기준을 물었습니다. 단순히 프롬프트 예문을 나열하는 대신 실제 프로젝트에서 무엇을 먼저 확인하고 어디서 작업을 멈춰야 하는지 깊이 있게 짚습니다.

AI 리팩토링은 왜 한 번에 맡기면 위험한가

Q. 코드 전체를 붙여 넣고 개선을 요청하면 왜 결과가 흔들리나요?

강예준: AI는 화면에 보이는 코드만으로 시스템의 역사와 숨은 계약까지 완벽하게 알 수 없습니다. 예를 들어 이름이 이상한 함수라도 외부 배치 프로그램이 그 이름을 직접 호출할 수 있고, 중복처럼 보이는 조건문도 과거 장애를 막기 위해 남겨 둔 방어 로직일 수 있습니다. 사용자는 이를 업무 지식으로 알고 있지만 AI에게 전달하지 않으면 모델은 일반적인 모범 사례를 기준으로 코드를 재구성합니다.

특히 “전체 구조를 최신 방식으로 바꿔 줘”라는 요청은 수정 범위를 무제한으로 엽니다. 함수 이름, 데이터 형식, 예외 처리, 의존성 버전이 동시에 변하면 오류가 발생했을 때 원인을 찾기 어렵습니다. 좋은 리팩토링은 큰 변화를 만드는 작업이 아니라, 동작을 보존하면서 작은 변화를 검증 가능한 단위로 쌓는 작업입니다.

독자 여러분의 코드에는 문서에 기록되지 않은 규칙이 몇 개나 있을까요? 할인 금액의 소수점 처리, 빈 문자열과 null의 구분, 특정 오류 코드 유지처럼 사소해 보이는 조건이 실제 서비스에서는 계약입니다. AI에게 코드를 맡기기 전에는 아래 정보를 최소 입력값으로 준비해야 합니다.

  • 현재 동작: 입력과 출력의 예시, 정상 흐름과 실패 흐름을 각각 적습니다.
  • 변경 목적: 가독성, 성능, 중복 제거, 테스트 용이성 중 우선순위 하나를 지정합니다.
  • 보존 조건: 공개 API, 함수 시그니처, 데이터베이스 스키마, 오류 메시지 등 바꾸면 안 되는 대상을 선언합니다.
  • 허용 범위: 수정 가능한 파일과 새로 만들 수 있는 파일, 패키지 추가 가능 여부를 알려 줍니다.
  • 검증 수단: 실행할 테스트 명령과 통과 기준, 성능 기준값을 제공합니다.
전문가 조언: “리팩토링해 줘”보다 “외부 동작을 보존한 채 이 함수의 조건 분기만 단순화하고, 변경 전에 특성 테스트를 제안해 줘”가 훨씬 안전한 요청입니다.

Q. AI가 제안한 코드는 어디까지 신뢰해도 됩니까?

강예준: AI의 답변은 완성품보다 검토가 필요한 변경 후보로 다뤄야 합니다. 문법적으로 정확한 코드도 동시성, 권한, 개인정보, 트랜잭션 경계에서는 잘못된 판단을 포함할 수 있습니다. 특히 입력 검증이나 인증 로직을 단순화할 때는 일반 리팩토링보다 엄격한 검토가 필요하며, 배경 개념은 코드 보안 관련 지식백과 설명도 함께 참고할 수 있습니다.

좋은 질문은 코드보다 먼저 경계를 설계한다

Q. 실무에서 사용하는 AI 코딩 프롬프트 구조가 있나요?

강예준: 저는 프롬프트를 역할, 상황, 목표, 제약, 절차, 출력 형식의 여섯 부분으로 나눕니다. 역할만 “시니어 개발자처럼 답해 줘”라고 지정하는 방식은 효과가 제한적입니다. 모델이 어떤 판단을 해야 하는지보다 어떤 판단을 해서는 안 되는지를 명시할 때 결과가 더 안정적으로 좁혀집니다.

상황에는 언어와 프레임워크 이름만 적지 말고 실행 환경과 코드의 책임을 포함해야 합니다. “Java 서비스”보다는 “주문 취소를 처리하는 Java 애플리케이션 서비스이며, 외부 결제 API 재호출을 막아야 한다”가 좋습니다. 목표도 “클린 코드로 변경”이 아니라 “중첩 조건을 줄이되 반환값과 예외 유형은 유지”처럼 관찰 가능한 문장으로 바꿔야 합니다.

다음 틀은 특정 AI 도구에 종속되지 않습니다. 코드 조각을 붙이기 전에 대괄호 부분을 프로젝트 상황에 맞게 채우고, 민감한 값과 실제 고객 데이터는 제거하세요.

  1. 역할: “당신은 [언어]와 [프레임워크]의 리팩토링 리뷰어다.”
  2. 상황: “이 코드는 [업무 기능]을 담당하며 [호출 관계]에서 사용된다.”
  3. 목표: “외부 동작을 유지하면서 [한 가지 문제]를 개선한다.”
  4. 제약: “[공개 API·스키마·라이브러리]는 변경하지 않는다.”
  5. 절차: “먼저 위험과 가정을 열거하고, 모호한 점은 질문한 뒤 수정안을 제시한다.”
  6. 출력: “변경 이유, 패치, 추가 테스트, 남은 위험을 구분해 작성한다.”

Q. AI가 코드를 바로 수정하지 않고 먼저 질문하게 만들 수 있나요?

강예준: 가능합니다. 프롬프트 끝에 “정보가 부족하면 구현하지 말고 최대 다섯 개의 확인 질문을 우선 제시하라”고 적어 보세요. 이 한 문장이 환각을 완전히 없애지는 못하지만, 모델이 임의로 가정하는 상황을 눈에 띄게 줄여 줍니다. 답변을 받은 뒤에는 가정 목록을 다시 출력하게 하고 사용자가 승인한 항목만 기반으로 작업하도록 이어 가면 좋습니다.

질문은 단계별로 분리해야 합니다. 첫 대화에서는 코드의 책임과 위험만 분석하고, 두 번째에서는 테스트 케이스를 만들며, 세 번째에서 최소 패치를 요청합니다. 마지막에는 “수정된 줄마다 어떤 기존 동작을 보존하는가”를 설명하게 하세요. 이 방식은 토큰을 조금 더 사용하지만 잘못된 대규모 변경을 되돌리는 시간보다 대개 저렴합니다.

  • 1차 질문: 이 코드에서 추론할 수 없는 업무 규칙은 무엇인가?
  • 2차 질문: 리팩토링 전에 고정해야 할 현재 동작과 엣지 케이스는 무엇인가?
  • 3차 질문: 목표 달성을 위한 최소 변경 파일은 어디인가?
  • 4차 질문: 제안한 변경이 실패할 수 있는 반례를 세 가지 만들어 달라.
  • 5차 질문: 사람이 반드시 검토해야 할 보안·성능·데이터 항목을 표시해 달라.
AI에게 좋은 답을 강요하기보다 성급한 구현을 보류할 조건을 알려 주는 것이 효과적입니다. 모호함을 발견하는 능력도 코딩 능력의 일부입니다.

패치 크기와 테스트 순서가 품질을 결정한다

Q. 실제 저장소에서는 어떤 순서로 작업해야 안전할까요?

강예준: 가장 먼저 현재 동작을 고정하는 특성 테스트를 만듭니다. 특성 테스트는 코드가 이상적으로 어떻게 작동해야 하는지가 아니라 지금 어떤 입력에 어떤 결과를 내는지를 기록합니다. 오래된 코드에 버그처럼 보이는 동작이 있어도 즉시 고치지 않고 테스트로 드러낸 뒤, 버그 수정과 구조 개선을 별도 변경으로 나누는 것이 핵심입니다.

그다음 AI에게 함수 하나나 모듈 하나의 분석을 요청하고, 영향받는 호출 지점을 찾게 합니다. 하지만 AI가 찾았다는 이유만으로 목록이 완전하다고 믿어서는 안 됩니다. 정적 검색, 타입 검사, 테스트 커버리지, 실행 로그를 함께 확인해야 합니다. 코드 생성 결과와 저장소의 실제 의존 관계가 다르면 사람이 확인한 저장소 정보가 우선입니다.

권장 흐름은 아래와 같습니다. 단계 하나가 실패하면 다음 단계로 넘어가지 않는 방식이 좋습니다. 여러분이 리뷰어라면 한 번에 2천 줄이 바뀐 패치와 목적별로 80줄씩 나뉜 패치 중 어느 쪽을 더 정확하게 검토할 수 있을지 떠올려 보세요.

  1. 기준선 확보: 기존 테스트, 빌드 시간, 핵심 API 응답, 성능 수치를 기록합니다.
  2. 특성 테스트 추가: 정상 입력뿐 아니라 빈 값, 경계값, 중복 요청, 외부 API 실패를 포함합니다.
  3. 영향 범위 탐색: 호출자, 인터페이스 구현체, 직렬화 형식, 설정 파일을 확인합니다.
  4. 최소 패치 생성: 이름 변경과 로직 변경을 한 패치에 섞지 않고 한 목적만 수행합니다.
  5. 자동 검증: 포매터, 린터, 타입 검사, 단위 테스트, 통합 테스트 순으로 실행합니다.
  6. 수동 검토: 권한 검사, 트랜잭션, 로그의 개인정보, 시간대, 재시도 동작을 살핍니다.
  7. 점진적 배포: 가능한 환경이라면 제한된 트래픽에서 오류율과 지연 시간을 비교합니다.

Q. 테스트가 거의 없는 레거시 코드라면 비용이 너무 커지지 않나요?

강예준: 전체 테스트 체계를 한 번에 만들 필요는 없습니다. 변경하려는 경계부터 얇게 감싸면 됩니다. 예를 들어 데이터베이스와 결제 API가 얽힌 함수라면 내부 구현을 모두 단위 테스트하려 하지 말고, 대표 입력에 대한 반환값과 외부 호출 횟수를 먼저 고정합니다. 이때 AI에게 테스트를 작성하게 할 수 있지만, 테스트가 현재 구현을 그대로 복사한 것은 아닌지 사람이 확인해야 합니다.

비용은 구독료만으로 계산하면 안 됩니다. 작은 코드 조각을 다루는 작업은 무료 또는 저가 요금제에서도 가능하지만, 큰 저장소 탐색과 긴 컨텍스트, 조직 보안 정책, 감사 로그가 필요하면 팀용 환경이 유리할 수 있습니다. 반대로 중요한 파일만 선별하고 질문을 분할하면 고가 모델을 매 요청에 사용할 이유가 줄어듭니다. 저비용 모델로 영향 범위를 정리하고, 고난도 변경과 최종 리뷰에 성능이 높은 모델을 배치하는 방식도 현실적인 선택입니다.

작업 유형AI에 맡길 범위사람이 확인할 기준
이름·구조 개선후보 명칭과 최소 패치공개 API와 직렬화 이름 유지
중복 로직 제거공통점과 차이점 분석분기별 업무 규칙 손실 여부
테스트 생성경계값과 실패 사례 초안구현 복제 여부와 실제 기대값
성능 개선병목 가설과 측정 코드실측 결과와 메모리 사용량
보안 관련 변경위험 지점 식별과 대안 제안권한 우회, 입력 검증, 비밀정보 노출

보안 수정에서는 단순히 취약한 함수를 안전한 함수로 치환하는 데 그치지 말아야 합니다. 위협의 원인과 보호 대상, 공격 경로를 함께 검토해야 하며 코드 보안 요약 자료처럼 기본 원칙을 확인한 뒤 조직의 보안 기준과 대조하는 과정이 필요합니다.

좋은 코드는 반드시 더 짧아야 한다는 주장에 답하다

Q. AI를 쓰면 코드가 짧고 현대적으로 바뀌니 그것만으로 성공 아닌가요?

강예준: 코드가 짧아지는 것은 결과일 수 있지만 목표가 되어서는 안 됩니다. 세 줄짜리 고차 함수가 열 줄짜리 반복문보다 간결해 보여도 팀원이 익숙하지 않거나 디버깅이 어려우면 유지보수 비용은 증가합니다. 반대로 명시적인 조건문을 조금 더 남겨 두는 편이 금융 계산이나 권한 판정처럼 업무 규칙을 드러내는 데 유리할 때도 있습니다.

최신 문법과 새 라이브러리 도입 역시 항상 정답은 아닙니다. 런타임 버전이 고정된 서비스, 지원 종료가 임박한 외부 제품과 연동하는 서비스, 배포 승인이 오래 걸리는 조직에서는 의존성을 늘리지 않는 선택이 더 안전할 수 있습니다. AI는 보편적인 개발 관행을 추천하기 쉽지만, 좋은 코드는 특정 팀이 실제로 운영하고 고칠 수 있는 코드라는 기준을 놓치면 안 됩니다.

따라서 최종 리뷰에서는 줄 수보다 이해 가능성과 변경 가능성을 질문해야 합니다. 새로 합류한 개발자가 함수의 책임을 설명할 수 있는지, 장애가 발생했을 때 로그로 분기 지점을 찾을 수 있는지, 이전 버전으로 되돌릴 수 있는지를 확인하세요. 아래 질문에 명확히 답하지 못한다면 패치가 세련되어 보여도 병합을 잠시 보류할 이유가 충분합니다.

  • 설명 가능성: 변경 이유를 코드 스타일 취향이 아니라 실제 문제와 연결해 설명할 수 있는가?
  • 행동 보존: 기존 입력과 출력, 예외, 부수 효과가 테스트로 고정되어 있는가?
  • 운영 가능성: 오류 발생 시 로그와 지표로 변경 전후를 구분할 수 있는가?
  • 복구 가능성: 데이터 변환 없이 이전 버전으로 되돌릴 수 있는가?
  • 팀 적합성: 현재 팀이 새 추상화와 문법을 리뷰하고 유지할 수 있는가?

Q. 그렇다면 AI 리팩토링을 아예 사용하지 않는 편이 낫다는 의견도 타당합니까?

강예준: 충분히 타당한 상황이 있습니다. 테스트할 수 없는 안전 필수 시스템, 법적 검토 없이 외부 도구에 코드를 전달할 수 없는 환경, 소유권과 책임자가 불분명한 저장소라면 AI 도입보다 문서화와 접근 통제부터 해결해야 합니다. 또한 변경 규모가 매우 작고 숙련 개발자가 맥락을 완전히 이해한다면 AI와 대화하는 시간이 직접 수정하는 시간보다 길 수도 있습니다.

다만 사용 여부를 찬반으로만 나눌 필요는 없습니다. 코드를 외부에 보내지 않고도 요구사항을 질문 목록으로 바꾸거나, 익명화한 의사 코드로 엣지 케이스를 탐색하거나, 완료된 패치의 리뷰 관점을 얻는 제한적 활용이 가능합니다. 반대 의견이 제기될 때는 생산성 수치만 내세우기보다 어떤 데이터가 입력되고 어디에 보관되며 누가 결과를 승인하는지 먼저 공개하는 편이 신뢰를 높입니다.

현장 기준: AI가 없어도 검증할 수 있는 작업에 AI를 사용하고, AI 없이는 옳고 그름을 판단할 수 없는 작업에는 먼저 사람의 지식과 테스트를 보강하세요.

결국 중요한 선택은 “AI를 쓸 것인가”가 아니라 “어떤 판단까지 위임할 것인가”입니다. 초안 생성과 대안 탐색은 빠르게 맡길 수 있지만 업무 규칙 승인, 보안 위험 수용, 배포 결정은 책임 있는 사람이 맡아야 합니다. 때로는 리팩토링을 하지 않고 이해하기 어려운 부분에 설명과 테스트만 추가하는 선택이 가장 전문적인 개선이 될 수 있습니다.

댓글목록

등록된 댓글이 없습니다.