JShell로 Java 코드 즉시 실행하기
Java 9에서 도입된 JShell REPL 환경의 기본 사용법, 슬래시 명령, 자동완성, 스크립트 실행, 학습과 프로토타이핑에 활용하는 실전 팁을 정리합니다.
지난 글에서 Javadoc으로 API 문서를 만드는 방법을 살펴봤습니다. 이번에는 같은 JDK 안에 포함된 JShell을 다룹니다. JShell은 Java 9에서 처음 도입된 REPL(Read-Eval-Print Loop) 환경으로, .java 파일을 만들고 컴파일하는 과정 없이 코드를 한 줄씩 입력해 즉시 결과를 확인할 수 있습니다. 새로운 API를 탐험하거나, 간단한 알고리즘을 빠르게 검증할 때 매우 유용한 도구입니다.
JShell 시작하기
JDK 9 이상이 설치되어 있다면 터미널에서 바로 실행할 수 있습니다.
$ jshell
| JShell 시작 -- 도움말은 /help 입력
| Good bye
# 종료는 /exit 또는 Ctrl+D
프롬프트 jshell> 가 나타나면 Java 표현식·선언·명령을 입력하면 됩니다.
기본 사용법
JShell은 소스 파일과 다르게 세미콜론을 생략해도 되고, 클래스 안에 넣지 않아도 됩니다. 표현식을 입력하면 결과가 ==> 표시와 함께 즉시 출력됩니다.
jshell> 1 + 2
$1 ==> 3
jshell> "Hello".toUpperCase()
$2 ==> "HELLO"
jshell> Math.PI
$3 ==> 3.141592653589793
$1, $2 같은 이름은 JShell이 자동으로 만드는 임시 변수로, 이후 표현식에서 재사용할 수 있습니다.
변수·메서드·클래스 선언
jshell> int x = 10
x ==> 10
jshell> int square(int n) { return n * n; }
| square 메서드 생성됨
jshell> square(x)
$1 ==> 100
jshell> record Point(int x, int y) {}
| Point 레코드 생성됨
jshell> new Point(3, 4)
$2 ==> Point[x=3, y=4]
선언한 변수·메서드·타입은 세션이 끝날 때까지 유지됩니다. 변수 이름을 다시 입력해서 재선언(덮어쓰기)도 가능합니다.
var 추론
Java 10의 var 키워드도 JShell에서 사용할 수 있습니다.
jshell> var list = List.of("a", "b", "c")
list ==> [a, b, c]
jshell> list.stream().filter(s -> s.compareTo("b") > 0).toList()
$1 ==> [c]
REPL 동작 원리
JShell은 네 단계를 반복합니다.
- READ — 프롬프트에서 한 줄(또는 여러 줄) 입력을 읽습니다.
- EVAL — 입력을 스니펫(snippet)으로 파싱·컴파일해 JVM에서 실행합니다.
- PRINT — 결과값과 부수 효과(출력·예외 등)를 화면에 보여줍니다.
- LOOP — 다음 입력을 기다리며 처음으로 돌아갑니다.
JShell이 파싱하는 기본 단위를 스니펫이라고 합니다. 스니펫의 종류에는 표현식(expression), 선언(declaration), 임포트(import), 명령(statement)이 있습니다.
슬래시 명령
JShell에는 /로 시작하는 내장 명령이 있습니다. 코드가 아니라 JShell 자체를 제어하는 메타 명령입니다.
/list — 이 세션에서 입력한 스니펫 목록
/vars — 선언된 변수 목록
/methods — 정의된 메서드 목록
/types — 클래스·인터페이스·열거형 목록
/imports — 현재 활성화된 임포트 목록
/history — 모든 입력 이력 (슬래시 명령 포함)
/edit N — 스니펫 N번을 편집기에서 수정
/open 파일 — 파일을 읽어 줄 단위로 실행
/save 파일 — 현재 스니펫을 파일로 저장
/reset — JShell 상태 완전 초기화
/exit — JShell 종료
/help — 전체 도움말
활용 예시
jshell> int a = 5
a ==> 5
jshell> int b = a * 3
b ==> 15
jshell> /vars
| int a = 5
| int b = 15
jshell> /list
1 : int a = 5
2 : int b = a * 3
jshell> /edit 1
/edit 1을 입력하면 JShell 설정 편집기(기본은 간단한 스윙 에디터)에서 스니펫 1번을 수정할 수 있습니다. 외부 편집기를 사용하려면 환경변수 EDITOR를 설정하거나 /set editor로 지정합니다.
Tab 자동완성
JShell에서 Tab 키를 누르면 메서드·필드·변수 이름을 자동완성합니다.
jshell> "hello".
// Tab 입력
chars() codePointAt() codePointBefore()
codePointCount() codePoints() compareTo() ...
패키지 이름, 클래스 이름, 임포트 등도 자동완성됩니다. Tab을 두 번 누르면 가능한 후보 목록이 모두 나타납니다.
다중 임포트와 스타트업 설정
JShell은 시작할 때 java.lang.*, java.io.*, java.math.*, java.util.*, java.util.function.*, java.util.stream.* 등 자주 쓰는 패키지를 기본으로 임포트합니다.
추가 임포트가 필요하면 세션 안에서 직접 선언합니다.
jshell> import java.time.LocalDate
jshell> LocalDate.now()
$1 ==> 2026-05-05
스타트업 파일(.jshell) 기능을 사용하면 반복적인 임포트나 공통 설정을 자동 실행할 수 있습니다.
# 스타트업 파일 만들기
$ cat > ~/.jshell_startup << 'EOF'
import java.time.*
import java.nio.file.*
void println(Object o) { System.out.println(o); }
EOF
# 지정 파일로 JShell 시작
$ jshell ~/.jshell_startup
스크립트 파일 실행
JShell은 Java 코드를 담은 파일을 스크립트처럼 실행할 수 있습니다.
// demo.jsh
int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
for (int i = 0; i < 10; i++) {
System.out.println("fib(" + i + ") = " + fib(i));
}
$ jshell demo.jsh
fib(0) = 0
fib(1) = 1
fib(2) = 1
...
/open demo.jsh로 실행 중인 JShell 세션 안에서 불러올 수도 있습니다.
클래스패스 지정
JShell을 시작할 때 -cp 옵션으로 외부 라이브러리를 추가하거나, 세션 안에서 /env -class-path 명령으로 변경할 수 있습니다.
# 외부 JAR 포함하여 시작
$ jshell --class-path lib/guava-33.0.jar
# 세션 내에서 클래스패스 추가
jshell> /env -class-path lib/guava-33.0.jar
# 추가 후 사용
jshell> import com.google.common.collect.ImmutableList
jshell> ImmutableList.of(1, 2, 3)
$1 ==> [1, 2, 3]
JShell API — 프로그래밍 방식 제어
JShell은 jdk.jshell 모듈을 통해 Java 프로그램 안에서 JShell을 제어하는 API도 제공합니다. 커스텀 REPL 도구나 교육용 인터프리터를 만들 때 유용합니다.
import jdk.jshell.JShell;
import jdk.jshell.SnippetEvent;
try (JShell shell = JShell.create()) {
shell.eval("int x = 42;")
.forEach(e -> System.out.println(e.status()));
shell.eval("x * 2")
.stream()
.filter(e -> e.value() != null)
.forEach(e -> System.out.println("결과: " + e.value()));
}
JShell.create() 는 독립된 JShell 인스턴스를 반환하며 AutoCloseable을 구현합니다. eval() 의 반환값인 List<SnippetEvent>에서 실행 결과·상태·오류 정보를 얻을 수 있습니다.
실전 활용 팁
API 탐색 — 처음 보는 라이브러리의 메서드를 알아볼 때 JShell과 Tab 자동완성을 함께 쓰면 Javadoc을 열지 않아도 빠르게 파악할 수 있습니다.
알고리즘 검증 — 재귀·스트림 파이프라인을 즉시 실행해보고 결과를 확인한 뒤 실제 코드에 옮기면 시행착오를 줄일 수 있습니다.
정규식 테스트 — "문자열".matches("패턴")처럼 정규식 동작을 바로 확인할 수 있습니다.
날짜·시간 계산 — LocalDate.now().plusDays(30) 등 날짜 연산을 대화형으로 검증할 수 있습니다.
JShell은 프로덕션 코드를 작성하는 IDE와 병행해 쓰는 보조 도구로 가장 효과적입니다. 빠른 실험과 검증이 필요한 순간마다 꺼내 쓰면, 개발 리듬을 끊지 않고도 불확실한 부분을 빠르게 해소할 수 있습니다.
지난 글: Javadoc으로 API 문서 작성하기
다음 글: JVM 아키텍처 완전 정복
읽어주셔서 감사합니다. 😊