한국어
GitHub
테마

자바를 위한 데스크톱 UI

자바 데스크톱 앱을, 처음부터 직접 그립니다.

Limn은 픽셀을 스스로 그립니다. 위젯, 레이아웃, 텍스트, 차트, 미디어, 3D 뷰포트를 의존성 하나로 제공합니다. Swing도, JavaFX도, 아래에 깔린 네이티브 툴킷도 없습니다.

JDK 17 · Windows, macOS, Linux · Apache-2.0

Claude Code로, 숨김없이 만들었습니다. 코드는 Claude가 썼고, 방향을 정하고 검증한 것은 사람들입니다. 만드는 데 든 비용은 이미 치렀으니, 여러분이 다시 치를 필요가 없습니다. Limn은 어떻게 만들어지는가

이번 빌드 중에 Limn이 그린 데모 애플리케이션.
이번 빌드 중에 Limn이 그린 데모 애플리케이션.
이번 빌드 중에 Limn이 그린 데모 애플리케이션.

지금 실행해 보기

데모와 테마 편집기를 Maven Central에서 바로. 클론할 것 없이, JDK가 없으면 jbang이 받아 옵니다. JBang은 최신 릴리스를 한 번만 확인하고 그대로 유지합니다. 더 새 릴리스를 받으려면 --fresh를 붙이세요.

# 쇼케이스
jbang demo@limn-toolkit/limn-toolkit
# 테마 편집기
jbang theme-editor@limn-toolkit/limn-toolkit
# 쇼케이스
jbang --java-options=-XstartOnFirstThread demo@limn-toolkit/limn-toolkit
# 테마 편집기
jbang --java-options=-XstartOnFirstThread theme-editor@limn-toolkit/limn-toolkit

5분

의존성 하나와 main 메서드

마크업 언어도, 애너테이션 프로세서도, 빌드 플러그인도 없습니다. 툴킷을 함께 가져오는 백엔드를 추가하고 평범한 자바를 쓰면 창이 생깁니다.

설치 가이드 읽기
build.gradle.kts
dependencies {
    implementation("io.github.limn-toolkit:limn-backend-lwjgl:1.0.0")
}
pom.xml
<dependency>
  <groupId>io.github.limn-toolkit</groupId>
  <artifactId>limn-backend-lwjgl</artifactId>
  <version>1.0.0</version>
</dependency>
Main.java
import limn.backend.Backend;
import limn.backend.NativeWindow;
import limn.backend.WindowConfig;
import limn.backend.lwjgl.LwjglBackend;
import limn.components.Button;
import limn.components.Label;
import limn.scene.Insets;
import limn.scene.Scene;
import limn.scene.layout.Column;
import limn.scene.layout.Padding;

/** A window with a label and a button that closes it. */
public final class HelloWindow {

    public static void main(String[] args) {
        // macOS needs -XstartOnFirstThread on the JVM command line; it is macOS-only and a
        // JVM elsewhere given it will not start.
        try (Backend backend = new LwjglBackend()) {
            NativeWindow window = backend.createWindow(
                    WindowConfig.of("Hello, Limn", 480, 320));

            Column column = new Column();
            column.gap(12);
            column.add(new Label("A window, drawn by Limn."));
            column.add(new Button("Close").onAction(window::requestClose));

            Scene scene = new Scene(new Padding(Insets.all(24), column));
            scene.bind(window);

            backend.runEventLoop();
        }
    }
}

무엇을 얻게 되는가

직접 만들지 않아도 되는 컴포넌트 모음

버튼, 입력란, 목록, 표, 트리, 날짜 선택기, 탭, 메뉴, 대화상자, 카드, 분할 패널, 색 선택기, 막대·선·도넛 차트, 그리고 100만 행이 20행과 같은 비용으로 끝나는 가상화 목록. 모두 색과 모양과 밀도를 테마에서 읽으므로 코드에 박아 넣은 값이 없고, 조밀 모드는 한 줄입니다. 창 밖에서도 애플리케이션은 종이나 PDF로 인쇄하고, 트레이에 아이콘을 두고, macOS 메뉴 막대에 메뉴를 올리고, 다른 프로그램과 끌어서 놓기로 내용을 주고받습니다.

전부 보기
Button
Button
ComboBox
ComboBox
Slider
Slider
SegmentedControl
SegmentedControl
Checkbox and switch
Checkbox and switch
Spinner
Spinner

머릿속에 들어오는 레이아웃

위젯 여섯과 표시자 하나. 열은 쌓고, 행은 펼치고, 랩은 너비가 다하면 다음 줄로 넘기고, 그리드는 셀을 가로세로로 맞추고, 스택은 겹치고, 패딩은 안쪽으로 들이고, Expanded가 남은 공간을 누가 가질지 정합니다. Opacity와 Transform은 주변 레이아웃을 흐트러뜨리지 않고 창의 일부를 페이드시키고, 옮기고, 확대·축소하고, 회전시킵니다. 설정할 제약 해결기도 설치할 레이아웃 매니저도 없습니다.

레이아웃 가이드 읽기
Limn으로 배치한 창
Limn으로 배치한 창
열 하나, 행 하나, 분할 하나, Expanded 하나로 만든 창.

프레임워크 없는 폼

입력란은 위젯이고, 검증 규칙은 리스너이며, 제출은 메서드 호출입니다. 바인딩할 것도 등록할 것도 없고, 사용자가 고치는 순간 검증 상태가 입력란 색을 되돌립니다.

폼 가이드 읽기
Limn으로 만든 폼
Limn으로 만든 폼
라벨, 검증, 선택, 그리고 동작 줄.

표와 트리와 날짜, 이미 만들어져 있습니다

표는 애플리케이션이 가진 목록 위에 놓인 형식 있는 열이고, 툴킷이나 당신의 서버가 정렬하며, 바닥글이 합계를 냅니다. 트리는 당신이 주는 자식 위에 놓인 개요이고, 행은 자식의 이름을 대기 전에 자식이 있다고 약속할 수 있습니다. 날짜 입력란은 읽는 사람 자신의 달력으로 ISO 날짜를 입력하고, 날짜 선택기는 그 뒤에 월 격자를 엽니다.

목록 가이드 읽기
Limn 창 안의 표, 트리, 날짜 위젯 두 개
Limn 창 안의 표, 트리, 날짜 위젯 두 개
창 하나에 담긴 표, 트리, 날짜 입력란, 날짜 선택기.

영상과 3D도 위젯입니다

물리 기반 3D 뷰포트와 비디오 플레이어가 보통 위젯처럼 합성됩니다. 스크롤 뷰가 잘라내고, 스택이 위에 그리며, 라벨과 똑같이 레이아웃에 참여합니다.

미디어 가이드 읽기
Limn의 3D 뷰포트
Limn의 3D 뷰포트
평범한 창에 합성된 3D 뷰포트.

모두를 위해

모든 언어, 그리고 모든 화면 낭독기

사용자의 언어로

라틴·그리스·키릴·CJK 문자가 한 문자열에 섞이고, 글꼴은 같은 문자 체계의 구간마다 선택됩니다. 아랍 문자, 히브리 문자, 데바나가리, 태국 문자는 올바르게 셰이핑되고(연결형, 합자, 결합 기호), 오른쪽에서 왼쪽으로 쓰는 언어에서는 창 전체가 거울상이 됩니다: 행, 여백, 스크롤바, 화살표 키. 입력기는 필드 안에서 조합하고, 편집은 자소 단위로 움직입니다.

텍스트 가이드 읽기
같은 화면을 일본어, 중국어 간체, 한국어, 러시아어로 촬영해 하나의 창으로 이어 붙인 모습.
같은 화면을 일본어, 중국어 간체, 한국어, 러시아어로 촬영해 하나의 창으로 이어 붙인 모습.
이번 빌드 중에 네 가지 언어로 찍은 같은 화면.

같은 언어로, 소리 내어 읽힙니다

Windows용 스크린 리더, macOS의 VoiceOver, Linux의 Orca는 각 플랫폼 고유의 접근성 API를 통해 Limn 창을 읽습니다. 애플리케이션에 플랫폼 코드는 없습니다. 모든 컨트롤은 인터페이스가 표시되는 언어로 역할·이름·상태를 스스로 알립니다. 컨트롤에 이름을 붙이는 것은 호출 한 번입니다.

접근성 가이드 읽기
  1. heading“Create your account”
  2. label“Full name”
  3. text field“Full name”label · focusable, editable, required
  4. label“12 / 40”
  5. label“Email”
  6. text field“Email”label · focusable, editable, invalid, required
  7. label“Enter an address like ada@example.com”
  8. label“Password”
  9. password field“Password”label · focusable, editable, password
  10. label“At least 12 characters”
  11. label“Plan”
  12. combo box“Plan”label · focusable, expandable, has-popup
  13. switch“Email me release notes”focusable, checked
  14. separatorhorizontal
위의 폼을 화면 낭독기가 전달받는 그대로, 이 빌드 중에 캡처했습니다.

툴킷의 얼굴이 아니라, 당신 제품의 얼굴

애플리케이션은 그것을 만든 라이브러리가 아니라 당신의 제품처럼 보여야 합니다. 테마는 순수한 데이터입니다. 모든 색, 모서리 반경, 각 컨트롤이 상속하는 크기 단계까지 데이터이며, 실행 중 한 번의 호출로 교체됩니다. 브랜드 서체는 당신이 관리하는 파일에서 불러오므로 툴킷 고유의 외형은 하나도 남지 않습니다.

테마가 동작하는 방식
컨트롤이 빽빽한 같은 화면을 일곱 번 나란히 렌더링한 모습으로, 띠마다 팔레트와 크기 단계와 서체가 다릅니다.

같은 컴포넌트, 일곱 가지 테마

열에 포인터를 올리면 그 테마가 화면 전체에 펼쳐집니다.열을 탭하면 그 테마가 보이고, 옆으로 밀면 바뀝니다.

화면 하나, 테마 일곱 개. 각 띠 뒤의 코드는 동일합니다.

숨김없이

Limn은 어떻게 만들어지는가

Limn의 코드는 Anthropic의 모델인 Claude가 Claude Code 안에서 쓰고, 사람들이 방향을 정하고 검증합니다. 알고 싶으실 테니 처음부터 밝혀 둡니다.

방향을 정한다는 것은 모든 설계 결정을 코드보다 먼저 docs/adr에 글로 남기고, 논의하고, 승인한다는 뜻입니다. 검증한다는 것은 모든 변경을 코드 자체보다 큰 테스트 스위트에 돌리고, 접근성을 짐작하지 않고 직접 들어 보고(Windows용 스크린 리더, macOS의 VoiceOver, Linux의 Orca가 실제 창을 읽게 해서), 정확성과 성능과 API 설계를 거듭 감사한다는 뜻입니다.

여기까지 오는 데 수천 번의 모델 호출과 수백만 개의 생성 토큰이 들었습니다. 추정 모델 COCOMO II에 따르면, 테스트를 빼고도 10만 줄이 넘는 코드는 약 20명의 팀이 2년 넘게 해야 할 일에 해당합니다. 그 일은 끝났습니다. 다시 하는 대신 그 위에 만들 수 있습니다.

설계 기록 읽기

5분이면 화면에 창 하나

설치 가이드는 실행되는 프로그램으로 끝납니다. 그 뒤는 가이드와 컴포넌트 갤러리, 그리고 API 레퍼런스입니다.