샘플 API에서 CORS 및 테스트 관리 - C# 코스 빌드하기
C#에서 웹 API를 사용할 때 CORS(교차 출처 리소스 공유)는 종종 걸림돌이 됩니다. 특히 프런트엔드와 백엔드가 서로 다른 도메인이나 포트에 있는 경우 더욱 그렇습니다. 이는 현대 소프트웨어 개발에서 흔히 볼 수 있는 시나리오로, API가 Blazor WebAssembly, Angular 또는 React와 같은 프런트엔드 클라이언트에 서비스를 제공합니다.
Tim Corey는 " CORS 관리 및 테스트 - C#으로 샘플 API 구축하기 "라는 제목의 비디오 튜토리얼에서 샘플 API를 구축하고 테스트하는 동안 CORS를 효과적으로 관리하는 방법을 보여줍니다. 이러한 접근 방식은 개발자가 출처 간 문제를 해결할 뿐만 아니라 단위 테스트, 통합 테스트 및 자동화된 워크플로와 같은 고급 테스트 기법을 준비하는 데에도 도움이 됩니다.
그럼 영상 속으로 들어가서 팀의 안내를 단계별로 따라가 봅시다.
Blazor 프런트엔드 설정하기
Tim은 SampleTestUI라는 이름의 간단한 Blazor WebAssembly 프런트엔드 프로젝트를 생성하는 것으로 수업을 시작합니다. 이 프런트엔드는 실제 운영 환경에 적합하지 않습니다. API와의 연결성을 확인하고 의도적으로 CORS 문제를 발생시키기 위한 테스트 프로젝트입니다.
Tim은 .NET 9 템플릿을 사용하며 인증이나 PWA 기능은 사용하지 않습니다.
프런트엔드의 목적은 실제 API 호출을 시뮬레이션하고 다른 출처의 요청과 관련된 테스트 실패를 드러내는 것입니다.
그는 홈페이지를 수정하여 /courses API 엔드포인트를 호출하고 관련 이미지와 함께 강좌 목록을 표시합니다.
프런트엔드는 API와 모델을 공유하는 대신 별도로 생성된 간단한 모델 클래스(CourseModel)를 사용합니다. Tim은 결합도를 줄이고 유지 관리성을 높이기 위해 프런트엔드 모델과 데이터 액세스 모델을 분리해야 한다고 강조합니다(2:28). 이는 유지보수 가능한 테스트와 테스트 가능한 코드를 작성할 때 중요한 원칙입니다.
API 호출 작성하기
API에서 데이터를 가져오려면 다음 단계를 따르세요.
Tim은 HttpClient를 주입합니다.
그는 Http.GetFromJsonAsync를 사용하여 비동기 메서드를 작성합니다. <List
>(). - 해당 메서드는 로컬 API URL(4:00)로 하드코딩되어 있으며, 프런트엔드와 백엔드 간의 통신을 검증하기 위한 간단한 테스트 역할을 합니다.
여기에는 테스트 메서드나 오류 처리가 없고, 그냥 간단한 호출만 있습니다. 이러한 구성은 구성 요소 간의 기본 상호 작용을 검증하는 것부터 시작하는 단위 테스트 작성의 초기 단계를 반영합니다.
데이터 가져오기 로직 및 UI 구축
4분 지점에 API URL을 하드코딩한 후, Tim은 API에서 강좌 데이터를 가져와 Blazor 프런트엔드에 표시하는 핵심 로직 구축에 집중합니다. 이는 자동화된 테스트를 작성하거나 테스트 프레임워크를 사용하기 전에도 프런트엔드가 백엔드와 상호 작용할 수 있는지 검증하는 데 매우 중요한 단계입니다.
먼저, 그는 API의 launchSettings.json에서 올바른 URL이 사용되었는지 확인합니다. 즉, HTTPS 주소를 가져와서 /courses를 추가하여 완전한 엔드포인트를 구성합니다. 이는 브라우저가 보안 페이지에서 HTTPS가 아닌 API 호출을 거부하는 경우가 많기 때문에 중요합니다.
courses = await Http.GetFromJsonAsync<List<CourseModel>>("https://localhost:port/courses");courses = await Http.GetFromJsonAsync<List<CourseModel>>("https://localhost:port/courses");데이터 표시
데이터를 가져온 후 Tim은 Razor 구문을 사용하여 강좌 목록을 순회하는 간단한 UI 루프를 작성합니다.
@foreach (var c in courses) { <a href="@c.CourseUrl"> <img width="300" src="@c.CourseImage" /> </a> }@foreach (var c in courses) { <a href="@c.CourseUrl"> <img width="300" src="@c.CourseImage" /> </a> }각 강좌는 하이퍼링크로 둘러싸인 이미지 형태로 표시됩니다. 팀은 이미지 크기가 크기 때문에(1920x1080) 페이지가 너무 복잡해 보이지 않도록 너비를 300px로 제한했다고 언급했습니다.
이 출력 결과는 API 데이터가 프런트엔드로 올바르게 전달되고 있음을 시각적으로 확인시켜 줍니다. 이는 테스트 메서드가 통과했을 때 얻고자 하는 피드백과 유사합니다. 이미지가 표시되면 요청이 성공한 것입니다.
발사 준비 중
Tim은 애플리케이션을 실행하기 전에 Visual Studio에서 여러 시작 프로젝트를 구성합니다. 그는 API 프로젝트를 먼저 시작하고 그 다음에 Blazor 프런트엔드를 시작하도록 설정합니다. 이 순서는 프런트엔드가 데이터를 가져오려고 할 때 API가 준비되도록 보장하는 데 필수적입니다.
6시 30분에 진행되는 이 마지막 단계는 테스트를 실행하고 CORS 오류를 발견하는 데 필요한 기반을 마련하며, 바로 이 부분에서 튜토리얼의 다음 부분이 시작됩니다.
CORS 문제에 부딪히다
Tim이 Visual Studio의 솔루션 탐색기를 사용하여 두 프로젝트를 동시에 실행하자 프런트엔드가 API를 호출하려고 시도하지만 실패합니다. 브라우저 콘솔에 익숙한 메시지가 표시됩니다.
"CORS 정책에 의해 '[프런트엔드 URL]'에서 '[API URL]'로의 가져오기 액세스가 차단되었습니다..."(7:02)
바로 이 지점에서 CORS를 이해하고 관리하는 것이 필수적입니다. 적절한 헤더가 없으면 브라우저는 한 출처에서 다른 출처로의 요청을 차단합니다.
CORS 구성 클래스 생성
Tim은 Program.cs 파일을 복잡하게 만드는 대신, Startup 폴더에 CorsConfig라는 이름의 전용 클래스를 만듭니다. 그는 Swagger 및 OpenAPI 설정에 사용되는 것과 동일한 구성 패턴을 적용하기 위해 정적 클래스 구조를 사용합니다.
이는 클린 코드 작성 원칙에 부합하며 애플리케이션의 테스트 용이성을 높여줍니다. 이와 같은 모듈식 구성은 로직이 분리되어 있어 모킹이나 오버라이드가 용이하므로 나중에 단위 테스트 메서드를 작성하기가 더 쉬워집니다.
관대한 CORS 정책 적용
Tim은 모든 출처 간 액세스를 허용하기 위해 매우 개방적인 CORS 정책을 정의합니다.
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();이러한 설정은 외부 서비스 또는 프런트엔드 앱이 API에 대한 완전한 액세스 권한이 필요한 테스트 주도 개발 및 통합 테스트에서 유용합니다. 팀은 이 정책을 "AllowAll"이라고 부르고 오타와 불일치를 방지하기 위해 해당 이름을 상수로 저장합니다(11:00).
private const string AllowAllPolicy = "AllowAll";private const string AllowAllPolicy = "AllowAll";그는 이것이 실제 운영 환경에서 사용되어서는 안 되지만, 개발자들이 실험을 하거나 실제 엔드포인트에 대한 단위 테스트를 작성할 때 로컬 환경이나 Docker 컨테이너 내부에서 API를 테스트하는 데는 이상적이라고 지적합니다.
Program.cs에 설정 통합
Tim은 CORS 서비스를 등록하고 Program.cs 파일에 구성을 적용합니다.
builder.Services.AddCorsServices(); app.ApplyCorsConfig();builder.Services.AddCorsServices(); app.ApplyCorsConfig();이러한 모듈화는 코드 품질을 향상시키고, 향후 모킹 프레임워크를 추가하거나 테스트 동작을 주입하는 것을 더 쉽게 만듭니다. 이는 C#에서 단위 테스트를 위해 구조를 설계하는 방식을 반영한 것으로, 중앙 집중식 구성을 통해 테스트 설정을 간소화할 수 있습니다.
프런트엔드 재테스트
CORS 수정 사항을 적용한 후 Tim은 두 애플리케이션을 모두 다시 실행합니다. 이번에는 Blazor 프런트엔드가 예상대로 작동합니다. 강좌 데이터가 성공적으로 로드되고 각 강좌 이미지가 해당 URL로 연결됩니다.
중요한 점은 프런트엔드에는 아무런 변경 사항이 없었다는 것입니다. 이 문제는 API 수준에서 적절한 CORS 설정을 통해 해결되었습니다.
테스트 및 설정 전략에 대한 교훈
이 영상에서 팀은 유닛 테스트 프레임워크를 직접적으로 다루지는 않지만, 그의 접근 방식은 이를 위한 기초를 다져줍니다. 방법은 다음과 같습니다.
그는 관심사를 깔끔하게 분리하여 향후 테스트 클래스와 모의 객체를 활용할 수 있도록 합니다.
전용 CORS 설정 파일은 테스트 중에 재사용하거나 모의 구성으로 대체할 수 있습니다.
- 그의 빠른 프런트엔드 프로젝트는 수동 통합 테스트처럼 작동합니다. 즉, 전체 단위 테스트 프로젝트를 작성하기 전에 초기 검증을 수행하는 것입니다.
이는 Visual Studio에서 테스트에 접근하는 방식과 유사합니다.
메인 애플리케이션과 함께 유닛 테스트 프로젝트를 생성하세요.
테스트 탐색기를 사용하여 모든 테스트 메서드를 실행하고 결과를 추적하세요.
HTTP 요청, 데이터베이스 호출 또는 구성 파일과 같은 외부 종속성을 모의합니다.
- 예상되는 동작을 검증하기 위해 간단한 단위 테스트를 작성한 다음, 예외적인 상황을 포함하는 테스트 케이스로 확장하십시오.
CORS 시나리오에 대한 단위 테스트 고려 사항
팀의 영상은 주로 CORS 설정에 관한 것이지만, 소프트웨어 테스트에 미치는 영향은 분명합니다.
구성 서비스를 검증하는 단위 테스트 메서드를 만들 수 있습니다.
모킹 프레임워크를 사용하여 다른 출처 또는 HTTP 메서드와 같은 외부 요인을 시뮬레이션합니다.
CI/CD 프로세스의 일부로 테스트 실행을 수행하여 테스트 메서드가 일관되게 통과하는지 확인하십시오.
- Visual Studio 테스트 탐색기에 테스트를 통합하여 오류를 추적하고 안정성을 확보하십시오.
결론
이 비디오 튜토리얼에서 Tim Corey는 C# 웹 API에서 CORS를 관리하는 실용적인 예제를 제공하고, 연결 테스트를 위한 간단한 Blazor 프런트엔드를 구축하는 과정을 보여줍니다. 그의 접근 방식은 단순히 브라우저 오류를 수정하는 데 그치지 않고, 유지보수 가능한 코드, 깔끔한 아키텍처, 그리고 자동화된 테스트로의 손쉬운 확장을 장려하는 구조를 구축하는 데 중점을 둡니다.
여기서부터 개발자들은 자신 있게 단위 테스트 작성, 통합 테스트 설정, 그리고 Visual Studio, Test Explorer, 모킹 프레임워크와 같은 도구를 사용하여 코드 품질과 안정성을 향상시킬 수 있습니다.
테스트를 시작하는 방법, 첫 번째 단위 테스트를 작성하는 방법, 또는 테스트 메서드가 예상대로 실패하는지 확인하는 방법을 배우든, 이 강의는 탄탄한 개발 프로세스를 위한 기초를 제공합니다. 그리고 무엇보다 중요한 것은, 모든 것은 아키텍처와 구성을 제대로 하는 것에서 시작된다는 점입니다.


