연습: Visual F#을 사용하여 응용 프로그램 만들기, 디버깅 및 배포

이 연습에서는 Visual Studio에서 .NET Framework 4.5와 함께 F#을 사용하는 환경에 대해 소개합니다.

이 연습에서는 미국 재무부 증권의 이자율을 역사적으로 분석하는 예제를 통해 Visual Studio를 사용하여 F# 응용 프로그램 작성을 시작하는 방법에 대해 알아봅니다.먼저 F# Interactive 창을 사용하여 데이터에 대한 신속한 분석을 수행한 후 데이터를 분석하는 코드를 작성 및 테스트한 다음, F# 코드를 다른 .NET 언어와 통합하는 방법을 검토하는 C# 프런트 엔드를 추가합니다.

사전 요구 사항

이 연습을 완료하려면 다음 구성 요소가 필요합니다.

  • Visual Studio

[!참고]

다음 지침처럼 컴퓨터에서 Visual Studio 사용자 인터페이스 요소 일부에 대한 이름이나 위치를 다르게 표시할 수 있습니다. 이러한 요소는 사용하는 Visual Studio 버전 및 설정에 따라 결정됩니다. 자세한 내용은 Visual Studio 설정을 참조하십시오.

F# 스크립트를 만들려면

  1. 먼저 F# 스크립트를 만듭니다.파일 메뉴에서 새로 만들기를 가리키고 파일을 클릭합니다.새 파일 대화 상자에서 설치된 템플릿 목록의 일반에서 스크립트를 선택한 다음 F# 스크립트 파일을 선택합니다.열기를 클릭하여 파일을 만든 다음 파일을 RateAnalysis.fsx로 저장합니다.

  2. .NET 및 F# API를 사용하여 미국 연방 준비 은행의 인터넷 사이트에 있는 데이터에 액세스합니다.다음과 같은 코드를 입력합니다.

    open System.Net
    open System.IO
    
    let url = sprintf "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=bcb44e57fb57efbe90002369321bfb3f&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn"
    let req = WebRequest.Create(url, Timeout = 10000000)
    let resp = req.GetResponse()
    let stream = resp.GetResponseStream()
    let reader = new StreamReader(stream)
    let csv = reader.ReadToEnd()
    

    다음 내용을 참고하십시오.

    • 문자열 및 키워드는 다른 색으로 표시됩니다.

    • 마침표(.)를 입력할 때마다 완성 목록이 나타납니다.

    • 식별자 중간에서 바로 가기 키 Ctrl+SPACE 또는 Ctrl+J를 사용하여 메서드 이름 및 다른 식별자가 Visual Studio에서 자동으로 완성되도록 할 수 있습니다.Ctrl+J를 사용하면 완성 목록이 나타납니다.

    • 코드에 있는 식별자 위에 마우스 포인터를 올려 놓으면 해당 식별자에 대한 정보를 포함하는 도구 설명이 표시됩니다.

    • 커서가 WebRequest에 있을 때 F1 키를 누르면 예상한 문서가 나타납니다.

    • 커서가 let에 있을 때 F1 키를 누르면 예상한 문서가 나타납니다.

    • mscorlib.dll, System.dll 및 System.Windows.Forms.dll의 형식 및 네임스페이스가 기본적으로 참조됩니다.

    • 여기에서 설정하는 Timeout 값은 생성자 인수가 아니라 속성입니다.F#에서는 속성 값을 이와 같이 설정할 수 있습니다.

    • 이 예제의 URL을 브라우저에 복사하면 날짜 및 이자율을 포함하며 미국 연방 준비 은행에서 게시한 쉼표로 구분되는 값 목록이 반환됩니다.

  3. 이 단계에서는 F# Interactive를 사용하여 코드를 실행합니다.마우스를 사용하거나 Ctrl+A를 눌러 모든 코드를 선택하고 마우스 오른쪽 단추를 클릭한 다음 @@@Interactive에서 실행를 클릭합니다.또는 Alt+Enter를 눌러도 됩니다.

    • F# Interactive 창이 아직 표시되어 있지 않으면 이 창이 나타납니다.

    • 코드가 성공적으로 실행됩니다.

    • F# Interactive 창에 다음이 표시됩니다.

      val url : string =
        "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H1"+[107 chars]
      val req : System.Net.WebRequest
      val resp : System.Net.WebResponse
      val stream : System.IO.Stream
      val reader : System.IO.StreamReader
      
      val csv : string =
        ""Series Description","Market yield on U.S. Treasury securities"+[224219 chars]
      
      >
      
  4. 다음 단계로 F# Interactive를 사용하여 데이터를 검사합니다.F# Interactive 프롬프트에 csv;;을 입력하고 Enter 키를 누릅니다.csv.Length;;을 입력하고 Enter 키를 누릅니다.다음 내용을 참고하십시오.

    • 표시되는 데이터는 최신 데이터입니다.

    • F# Interactive에서는 다음과 같이 문자열 csv의 값 및 길이를 표시합니다.

      07/10/2009, 3.32
      07/13/2009, 3.38
      07/14/2009, 3.50
      07/15/2009, 3.63
      "
      > csv.Length;;
      val it : int = 224513
      
    • 다음 그림에서는 F# Interactive 창을 보여 줍니다.

      F# Interactive

      F# Interactive 창

  5. 이 단계에서는 CSV(쉼표로 구분된 값) 데이터를 구문 분석하는 F# 코드를 작성합니다.CSV 파일에는 쉼표로 구분된 값이 포함되기 때문에 CSV라는 이름이 사용됩니다.코드 편집기에서 다음 코드를 추가합니다.또한, 파일의 맨 위에 open System.Globalization를 추가합니다.각 줄을 입력할 때 부분적 결과를 확인하려면 이 섹션에 추가된 코드를 해당 줄까지 선택하고 Alt+Enter를 누릅니다.다음 내용을 참고하십시오.

    • IntelliSense에서는 사용자가 마침표를 입력하면 유용한 정보를 제공하며, 이는 복잡하고 중첩된 식을 입력하는 중에도 마찬가지입니다.

    • 코드가 완성되지 않았거나 잘못된 경우 코드에 구문 및 의미 오류가 있음을 나타내는 빨간색 물결선이 표시됩니다.

    • 파이프 연산자(|>)를 사용하여 파이프라인을 만듭니다.파이프 연산자는 특정 식의 반환 값을 받아들여 다음 줄에 있는 함수의 인수로 사용합니다.파이프라인 및 F# Interactive를 사용하면 데이터 처리 코드를 손쉽게 부분적으로 실행할 수 있습니다.

    let interest = 
        csv.Split([|'\n'|])
        |> Seq.skip 8
        |> Seq.map (fun line -> line.Trim())
        |> Seq.filter (fun line -> not (line.EndsWith("ND")))
        |> Seq.filter (fun line -> not (line.Length = 0))
        |> Seq.map (fun line -> line.Split([|','|]))
        |> Seq.map ( fun values ->
            System.DateTime.Parse(values.[0], CultureInfo.CreateSpecificCulture("en-US")),
            float values.[1])
    
  6. 이 단계에서는 이 기능에 이름을 지정합니다.url의 정의에서 시리즈 ID bcb44e57fb57efbe90002369321bfb3f을를 제거하고 이를 %s로 바꾸어 문자열 리터럴을 서식 문자열로 대체합니다.서식 문자열 뒤에 seriesID를 추가합니다.열린 지시문을 제외한 나머지 모든 코드를 선택하고 Tab 키를 누릅니다.들여쓴 코드 블록 위에 다음 코드 줄을 추가합니다.

    let loadRates maturity =
        // The following tuples associate various maturity durations, in years,
        // with codes defined for treasury bills by the Federal Reserve.
        let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac")
                                        (2, "c66ea77a2e8f0919c5133c7633065908")
                                        (5, "fbb02942bfdbff31a479e98bcbe26388")
                                        (10, "bcb44e57fb57efbe90002369321bfb3f")
                                        (20, "a1ebeb6e84ca6389772dd054dc980191")]
        let seriesID = Map.find maturity maturitiesMap
    

    들여쓴 블록 끝에 interest를 추가합니다.다음 내용을 참고하십시오.

    • F#에서 들여쓰기는 특별한 의미를 가집니다.들여쓰기는 중첩 수준을 나타냅니다.

    • Tab 키는 메서드 추출 리팩터링(C#)과 거의 유사합니다.

    이제 코드는 다음과 같습니다.

    open System.Net
    open System.IO
    
    let loadRates maturity =
        // The following tuples associate various maturity durations, in years,
        // with codes defined for treasury bills by the Federal Reserve.
        let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac")
                                        (2, "c66ea77a2e8f0919c5133c7633065908")
                                        (5, "fbb02942bfdbff31a479e98bcbe26388")
                                        (10, "bcb44e57fb57efbe90002369321bfb3f")
                                        (20, "a1ebeb6e84ca6389772dd054dc980191")]
        let seriesID = Map.find maturity maturitiesMap
        let url = sprintf "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=%s&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn" seriesID
        let req = WebRequest.Create(url, Timeout = 10000000)
        let resp = req.GetResponse()
        let stream = resp.GetResponseStream()
        let reader = new StreamReader(stream)
        let csv = reader.ReadToEnd()
    
    
        let interest = 
            csv.Split([|'\n'|])
            |> Seq.skip 8
            |> Seq.map (fun line -> line.Trim())
            |> Seq.filter (fun line -> not (line.EndsWith("ND")))
            |> Seq.filter (fun line -> not (line.Length = 0))
            |> Seq.map (fun line -> line.Split([|','|]))
            |> Seq.map ( fun values ->
                System.DateTime.Parse(values.[0], CultureInfo.CreateSpecificCulture("en-US")),
                float values.[1])
        interest
    
  7. 이 단계에서는 이 기능을 새 입력에 대해 사용합니다.F# Interactive를 사용하여 모든 코드를 선택하고 Alt+Enter를 눌러 실행합니다.F# Interactive 프롬프트에서 여러 연도의 다른 만기 이자율 1, 2 및 5에 대해 새 loadRates 함수를 호출합니다.다음 내용을 참고하십시오.

    • 이전 정의가 F# Interactive에서 그대로 유지되지만 새 정의를 사용할 수 있습니다.

    • 복잡한 구조적 데이터는 특별한 인쇄 기능으로 렌더링됩니다.

F#을 사용하여 구성 요소를 개발하려면

  • 만들어 둔 기능을 노출하는 라이브러리 프로젝트를 만듭니다.파일 메뉴에서 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.새 프로젝트 대화 상자의 설치된 목록에서 **Visual F#**을 선택한 다음 F# 라이브러리를 선택하여 새 라이브러리 프로젝트를 만듭니다.프로젝트 이름을 RateAnalysis로 지정합니다.RateAnalysis.fsx에서 이전에 만든 코드를 복사하여 Library1.fs에 붙여 넣습니다.모듈 선언을 module RateLoader 파일 상단에 추가합니다.솔루션 탐색기에서 Library1.fs의 이름을 RateLoader.fs로 바꾸고 파일을 저장합니다.다음 내용을 참고하십시오.

    • 기본 F# 라이브러리 템플릿에서는 확장명이 .fs인 코드 파일 및 확장명이 .fsx인 스크립트를 제공합니다.이 스크립트 파일을 사용하면 라이브러리 코드를 대화형으로 테스트할 수 있습니다.
  1. 이 단계에서는 원하는 기능을 노출하는 F# 클래스를 만듭니다.솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.새 항목 추가 대화 상자에서 F# 소스 파일을 선택합니다.파일 이름을 Analyzer.fs로 지정합니다.솔루션 탐색기에서 Script.fsx를 마우스 오른쪽 단추로 클릭한 다음 아래로 이동을 클릭합니다.또는 Alt+아래쪽 화살표를 눌러도 됩니다. Analyzer.fs에 다음 코드를 붙여 넣습니다.

    module RateAnalysis.Analyzer
    
    open RateLoader
    
    /// Provides analysis of historical interest rate data.
    type Analyzer(ratesAndDates) = 
        let rates = 
            ratesAndDates
            |> Seq.map snd
    
        /// Construct Analyzer objects for each maturity category.
        static member GetAnalyzers(maturities) = 
            maturities
            |> Seq.map loadRates
            |> Seq.map (fun ratesAndDates -> new Analyzer(ratesAndDates))
    
        member sa.Min =
            let date, minRate = (Seq.minBy (fun (_, rate) -> rate) ratesAndDates)
            (minRate, date.ToString("d"))
    
        member sa.Max = 
            let date, maxRate = (Seq.maxBy (fun (_, rate) -> rate) ratesAndDates)
            (maxRate, date.ToString("d"))
    
        member sa.Current =
            rates |> List.ofSeq |> List.rev |> List.head 
    

    다음 내용을 참고하십시오.

    • F#에서는 개체 지향 프로그래밍 개념을 지원합니다.자세한 내용은 클래스(F#), 상속(F#) 및 F# 언어 참조의 기타 관련 항목을 참조하십시오.
  2. 프로젝트를 빌드하려면 Ctrl+Shift+B 또는 F6을 누릅니다.다음 내용을 참고하십시오.

    • 프로젝트가 올바르게 빌드됩니다.

    • 오류 목록 창에 어떠한 오류도 표시되지 않습니다.

    • 출력 디렉터리에는 .dll, .pdb 및 .xml 파일이 있습니다.

    • 출력 창에는 다음이 표시됩니다.

      ------ Build started: Project: RateAnalysis, Configuration: Debug Any CPU ------
          C:\Program Files (x86)\Microsoft F#\v4.0\fsc.exe -o:obj\Debug\RateAnalysis.exe -g --debug:full --noframework --define:DEBUG --define:TRACE --optimize- --tailcalls- -r:"C:\Program Files (x86)\Microsoft F#\v4.0\FSharp.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" --target:exe --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths --flaterrors Program.fs RateLoader.fs ValueAnalyzer.fs 
          RateAnalysis -> C:\Users\ghogen\Documents\Visual Studio 10\Projects\RateAnalysis\RateAnalysis\bin\Debug\RateAnalysis.exe
      ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
      
  3. C# 클라이언트 응용 프로그램을 추가하려면 솔루션 노드의 바로 가기 메뉴를 열고 추가를 선택한 다음 새 프로젝트를 선택합니다.새 프로젝트 추가 대화 상자의 설치된 템플릿 목록에서 **Visual C#**을 선택한 다음 콘솔 응용 프로그램을 선택합니다.경우에 따라서는 다른 언어 노드를 확장해야 할 수도 있습니다.프로젝트 CSharpDriver의 이름을 지정한 다음 확인 단추를 선택합니다.프로젝트의 참조 노드에 대한 바로 가기 메뉴를 열고 참조 추가를 선택합니다.솔루션 노드를 선택한 다음 프로젝트 노드를 선택합니다.RateAnalysis 프로젝트 옆의 확인란을 선택한 다음 확인 단추를 선택합니다.CSharpDriver 프로젝트 노드의 바로 가기 메뉴를 열고 시작 프로젝트로 설정을 클릭합니다.C# 응용 프로그램의 Main 메서드 본문에 다음 코드를 입력합니다.

    var maturities = new[] { 1, 2, 5, 10 };
    var analyzers = RateAnalysis.Analyzer.Analyzer.GetAnalyzers(maturities);
    
    foreach (var item in analyzers)
    {
        Console.WriteLine("Min = {0}, \t Max = {1}, \t Current = {2}", item.Min, item.Max, item.Current);
    }
    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
    

    다음 내용을 참고하십시오.

    • C#에서 F#으로 또는 F#에서 C#으로 프로젝트 간 참조를 추가할 수 있습니다.

    • F#에서 정의한 네임스페이스 및 C#의 형식을 다른 형식과 마찬가지로 사용할 수 있습니다.

    • C# IntelliSense에서 F# 문서 주석을 사용할 수 있습니다.

    • C#에서 F# API의 튜플 반환 값에 액세스할 수 있습니다.튜플은 .NET Framework 4.5의 Tuple 값입니다.

  4. 응용 프로그램을 디버깅하려면 F11 키를 눌러 응용 프로그램을 빌드하고 디버거에서 응용 프로그램을 시작한 다음, 실행된 코드의 첫 번째 줄을 시작합니다.GetAnalyzers 멤버의 본문에 있는 F# 코드를 시작할 때까지 F11 키를 여러 번 누릅니다.다음 내용을 참고하십시오.

    • C# 코드에서 F# 코드를 손쉽게 시작할 수 있습니다.

    • F#의 각 식은 디버거에서 단일 단계에 해당합니다.

    • 지역 창에는 maturities의 값이 표시됩니다.

    • F11 키를 계속 누르면 응용 프로그램의 나머지 부분이 실행됩니다.

    • 커서까지 실행, 다음 문 설정, 중단점 삽입, 조사식 추가디스어셈블리로 이동 같은 디버거 명령은 모두 정상적으로 작동합니다.

응용 프로그램을 배포하려면

  1. 계속 디버깅 하려면, SHIFT + F5를 사용하여 디버깅을 중지하거나 디버그 메뉴를 열어 디버그 중단을 선택합니다.

  2. CSharpDriver 프로젝트의 바로 가기 메뉴를 열고 속성을 선택합니다.

  3. 프로젝트 디자이너에서 응용 프로그램 배포를 위한 옵션을 보여주는 게시 탭을 선택합니다.

  4. 게시 마법사 단추를 선택합니다.

    게시 마법사가 시작되고 첫 화면에서는 게시된 파일을 놓을 위치를 묻습니다.

  5. 텍스트 상자에서 게시하거나 위치를 탐색하기 위해 찾아보기 단추를 선택할 때 응용 프로그램의 위치를 지정할 파일을 설치하는 로컬 디스크에 파일 위치를 지정합니다.

  6. 완료 단추를 선택하여 클라이언트 컴퓨터에 배포할 수 있는 모든 기본 표준 설정 빌드를 허용하거나, 또는 다음 단추를 선택하여 다른 게시 옵션을 봅니다.

    설치 실행 파일과 지원 파일은 사용자가 지정한 위치에 게시됩니다.

다음 단계

연습: 첫 번째 F# 프로그램를 읽어 보고 F# 코드 작성을 시작하거나 함수를 고급 값으로 상승(F#)를 읽어 보고 F#의 함수에 대해 학습합니다.F# 언어대한 자세한 내용은 F# 언어 참조에서 살펴볼 수 있습니다.

참고 항목

기타 리소스

Visual F# 샘플 및 연습

Visual F# 샘플 및 연습