테스트 및 디버깅
클래식 프로그래밍과 마찬가지로 양자 프로그램이 의도한 대로 작동하는지 확인하고 잘못된 동작을 진단할 수 있어야 합니다. 그러나 전통적 프로그래밍과는 달리 양자 시스템의 상태를 관찰하고 양자 프로그램의 작동을 추적하는 것이 항상 쉽지는 않습니다. 이 섹션에서는 양자 프로그램을 테스트하고 디버깅하기 위해 에서 제공하는 Quantum Development Kit 도구를 다룹니다.
단위 테스트
클래식 프로그램을 테스트하는 일반적인 방법 중 하나는 라이브러리에서 코드를 실행하고 출력을 예상 출력과 비교하는 ‘단위 테스트’라는 작은 프로그램을 작성하는 것입니다.
예를 들어, $2^2 = 4$라는 것을 ‘선험적’으로 알고 있으므로 Square(2)
가 4
를 반환한다는 것을 보장할 수 있습니다.
Q#는 양자 프로그램에 대한 단위 테스트 만들기를 지원하고 xUnit 단위 테스트 프레임워크 내에서 테스트로 실행할 수 있습니다.
테스트 프로젝트 만들기
Visual Studio 2022를 엽니다. 파일 메뉴로 이동하여 새로 만들기 > 프로젝트...를 선택합니다. 오른쪽 위에서 Q#
을 검색하고 Q#테스트 프로젝트 템플릿을 선택합니다.
새 프로젝트에는 두 개의 파일 코드 파일과 프로젝트 파일이 있습니다. Tests.qs
는 새 Q# 단위 테스트를 정의하는 데 편리한 장소를 제공하며, .csproj
파일에는 프로젝트를 빌드하는 데 필요한 구성 매개 변수가 포함되어 있습니다.
처음에 코드 파일에는 새로 할당된 큐비트가 $\ket{0}$ 상태인지 확인하고 메시지를 출력하는 하나의 샘플 단위 테스트 AllocateQubit
가 포함되어 있습니다.
namespace TestProject {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
@Test("QuantumSimulator")
operation AllocateQubit () : Unit {
use qubit = Qubit();
AssertMeasurement([PauliZ], [qubit], Zero, "Newly allocated qubit must be in the |0⟩ state.");
Message("Test passed");
}
}
Unit
형식의 인수를 사용하고 Unit
을 반환하는 모든 Q# 연산 또는 함수는 @Test("...")
특성을 통해 단위 테스트로 표시될 수 있습니다.
이전 예제에서 해당 특성에 대한 인수는 "QuantumSimulator"
테스트가 target 실행되는 을 지정합니다. 단일 테스트는 여러 targets에서 실행할 수 있습니다. 예를 들어 AllocateQubit
앞에 @Test("ToffoliSimulator")
특성을 추가합니다.
namespace TestProject {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
@Test("QuantumSimulator")
@Test("ToffoliSimulator")
operation AllocateQubit () : Unit {
...
}
}
파일을 저장한 후 테스트를 실행하면 두 개의 단위 테스트가 표시됩니다. 하나는 AllocateQubit
가 QuantumSimulator
에서 실행되고, 다른 하나는 ToffoliSimulator
에서 실행됩니다.
Q# 컴파일러는 단위 테스트에 유효한 실행 targets 으로 기본 제공 targets"QuantumSimulator"
, 및 "ToffoliSimulator"
를 인식합니다. 정규화된 시뮬레이터 이름을 지정하여 사용자 지정 실행 target을 정의할 수도 있습니다.
테스트 프로젝트 템플릿에는 코드 파일 외에도 다음 내용이 포함된 .csproj
파일이 포함됩니다.
<Project Sdk="Microsoft.Quantum.Sdk/0.24.201332">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.24.201332" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
</Project>
첫 번째 줄은 애플리케이션을 빌드하는 데 사용되는 Microsoft Quantum Development Kit 의 버전 번호를 지정합니다. 이 파일에 표시되는 정확한 버전 번호는 설치에 따라 달라집니다.
일반적으로 TargetFramework
에는 프로젝트 형식에 따라 Q# 애플리케이션에 대한 두 값 중 하나가 포함됩니다. 실행 파일 및 테스트 프로젝트인 경우 net6.0
이 포함되고, 라이브러리인 경우 netstandard2.1
이 포함됩니다. 다음으로, IsPackable
매개 변수는 false(생략할 경우 true)로 설정됩니다. 이 매개 변수는 dotnet pack
명령이 실행될 때 이 프로젝트에서 NuGet 패키지가 생성되는지 여부를 결정합니다.
마지막으로, 파일은 <ItemGroup>
태그 내에 NuGet 패키지 종속성을 나열합니다. xUnit은 Q# 테스트 프로젝트에서 사용하는 .NET 프레임워크용으로 많이 사용되는 테스트 프레임워크입니다(목록의 세 번째 참조). Microsoft.Quantum.Xunit
및 Microsoft.NET.Test.Sdk
패키지는 Q# 구문을 xUnit에 노출하고 .NET 테스트 프로젝트를 빌드하는 데 사용됩니다. 테스트를 실행하려면 xUnit에 단위 테스트 실행기도 필요합니다. 명령줄에서 테스트를 실행하려면 xunit.runner.visualstudio
및 dotnet-xunit
실행기가 모두 필요하지만, Visual Studio 내에서 테스트를 실행하는 경우에는 전자만 있으면 충분합니다. 테스트 프로젝트를 수동으로 만들거나 일반 프로젝트에서 변환하는 경우 적절한 패키지 참조를 포함해야 합니다.
Q# 단위 테스트 실행
솔루션당 1회씩 테스트 메뉴로 이동하고 테스트 설정 > 기본 프로세서 아키텍처 > X64를 선택합니다.
팁
Visual Studio의 기본 프로세서 아키텍처 설정은 각 솔루션의 솔루션 옵션(.suo
) 파일에 저장됩니다.
이 파일을 삭제하는 경우 프로세서 아키텍처로 X64를 다시 선택해야 합니다.
프로젝트를 빌드하고 테스트 메뉴를 열고 Windows > 테스트 탐색기를 선택합니다. AllocateQubit가 테스트 실행 안 함 그룹의 테스트 목록에 표시됩니다. 모두 실행을 선택하거나 이 개별 테스트를 실행합니다.
Message function 내장 함수에는 (String -> Unit)
형식이 있으며 이를 통해 진단 메시지를 만들 수 있습니다.
테스트 탐색기에서 테스트를 실행하고 테스트 이름을 클릭하면 테스트 실행에 대한 정보(통과/실패 상태, 경과된 시간 및 출력에 대한 링크)가 패널에 표시됩니다. 출력을 클릭하여 새 창에서 테스트 출력을 엽니다.
팩트 및 어설션
Q#의 함수에는 논리적 부작용이 없기 때문에 Q# 프로그램 내에서 출력 유형이 빈 튜플 ()
인 함수를 실행하는 것으로는 다른 종류의 영향을 발견할 수 없습니다.
즉, 머신은 target 이 누락이 다음 Q# 코드의 동작을 수정하지 않도록 보장하여 반환 ()
되는 함수를 실행하지 않도록 선택할 수 있습니다.
이 동작은 어설션 및 디버깅 논리를 Q# 프로그램에 포함하는 데 유용한 도구인 ()
을 반환하는 함수(예: Unit
)를 만듭니다.
간단한 예제를 살펴보겠습니다.
namespace DebuggingFactsTest {
@EntryPoint()
function PositivityFact(value : Int) : Unit {
if value <= 0 {
fail "Expected a positive number.";
}
}
}
여기서 키워드(keyword) fail
계산이 진행되지 않아야 하며 프로그램을 실행하는 컴퓨터에서 예외가 targetQ# 발생합니다.
정의상 컴퓨터가 문에 도달 fail
한 후 더 이상 코드를 실행 Q# 하지 않아 이러한 종류의 오류를 내부에서 Q#target 관찰할 수 없습니다.
따라서 PositivityFact
에 대한 호출을 계속 진행하는 경우 해당 입력이 0보다 큼을 확신할 수 있습니다.
이제 Microsoft.Quantum.Diagnostics namespace에서 Fact 함수를 사용하여 PositivityFact
와 동일한 동작을 구현할 수 있습니다.
Fact(value > 0, "Expected a positive number.");
반면 어설션은 팩트와 유사하게 사용되지만 컴퓨터의 target 상태에 따라 달라질 수 있습니다. 마찬가지로, 어설션은 연산으로 정의되는 반면 팩트는 이전 예제와 같이 함수로 정의됩니다.
해당 아이디어를 활용하는 prelude는 특히 유용한 두 가지 어설션, AssertMeasurement operation 및 AssertMeasurementProbability operation를 제공하며, 둘 다 ()
에 대한 연산으로 모델링됩니다. 해당 어설션은 각각 관련된 특정 측정값을 설명하는 Pauli 연산자, 측정이 수행되는 양자 레지스터 및 가상 결과를 사용합니다.
시뮬레이션으로 작업하는 대상 머신은 복제 불가 정리에 의해 바인딩되지 않으며 해당 어설션에 전달되는 레지스터를 방해하지 않고 이러한 측정을 수행할 수 있습니다.
그러면 시뮬레이터는 이전의 PositivityFact
함수와 유사하게 가설에서 나온 결과가 실제로 관찰되지 않는 경우 계산을 중지할 수 있습니다.
namespace AssertionsTest {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Diagnostics;
@EntryPoint()
operation Assert() : Unit {
use register = Qubit();
H(register);
AssertMeasurement([PauliX], [register], Zero, "The state of the quantum register is not |+〉");
ResetAll([register]);
// Even though we do not have access to states in Q#,
// we know by the anthropic principle that the state
// of register at this point is |+〉.
}
}
복제 불가 정리에서 양자 상태를 검사하지 못하게 하는 물리적 양자 하드웨어에서 AssertMeasurement
및 AssertMeasurementProbability
연산은 다른 영향 없이 단순히 ()
을 반환합니다.
Microsoft.Quantum.Diagnostics namespace는 더 많은 고급 조건을 확인할 수 있는 함수와 함께 여러 Assert
함수 모음을 제공합니다.
덤프 함수
Q#은 실제 양자 계산과 마찬가지로 큐비트 상태에 직접 액세스하도록 허용하지 않습니다. 그러나 는 컴퓨터의 Microsoft.Quantum.Diagnostics namespacetarget 현재 상태 파일에 덤프할 수 있는 세 가지 함수를 제공하며, 전체 상태 시뮬레이터 DumpRegister functionDumpOperation operationDumpMachine function 와 함께 사용할 때 디버깅 및 학습에 중요한 인사이트를 제공할 수 있습니다. 각 의 생성된 출력은 머신에 target 따라 달라집니다.
DumpOperation
행렬로 설명하는 양자 게이트를 구현한다고 가정해 보겠습니다. Q# 연산을 작성했으며 원하는 단위 행렬을 정확히 구현하는지 확인하고자 합니다. DumpOperation operation은 매개 변수로 큐비트 배열에서 작동하는 연산을 취하며(연산이 대부분의 내재 게이트처럼 단일 큐비트 또는 개별 큐비트와 큐비트 배열에서 작동한다면 여기에 DumpOperation
을 사용하기 위한 래퍼를 작성해야 함) 이 연산에서 구현된 행렬을 출력합니다. CNOT 게이트를 예로 살펴보겠습니다.
namespace DumpOperationTest {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Diagnostics;
@EntryPoint()
operation DumpCnot() : Unit {
DumpOperation(2, ApplyToFirstTwoQubitsCA(CNOT, _));
}
}
DumpOperation
을 호출하면 다음 행렬이 출력됩니다.
Real:
[[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0]]
Imag:
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
참고
DumpOperation
및 나머지 Dump 함수는 기본 상태를 행렬 원소의 인덱스로 변환하기 위해 Little Endian 인코딩을 사용합니다. 따라서 CNOT 행렬의 두 번째 열은 입력 상태 |1⟩_{LE} = |10⟩에 해당하며, CNOT 게이트는 |11⟩ = |3_{LE}로 변환됩니다. 마찬가지로 입력 상태 |2⟩_{LE} = |01⟩입니다.
DumpMachine
파일에 쓰기의 Quantum Development Kit 일부로 분산된 전체 상태 양자 시뮬레이터는 전체 양자 시스템의 웨이브 함수 를 복소수의 1차원 배열로, 각 요소는 계산 기준 상태 $\ket{n}$를 측정할 확률의 진폭을 나타냅니다. 여기서 $\ket{n} = \ket{b_{n-1}... 비트 ${b_i}$에 대한 b_1b_0}$ 예를 들어 두 큐비트를 할당하고 그 위에 균등하지 않은 중첩 상태를 준비하는 다음 연산을 고려해 보겠습니다.
namespace MultiDumpMachineTest {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Diagnostics;
@EntryPoint()
operation MultiQubitDumpMachineDemo() : Unit {
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[1]);
R1Frac(1, 2, qubits[1]);
DumpMachine("dump.txt");
ResetAll(qubits);
}
}
MultiQubitDumpMachineDemo
연산의 결과인 양자 상태는 다음과 같습니다.
$$ \begin{align} \ket{\psi} = \frac{1}{\sqrt{2}} \ket{00} - \frac{(1 + i)}{2} \ket{10}. \end{align} $$
이전 양자 상태에서 DumpMachine function을 호출하면 다음 출력이 생성됩니다.
# wave function for qubits with ids (least to most significant): 0;1
∣0❭: 0.707107 + 0.000000 i == ********** [ 0.500000 ] --- [ 0.00000 rad ]
∣1❭: 0.000000 + 0.000000 i == [ 0.000000 ]
∣2❭: -0.500000 + -0.500000 i == ********** [ 0.500000 ] / [ -2.35619 rad ]
∣3❭: 0.000000 + 0.000000 i == [ 0.000000 ]
첫 번째 행은 중요한 순서대로 나열된 해당 큐비트의 ID에 대한 주석을 제공합니다. 나머지 행은 카티전 및 극좌표 형식의 기저 상태 벡터 $\ket{n}$를 측정하는 확률 진폭을 설명합니다. 첫 번째 행에 대한 자세한 내용은 다음과 같습니다.
∣0❭:
이 행은0
계산 기저 상태에 해당합니다.0.707107 + 0.000000 i
: 카티전 형식의 확률 진폭입니다.==
:equal
부호는 두 동등한 표현을 구분합니다.**********
: 크기의 그래픽 표현이며,*
의 개수는 이 상태 벡터를 측정할 확률에 비례합니다.[ 0.500000 ]
: 크기의 숫자 값입니다.---
: 진폭의 위상을 그래픽으로 표현한 것입니다(다음 출력 참조).[ 0.0000 rad ]
: 위상의 숫자 값입니다(라디안 단위).
크기와 위상이 모두 그래픽 표현으로 표시됩니다. 크기 표현은 직관적입니다. 즉, *
막대를 표시하며, 확률이 높을수록 막대가 커집니다. 위상의 경우 범위에 따라 각도를 나타내기 위해 다음 기호를 표시합니다.
[ -π/16, π/16) ---
[ π/16, 3π/16) /-
[ 3π/16, 5π/16) /
[ 5π/16, 7π/16) +/
[ 7π/16, 9π/16) ↑
[ 8π/16, 11π/16) \-
[ 7π/16, 13π/16) \
[ 7π/16, 15π/16) +\
[15π/16, 19π/16) ---
[17π/16, 19π/16) -/
[19π/16, 21π/16) /
[21π/16, 23π/16) /+
[23π/16, 25π/16) ↓
[25π/16, 27π/16) -\
[27π/16, 29π/16) \
[29π/16, 31π/16) \+
[31π/16, π/16) ---
다음 예에서는 DumpMachine
의 몇 가지 일반적인 상태를 보여 줍니다.
∣0❭
# wave function for qubits with ids (least to most significant): 0
∣0❭: 1.000000 + 0.000000 i == ******************** [ 1.000000 ] --- [ 0.00000 rad ]
∣1❭: 0.000000 + 0.000000 i == [ 0.000000 ]
∣1❭
# wave function for qubits with ids (least to most significant): 0
∣0❭: 0.000000 + 0.000000 i == [ 0.000000 ]
∣1❭: 1.000000 + 0.000000 i == ******************** [ 1.000000 ] --- [ 0.00000 rad ]
∣+❭
# wave function for qubits with ids (least to most significant): 0
∣0❭: 0.707107 + 0.000000 i == ********** [ 0.500000 ] --- [ 0.00000 rad ]
∣1❭: 0.707107 + 0.000000 i == ********** [ 0.500000 ] --- [ 0.00000 rad ]
∣-❭
# wave function for qubits with ids (least to most significant): 0
∣0❭: 0.707107 + 0.000000 i == ********** [ 0.500000 ] --- [ 0.00000 rad ]
∣1❭: -0.707107 + 0.000000 i == ********** [ 0.500000 ] --- [ 3.14159 rad ]
참고
큐비트의 ID는 런타임에 할당되며, 해당 큐비트를 할당한 순서 또는 큐비트 레지스터 내 위치에 따라 정렬되지 않을 수도 있습니다.
팁
Visual Studio에서 코드에 중단점을 배치하고 큐비트 변수 값을 검사하여 큐비트 ID를 찾을 수 있습니다. 예를 들면 다음과 같습니다.
register2
의 인덱스가 0
인 큐비트의 경우 id=3
이며, 인덱스가 1
인 큐비트의 경우 id=2
입니다.
Jupyter Notebook 포함 DumpMachine
편의상 이전 테스트 및 디버깅 도구에서 Q# 독립 실행형 애플리케이션을 사용하는 코드 예제를 명령 프롬프트 및 모든 IDE에 표시했습니다. 그러나 에서 제공하는 Quantum Development Kit 개발 옵션을 사용하여 에서 Q#양자 컴퓨팅 애플리케이션을 개발할 수 있습니다. 자세한 내용은 QDK 설정을 참조하세요.
DumpMachine function에 대한 예제에서는 Q# Jupyter Notebook을 사용한 개발을 명시합니다. 양자 프로그램 테스트 및 디버그를 위한 시각화 도구를 더 많이 제공하기 때문입니다.
- Jupyter Notebook에서
DumpMachine
을 실행하려면 Q# 커널로 새 Jupyter Notebook을 실행하고 다음 코드를 첫 번째 Notebook 셀에 복사합니다.
open Microsoft.Quantum.Diagnostics;
operation MultiQubitDumpMachineDemo() : Unit {
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[1]);
R1Frac(1, 2, qubits[1]);
DumpMachine();
ResetAll(qubits);
}
- 새 셀에서
%simulate
매직 명령을 사용하여 전체 상태 양자 시뮬레이터에 대해MultiQubitDumpMachineDemo
연산을 실행합니다.DumpMachine
이 호출은 Controlled Ry 게이트 다음의 프로그램 양자 상태에 관한 정보를 줄 집합 형태로 출력합니다. 기본 상태마다 한 줄로, 복합 진폭, 위상, 측정 확률을 나타냅니다.
참고
%config (magic command)(Q# Jupyter Notebooks에서만 사용 가능)를 사용하여 DumpMachine
출력의 형식을 조정할 수 있습니다. 다양한 시나리오에서 사용할 수 있는 많은 설정을 제공합니다. 예를 들어 기본적으로 DumpMachine
은 Little Endian 정수를 사용하여 기본 상태를 나타냅니다. 원시 비트 문자열이 더 읽기 쉽다면 %config dump.basisStateLabelingConvention="Bitstring"
을 사용하여 전환할 수 있습니다.
- Jupyter Notebooks는 %trace (magic command)(Q# Jupyter Notebooks에서만 사용 가능)를 사용하여 양자 프로그램의 실행을 양자 회로로 시각화하는 옵션을 제공합니다. 이 명령은 하나의 Q# 프로그램 실행을 추적하고 그 실행을 기초로 회로를 빌드합니다. 이것은
%trace MultiQubitDumpMachineDemo
실행에서 발생하는 회로입니다.
시각화는 대화형이기 때문에 각 블록을 클릭하여 내장 게이트까지 드릴다운할 수 있습니다.
- 마지막으로 %debug (magic command)(Q# Jupyter Notebooks에서 제공)를 사용하면 확산과 동시에 프로그램 실행 추적(회로로)과 프로그램 상태 관찰을 결합할 수 있습니다. 시각화도 대화형입니다. 프로그램 시작 부분의 측정 확률 대신, 프로그램 실행이 완료될 때까지 각 단계를 클릭하고 전환하여 진폭의 실제 및 가상 구성 요소를 관찰할 수 있습니다.
DumpRegister
DumpRegister function는 해당하는 큐비트와 관련된 정보로만 정보량을 제한하는 큐비트 배열을 사용한다는 점을 제외하고는 DumpMachine function과 유사하게 작동합니다.
와 DumpMachine function마찬가지로 에서 생성된 DumpRegister function 정보는 머신에 target 따라 달라집니다. 전체 상태 양자 시뮬레이터의 경우, DumpMachine function과 동일한 형식으로 제공되는 큐비트에 의해 생성된 양자 하위 시스템의 글로벌 위상까지 wave 함수를 파일에 기록합니다. 예를 들어 두 큐비트만 할당되고 양자 상태가 qubit[0]
에 대해 DumpRegister function를 호출하는 $$ \begin{align} \ket{\psi} = \frac{1}{\sqrt{2}} \ket{00} - \frac{(1 + i)}{2} \ket{10} = - e^{-i\pi/4} ( (\frac{1}{\sqrt{2}} \ket{0} - \frac{(1 + i)}{2} \ket{1} ) \otimes \frac{-(1 + i)}{\sqrt{2}} \ket{0} ), \end{align} $$인 머신은 다음 출력을 생성합니다.
# wave function for qubits with ids (least to most significant): 0
∣0❭: -0.707107 + -0.707107 i == ******************** [ 1.000000 ] / [ -2.35619 rad ]
∣1❭: 0.000000 + 0.000000 i == [ 0.000000 ]
그리고 qubit[1]
에 대해 DumpRegister function를 호출하면 다음 출력이 생성됩니다.
# wave function for qubits with ids (least to most significant): 1
∣0❭: 0.707107 + 0.000000 i == *********** [ 0.500000 ] --- [ 0.00000 rad ]
∣1❭: -0.500000 + -0.500000 i == *********** [ 0.500000 ] / [ -2.35619 rad ]
일반적으로 다른 레지스터와 함께 사용되는 레지스터의 상태는 순수 상태가 아닌 혼합된 상태입니다. 이 경우 DumpRegister function는 다음 메시지를 출력합니다.
Qubits provided (0;) are entangled with some other qubit.
다음 예제에서는 Q# 코드에서 DumpRegister function 및 DumpMachine function을 모두 사용하는 방법을 보여 줍니다.
namespace DumpRegisterTest {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Diagnostics;
@EntryPoint()
operation DumpRegisterTestOp () : Unit {
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[1]);
R1Frac(1, 2, qubits[1]);
DumpMachine("dump.txt");
DumpRegister("q0.txt", qubits[0..0]);
DumpRegister("q1.txt", qubits[1..1]);
ResetAll(qubits);
}
}
디버깅
Assert
및 Dump
함수 및 연산을 기반으로 하는 Q#은 표준 Visual Studio 디버깅 기능의 하위 집합을 지원합니다. 줄 중단점 설정, F10 키를 사용하여 살펴보기 및 클래식 변수의 값 검사는 모두 시뮬레이터에서 코드를 실행할 때 가능합니다.
Visual Studio Code에서 디버깅하려면 OmniSharp에서 제공하는 C# for Visual Studio Code 확장에서 제공하는 디버깅 기능을 활용하고, 최신 버전을 설치해야 합니다.