Skip to main content

Copilot을 사용하여 프로젝트를 다른 프로그래밍 언어로 마이그레이션

GitHub Copilot Chat은 프로젝트를 다른 언어로 이동하는 데 도움이 될 수 있습니다. 이 가이드에서는 마이그레이션 프로세스에 관련된 내용을 설명하고 PHP에서 Python으로 마이그레이션하는 예제를 제공합니다.

소개

프로젝트를 새 프로그래밍 언어로 마이그레이션하는 작업은 어렵고 시간이 많이 소요되는 작업일 수 있습니다. GitHub Copilot은 필요한 변경 내용을 설명하고 새 언어로 대체 코드를 제안하여 이 프로세스에 도움이 될 수 있습니다.

프로젝트를 새 언어로 마이그레이션하는 원칙

마이그레이션 프로세스를 시작하기 전에 다음 사항을 고려합니다.

  • 코딩 지식

    두 프로그래밍 언어를 모두 잘 이해하고 있는지 확인합니다. Copilot에서 코드를 번역할 수는 있지만, 제안 사항을 이해하고 제안을 사용할지 아니면 다른 제안을 요청할지 결정해야 합니다.

  • 마이그레이션하는 시스템에 대한 지식

    사용자에게 제공하는 기능과 기능 외에도 현재 시스템의 아키텍처와 논리를 이해해야 합니다. 번역된 코드가 원래 코드와 동일한 작업을 모두 수행하고 동일한 결과를 생성하는지 확인할 수 있어야 합니다.

  • AI 활용

    번역하려는 코드의 특정 부분을 이해하지 못하는 경우 전체 파일 또는 파일 내의 코드에서 선택한 부분에 대해 알아 보려면 Copilot의 "설명" 기능을 사용합니다. IDE에서 GitHub Copilot에 질문하기을(를) 참조하세요.

  • 마이그레이션 완료 시간 예약

    변환은 다단계 프로세스입니다. 변환할 프로젝트가 클수록 수행해야 하는 단계 수가 늘어나게 됩니다. 전체 프로세스를 완료하는 데 충분한 시간을 허용해야 합니다.

  • 반복적으로 작업

    프로젝트의 신중한 부분을 별도로 변환하는 것을 목표로 합니다. 프로젝트의 다른 부분으로 이동하기 전에 변경한 내용을 모두 확인했는지 확인합니다. 진행하면서 프로젝트의 개별 부분에 대한 테스트를 작성하여 각 새 구성 요소가 예상대로 작동하는지 확인할 수 있습니다.

  • 프로세스에 복잡성 추가 방지

    처음에는 기존과 유사하게 변환할 것을 목표로 해야 합니다. 프로젝트의 모든 코드에서는 이 작업을 수행할 수 없습니다. 그러나 마이그레이션 작업에 복잡성을 추가하지 않도록 하려면 코드를 변환하고 새 프레임워크와 적절한 종속성을 사용하는 것 외에 새로 추가하는 변경 횟수를 제한해야 합니다.

  • 번역된 코드 벤치마킹 및 리팩터링

    초기 변환을 완료하고 작업 시스템이 있는 경우 벤치마킹을 수행하여 이전 시스템과 새 시스템을 비교할 수 있습니다. 이제 새 언어로 코드를 리팩터링할 수 있습니다. 코드를 최적화하고 기술적인 문제를 줄일 수 있는 기회입니다.

Copilot을 사용하여 프로젝트를 새 언어로 마이그레이션

기존 프로젝트에 이미 익숙해진 경우 마이그레이션을 시작하는 좋은 방법은 편집기에서 리포지토리의 분기를 열고 Copilot에 도움을 요청하는 것입니다.

  1. 편집기에서 Copilot Chat 패널을 엽니다. IDE에서 GitHub Copilot에 질문하기을(를) 참조하세요.

  2. Copilot에 문의하여 프로젝트를 새 언어로 마이그레이션하는 데 필요한 단계를 간략하게 설명합니다.

    예를 들어 PHP에서 Python으로 마이그레이션하는 경우 다음과 같이 물을 수 있습니다.

    @workspace I want to migrate this project from PHP to Python. Give me a high level overview of the steps I need to take. Don't go into detail at this stage.

    Note

    @workspace 채팅 참가자는 현재 작업 영역의 파일을 사용자가 묻는 질문의 컨텍스트로 설정합니다.

    Copilot은 일반적으로 프로젝트를 마이그레이션하기 위해 수행해야 하는 단계 목록과 함께 반환됩니다.

  3. Copilot의 응답을 복사하여 프로세스 전체에서 참조할 위치에 저장합니다.

  4. 프로세스의 각 단계를 진행하면서 필요에 따라 Copilot에 자세한 도움을 요청합니다.

    Copilot의 각 제안을 신중하게 고려합니다. 제안하는 코드를 이해하고 해당 코드가 프로젝트에 적합한지 평가합니다. 확실하지 않은 경우 Copilot에 코드를 설명해 달라고 요청합니다.

    Copilot에서 제안하는 변경 내용이 어떤 식으로든 옳지 않다고 생각되면 대체 제안을 요청합니다.

  5. 구성 요소를 실행할 수 있는 상태로 마이그레이션하는 즉시 예상대로 작동하는지 확인합니다. 오류가 발생하는 경우 Copilot Chat 보기에 오류를 복사하고 Copilot에 오류를 해결하도록 요청합니다.

  6. 초기 변환을 완료한 후 Copilot을 사용하여 새 언어로 코드를 리팩터링할 수 있습니다. 자세한 내용은 GitHub Copilot를 사용하여 코드 리팩터링을(를) 참조하세요.

예: PHP 프로젝트를 Python으로 마이그레이션

다음 예제에서는 간단한 웹 애플리케이션을 PHP에서 Python으로 마이그레이션하는 방법을 설명합니다. 마이그레이션에 사용하는 프로그래밍 언어가 아니더라도 여기에 설명된 단계를 수행하여 프로젝트 마이그레이션을 숙지하는 것이 유용할 수 있습니다. 이 단계는 다른 작은 프로젝트를 한 언어에서 다른 언어로 마이그레이션하는 단계와 유사합니다.

PHP에서 Python으로 마이그레이션하기 전에 '간단한 PHP 웹 사이트'의 스크린샷

이 예제에서는 다음을 가정합니다.

  • Visual Studio Code에서 작업하고 있습니다.
  • 두 언어(PHP 및 Python 버전 3.12 이상)가 모두 설치되어 있습니다.

간단한 웹 사이트 프로젝트 마이그레이션

GitHub의 퍼블릭 리포지토리인 docs/simple-php-website의 코드를 마이그레이션할 예정입니다.

리포지토리는 다음 파일로 구성됩니다.

.gitignore
.htaccess
LICENSE
content
├── 404.phtml
├── about-us.phtml
├── contact.phtml
├── home.phtml
└── products.phtml
includes
├── config.php
└── functions.php
index.php
readme.md
template
├── style.css
└── template.php

이 예제에서는 마이그레이션을 완료하기 위해 Copilot Chat에 입력할 수 있는 프롬프트와 이 마이그레이션의 한 인스턴스에 반환된 응답 Copilot을 제공합니다. Copilot Chat 응답은 비결정적이므로 여기에 표시된 응답과 다른 응답을 받게 될 수 있습니다.

마이그레이션 프로세스 중, 계속 진행하기 전에 수정해야 하는 오류가 발생할 수 있습니다. Copilot가 도움이 될 수 있습니다. 이 예제에서는 몇 가지 오류가 포함되어 있으며 Copilot을 가져오는 방법을 보여 줍니다.

Copilot Chat에서 얻게 되는 응답은 여기에 표시된 응답과 다를 수 있으므로 다른 오류가 발생할 수 있습니다. 따라서 Copilot에서 직접 얻는 응답보다는 여기에 표시된 응답을 사용하여 이 예제 마이그레이션을 더 쉽게 단계별로 진행할 수 있습니다.

이 예제 마이그레이션을 완료한 후에는 자체 프로젝트에서 동일한 방법론을 사용할 수 있습니다.

  1. 리포지토리 복사본을 로컬 머신에 복제하는 것부터 시작하세요.

  2. 애플리케이션을 실행하여 작동하는지 확인합니다.

    이렇게 하려면 터미널에서 복제된 리포지토리의 루트로 이동하여 다음 명령을 실행합니다.

    Shell
     php -S localhost:8000
    

    그런 다음, 브라우저에서 http://localhost:8000으로 이동합니다.

  3. 해당 웹 사이트에 대해 알아보려면 사이트를 클릭하여 마이그레이션이 성공했는지 확인할 수 있습니다.

  4. 리포지토리에 작업 분기를 만들고 Visual Studio Code에서 새 작업 영역으로 엽니다.

  5. 기존 프로젝트의 내용과 아키텍처를 숙지합니다. Copilot에서 다음과 같이 도움을 제공할 수 있습니다.

    1. Copilot Chat 보기 열기

    2. 다음 프롬프트 입력:

      @workspace Describe this project in detail, explaining what the various components do and how they interact.

  6. 마이그레이션 프로세스에 대한 개략적인 개요에 관하여 Copilot에 문의하세요.

    @workspace I want to migrate this project from PHP to Python. Give me a high level overview of the steps I need to take. Don't go into detail at this stage.

    Copilot에서 다음과 같은 지침으로 응답합니다.

    To migrate this project from PHP to Python, follow these high-level steps:
    
    1. Set Up Python Environment:
       - Install Python and set up a virtual environment.
       - Install necessary packages (e.g., Flask for web framework).
    
    2. Convert Configuration:
       - Translate the configuration settings from config.php to a Python configuration file.
    
    3. Rewrite Functions:
       - Convert PHP functions in functions.php to Python functions.
    
    4. Create Flask Application:
       - Set up a Flask application to handle routing and views.
       - Map the routes to corresponding views.
    
    5. Convert Templates:
       - Translate template.php to a Jinja2 template.
       - Update the CSS file path in the template.
    
    6. Convert Content Pages:
       - Convert .phtml content files to HTML or Jinja2 templates.
    
    7. Update .htaccess Rules:
       - Translate .htaccess rewrite rules to Flask route handling.
    
    8. Run and Test:
       - Run the Flask application and test all routes and functionalities.
       - Ensure the site works as expected and fix any issues.
    
    9. Documentation:
       - Update the readme.md with new instructions for running the Python project.
    
  7. Copilot의 응답을 복사하여 이 프로세스의 나머지 부분에서 참조할 수 있는 위치에 저장합니다. 이러한 각 단계를 진행하면서 Copilot에 도움을 요청하게 됩니다.

  8. 사용할 Python 프레임워크를 아직 결정하지 않은 경우 Copilot에 조언을 요청할 수 있습니다.

    @workspace What Python frameworks can I use for this project once it is migrated to Python? Give me a selection of options, with a brief summary of the pros and cons of each in relation to this website project. Which framework would you recommend?

    Copilot은 다양한 프레임워크에 대한 정보로 응답하고 다음과 같은 결론을 내립니다.

    For a project like yours - which is a simple, content-driven website - Flask is highly recommended. Its simplicity, flexibility, and ease of use (especially with its templating system that can easily replace your current PHP template structure) make it a great fit.
    

    Copilot의 조언을 받아들여 Flask를 사용합니다.

  9. Copilot의 개략적인 개요로 돌아가서 첫 번째 단계는 Python 환경을 설정하고 필요한 패키지를 설치하는 것입니다. 이 작업을 수행하는 방법을 알아보려면 Copilot Chat에 다음을 입력합니다.

    @workspace I want to use Flask. Tell me how to set up a virtual environment and install the necessary packages.

    Copilot에서 다음과 같은 지침으로 응답합니다.

    1. Create a virtual environment:
       - Open a terminal and navigate to your project directory.
       - Run the following command to create a virtual environment:
         python3 -m venv venv
    
    2. Activate the virtual environment:
       - On macOS and Linux:
         source venv/bin/activate
    
       - On Windows:
         venv\Scripts\activate
    
    3. Install Flask and necessary packages:
       - With the virtual environment activated, run the following command
         to install Flask and other necessary packages:
         pip install Flask
    
    4. Verify the installation:
       - You can verify that Flask is installed by running:
         pip list
    
  10. Copilot의 지침에 따라 pip list를 사용하여 Flask가 설치되어 있는지 확인합니다.

  11. 마이그레이션 프로세스에 대한 Copilot의 개요로 돌아가서 다음 단계는 구성을 변환하는 것입니다. 이에 대해 Copilot에 도움을 요청합니다. 예시:

    @workspace As the first step in migrating this project from PHP to Python, create a Python configuration file by converting the functions in functions.php to Python functions. Tell me where to locate the Python config file in the project.

    Copilot에서는 다음 코드를 포함하는 includes 디렉터리에 config.py라는 파일을 만들 것을 제안합니다.

    Python
    config = {
       'name': 'Simple Python Website',
       'site_url': '',
       'pretty_uri': False,
       'nav_menu': {
          '': 'Home',
          'about-us': 'About Us',
          'products': 'Products',
          'contact': 'Contact',
       },
      'template_path': 'template',
      'content_path': 'content',
      'version': 'v3.1',
    }
    
    def get_config(key=''):
       return config.get(key, None)
    
    def site_name():
       return get_config('name')
    
    def site_url():
       return get_config('site_url')
    
    def site_version():
       return get_config('version')
    
    def nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
    
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
    
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
    
       return nav_menu.strip(sep)
    
    def page_title():
       page = request.args.get('page', 'Home')
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def page_content():
       page = request.args.get('page', 'home')
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
    
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
    
       with open(path, 'r') as file:
          return file.read()
    
    def init():
       template_path = os.path.join(get_config('template_path'), 'template.html')
       with open(template_path, 'r') as file:
          return file.read()
    
  12. includes/config.py 파일을 만들고 기존 includes/config.php 파일을 삭제합니다.

  13. 개요로 다시 돌아가서 Copilot에 PHP 함수를 다시 작성하는 데 도움을 요청하세요.

    @workspace Continuing the migration of this project from PHP to Python, create Python functions to replace the existing PHP functions. Tell me where to locate the Python functions in the project.

    Copilot에서는 다음 코드를 포함하는 includes 디렉터리에 functions.py라는 파일을 만들 것을 제안합니다.

    Python
    import os
    from flask import request
    from .config import get_config
    
    def site_name():
       return get_config('name')
    
    def site_url():
       return get_config('site_url')
    
    def site_version():
       return get_config('version')
    
    def nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
    
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
    
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
    
       return nav_menu.strip(sep)
    
    def page_title():
       page = request.args.get('page', 'Home')
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def page_content():
       page = request.args.get('page', 'home')
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
    
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
    
       with open(path, 'r') as file:
          return file.read()
    
    def init():
       template_path = os.path.join(get_config('template_path'), 'template.html')
       with open(template_path, 'r') as file:
          return file.read()
    
  14. includes/functions.py 파일을 만들고 기존 includes/functions.php 파일을 삭제합니다.

  15. 개요에 이은 다음 단계는 Flask 애플리케이션을 만드는 것입니다. Copilot에게 도움을 요청하세요.

    @workspace Set up a Flask application to handle routing and views, and map the routes to corresponding views. Tell me the location of any files that need to be created or changed.

    Copilot에서는 프로젝트 루트에 다음 코드를 포함하는 app.py라는 파일을 만들 것을 제안합니다.

    Python
    from flask import Flask, render_template, request
    import os
    
    app = Flask(__name__)
    
    config = {
       'name': 'Simple Python Website',
       'site_url': '',
       'pretty_uri': False,
       'nav_menu': {
          '': 'Home',
          'about-us': 'About Us',
          'products': 'Products',
          'contact': 'Contact',
       },
       'template_path': 'template',
       'content_path': 'content',
       'version': 'v3.1',
    }
    
    def get_config(key=''):
       return config.get(key, None)
    
    @app.route('/')
    @app.route('/<page>')
    def index(page='home'):
       page_content = get_page_content(page)
       page_title = get_page_title(page)
       nav_menu = get_nav_menu()
       return render_template('template.html', page_title=page_title, page_content=page_content, nav_menu=nav_menu)
    
    def get_page_title(page):
       return ' '.join(word.capitalize() for word in page.split('-'))
    
    def get_page_content(page):
       path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
       if not os.path.exists(path):
          path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
       with open(path, 'r') as file:
          return file.read()
    
    def get_nav_menu(sep=' | '):
       nav_menu = ''
       nav_items = get_config('nav_menu')
       for uri, name in nav_items.items():
          query_string = request.args.get('page', '')
          class_active = ' active' if query_string == uri else ''
          url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
          nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
       return nav_menu.strip(sep)
    
    if __name__ == '__main__':
       app.run(debug=True)
    

    Copilot은 또한 template/template.php의 이름을 template/template.html로 바꾸고 Jinja2 템플릿 구문을 사용하도록 파일을 업데이트할 것을 제안합니다.

    HTML
    
    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8" />
       <meta http-equiv="x-ua-compatible" content="ie=edge"/>
       <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
       <title>{{ page_title }} | {{ get_config('name') }}</title>
       <link href="{{ get_config('site_url') }}/template/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
    <div class="wrap">
    
       <header>
          <h1>{{ get_config('name') }}</h1>
          <nav class="menu">
             {{ nav_menu|safe }}
          </nav>
       </header>
    
       <article>
          <h2>{{ page_title }}</h2>
          {{ page_content|safe }}
       </article>
    
       <footer>
          <small>&copy;{{ get_config('version') }} {{ get_config('name') }}.<br>{{ get_config('version') }}</small>
       </footer>
    
    </div>
    </body>
    </html>
    
    
  16. 안내에 따라 app.pytemplate/template.html 파일을 만듭니다.

  17. Copilot은 또한 이러한 파일을 만든 후, 터미널의 리포지토리 루트에서 python app.py를 실행한 다음, http://127.0.0.1:5000[](http://127.0.0.1:5000)으로 이동할 것을 제안할 수도 있습니다.

    Note

    컴퓨터에 Python을 설치하는 방법에 따라 올바른 버전의 Python이 사용되는지 확인하려면 python app.py 대신 python3 app.py 명령을 사용해야 할 수도 있습니다.

    이렇게 하면 브라우저에 오류 메시지가 표시됩니다.

  18. 초기 TemplateNotFound 오류 메시지를 Copilot Chat 보기에 복사하고 이 문제를 해결하는 방법을 문의하세요. 예시:

    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.TemplateNotFound: template.html`. How can I fix this?

    Copilot은 Flask에서 template.html 파일을 찾을 수 없다는 것을 나타내는 오류로 응답합니다.

    기본적으로 Flask는 프로젝트의 루트 디렉터리에 있는 templates라는 폴더에서 템플릿을 찾습니다. 그러나 template.html 파일이 template 디렉터리에 있습니다. 이 문제를 해결하려면 Flask 앱을 만들 때 올바른 템플릿 폴더를 지정해야 합니다. template_folder 매개 변수를 포함하도록 할당 app = Flask(__name__)을 변경하여 app.py 파일을 업데이트할 것을 제안합니다.

    Python
    app = Flask(__name__, template_folder='template')
    
  19. Flask 개발 서버가 계속 실행 중이라고 가정하고 브라우저 페이지를 http://127.0.0.1:5000/에서 새로 고치면 이제 get_config 함수와 관련된 새로운 오류가 표시됩니다.

    이 오류 메시지를 Copilot Chat 보기에 복사하고 도움을 요청합니다.

    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.UndefinedError: 'get_config' is undefined.` How can I fix this?

    Copilot은 Jinja2 템플릿 컨텍스트에서 get_config를 사용할 수 없기 때문에 오류가 발생한다고 응답합니다. app.py 파일의 @app.route('/') 줄 바로 앞에 다음 코드를 추가하는 것이 좋습니다.

    Python
    app.jinja_env.globals.update(get_config=get_config)
    
  20. 브라우저를 새로 고치면 이제 웹 사이트가 표시됩니다.

    CSS 스타일을 지정하지 않은 '간단한 Python 웹 사이트'의 스크린샷

    그러나 CSS 스타일은 적용되지 않습니다. 이 문제는 다음 단계에서 수정하겠습니다.

  21. Copilot에 묻습니다.

    @workspace The deployed website does not use the CSS styles. How can I fix this?

    Copilot은 Flask에서 CSS 파일이 static이라는 디렉터리에 있을 것으로 예상한다는 것을 알려줍니다. 기존 style.css 파일을 template 디렉터리에서 새로운 static 디렉터리로 이동한 다음, template.html 파일의 head 부분에 있는 style.css 파일로 경로를 업데이트하는 것이 좋습니다. 다음과 같이 변경하세요.

    HTML
    
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    
    

    브라우저를 새로 고치면 웹 사이트가 올바르게 렌더링됩니다.

    초기 마이그레이션을 완료하려면 Copilot이 제공한 개략적인 개요의 단계를 계속 진행하여 필요에 따라 도움을 요청합니다.

마이그레이션 완료

마이그레이션 프로세스를 성공적으로 완료하기 위한 추가 작업에는 다음이 포함됩니다.

  • 확인 초기 마이그레이션 철저히 확인
  • 버그 수정 예를 들어, 현재 여기에 설명된 예시에서 페이지 링크는 app.py 파일의 config 섹션에서 pretty_uriTrue로 설정한 경우에만 작동합니다. 페이지 URL에서 쿼리 문자열 매개 변수를 사용하는 옵션을 사용하거나 코드에서 이 옵션을 제거하려는 경우 Copilot에게 이 작업을 수행하도록 요청할 수 있습니다.
  • 테스트 작성 마이그레이션된 프로젝트에 대한 테스트 작성
  • 정리 더 이상 필요하지 않은 파일을 제거하여 프로젝트 정리
  • 리팩터링 새로운 언어로 코드 리팩터링 마이그레이션 프로세스로 인해 원래 PHP 프로젝트의 아키텍처를 기반으로 하는 Python 프로젝트가 생성되었습니다. 초기 마이그레이션을 완료한 후, 이제 코드를 리팩터링하여 Python 언어 및 Flask 프레임워크의 기능을 최대한 활용할 수 있습니다.
  • 문서 업데이트 readme.md 파일이 만료되어 다시 작성해야 합니다.