VS Code 및 PowerShell의 파일 인코딩 이해

VS Code를 사용하여 PowerShell 스크립트를 편집할 때 올바른 문자 인코딩 형식을 사용하여 파일을 저장해야 합니다.

파일 인코딩이란 무엇이며 왜 중요한가요?

VS Code는 사용자가 버퍼에 문자 문자열을 입력하고 파일 시스템에 바이트 블록을 읽거나 쓰는 인터페이스를 관리합니다. VS Code는 파일을 저장할 때 텍스트 인코딩을 사용하여 각 문자가 되는 바이트를 결정합니다. 자세한 내용은 about_Character_Encoding 참조하세요.

마찬가지로 PowerShell에서 스크립트를 실행할 때 파일을 PowerShell 프로그램으로 다시 구성하려면 파일의 바이트를 문자로 변환해야 합니다. VS Code는 파일을 작성하고 PowerShell은 파일을 읽기 때문에 동일한 인코딩 시스템을 사용해야 합니다. PowerShell 스크립트를 구문 분석하는 이 프로세스는 바이트 ->characters ->tokens ->abstract 구문 트리 ->execution입니다.

VS Code 및 PowerShell은 모두 적절한 기본 인코딩 구성으로 설치됩니다. 그러나 PowerShell에서 사용하는 기본 인코딩은 PowerShell 6 릴리스와 함께 변경되었습니다. VS Code에서 PowerShell 또는 PowerShell 확장을 사용하는 데 문제가 없도록 하려면 VS Code 및 PowerShell 설정을 올바르게 구성해야 합니다.

인코딩 문제의 일반적인 원인

VS Code를 인코딩하거나 스크립트 파일이 예상되는 PowerShell 인코딩과 일치하지 않는 경우에 인코딩 문제가 발생합니다. PowerShell에서 파일 인코딩을 자동으로 확인할 수 있는 방법은 없습니다.

7비트 ASCII 문자 집합에 없는 문자를 사용하는 경우 인코딩 문제가 발생할 가능성이 높습니다. 예시:

  • em 대시(), 구분되지 않는 공백() 또는 왼쪽 큰따옴표"( )와 같은 문자가 아닌 확장 문자
  • 악센트 부호가 있는 라틴어 문자(É, ü)
  • 키릴 자모와 같은 라틴 문자가 아닌 문자(Д, Ц)
  • CJK 문자(, , )

인코딩 문제에 대한 일반적인 원인은 다음과 같습니다.

  • VS Code 및 PowerShell 인코딩의 기본값은 변경되지 않았습니다. PowerShell 5.1 이하의 경우 기본 인코딩은 VS Code와 다릅니다.
  • 다른 편집기가 새 인코딩에서 파일을 열고 덮어씁니다. 이는 종종 ISE에서 발생합니다.
  • 파일이 VS Code 또는 PowerShell에서 예상하는 것과 다른 인코딩으로 소스 제어에 체크 인되었습니다. 공동 작업자가 다른 인코딩 구성이 있는 편집기를 사용할 때 이 문제가 발생할 수 있습니다.

인코딩 문제가 발생하는 경우를 구별하는 방법

종종 인코딩 오류는 스크립트에서 구문 분석 오류로 나타납니다. 스크립트에서 이상한 문자 시퀀스를 찾으면 이 경우에 문제가 발생할 수 있습니다. 아래 예제에서는 대시 부호()가 â€" 문자로 표시됩니다.

Send-MailMessage : A positional parameter cannot be found that accepts argument 'Testing FuseMail SMTP...'.
At C:\Users\<User>\<OneDrive>\Development\PowerShell\Scripts\Send-EmailUsingSmtpRelay.ps1:6 char:1
+ Send-MailMessage â&euro;"From $from â&euro;"To $recipient1 â&euro;"Subject $subject  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage

VS Code가 UTF-8의 문자를 바이트로 인코딩하기 때문에 이 문제가 발생합니다 0xE2 0x80 0x93. 이러한 바이트가 Windows-1252로 디코딩되면 â&euro;" 문자로 해석됩니다.

표시될 수 있는 몇 가지 이상한 문자 시퀀스는 다음과 같습니다.

  • â&euro;" 대신 (en-dash)
  • â&euro;" 대신 (em 대시)
  • Ä2 대신에 Ä
  •  (줄 바꿈하지 않는 공백) 대신 Â
  • Ã&copy; 대신에 é

이 유용한 참조에서는 UTF-8/Windows-1252 인코딩 문제를 나타내는 일반적인 패턴을 나열합니다.

VS Code의 PowerShell 확장이 인코딩과 상호 작용하는 방법

PowerShell 확장은 다음과 같은 다양한 방법으로 스크립트와 상호 작용합니다.

  1. VS Code에서 스크립트를 편집하면 VS Code에서 확장에 콘텐츠를 보냅니다. 언어 서버 프로토콜은 이 내용이 UTF-8로 전송되도록 지정합니다. 따라서 확장 프로그램이 잘못 인코딩될 수는 없습니다.
  2. 통합 콘솔에서 직접 스크립트를 실행하면 PowerShell에서 직접 파일에서 읽습니다. PowerShell의 인코딩이 VS Code의 인코딩과 다른 경우 여기에서 문제가 발생할 수 있습니다.
  3. VS Code에서 열려 있는 스크립트가 VS Code에서 열려 있지 않은 다른 스크립트를 참조하는 경우 확장 프로그램은 파일 시스템에서 해당 스크립트의 내용을 로드하도록 대체됩니다. PowerShell 확장은 UTF-8 인코딩을 기본값으로 지정하지만 바이트 순서 표시(또는 BOM) 검색 기능을 사용하여 올바른 인코딩을 선택할 수도 있습니다.

BOM이 없는 형식(예: BOM을 포함하지 않는 UTF-8Windows-1252)으로 인코딩한다고 가정하는 경우 이 문제가 발생합니다. PowerShell 확장은 기본적으로 UTF-8로 설정됩니다. 확장 프로그램은 VS Code의 인코딩 설정을 변경할 수 없습니다. 자세한 내용은 문제 #824를 참조하세요.

올바른 인코딩 선택

시스템 및 애플리케이션이 서로 다른 인코딩을 사용할 수 있습니다.

  • .NET Standard, 웹 및 Linux 세계에서 UTF-8은 이제 주요 인코딩입니다.
  • 다수의 .NET Framework 애플리케이션이 UTF-16을 사용하고 있습니다. 기록적인 이유로 이 용어는 UTF-8 및 UTF-16을 모두 포함하는 광범위한 표준을 나타내는 용어인 "유니코드"라고도 합니다.
  • Windows에서 유니코드보다 앞선 많은 네이티브 애플리케이션이 기본적으로 계속 Windows-1252를 사용하고 있습니다.

유니코드 인코딩에는 BOM(바이트 순서 표시)라는 개념도 포함됩니다. BOM은 텍스트의 시작 부분에서 발생하여 텍스트가 사용 중인 인코딩을 디코더에 알립니다. 멀티바이트 인코딩의 경우 BOM은 인코딩의 엔디언을 나타내기도 합니다. BOM은 유니코드가 아닌 텍스트에서 거의 표시되지 않는 바이트로 설계되었으므로 BOM이 있는 경우 텍스트가 유니코드라고 적절히 추측할 수 있습니다.

BOM은 선택 사항이며, UTF-8의 신뢰할 수 있는 규칙이 모든 곳에서 사용되기 때문에 LINux 환경에서는 채택이 인기가 없습니다. 대부분의 Linux 애플리케이션은 텍스트 입력이 UTF-8로 인코딩된 것으로 가정합니다. 대부분의 Linux 애플리케이션에서는 BOM을 제대로 인식하고 처리하지만 일부는 그렇지 않으므로 텍스트에서 해당 애플리케이션으로 조작된 아티팩트가 발생합니다.

따라서 다음 작업을 수행하세요:

  • 주로 Windows 애플리케이션 및 Windows PowerShell으로 작업하는 경우 BOM이 포함된 UTF-8 또는 UTF-16과 같은 인코딩을 사용하는 것이 좋습니다.
  • 여러 플랫폼에서 작업하는 경우 BOM을 사용하는 UTF-8을 선호해야 합니다.
  • Linux 관련 컨텍스트에서 기본 작업하는 경우 BOM이 없는 UTF-8을 선호해야 합니다.
  • Windows-1252 및 라틴어-1은 가능하면 피해야 하는 기본적으로 레거시 인코딩입니다. 그러나 일부 이전 Windows 애플리케이션은 이에 따라 달라질 수 있습니다.
  • 또한 스크립트 서명은 인코딩에 따라 달라지므로 서명된 스크립트에서 인코딩을 변경하려면 다시 사임해야 합니다.

VS Code 구성

VS Code의 기본 인코딩은 BOM이 포함되지 않은 UTF-8입니다.

VS Code의 인코딩을 설정하려면 VS Code 설정(Ctrl+)으로 이동하여 설정을 설정합니다."files.encoding"

"files.encoding": "utf8bom"

가능한 값은 다음과 같습니다.

  • utf8: BOM이 포함되지 않은 [UTF-8]
  • utf8bom: BOM을 사용하는 [UTF-8]
  • utf16le: Little endian [UTF-16]
  • utf16be: Big endian [UTF-16]
  • windows1252: [Windows-1252]

GUI 보기에서 이에 대한 드롭다운을 얻거나 JSON 보기에서 완료해야 합니다.

가능한 경우 인코딩을 자동으로 검색하기 위해 다음을 추가할 수도 있습니다.

"files.autoGuessEncoding": true

이러한 설정이 모든 파일 형식에 영향을 주지 않으려는 경우 VS Code에서 언어별 구성을 허용할 수도 있습니다. 필드에 설정을 배치하여 언어별 설정을 만듭니다 [<language-name>] . 예시:

"[powershell]": {
    "files.encoding": "utf8bom",
    "files.autoGuessEncoding": true
}

Visual Studio Code용 Gremlins 추적기를 설치하는 것도 고려할 수 있습니다. 이 확장은 보이지 않거나 다른 일반 문자처럼 보이기 때문에 쉽게 손상되는 특정 유니코드 문자를 드러냅니다.

PowerShell 구성

PowerShell의 기본 인코딩은 버전에 따라 다릅니다.

  • PowerShell 6+에서 기본 인코딩은 모든 플랫폼에서 BOM를 포함하지 않는 UTF-8입니다.
  • Windows PowerShell에서 기본 인코딩은 일반적으로 Windows-1252로, 라틴어-1(ISO 8859-1이라고도 함)의 확장입니다.

PowerShell 5 이상에서는 다음을 포함한 기본 인코딩을 확인할 수 있습니다.

[psobject].Assembly.GetTypes() | Where-Object { $_.Name -eq 'ClrFacade'} |
  ForEach-Object {
    $_.GetMethod('GetDefaultEncoding', [System.Reflection.BindingFlags]'nonpublic,static').Invoke($null, @())
  }

다음 스크립트 를 사용하여 BOM 없이 스크립트에 대해 PowerShell 세션이 유추하는 인코딩을 결정할 수 있습니다.

$badBytes = [byte[]]@(0xC3, 0x80)
$utf8Str = [System.Text.Encoding]::UTF8.GetString($badBytes)
$bytes = [System.Text.Encoding]::ASCII.GetBytes('Write-Output "') + [byte[]]@(0xC3, 0x80) + [byte[]]@(0x22)
$path = Join-Path ([System.IO.Path]::GetTempPath()) 'encodingtest.ps1'

try
{
    [System.IO.File]::WriteAllBytes($path, $bytes)

    switch (& $path)
    {
        $utf8Str
        {
            return 'UTF-8'
            break
        }

        default
        {
            return 'Windows-1252'
            break
        }
    }
}
finally
{
    Remove-Item $path
}

프로필 설정을 사용하여 보다 일반적으로 지정된 인코딩을 사용히도록 PowerShell을 구성할 수 있습니다. 다음 문서를 참조하세요.

PowerShell에서 특정 입력 인코딩을 사용하도록 강제할 수 없습니다. 로캘이 en-US로 설정된 Windows에서 실행되는 PowerShell 5.1 이하는 BOM이 없는 경우 기본적으로 Windows-1252 인코딩으로 설정됩니다. 다른 로캘 설정은 다른 인코딩을 사용할 수 있습니다. 상호 운용성을 보장하기 위해 BOM을 사용하여 유니코드 형식으로 스크립트를 저장하는 것이 가장 좋습니다.

Important

PowerShell 스크립트에 관련된 다른 도구가 인코딩 선택에 따라 달라지거나 다른 인코딩으로 스크립트를 다시 인코딩할 수도 있습니다.

기존 스크립트

파일 시스템에 이미 있는 스크립트는 선택한 새 인코딩으로 다시 인코딩해야 할 수 있습니다. VS Code의 아래쪽 막대에서 UTF-8 레이블이 표시됩니다. 해당 항목을 클릭하여 작업 모음을 열고 인코딩하여 저장을 선택합니다. 이제 해당 파일에 대한 새 인코딩을 선택할 수 있습니다. 전체 지침은 VS Code의 인코딩을 참조하세요.

여러 파일을 다시 인코딩해야 하는 경우 다음 스크립트를 사용할 수 있습니다.

Get-ChildItem *.ps1 -Recurse | ForEach-Object {
    $content = Get-Content -Path $_
    Set-Content -Path $_.Fullname -Value $content -Encoding UTF8 -PassThru -Force
}

PowerShell ISE(통합 스크립팅 환경)

PowerShell ISE를 사용하여 스크립트를 편집하는 경우 인코딩 설정을 동기화해야 합니다.

ISE는 BOM을 적용해야 하지만 리플렉션을 사용하여 인코딩을 설정할 수도 있습니다. 이 설정은 시작 시 유지되지 않습니다.

소스 제어 소프트웨어

git와 같은 일부 소스 제어 도구는 인코딩을 무시합니다. git은 바이트를 추적합니다. Azure DevOps 또는 Mercurial과 같은 다른 도구는 그렇지 않습니다. 일부 git 기반 도구도 텍스트 디코딩을 사용합니다.

이 경우 다음을 확인합니다.

  • VS Code 구성과 일치하도록 소스 제어에서 텍스트 인코딩을 구성합니다.
  • 모든 파일이 관련 인코딩의 소스 제어에 검사.
  • 소스 제어를 통해 수신된 인코딩의 변경 내용에 주의하세요. 여기서 주요 기호는 변경을 나타내는 Diff이지만 변경되지 않은 것처럼 보입니다(바이트는 변경되었지만 문자가 변경되지 않기 때문에).

공동 작업자 환경

소스 제어를 구성하려면 공유하는 파일에서 공동 작업자가 PowerShell 파일을 다시 인코딩하여 인코딩을 재정의하도록 설정하지 않았는지를 확인합니다.

다른 프로그램

PowerShell 스크립트를 읽거나 쓰는 다른 프로그램은 다시 인코딩할 수 있습니다.

다음은 몇 가지 예입니다.

  • 클립보드를 사용하여 스크립트를 복사하고 붙여넣습니다. 이는 다음과 같은 시나리오에서 일반적입니다.
    • VM에 스크립트 복사
    • 전자 메일 또는 웹 페이지에서 스크립트 복사
    • Microsoft Word 또는 PowerPoint 문서로 또는 외부로 스크립트 복사
  • 기타 텍스트 편집기( 예:
    • 메모장
    • vim
    • 다른 PowerShell 스크립트 편집기
  • 다음과 같은 텍스트 편집 유틸리티:
    • Get-Content/Set-Content/Out-File
    • >>>와 같은 PowerShell 리디렉션 연산자
    • sed/awk
  • 다음과 같은 파일 전송 프로그램:
    • 스크립트를 다운로드하는 경우 웹 브라우저
    • 파일 공유

이러한 도구 중 일부는 텍스트가 아닌 바이트를 처리하지만 다른 도구는 인코딩 구성을 제공합니다. 인코딩을 구성해야 하는 경우 이러한 문제를 방지하기 위해 인코딩하는 편집기와 동일하게 만들어야 합니다.

PowerShell의 인코딩에 대한 기타 리소스

PowerShell에서 인코딩 및 구성에 대한 몇 가지 다른 유용한 게시물은 읽을 만한 가치가 있습니다.