Skip to main content

GitHub Copilot을 사용하여 레거시 코드 현대화

Copilot Chat은 리팩터를 제안하고 잠재적인 문제를 파악하기 위한 테스트를 만들어 레거시 코드를 현대화하는 데 도움이 됩니다.

Note

이 문서에 표시된 응답은 예제입니다. Copilot Chat 응답은 비결정적이므로 여기에 표시된 응답과 다른 응답을 얻을 수 있습니다.

레거시 코드란 원조 개발자가 더 이상 지원하지 않는 오래된 코드를 의미합니다. 일관된 명명 규칙을 사용하거나 명확한 문서를 작성하는 등의 최신 모범 사례를 따르지 않을 수 있으므로 유지 관리 및 확장이 어려울 수 있습니다.

레거시 코드를 현대화하면 다음과 같은 지원을 받을 수 있습니다.

  • 성능 및 확장성을 개선합니다.
  • 코드를 더 쉽게 유지 관리하고 확장할 수 있습니다.
  • 변경 작업을 수행할 때 버그가 발생할 위험을 줄입니다.
  • 코드를 테스트하기 쉽게 만듭니다.

Copilot은 다음을 통해 레거시 코드를 현대화하는 데 도움이 될 수 있습니다.

  • 최신 모범 사례를 따르도록 코드를 리팩터링하기 위한 제안을 제공합니다.
  • 코드 작동 방식을 이해하는 데 도움이 되는 문서를 생성합니다.
  • 변경 작업을 수행할 때 버그가 발생하지 않았는지 확인하는 데 도움이 되는 테스트를 생성합니다.

예제 시나리오

이 예제에서는 COBOL로 작성된 계정 관리 시스템을 살펴보고 이를 Node.js로 현대화합니다. COBOL 코드는 modernize-legacy-cobol-app 리포지토리에서 찾을 수 있습니다.

계정 관리 시스템은 다음 세 가지 키 파일로 구성됩니다.

  • main.cob: 사용자로부터 입력을 받아 적절한 하위 프로그램을 호출하는 주요 프로그램입니다.
  • operations.cob: 신용, 직불, 잔액 보기와 같은 계정 데이터에 대한 작업을 수행하는 하위 프로그램입니다.
  • data.cob: 계정 잔액의 스토리지를 관리하는 하위 프로그램입니다.

1단계: 리포지토리의 로컬 복사본 가져오기

프로그램을 컴파일하고 실행하기 전에 코드를 로컬에 두어야 합니다. 리포지토리를 아직 복제하지 않은 경우 프로젝트를 저장할 디렉터리로 이동하여 다음 명령을 실행합니다.

Shell
git clone https://github.com/continuous-copilot/modernize-legacy-cobol-app.git

2단계: 프로그램 컴파일 및 실행

선호하는 개발 환경(예: 오픈 소스 GnuCOBOL 컴파일러)에 COBOL 컴파일러를 설치하거나 GitHub Codespaces의 Copilot Chat을 사용할 수 있습니다.

MacOS를 사용하는 경우 Homebrew를 사용하여 GnuCOBOL을 설치할 수 있습니다.

Shell
brew install gnu-cobol

Codespaces나 Ubuntu Linux 시스템을 사용하는 경우 apt를 사용하여 GnuCOBOL을 설치할 수 있습니다.

Shell
sudo apt-get update && \
sudo apt-get install gnucobol

코드를 컴파일하고, 파일을 연결하고, 실행 파일을 만들려면 리포지토리 루트에서 다음 명령을 실행합니다.

Shell
cobc -x main.cob operations.cob data.cob -o accountsystem

프로그램을 실행하려면 다음 명령을 사용하세요.

Shell
./accountsystem

3단계: 파일 및 코드 설명

코드를 현대화하는 첫 번째 단계는 코드의 작동 방식을 이해하는 것입니다. Copilot Chat에 각 파일의 코드를 설명해 달라고 요청할 수 있습니다.

IDE에서 리포지토리를 연 다음, Copilot Chat 패널에 다음 프롬프트를 입력합니다.

예제 프롬프트 1

/explain #file:main.cob #file:operations.cob #file:data.cob Can you please create a high level overview of the app. It will be great if you can explain each file in detail and how they are linked.

예제 응답 1

위의 프롬프트에 대한 응답에서 발췌한 내용입니다.

Sure! Here's a high-level overview of the COBOL application, along with detailed explanations of each file and how they are linked together.

High-Level Overview

This COBOL application simulates an account management system. It allows users to view the current balance, credit the account, debit the account, and exit the application. The application is divided into three main COBOL source files: main.cob, operations.cob, and data.cob. ...

4단계: 파일 간의 데이터 흐름 차트

다음 단계는 파일이 어떻게 연결되어 있는지 이해하는 것입니다. @workspace를 사용하여 애플리케이션의 데이터 흐름 다이어그램을 만들 수 있습니다.

Note

VS Code 및 Visual Studio의 채팅 참가자는 @workspace Copilot에게 작업 영역의 모든 코드에 대한 컨텍스트를 제공합니다. Copilot가 프로젝트의 구조, 코드의 여러 부분이 상호 작용을 하는 방식을 고려하도록 하려면 @workspace를 사용하세요. JetBrains IDE를 사용하는 경우 @workspace 대신 @project를 사용합니다.

예제 프롬프트 2

@workspace can you create a sequence diagram of the app showing the data flow of the app. Please create this in mermaid format so that I can render this in a markdown file.

Copilot은 애플리케이션의 작동 방식을 보여 주는 전체 시퀀스 다이어그램에 대한 Mermaid 마크업을 출력합니다. 이 마크업을 복사하여 Mermaid 애플리케이션에 붙여넣어 다이어그램을 생성할 수 있습니다.

5단계: 테스트 계획 생성

변경 작업을 수행한 후, 애플리케이션이 예상대로 작동하는지 확인하기 위해 테스트 계획을 수립하세요. @workspace를 사용하여 프로젝트의 모든 파일을 다루는 테스트 계획을 생성할 수 있습니다.

예제 프롬프트 3

@workspace The current Cobol app has no tests. Can you please create a test plan of current business logic that I can use to validate with business stakeholders about the current implementation.

Later I would like to use this test plan to create unit and integration tests in a node.js app. I am in the middle of transforming the current Cobol app to a node.js app.

The test plan should include the following:

1. Test Case ID
2. Test Case Description
3. Pre-conditions
4. Test Steps
5. Expected Result
6. Actual Result
7. Status (Pass/Fail)
8. Comments

Please create the test plan in a markdown table format. The test plan should cover all the business logic in the current Cobol app.

Convert this to markdown syntax to insert as a new file

Copilot은 애플리케이션의 유효성을 검사하는 데 사용할 수 있는 Markdown 형식의 테스트 계획을 출력합니다. 이 계획을 나중에 프로세스에서 사용하려면 TESTPLAN.md이라는 파일을 만들고 제안된 계획을 여기에 복사하세요. 이렇게 하면 다음 단계에서 테스트 사례를 생성할 때 테스트 계획을 참조할 수 있습니다.

6단계: 파일을 COBOL에서 Node.js로 변환

다음 단계는 COBOL 파일을 Node.js로 변환하는 것입니다. 다음과 같은 프롬프트 작성 방법을 염두에 두는 것이 중요합니다.

  • 컨텍스트 제공
  • 명확한 지침 제공
  • 달성하고자 하는 결과에 대한 구체적으로 설명

프로젝트 내에 임시 디렉토리를 만들고, 여기에 만들려는 JavaScript 파일을 저장하세요.

Shell
mkdir temp-JS-project-directory

그런 다음, 반복적으로 COBOL 파일을 Node.js로 변환합니다.

예제 프롬프트 4

Can you convert code in #file:main.cob to node.js?

예제 응답 4

Sure! Here is the equivalent Node.js code for the main.cob file. This code will simulate the same account management system functionality.

### COBOL Code:

main.cob

```COBOL
IDENTIFICATION DIVISION.
       PROGRAM-ID. MainProgram.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  CONTINUE-FLAG      PIC X VALUE 'Y'.
       01  USER-CHOICE        PIC 9.
       01  FINAL-BALANCE      PIC 9(6)V99 VALUE 1000.00.

       PROCEDURE DIVISION.
           PERFORM UNTIL CONTINUE-FLAG = 'N'
               DISPLAY "1. View Balance"
               DISPLAY "2. Credit Account"
               DISPLAY "3. Debit Account"
               DISPLAY "4. Exit"
               ACCEPT USER-CHOICE

               EVALUATE USER-CHOICE
                   WHEN 1
                       CALL 'Operations' USING 'TOTAL'
                   WHEN 2
                       CALL 'Operations' USING 'CREDIT'
                   WHEN 3
                       CALL 'Operations' USING 'DEBIT'
                   WHEN 4
                       MOVE 'N' TO CONTINUE-FLAG
                       DISPLAY "Exiting the program. Goodbye!"
                   WHEN OTHER
                       DISPLAY "Invalid choice. Please try again."
               END-EVALUATE
           END-PERFORM
           STOP RUN.

### Node.js Code: `main.js`
```javascript
const readline = require('readline');

let continueFlag = 'Y';
let finalBalance = 1000.00;

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

function displayMenu() {
    console.log("1. View Balance");
    console.log("2. Credit Account");
    console.log("3. Debit Account");
    console.log("4. Exit");
}

function handleUserChoice(choice) {
    switch (choice) {
        case '1':
            viewBalance();
            break;
        case '2':
            creditAccount();
            break;
        case '3':
            debitAccount();
            break;
        case '4':
            continueFlag = 'N';
            console.log("Exiting the program. Goodbye!");
            rl.close();
            break;
        default:
            console.log("Invalid choice. Please try again.");
            promptUser();
            break;
    }
}

function viewBalance() {
    console.log(`Current balance: ${finalBalance.toFixed(2)}`);
    promptUser();
}

function creditAccount() {
    rl.question("Enter credit amount: ", (amount) => {
        amount = parseFloat(amount);
        if (!isNaN(amount) && amount > 0) {
            finalBalance += amount;
            console.log(`Amount credited. New balance: ${finalBalance.toFixed(2)}`);
        } else {
            console.log("Invalid amount. Please try again.");
        }
        promptUser();
    });
}

function debitAccount() {
    rl.question("Enter debit amount: ", (amount) => {
        amount = parseFloat(amount);
        if (!isNaN(amount) && amount > 0) {
            if (finalBalance >= amount) {
                finalBalance -= amount;
                console.log(`Amount debited. New balance: ${finalBalance.toFixed(2)}`);
            } else {
                console.log("Insufficient funds for this debit.");
            }
        } else {
            console.log("Invalid amount. Please try again.");
        }
        promptUser();
    });
}

function promptUser() {
    if (continueFlag === 'Y') {
        displayMenu();
        rl.question("Select an option: ", handleUserChoice);
    }
}

promptUser();

This Node.js code replicates the functionality of the COBOL main.cob file, providing a simple command-line interface for viewing the balance, crediting the account, debiting the account, and exiting the application.

제안된 코드를 사용하기 전에 철저히 검토해야 합니다. 생성된 코드에 만족하면 다음 단계에 따라 코드를 로컬로 저장하고 변환을 완료합니다.

  1. 이전에 만든 임시 디렉터리에 main.js라는 새 파일을 만듭니다.
  2. 생성된 코드를 Copilot Chat 패널에서 복사하여 main.js에 붙여넣습니다.
  3. 파일을 저장합니다.
  4. 비슷한 프롬프트를 사용하여 operations.cobdata.cob을 Node.js로 변환합니다.
  5. 동일한 임시 디렉토리에 해당하는 JavaScript 파일 operations.jsdata.js를 생성합니다.
  6. 생성된 코드를 각 파일에 복사하여 붙여넣은 다음 저장합니다.

모든 파일을 Node.js로 변환한 후에는 파일을 서로 연결하고 작동하는 Node.js 프로젝트를 설정해야 합니다.

  1. 터미널의 임시 디렉터리로 이동합니다.

  2. 다음 명령을 실행하여 package.json 파일을 만듭니다.

    Shell
    npm init -y
    
  3. 애플리케이션에 외부 패키지가 필요한 경우 다음을 실행하여 설치합니다.

    Shell
    npm install
    
  4. 다음을 실행하여 앱을 실행합니다.

    Shell
    npm start
    

이 시점에서 Node.js 애플리케이션은 원래 COBOL 프로그램의 기능을 완전히 복제하지 못할 수 있습니다. 예를 들어, 잔액이 올바르게 업데이트되지 않거나 계산이 COBOL 논리와 일치하지 않을 수 있습니다.

애플리케이션을 구체화하려면 다음을 수행해야 합니다.

  • 잘못된 동작을 식별하기 위해 프로그램을 실행하고 COBOL 버전과 비교합니다.

  • Copilot을 사용하여 반복적으로 작업하여 Node.js 프로그램이 예상대로 동작할 때까지 논리를 조정합니다.

  • 대상이 지정된 프롬프트를 사용하여 다음과 같은 코드의 특정 부분을 디버깅하고 개선합니다.

    @workspace - analyze main.js and ensure account balance updates correctly when crediting an account.

레거시 코드 리팩터링이 항상 한 단계 프로세스인 것은 아닙니다. Copilot은 새 Node.js 구현을 구체화할 때 기능을 디버깅하고 개선하는 데 도움이 될 수 있습니다.

8단계: 단위 및 통합 테스트 생성

다음 단계는 단위 테스트 및 통합 테스트를 생성하여 애플리케이션이 예상대로 작동하는지 확인하는 것입니다. @workspace를 사용하여 프로젝트의 모든 파일을 다루는 테스트 계획을 생성할 수 있습니다.

예제 프롬프트 5

@workspace I would like to create unit and integration tests cases from the test plan mentioned in #file:TESTPLAN.md file The node.js code is in node-accounting-app folder and I am looking to generate tests for #file:operations.js file. Use a popular testing framework and also provide all the dependencies required to run the tests.

예제 응답 5

Copilot은 JavaScript 테스트 프레임워크인 Jest에서 여러 테스트를 생성하며, 이를 구현하고 실행하는 방법에 대한 전체 단계별 가이드를 제공합니다.

위의 프롬프트에 대한 응답에서 발췌한 내용입니다.

“This test plan covers the main functionalities of the COBOL application, including viewing the balance, crediting the account, debiting the account, and exiting the application. The test cases are implemented using Jest, a popular testing framework for Node.js. Validate this test plan with the business stakeholders to ensure it meets the business requirements. Once validated, you can use this plan to create corresponding unit tests and integration tests for the Node.js application.”

9단계: 테스트 실행 및 코드 구체화

테스트 계획을 생성하고 테스트를 작성한 후에는 테스트 계획을 실행하고 실패한 테스트를 수정해야 합니다. 테스트는 반복적인 프로세스이므로 문제를 해결하기 위해 코드를 수정한 다음, 모든 것이 통과될 때까지 테스트를 다시 실행해야 할 수 있습니다.

테스트가 실패하면 Copilot을 사용하여 디버깅을 돕고 구현을 개선합니다.

예제 프롬프트 6

@workspace - analyze test failures in operations.test.js and suggest fixes to match the expected behavior.

모든 테스트가 통과하더라도 프로그램에는 여전히 문제가 있을 수 있습니다. 자동화된 테스트가 누락된 기능이나 논리 오류를 항상 포착하지는 않으므로 애플리케이션이 예상대로 작동하는지 확인하려면 수동 테스트가 필요합니다.

10단계: JavaScript 프로젝트를 새 위치로 이동

애플리케이션이 예상대로 작동하면 새 JavaScript 프로젝트를 COBOL 디렉터리 밖으로 옮겨 별도로 유지합니다.

  1. COBOL 프로젝트의 부모 디렉터리로 이동합니다.

  2. JavaScript 프로젝트를 새 위치로 이동합니다.

    Shell
    mv modernize-legacy-cobol-app new-js-project
    
  3. 새 프로젝트 디렉터리로 이동하여 모든 항목이 올바르게 실행되는지 확인합니다.

    Shell
    cd new-js-project
    npm start
    

이제 리팩터링된 Node.js 애플리케이션은 원본 COBOL 파일과는 별도로 분리된 자체 독립 실행형 프로젝트 폴더에 있습니다.

결론

이 예제에서는 COBOL로 작성된 계정 관리 시스템을 살펴보고 Node.js로 현대화했습니다. Copilot Chat을 사용하여 코드를 설명하고, 데이터 흐름을 차트로 표시하고, 테스트 계획을 생성하고, 코드를 Node.js로 변환했습니다. 이러한 단계를 수행하면 레거시 코드를 현대화하고 더 쉽게 유지 관리 및 확장할 수 있습니다. 레거시 코드를 현대화하기 위한 몇 가지 추가 팁은 다음과 같습니다.

  • 모범 사례를 촉구하는 것이 핵심입니다. 프롬프트의 품질이 Copilot의 제안 품질을 결정합니다. 명확한 컨텍스트를 제공하고, 복잡한 작업을 더 작은 단계로 분할하고, 예제를 제시하고, Copilot이 달성하기 위한 특정 목표를 제공합니다. 이렇게 하면 워크플로가 더 원활해지고 결과가 더욱 정확해집니다.
  • 코드를 사용하기 전에 검토합니다. 애플리케이션에서 코드를 사용하기 전에 Copilot이 제공하는 코드를 이해했는지 확인하세요. 이렇게 하면 잠재적인 문제를 파악하고 코드가 요구 사항을 충족하는지 확인하는 데 도움이 됩니다.
  • 변경 내용의 유효성을 검사합니다. 코드를 변경한 후에도 애플리케이션이 예상대로 작동하는지 확인하는 것이 중요합니다. Copilot에서 생성한 테스트 계획을 사용하여 애플리케이션에 대한 단위 및 통합 테스트를 만들 수 있습니다.

추가 참고 자료