React 웹사이트
이 생성기는 기본적으로 shadcn/ui가 구성된 새로운 React 웹사이트를 생성하며, S3에 호스팅되고 CloudFront로 제공되며 WAF로 보호되는 정적 웹사이트로 클라우드에 배포하기 위한 AWS CDK 또는 Terraform 인프라를 함께 생성합니다.
생성된 애플리케이션은 빌드 도구 및 번들러로 Vite를 사용합니다. 타입 안전 라우팅을 위해 TanStack Router를 사용합니다.
사용법
섹션 제목: “사용법”React 웹사이트 생성
섹션 제목: “React 웹사이트 생성”두 가지 방법으로 새로운 React 웹사이트를 생성할 수 있습니다:
pnpm nx g @aws/nx-plugin:ts#website --framework=reactyarn nx g @aws/nx-plugin:ts#website --framework=reactnpx nx g @aws/nx-plugin:ts#website --framework=reactbunx nx g @aws/nx-plugin:ts#website --framework=react어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
pnpm nx g @aws/nx-plugin:ts#website --framework=react --dry-runyarn nx g @aws/nx-plugin:ts#website --framework=react --dry-runnpx nx g @aws/nx-plugin:ts#website --framework=react --dry-runbunx nx g @aws/nx-plugin:ts#website --framework=react --dry-run- 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
- VSCode에서 Nx 콘솔 열기
- 클릭
Generate (UI)"Common Nx Commands" 섹션에서 - 검색
@aws/nx-plugin - ts#website - 필수 매개변수 입력
- framework: react
- 클릭
Generate
| 매개변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| name 필수 | string | - | 애플리케이션의 이름입니다. |
| framework | react | react | 사용할 프론트엔드 프레임워크입니다. |
| directory | string | packages | 새 애플리케이션의 디렉토리입니다. |
| subDirectory | string | - | 프로젝트가 배치되는 하위 디렉토리입니다. 기본값은 프로젝트 이름입니다. |
| ux | none | cloudscape | shadcn | shadcn | 선호하는 UX 제공자입니다. |
| tailwind | boolean | true | 유틸리티 우선 스타일링을 위해 TailwindCSS를 활성화합니다. |
| tanstackRouter | boolean | true | 타입 안전 라우팅을 위해 Tanstack router를 활성화합니다. |
| infra | cloudfront-s3 | none | cloudfront-s3 | 웹사이트를 배포할 인프라 유형입니다. |
| iac | inherit | cdk | terraform | inherit | 선호하는 IaC 제공자입니다. 기본적으로 초기 선택에서 상속됩니다. |
| preferInstallDependencies | boolean | true | 생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 처리할 때 설치를 연기하려면 false로 설정하세요(후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다). 마지막에 한 번만 설치하세요. |
생성기 출력
섹션 제목: “생성기 출력”생성기는 <directory>/<name> 디렉토리에 다음과 같은 프로젝트 구조를 생성합니다:
- index.html HTML 진입점
- public 정적 자산
디렉터리src
- main.tsx React 설정이 포함된 애플리케이션 진입점
- config.ts 애플리케이션 구성 (예: 로고)
디렉터리components
- AppLayout 전체 레이아웃 및 네비게이션 바를 위한 컴포넌트
디렉터리hooks
- useAppLayout.tsx 중첩된 컴포넌트에서 AppLayout을 조정하기 위한 훅 (Cloudscape 전용)
디렉터리routes
- index.tsx TanStack Router를 위한 예제 라우트 (또는 페이지)
- styles.css 전역 스타일
- vite.config.mts Vite 및 Vitest 구성
- tsconfig.json 소스 및 테스트를 위한 기본 TypeScript 구성
- tsconfig.app.json 소스 코드를 위한 TypeScript 구성
- tsconfig.spec.json 테스트를 위한 TypeScript 구성
- package.json 프로젝트의 패키지 이름과 의존성을 정의하는 프로젝트 매니페스트
인프라
섹션 제목: “인프라”이 생성기는 선택한 iac를 기반으로 코드형 인프라를 제공하므로, 관련 CDK constructs 또는 Terraform 모듈을 포함하는 packages/common에 프로젝트를 생성합니다.
공통 코드형 인프라 프로젝트는 다음과 같이 구성됩니다:
디렉터리packages/common/constructs
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Constructs
- …
디렉터리core/
app의 constructs에서 재사용되는 일반 constructs- …
- index.ts
app에서 constructs를 내보내는 진입점
- project.json 프로젝트 빌드 타겟 및 구성
디렉터리packages/common/terraform
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Terraform 모듈
- …
디렉터리core/
app의 모듈에서 재사용되는 일반 모듈- …
- project.json 프로젝트 빌드 타겟 및 구성
생성기는 선택한 iac에 따라 웹사이트 배포를 위한 코드형 인프라를 생성합니다:
디렉터리packages/common/constructs/src
디렉터리app
디렉터리static-websites
- <name>.ts 웹사이트에 특화된 인프라
디렉터리core
- static-website.ts 범용 StaticWebsite 구성
디렉터리packages/common/terraform/src
디렉터리app
디렉터리static-websites
디렉터리<name>
- <name>.tf 웹사이트에 특화된 모듈
디렉터리core
디렉터리static-website
- static-website.tf 범용 정적 웹사이트 모듈
아키텍처
섹션 제목: “아키텍처”배포된 웹사이트는 다음과 같은 아키텍처를 가집니다:
웹사이트 구현
섹션 제목: “웹사이트 구현”React 문서는 React로 빌드하는 기본 사항을 배우기 좋은 출발점입니다.
사용 가능한 컴포넌트와 사용 방법에 대한 자세한 내용은 Cloudscape 문서를 참조하세요.
사용 가능한 컴포넌트와 사용 방법에 대한 자세한 내용은 shadcn/ui 문서를 참조하세요.
라우트
섹션 제목: “라우트”라우트/페이지 생성
섹션 제목: “라우트/페이지 생성”웹사이트에는 기본적으로 TanStack Router가 구성되어 있습니다. 이를 통해 새로운 라우트를 쉽게 추가할 수 있습니다:
- 로컬 개발 서버 실행
src/routes에 새로운<page-name>.tsx파일을 생성하며, 파일 트리에서의 위치가 경로를 나타냅니다Route와RouteComponent가 자동으로 생성되는 것을 확인하세요. 여기서 페이지 빌드를 시작할 수 있습니다!
페이지 간 탐색
섹션 제목: “페이지 간 탐색”페이지 간 탐색을 위해 Link 컴포넌트 또는 useNavigate 훅을 사용할 수 있습니다:
import { Link, useNavigate } from '@tanstack/react-router';
export const MyComponent = () => { const navigate = useNavigate();
const submit = async () => { const id = await ... // Use `navigate` for redirecting after some asynchronous action navigate({ to: '/products/$id', { params: { id }} }); };
return ( <> <Link to="/products">Cancel</Link> <Button onClick={submit}>Submit</Button> </> )};자세한 내용은 TanStack Router 문서를 확인하세요.
웹사이트 배포
섹션 제목: “웹사이트 배포”React 웹사이트 생성기는 선택한 iac에 따라 CDK 또는 Terraform 코드형 인프라를 생성합니다. 이를 사용하여 웹사이트를 배포할 수 있습니다.
웹사이트를 배포하려면 ts#infra 생성기를 사용하여 CDK 애플리케이션을 생성하는 것을 권장합니다.
packages/common/constructs에 생성된 CDK 구성을 사용하여 웹사이트를 배포할 수 있습니다.
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite'); }}이는 다음을 설정합니다:
- 정적 웹사이트 파일 호스팅을 위한 S3 버킷
- 글로벌 콘텐츠 전송을 위한 CloudFront 배포
- 보안 보호를 위한 WAF Web ACL
- 안전한 S3 액세스를 위한 Origin Access Control
- 웹사이트 파일 및 런타임 구성의 자동 배포
웹사이트를 배포하려면 terraform#project 생성기를 사용하여 Terraform 프로젝트를 생성하는 것을 권장합니다.
packages/common/terraform에 생성된 Terraform 모듈을 사용하여 웹사이트를 배포할 수 있습니다.
# Deploy websitemodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }}이는 다음을 설정합니다:
- 정적 웹사이트 파일 호스팅을 위한 S3 버킷
- 글로벌 콘텐츠 전송을 위한 CloudFront 배포
- 보안 보호를 위한 WAF Web ACL (us-east-1에 배포)
- 안전한 S3 액세스를 위한 Origin Access Control
- 웹사이트 파일 및 런타임 구성의 자동 배포
보안 헤더
섹션 제목: “보안 헤더”CloudFront 배포는 모든 응답에 Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy 및 Content-Security-Policy를 설정하는 응답 헤더 정책을 적용합니다.
기본 Content-Security-Policy가 적용됩니다. 이는 XSS 및 클릭재킹을 완화하기 위해 스크립트와 프레이밍을 제한하면서, 배포 시점에만 알 수 있는 URL을 가진 AWS 서비스 엔드포인트(API Gateway, Cognito, Bedrock AgentCore 등)를 웹사이트가 호출할 수 있도록 HTTPS 및 WSS 연결을 허용합니다. 정책을 조정하려면(예: connect-src를 특정 원본으로 강화) 생성된 static-website.ts(CDK) 또는 static-website.tf(Terraform)의 content_security_policy 값을 편집하세요.
runtime-config.json은 Cache-Control: no-cache로 제공되어 브라우저가 재배포 후 캐시된 오래된 복사본을 사용하는 대신 항상 최신 구성을 가져오도록 합니다.
WAF
섹션 제목: “WAF”CloudFront 배포는 기본적으로 AWS WAFv2 Web ACL로 보호됩니다. Web ACL은 AWS 관리형 기본 규칙 세트(AWSManagedRulesCommonRuleSet 및 AWSManagedRulesKnownBadInputsRuleSet)를 사용하여 OWASP Top 10을 포함한 일반적인 웹 익스플로잇에 대한 보호를 제공합니다.
비활성화하려면 웹사이트를 생성할 때 enableWaf를 false로 설정하세요:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite, suppressRules } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
const website = new MyWebsite(this, 'MyWebsite', { enableWaf: false, });
// Disabling WAF fails the checkov CKV_AWS_68 check ("CloudFront // Distribution should have WAF enabled"). Suppress it explicitly. suppressRules( website.cloudFrontDistribution, ['CKV_AWS_68'], 'WAF is intentionally disabled for this distribution', ); }}비활성화하려면 enable_waf를 false로 설정하세요:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } enable_waf = false}버킷 암호화
섹션 제목: “버킷 암호화”웹사이트 버킷, CloudFront 배포 로그 버킷, 서버 액세스 로그를 수신하는 CloudWatch Logs 그룹은 기본적으로 고객 관리형 AWS KMS 키로 암호화됩니다. 이 키는 키 로테이션이 활성화된 상태로 자동으로 생성됩니다.
다른 암호화 구성을 사용하려면 웹사이트를 생성할 때 encryption, encryptionKey 및 enableKeyRotation 속성을 전달하세요:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { BucketEncryption } from 'aws-cdk-lib/aws-s3';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite', { encryption: BucketEncryption.S3_MANAGED, }); }}자동으로 생성되는 대신 자체 KMS 키를 사용하려면 encryptionKey를 전달하세요:
new MyWebsite(this, 'MyWebsite', { encryptionKey: myKey,});enableKeyRotation(기본값 true)은 자동으로 생성된 키에만 적용됩니다. 즉, encryption이 BucketEncryption.KMS(기본값)이고 encryptionKey가 제공되지 않은 경우입니다:
new MyWebsite(this, 'MyWebsite', { enableKeyRotation: false,});다른 암호화 구성을 사용하려면 encryption, kms_key_arn, create_kms_key 및 enable_key_rotation 변수를 설정하세요:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } encryption = "S3_MANAGED"}자동으로 생성되는 대신 자체 KMS 키를 사용하려면 kms_key_arn을 전달하고 create_kms_key를 false로 설정하세요:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } kms_key_arn = aws_kms_key.website.arn create_kms_key = false}고객이 제공한 키는 자체 키 정책에서 CloudWatch Logs, S3 및 CloudFront 서비스 주체에게 필요한 권한을 이미 부여해야 합니다.
enable_key_rotation(기본값 true)은 자동으로 생성된 키에만 적용됩니다. 즉, encryption이 "KMS"(기본값)이고 create_kms_key가 true인 경우입니다:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } enable_key_rotation = false}사용자 정의 도메인 및 TLS
섹션 제목: “사용자 정의 도메인 및 TLS”기본적으로 배포는 기본 CloudFront 도메인 이름(*.cloudfront.net)과 기본 인증서를 사용하며, 이는 최소 TLS 버전 1.2 적용을 지원하지 않습니다. 자체 도메인에서 웹사이트를 제공하려면 ACM 인증서(CloudFront와 함께 사용하려면 us-east-1에 있어야 함)와 도메인 이름을 제공하세요. 그러면 뷰어에 대해 최소 TLS 버전 1.2가 적용됩니다:
웹사이트를 생성할 때 certificate 및 domainNames 속성을 전달하세요:
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { Certificate } from 'aws-cdk-lib/aws-certificatemanager';import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
new MyWebsite(this, 'MyWebsite', { domainNames: ['www.example.com'], certificate: Certificate.fromCertificateArn(this, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/...'), }); }}custom_domain_names 및 acm_certificate_arn 변수를 설정하세요:
module "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 } custom_domain_names = ["www.example.com"] acm_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/..."}또한 CloudFront 배포를 가리키는 DNS 레코드(예: Route 53에서)를 생성해야 합니다.
런타임 구성
섹션 제목: “런타임 구성”인프라의 구성은 런타임 구성을 통해 웹사이트에 제공됩니다. 이를 통해 웹사이트는 애플리케이션이 배포될 때까지 알 수 없는 API URL과 같은 세부 정보에 액세스할 수 있습니다.
인프라
섹션 제목: “인프라”RuntimeConfig CDK 구성을 사용하여 CDK 인프라에서 구성을 추가하고 검색할 수 있습니다. @aws/nx-plugin 생성기(ts#api 및 py#api 등)가 생성한 CDK 구성은 자동으로 RuntimeConfig에 적절한 값을 추가합니다.
웹사이트 CDK 구성은 런타임 구성의 connection 네임스페이스를 S3 버킷의 루트에 runtime-config.json 파일로 배포합니다.
import { Stack } from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite, MyApi } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id);
// Website can be declared at any point, since runtime config is resolved lazily new MyWebsite(this, 'MyWebsite');
// Automatically adds values to the RuntimeConfig new MyApi(this, 'MyApi', { integrations: MyApi.defaultIntegrations(this).build(), }); }}Terraform을 사용하면 런타임 구성은 runtime-config 모듈을 통해 관리됩니다. @aws/nx-plugin 생성기(ts#api 및 py#api 등)가 생성한 Terraform 모듈은 자동으로 런타임 구성에 적절한 값을 추가합니다.
웹사이트 Terraform 모듈은 런타임 구성의 connection 네임스페이스를 S3 버킷의 루트에 runtime-config.json 파일로 배포합니다.
module "asset_bucket" { source = "../../common/terraform/src/core/asset-bucket"}
# Automatically adds values to runtime configmodule "my_api" { source = "../../common/terraform/src/app/apis/my-api"
asset_bucket_name = module.asset_bucket.bucket_name}
# Automatically deploys the runtime config to runtime-config.jsonmodule "my_website" { source = "../../common/terraform/src/app/static-websites/my-website"
providers = { aws.us_east_1 = aws.us_east_1 }
# Ensure API is deployed first to add to runtime config depends_on = [module.my_api]}웹사이트 코드
섹션 제목: “웹사이트 코드”웹사이트에서 useRuntimeConfig 훅을 사용하여 런타임 구성에서 값을 검색할 수 있습니다:
import { useRuntimeConfig } from '../hooks/useRuntimeConfig';
const MyComponent = () => { const runtimeConfig = useRuntimeConfig();
// Access values in the runtime config here const apiUrl = runtimeConfig.apis.MyApi;};로컬 런타임 구성
섹션 제목: “로컬 런타임 구성”로컬 개발 서버를 실행할 때 로컬 웹사이트가 백엔드 URL, 신원 구성 등을 알 수 있도록 public 디렉토리에 runtime-config.json 파일이 필요합니다.
웹사이트 프로젝트는 배포된 애플리케이션에서 runtime-config.json 파일을 가져오는 데 사용할 수 있는 load-runtime-config 타겟으로 구성되어 있습니다:
pnpm nx load-runtime-config <my-website>yarn nx load-runtime-config <my-website>npx nx load-runtime-config <my-website>bunx nx load-runtime-config <my-website>로컬 개발 서버
섹션 제목: “로컬 개발 서버”로컬 개발을 위한 표준 명령은 dev이며, 이는 하나의 명령으로 웹사이트(및 연결한 API의 로컬 서버)를 시작합니다:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>serve 타겟은 배포된 AWS 인프라를 가리키는 것과 로컬에서 실행되는 애플리케이션의 양을 제어해야 할 때 사용할 수 있습니다. 여러 구성 요소가 있는 프로젝트에서 dev가 동작하는 방식을 포함하여 연결된 프로젝트 전체의 로컬 개발에 대한 광범위한 개요는 로컬 개발 가이드를 참조하세요.
Serve 타겟
섹션 제목: “Serve 타겟”serve 타겟은 웹사이트를 위한 로컬 개발 서버를 시작합니다. 이 타겟을 사용하려면 웹사이트가 상호 작용하는 지원 인프라를 배포하고 로컬 런타임 구성을 로드해야 합니다.
다음 명령으로 이 타겟을 실행할 수 있습니다:
pnpm nx serve <my-website>yarn nx serve <my-website>npx nx serve <my-website>bunx nx serve <my-website>이 타겟은 “실제” 배포된 API 및 기타 인프라를 가리키면서 웹사이트 변경 작업을 할 때 유용합니다.
Dev 타겟
섹션 제목: “Dev 타겟”dev 타겟은 웹사이트를 위한 로컬 개발 서버(Vite MODE가 local-dev로 설정됨)를 시작하고, 연결 생성기를 통해 웹사이트에 연결한 API의 로컬 서버도 시작합니다.
이 타겟을 통해 로컬 웹사이트 서버가 실행되면 runtime-config.json이 자동으로 재정의되어 로컬에서 실행 중인 API URL을 가리킵니다.
다음 명령으로 이 타겟을 실행할 수 있습니다:
pnpm nx dev <my-website>yarn nx dev <my-website>npx nx dev <my-website>bunx nx dev <my-website>이 타겟은 웹사이트와 API 전반에 걸쳐 작업하고 인프라를 배포하지 않고 빠르게 반복하려는 경우 유용합니다.
모의 인증
이 모드에서 실행되고 runtime-config.json이 없는 경우, Cognito 인증을 구성했다면(ts#website#auth 생성기를 통해) 로그인이 건너뛰어지고 로컬 서버에 대한 요청에 인증 헤더가 포함되지 않습니다.
dev에 대한 로그인 및 인증을 활성화하려면 인프라를 배포하고 런타임 구성을 로드하세요.
build 타겟을 사용하여 웹사이트를 빌드할 수 있습니다. 이는 bundle, compile, test 및 lint 타겟을 실행하여 웹사이트를 타입 검사, 번들링, 테스트 및 린팅합니다.
pnpm nx build <my-website>yarn nx build <my-website>npx nx build <my-website>bunx nx build <my-website>bundle 타겟은 Vite를 사용하여 루트 dist/packages/<my-website>/bundle 디렉토리에 프로덕션 번들을 생성합니다. 이것이 웹사이트 인프라에서 사용하는 배포 가능한 아티팩트입니다. 단독으로 실행할 수 있습니다:
pnpm nx bundle <my-website>yarn nx bundle <my-website>npx nx bundle <my-website>bunx nx bundle <my-website>테스트
섹션 제목: “테스트”웹사이트 테스트는 표준 TypeScript 프로젝트에서 테스트를 작성하는 것과 매우 유사하므로 자세한 내용은 TypeScript 프로젝트 가이드를 참조하세요.
React 특정 테스트의 경우 React Testing Library가 이미 설치되어 있으며 테스트를 작성하는 데 사용할 수 있습니다. 사용법에 대한 자세한 내용은 React Testing Library 문서를 참조하세요.
test 타겟을 사용하여 테스트를 실행할 수 있습니다:
pnpm nx test <my-website>yarn nx test <my-website>npx nx test <my-website>bunx nx test <my-website>connection 생성기를 사용하여 이 프로젝트를 워크스페이스의 다른 프로젝트와 통합하세요. 다음 연결에는 이 프로젝트가 포함됩니다:
