Share via


RSS 리더 자습서(VS Code가 있는 Windows용 Rust)

이전 토픽에서는 Windows용 Rust 및 windows 상자를 소개했습니다.

이번에는 RSS(Really Simple Syndication) 피드에서 블로그 게시물의 제목을 다운로드하는 간단한 콘솔 앱을 작성하는 연습을 통해 Windows용 Rust를 사용해 보겠습니다.

  1. 명령 프롬프트(cmd.exe)를 시작하고, Rust 프로젝트를 보관할 폴더에 대해 cd를 실행합니다.

  2. Cargo를 사용하여 rss_reader라는 새 Rust 프로젝트를 만들고 cd를 새로 만든 폴더에 추가합니다.

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. 그런 다음, VS Code에서 rss_reader 프로젝트를 엽니다.

    code .
    
  4. 기본 rss_reader 프로젝트를 구현해 보겠습니다. 먼저 프로젝트 루트에서 Cargo.toml 파일을 엽니다. Cargo.toml 파일은 포함된 종속성을 비롯하여 Rust 프로젝트를 설명하는 텍스트 파일입니다.

    아래 목록과 같이 Windows 상자에 대한 종속성을 추가합니다. Windows 상자는 큽니다. 빌드 시간을 빠르게 유지하기 위해 이 코드에 필요한 Foundation_CollectionsWeb_Syndication 기능만 선택합니다.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. 그런 다음 rss_reader 프로젝트의 src/main.rs 소스 코드 파일을 엽니다. 여기에서 Cargo 기본 "Hello, world!" 코드를 찾을 수 있습니다. 다음 use 문을 main.rs의 시작 부분에 추가합니다.

    // src\main.rs
    use windows::{
        core::*,
        Foundation::Uri,
        Web::Syndication::SyndicationClient
    };
    
    fn main() {
        println!("Hello, world!");
    }
    

    use 선언은 우리가 사용할 형식의 경로를 단축합니다. 앞에서 언급한 Uri 형식이 있습니다.

  6. Uri를 만들려면 Cargo의 기본 main 함수를 다음으로 바꿉니다.

    // src\main.rs
    ...
    
    fn main() -> Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
    
        Ok(())
    }
    

    main 함수의 반환 형식은 Windows::core::Result입니다. 이렇게 하면 OS(운영 체제) API에서 발생하는 오류를 일반적인 방법으로 처리할 수 있으므로 작업이 더 쉬워집니다. Windows::core::Result는 오류 전파 및 간결한 오류 처리에 도움이 됩니다.

    코드 줄 끝에서 물음표 연산자를 볼 수 있습니다. 타이핑을 절약하기 위해 Rust의 오류 전파 및 단락 논리를 사용합니다. 즉, 이 간단한 예제에서 여러 오류를 수동으로 처리할 필요가 없습니다. Rust의 이 기능에 대한 자세한 내용은 오류를 더 쉽게 처리할 수 있는 ? 연산자를 참조하세요.

    Windows 상자의 h! 매크로도 확인합니다. 이를 사용하여 Rust 문자열 리터럴에서 HSTRING 참조를 구성합니다. WinRT API는 문자열 값에 HSTRING을 광범위하게 사용합니다.

  7. RSS 피드를 다운로드하기 위해 새 SyndicationClient를 만듭니다.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        Ok(())
    }
    

    new 함수는 Rust 생성자입니다. Windows 상자의 모든 개체는 Rust 규칙을 따르고 생성자의 이름을 new로 지정합니다.

  8. 이제 SyndicationClient를 사용하여 피드를 검색할 수 있습니다.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        Ok(())
    }
    

    RetrieveFeedAsync는 비동기 API이므로 예를 단순하게 유지하기 위해 차단 get 함수를 사용합니다. 또는 async 함수 내에서 await 연산자를 사용하여 협조하여 결과를 기다릴 수 있습니다. 그래픽 사용자 인터페이스가 있는 더 복잡한 앱은 async를 자주 사용합니다.

  9. 이제 결과 항목을 반복할 수 있으며 제목만 출력해 보겠습니다. 일부 RSS 피드에 필요하므로 사용자 에이전트 헤더를 설정하기 위해 아래에 몇 줄의 코드가 추가로 표시됩니다.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        client.SetRequestHeader(
            h!("User-Agent"),
            h!("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"),
        )?;
    
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        for item in feed.Items()? {
            println!("{}", item.Title()?.Text()?);
        }
    
        Ok(())
    }
    
  10. 이제 실행>디버깅하지 않고 실행을 클릭하여(또는 Ctrl+F5 키를 눌러) 빌드 및 실행이 가능한지 확인합니다. 예기치 못한 메시지가 표시되면 Hello, world! 자습서(VS Code를 사용한 Rust).

    텍스트 편집기 내부에도 디버그실행 명령이 포함되어 있습니다. 또는 rss_reader 폴더의 명령 프롬프트에서 cargo run을 입력하면 프로그램이 빌드되고 실행됩니다.

    The Debug and Run commands embedded in the text editor

    아래쪽 VS Code 터미널 창을 보면 Cargo가 성공적으로 Windows 상자를 다운로드하여 컴파일하고, 결과를 캐시하고, 그 결과를 사용하여 후속 빌드를 더 빠르게 완료하는 것을 확인할 수 있습니다. 그 후 샘플을 빌드하고 실행하여 블로그 게시물 제목 목록을 표시합니다.

    List of blog post titles

Windows용 Rust를 프로그래밍하는 것만큼 간단합니다. 그러나 내부적으로는 Rust가 ECMA-335(공용 언어 인프라 또는 CLI)를 기반으로 .winmd 파일을 구문 분석하고, 안전성과 효율성을 고려하여 런타임에 COM 기반 ABI(애플리케이션 이진 인터페이스)를 정확하게 사용할 수 있도록 도구를 빌드하는 데 많은 노력이 들어갑니다.

메시지 상자 표시

Windows용 Rust를 사용하면 모든 Windows API(과거, 현재 및 미래)를 호출할 수 있다고 했습니다. 따라서 이 섹션에서는 몇 가지 Windows 메시지 상자를 표시합니다.

  1. RSS 프로젝트에서 했던 것처럼 명령 프롬프트 cd에서 Rust 프로젝트가 있는 폴더로 이동합니다.

  2. message_box라는 새 프로젝트를 만들고 VS Code에서 엽니다.

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. VS Code에서 Cargo.toml을 열고 이 프로젝트에 대한 Windows 종속성을 추가합니다.

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. 이제 프로젝트의 src/main.rs 파일을 열고 새 네임스페이스로 use 선언을 추가합니다(아래 참조). 마지막으로 MessageBoxAMessageBoxW 함수를 호출하는 코드를 추가합니다. Windows API 문서는 주로 C/C++를 염두에 두고 작성되었으므로 API 문서를 windows 상자의 Rust 프로젝션 문서와 비교하는 것이 유용합니다. MessageBoxA(Rust)MessageBoxW(Rust).

    // src\main.rs
    use windows::{
        core::*,
        Win32::UI::WindowsAndMessaging::*
    };
    
    fn main() {
        unsafe {
            MessageBoxA(None, s!("Ansi"), s!("World"), MB_OK);
            MessageBoxW(None, w!("Wide"), w!("World"), MB_OK);
        }
    }
    

    보시다시피 unsafe 블록에서 이러한 Win32 API를 사용해야 합니다(안전하지 않은 블록 참조). 또한 s!w! 매크로는 Rust UTF-8 문자열 리터럴에서 LPCSTRLPCWSTR 인수를 만듭니다. rss_reader에 대해 h! 매크로를 사용하여 HSTRING을 만든 것과 같습니다. Rust는 기본적으로 UTF-8 문자열을 포함하는 유니코드이므로 ANSI(A-접미사) API보다 넓은 유니코드(W-접미사) Windows API를 사용하는 것이 좋습니다. 코드에 영어가 아닌 텍스트를 사용하는 경우 이는 중요할 수 있습니다.

이번에 빌드하고 실행할 때 Rust는 두 개의 Windows 메시지 상자를 표시합니다.