2022. 8. 25. 15:00

백엔드와 프론트엔드를 같이 디버깅하려면

백엔드 따로 프론트엔드 따로 실행 해야 합니다.

 

이전 포스팅에서는 디버깅을 포기하고 자동화를 했었습니다.

(참고 : [ASP.NET Core 6] 비주얼 스튜디오 + React 5 (1/3) - 개요 및 프로젝트 생성 )

 

이번 포스팅에서는

- 'SpaProxy'를 이용하여 백엔드를 실행한 후 npm을 실행 시키고

- 비주얼 스튜디오의 디버거에 연결하고

- 자바스크립트(javascript)를 비롯한 'NPM' 프로젝트를 디버깅을

할 수 있도록 하겠습니다.

 

연관글 영역

 

 

0. 문제의 시작

이것저것 다 귀찮으면 프론트엔드 출력물만 가지고 'ASP.NET Core 6'에서 웹서버 돌려서 해도 되긴 합니다.

소스맵만 잘 구성과 크로스 도메인(Cross Domain, CORS )만 어찌 잘 해결한다면 말이죠.

 

문제는 이렇게 하면 비주얼 스튜디오 2022(코드 버전 말고, 오리지널)에서는 디버깅이 되지 않습니다.

리액트 파일의 중단점이 작동하지 않는다.

 

비주얼 스튜디오의 자바스크립트 디버거가 NPM에 연결되지 않아서 그렇습니다.

이때 디버거를 연결하려면 'SpaProxy'를 사용해야 합니다.

 

 

1. 'SpaProxy' 설치 및 설정

프로젝트는 'ASP.NET Core Web API' 템플릿으로 생성하고

여기에 'SpaProxy'를 설치하고 설정해 봅시다.

 

 

1-1. 'SpaProxy' 설치

누겟에서 'Microsoft.AspNetCore.SpaProxy'를 찾아 설치해줍니다.

 

 

1-2. 'launchSettings.json' 설정

Properties > launchSettings.json

파일을 열고 'environmentVariables'항목에 'SpaProxy'설정을 추가합니다.

"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"

 

만약 'launchUrl'에 'swagger'가 있으면 지워 줍니다.

'applicationUrl'의 주소는 기억해두어야 합니다.

 

 

1-3. 프로젝트 파일 수정

프로젝트 파일을 더블클릭하면 아래와 같이 편집할 수 있습니다.

 

아래 내용이 테스트 프로젝트 파일의 내용입니다.

자신의 프로젝트에 맞게 추가합니다.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
	  <Nullable>enable</Nullable>
	  <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
	  <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
	  <IsPackable>false</IsPackable>
	  <SpaRoot>ClientApp\</SpaRoot>
	  <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
	  <SpaProxyServerUrl>https://localhost:44455</SpaProxyServerUrl>
	  <SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.8" />
    <PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="6.0.8" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>

	<ItemGroup>
		<!-- Don't publish the SPA source files, but do show them in the project files list -->
		<Content Remove="$(SpaRoot)**" />
		<None Remove="$(SpaRoot)**" />
		<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
	</ItemGroup>

	<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
		<!-- Ensure Node.js is installed -->
		<Exec Command="node --version" ContinueOnError="true">
			<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
		</Exec>
		<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
		<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
		<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
	</Target>

	<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
		<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
		<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
		<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

		<!-- Include the newly-built files in the publish output -->
		<ItemGroup>
			<DistFiles Include="$(SpaRoot)build\**" />
			<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
				<RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
				<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
				<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
			</ResolvedFileToPublish>
		</ItemGroup>
	</Target>
</Project>

 

SpaRoot : 'npm'프로젝트가 들어있는 폴더를 지정합니다.

SpaProxyServerUrl : 'npm'프로젝트가 사용할 주소를 설정합니다.

SpaProxyLaunchCommand : 'SpaProxy'가 시작되면 사용할 명령어 입니다.

 

 

2. 테스트용 'node' 프로젝트 복사하기

이 포스팅에서는 직접 npm 프로젝트를 세팅하지 않습니다.

그래서 기존 템플릿을 복사해서 테스트합니다.

 

전 리액트(React) 프로젝트로 했으나 다른 프로젝트도 상관없습니다.

 

 

2-1. 'node'용 폴더 생성

프로젝트 루트에 'ClientApp'폴더를 생성해 줍니다.

 

 

2-2. 파일 복사

'독립 실행형 JavaScript React 프로젝트' 템플릿으로 새 프로젝트를 만듭니다.

이때 '빈 ASP.NET Web API 프로젝트에 대한 통합을 추가합니다.'를 체크합니다.

 

'빈 ASP.NET Web API 프로젝트에 대한 통합을 추가합니다.' 이 옵션을 사용하면 수동으로 연결해야 하는 것들을 모두 자동으로 해줍니다.

이 옵션이 없어도 동작은 합니다.

테스트할 때 필요한 몇몇 작업이 안 돼 있을 뿐이죠.

* 따로 CRA(create react app)로 생성한 프로젝트를 복사해도 됩니다.

 

수동으로 세팅하는 내용은 다음 포스팅에서 할 예정입니다.

 

 

'nuget.config'를 제외한 파일을 'ClientApp'폴더에 복사합니다.

public

src

.gitignore

aspnetcore-https.js : https 인증서가 없으면 인증서를 생성하는 명령어를 실행시켜 주는 스크립트입니다.

aspnetcore-react.js : webpack 프록시에 사용할 환경파일(.env.development, .env.development.local)을 생성해주는 스크립트입니다.

package.json (package-lock.json는 복사하지 않아도 생성됩니다.)

README.md

(참고 : simooovanov.medium.com Simeon Vanov님의 글 - Inside ASP.NET Core 6 React Template )

 

 

2-3. 'setupProxy.js' 세팅

다시

Properties > launchSettings.json

파일을 열어 'applicationUrl'의 주소를 확인합니다.

 

'npm'프로젝트는 API의 주소를 모르므로 이 내용을 전달해야 합니다.

 

ClientApp > src > setupProxy.js

파일을 열고 'target'의 주소를 수정합니다.

 

2-4. 'NPM' 웹 주소 세팅

아래 명령어를 사용하여 'NPM' 웹서버를 실행시켜 줍니다.

npm run start

 

그러면 NPM의 웹서버에서 사용하는 주소가 표시됩니다.

 

이것을 프로젝트 파일의 'SpaProxyServerUrl' 항목에 넣어줍니다.

 

 

3. 테스트하기

중단점이 잡히는지 확인해야 하므로

ClientApp > src > App.js

파일을 열어 '16번' 라인에 중단점을 걸어 줍니다.

 

 

이제 실행해봅시다.

 

ASP.NET가 실행되고

자동으로 'SpaProxyLaunchCommand'에 설정된 'npm start'명령을 실행시키면서

NPM 페이지가 표시됩니다.

 

창이 2개 열린다는 문제가 있긴 하지만

중단점도 잘 잡히고, API도 잘 호출됩니다.

 

 

브라우저가 열리지 않게 설정

'ClientApp' 폴더에 '.env'파일을 생성하고 아래 코드를 넣습니다.

BROWSER=none

 

 

'Microsoft.AspNetCore.SpaProxy' 파일 찾지 못함 오류

'Microsoft.AspNetCore.SpaProxy'를 쓸 때 간혹 'FileNotFoundException'오류가 나곤 합니다.

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.SpaProxy, Culture=neutral, PublicKeyToken=null'. 지정된 파일을 찾을 수 없습니다.

 

이 오류가나면 해당 프로젝트에서 사용 중인 'Microsoft.AspNetCore.SpaProxy'의 버전이 해당 프로젝트와 맞지 않아서 일 수 있습니다.

 

누겟으로 가서 다른 버전으로 바꿔서 되는 버전을 찾아 사용합시다.

 

 

마무리

테스트 프로젝트 : gtihub - dang-gun/AspDotNetSamples/SpaProxyToNodeTest1/

 

와.....

이거 자료가 너무 없어서 못 찾을 줄 알았는데

'ASP.NET Core'의 템플릿부터

'CRA'까지 분석해가며 찾아냈습니다 ㅎㅎㅎㅎㅎ

 

문제는 아직 프론트엔드는 직접 구성하지 못한다는 거....

webpack를 직접 세팅하면 디버깅이 안된다는 문제 정도?

ㅎㅎㅎㅎ