[Rust] TUI: ratatui

ratatui๋Š” ํ„ฐ๋ฏธ๋„ UI ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.
GUI ์—†์ด ํ„ฐ๋ฏธ๋„ ํ™˜๊ฒฝ์—์„œ ์ด๋Ÿฐ์ €๋Ÿฐ ๋ณต์žกํ•œ ์ œ์–ด๊ธฐ๋Šฅ์„ ๋‹ค๋ฃจ๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.




์„ค์น˜

์•„๋ž˜ ๋””ํŽœ๋˜์‹œ๋ฅผ 2๊ฐœ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

[dependencies]
crossterm = "0.27.0"
ratatui = "0.26.0"




Hello World ์ž‘์„ฑํ•ด๋ณด๊ธฐ

๊ธฐ๋ณธ ์ฝ”๋“œ ์–‘์ด ์กฐ๊ธˆ ๋œ๋‹ค. ๋ถ„์„์— ์•ž์„œ์„œ ๋ณต๋ถ™ํ•˜๊ณ  ์‹คํ–‰๋ถ€ํ„ฐ ํ•ด๋ณด์ž.

use crossterm::{
    event::{self, KeyCode, KeyEventKind},
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
    ExecutableCommand,
};
use ratatui::{
    prelude::{CrosstermBackend, Stylize, Terminal},
    widgets::Paragraph,
};
use std::io::{stdout, Result};

fn main() -> Result<()> {
    stdout().execute(EnterAlternateScreen)?;
    enable_raw_mode()?;
    let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
    terminal.clear()?;

    loop {
        terminal.draw(|frame| {
            let area = frame.size();
            frame.render_widget(
                Paragraph::new("Hello Ratatui! (press 'q' to quit)")
                    .white()
                    .on_blue(),
                area,
            );
        })?;

        if event::poll(std::time::Duration::from_millis(16))? {
            if let event::Event::Key(key) = event::read()? {
                if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
                    break;
                }
            }
        }
    }

    stdout().execute(LeaveAlternateScreen)?;
    disable_raw_mode()?;
    Ok(())
}

๊ทธ๋Ÿผ ๋นŒ๋“œ ํ›„ ์‹คํ–‰์ด ๋  ๊ฒƒ์ด๊ณ , ์ „์šฉ ํ™”๋ฉด์ด ๋œฐ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  q๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ข…๋ฃŒ๋œ๋‹ค.




์ฝ”๋“œ ์‚ดํŽด๋ณด๊ธฐ

๋ญ๊ฐ€ ๋ณต์žกํ•ด๋ณด์ด๊ธด ํ•˜๋Š”๋ฐ, ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณด๋ฉด ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€๋Š” ์•Š๋‹ค.

  1. ๋จผ์ € Alternate ์Šคํฌ๋ฆฐ ๋ชจ๋“œ๋กœ ์ง„์ž…ํ•œ๋‹ค. ์ด๋ž˜์•ผ ์ž…์ถœ๋ ฅ์„ ๋ฐฉํ•ดํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋ž˜ํ”ฝ์Šค๋Ÿฐ ๋ Œ๋”๋ง์„ ์ž˜ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. raw mode๋ฅผ ์ผœ์„œ ํ„ฐ๋ฏธ๋„์˜ ์ž…์ถœ๋ ฅ์„ ์ œํ•œํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ ์ด ์•ฑ์—์„œ๋งŒ ํ„ฐ๋ฏธ๋„์„ ๋งˆ์Œ๋Œ€๋กœ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

  3. ๊ทธ๋ฆฌ๊ณ  ํ„ฐ๋ฏธ๋„ ๋ฐฑ์—”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด์ œ๋ถ€ํ„ฐ ์ด๊ฑธ๋กœ ํ†ต์ œ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

  4. ํ˜„์žฌ ํ„ฐ๋ฏธ๋„์„ ์ฒญ์†Œํ•œ๋‹ค.



๊ทธ๋Ÿฌ๋ฉด ๊ทธ ๋‹ค์Œ์—๋Š” ๋ฃจํ”„์— ์ง„์ž…ํ•ด์„œ ๋ Œ๋”๋ง ํ”„๋กœ์„ธ์Šค๋ฅผ ์ง„ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค.

  1. ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค draw๋กœ ๋ชจ์–‘์„ ๊ทธ๋ฆฐ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ƒ์„ธํžˆ ๋‹ค๋ฃจ์ง€ ์•Š์ง€๋งŒ, ์ขŒํ‘œ๊ธฐ๋ฐ˜์œผ๋กœ ์„ฌ์„ธํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
    ์ฐธ์กฐ https://ratatui.rs/concepts/layout/

  2. ๊ทธ๋ฆฌ๊ณ  ํ‚ค ์ด๋ฒคํŠธ๊ฐ€ ์˜ค๋˜, ๊ทธ๊ฒŒ q์ด๋ฉด ๋ฃจํ”„๋ฅผ ์ข…๋ฃŒํ•ด์„œ ํ”„๋กœ๊ทธ๋žจ์„ ๋‚˜๊ฐ€๋„๋ก ํ•ด๋’€๋‹ค.
    ์ฐธ์กฐ https://ratatui.rs/concepts/event-handling/

๋” ์ž์„ธํ•œ ๊ฒƒ์€ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
https://ratatui.rs/introduction/



์ฐธ์กฐ
https://ratatui.rs/highlights/v026/