GitHub Copilot을 활용하여 Stock App을 초신속하게 생성하는 방법을 설명합니다.


Stock 앱을 위해 필요 정보 수집

Stock App 디자인 하기

  • 샘플 스크린샷 기반으로 모으기
  • Figma 디자인 하기


Stock Data 가져오기


기능 구현하기

  • VS Code 세팅
  • Figma → Web source 가져오기
  • Azure Infra 만들기 (어플리케이션에 대한 정보 설명)
    내가 주식 관련한 웹 앱을 만들기 위해서 stock symbol을 검색할 수 있는 시스템을 만들고 싶어.
    그래서 첨부한 파일을 기반으로 Azure에서 검색 가능하도록 API를 구성하고 싶거든.
    
    예를 들면, Web 검색창에서 Microsoft를 검색하면 MSFT Symbol을 추천해주는 형태야.
    물론 MSFT로 검색이 되어도 좋고, MS만 치더라도 MSFT가 추천되어 나오는걸 기대해.
    
    그래서 위 파일의 내용을 DB에 두고, 검색이 되게끔 만들고 싶은데, 검색 조건으로 유의어도 자동으로 연동될 수 있도록 구성하고 싶어.
    예를 들면 처음에는 위 리스트 기반으로 DB에 저장 되지만, 나중에는 해당 데이터 기반 유의어도 검색되도록 업데이트를 할 수 있는 구조를 가져가고 싶어.
    
    이를 위해서 Azure에서 조합해서 쓸 수 있는 서비스들과 아키텍처를 추천해줘.
  • CHECK Bicep 몇번이나 에러가 났음. 이 부분에 대해서는 몇 번 반복하면서 최소화 할 수 있도록 노력 필요
    param location string = resourceGroup().location
    
    @minLength(2)
    @maxLength(24)
    param searchServiceName string = 'stocksearch${uniqueString(resourceGroup().id)}'
    
    @minLength(3)
    @maxLength(44)
    param cosmosAccountName string = 'stockcosmos${uniqueString(resourceGroup().id)}'
    
    param cosmosDatabaseName string = 'stockdb'
    param cosmosContainerName string = 'tickers'
    
    @minLength(3)
    @maxLength(24)
    param storageAccountName string = 'stockstore${uniqueString(resourceGroup().id)}'
    
    param functionAppName string = 'stockfunc-${uniqueString(resourceGroup().id)}'
    param appInsightsName string = 'stockai-${uniqueString(resourceGroup().id)}'
    param keyVaultName string = 'stockkv-${uniqueString(resourceGroup().id)}'
    
    var functionRuntimeVersion = '~4'
    var functionWorkerRuntime = 'node'
    
    resource search 'Microsoft.Search/searchServices@2023-11-01' = {
      name: searchServiceName
      location: location
      sku: {
        name: 'basic'
      }
      properties: {
        replicaCount: 1
        partitionCount: 1
        hostingMode: 'default'
        networkRuleSet: {
          ipRules: []
        }
      }
    }
    
    resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' = {
      name: cosmosAccountName
      location: location
      kind: 'GlobalDocumentDB'
      properties: {
        databaseAccountOfferType: 'Standard'
        locations: [
          {
            locationName: location
            failoverPriority: 0
            isZoneRedundant: false
          }
        ]
        consistencyPolicy: {
          defaultConsistencyLevel: 'Session'
        }
        capabilities: [
          {
            name: 'EnableServerless'
          }
        ]
        ipRules: []
        isVirtualNetworkFilterEnabled: false
        publicNetworkAccess: 'Enabled'
      }
    }
    
    resource cosmosDb 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2024-05-15' = {
      parent: cosmosAccount
      name: cosmosDatabaseName
      properties: {
        resource: {
          id: cosmosDatabaseName
        }
      }
    }
    
    resource cosmosContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2024-05-15' = {
      parent: cosmosDb
      name: cosmosContainerName
      properties: {
        resource: {
          id: cosmosContainerName
          partitionKey: {
            paths: ['/symbol']
            kind: 'Hash'
          }
          indexingPolicy: {
            indexingMode: 'consistent'
            automatic: true
            includedPaths: [{ path: '/*' }]
            excludedPaths: [{ path: '/"searchVector"/*' }]
          }
        }
        options: {}
      }
    }
    
    resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
      name: storageAccountName
      location: location
      sku: {
        name: 'Standard_LRS'
      }
      kind: 'StorageV2'
      properties: {
        supportsHttpsTrafficOnly: true
        allowBlobPublicAccess: false
        minimumTlsVersion: 'TLS1_2'
      }
    }
    
    resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
      name: appInsightsName
      location: location
      kind: 'web'
      properties: {
        Application_Type: 'web'
        Flow_Type: 'Bluefield'
        Request_Source: 'rest'
      }
    }
    
    resource hostingPlan 'Microsoft.Web/serverfarms@2022-09-01' = {
      name: 'plan-${functionAppName}'
      location: location
      sku: {
        name: 'Y1'
        tier: 'Dynamic'
        size: 'Y1'
        family: 'Y'
        capacity: 0
      }
      properties: {
        reserved: false
        targetWorkerCount: 0
        targetWorkerSizeId: 0
      }
    }
    
    resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = {
      parent: storage
      name: 'default'
    }
    
    resource functionStorage 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
      parent: blobService
      name: '$web'
      properties: {
        publicAccess: 'None'
      }
    }
    
    resource functionApp 'Microsoft.Web/sites@2022-09-01' = {
      name: functionAppName
      location: location
      kind: 'functionapp'
      identity: {
        type: 'SystemAssigned'
      }
      properties: {
        serverFarmId: hostingPlan.id
        httpsOnly: true
        siteConfig: {
          appSettings: [
            {
              name: 'AzureWebJobsStorage'
              value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storage.listKeys().keys[0].value}'
            }
            {
              name: 'FUNCTIONS_EXTENSION_VERSION'
              value: functionRuntimeVersion
            }
            {
              name: 'FUNCTIONS_WORKER_RUNTIME'
              value: functionWorkerRuntime
            }
            {
              name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
              value: appInsights.properties.InstrumentationKey
            }
            {
              name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
              value: appInsights.properties.ConnectionString
            }
            {
              name: 'WEBSITE_RUN_FROM_PACKAGE'
              value: '0'
            }
          ]
        }
      }
    }
    
    resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' = {
      name: keyVaultName
      location: location
      properties: {
        sku: {
          name: 'standard'
          family: 'A'
        }
        tenantId: subscription().tenantId
        enableSoftDelete: true
        publicNetworkAccess: 'Enabled'
        enabledForTemplateDeployment: true
        accessPolicies: [
          {
            tenantId: subscription().tenantId
            objectId: functionApp.identity.principalId
            permissions: {
              secrets: [
                'Get'
                'List'
              ]
            }
          }
        ]
      }
    }




  • 레이블 없음