[번역] JShell 사용자 가이드

[번역] JShell 사용자 가이드

이 문서는 Java9의 오라클 공식 문서 중 JShell 사용자 가이드의 한글화 문서입니다. 원문 정보는 다음과 같습니다.


1. JShell 소개

Java Shell(JShell)은 Java 프로그래밍 학습과 Java 코드 프로토타이핑을 위한 대화식 도구입니다. JShell에 선언문, 식(Expression), 문(Statement) 및 JShell 명령을 입력하면, 즉시 입력이 평가되고 그 결과(Feedback)가 출력됩니다. JShell은 Java9에 새로 추가된 REPL (Read-Evaluate-Print Loop)입니다. 이 도구는 커맨드 라인에서 실행됩니다.

  • 문서 구성
    • JShell는 왜 필요한가?
    • JShell 시작하고 종료하기

JShell의 추가 정보는 Java Platform, Standard Edition Tool Reference 문서의 jshell 절을 참조하시기 바랍니다.

JShell는 왜 필요한가?

JShell에 프로그램밍 요소를 입력하면, 실행 결과를 즉시 확인할 수 있습니다. 필요할 경우 프로그램 요소를 바로 수정할 수도 있습니다.

일반적으로 자바 프로그램은 다음 프로세스를 거쳐 개발됩니다.

  • 완전한 형태의 프로그램 개발
  • 프로그램 컴파일 및 에러 수정
  • 프로그램 실행
  • 프로그램 실행 중 오류 파악
  • 프로그램 수정
  • 지금까지 개발 절차 반복

자바 프로그램을 개발할 때, JShell을 사용하면 코드 실행과 옵션 탐색이 매우 편리합니다. JShell 세션에서 개별적인 문(Statement)을 실행하고 테스트할 수 있고, 메서드의 다양한 옵션을 시험해볼 수 있으며, 익숙하지 않은 API를 실험할 수 있습니다. 그러나 JShell이 IDE를 대체하는 것은 아닙니다. 프로그램을 개발할 때, JShell에 코드를 붙여넣고 시험할 수 있습니다. JShell에서 코드가 정상적으로 동작하면, JShell의 코드를 프로그램 편집기 및 IDE에 복사한는 방식으로 작업을 진행할 수 있습니다.

JShell 시작 및 종료

JShell은 JDK 9에 포함되어 있습니다. JShell을 시작하기 위해서는 터미널에 jshell 명령을 입력해야 합니다.

JShell을 사용하기 위해서는, 사용 중인 컴퓨터에 JDK 9이 설치되어 있어야 합니다. java-home/jdk-9/bin 디렉터리가 PATH 환경 변수에 설정되어 있다면, 디렉터리 위치와 상관없이 jshell을 어디서든지 실행할 수 있습니다.

다음은 jshell를 실행하고 JShell로 부터 결과를 받는 예제입니다. % 다음 코드는 사용자가 입력한 명령입니다.

% jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

jshell>

이 문서의 모든 예제는 verbose 모드(상세정보 출력 모드)로 실행한 결과입니다. 이 문서를 실습할 때 Verbose 모드를 사용할 것을 추천합니다. Verbose 모드를 사용하면 예제와 동일한 결과를 확인할 수 있습니다. JShell에 익숙해지면 일반 모드(Normal mode) 혹은 간결 모드(consice Mode)로 전환하여 JShell을 실행하는 것이 좋습니다.

JShell을 Verbose 모드로 실행하기 위해서 -v 옵션을 사용합니다.

% jshell -v

JShell 세션을 종료할 때는 /exit 명령을 사용합니다.

jshell> /exit
|  Goodbye

2. 스니펫

JShell에서 자바 문(statements), 정의 문(변수, 메서드, 클래스 둥), 임포트 문 및 식(expression)을 실행할 수 있습니다. JShell이 처리할 수 있는 이런 코드 조각을 스니펫(snippet)이라고 합니다.

  • 문서 구성
    • 스니펫 실행하기
    • 정의 변경
    • Forward References
    • 예외(Exceptions)
    • 스니펫 텝 자동 완성
    • 스니펫 변환

스니펫 실행하기

JShell에 자바 코드 스니펫을 입력하면 즉시 평가됩니다. 그리고 평가 결과, 수행 액션 및 발생 에러에 대한 피드백이 바로 출력됩니다. 이 절에서 소개하는 예제를 직접 JShell에 테스트해 보시기 바랍니다.

최대한 많은 피드백을 출력하기 위해서, verbose 옵션(-v)을 추가하여 JShell을 시작합니다.

% jshell -v
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

프롬프트에 다음 예제의 문(statement)을 입력하고, 출력 결과를 확인해 보시기 바랍니다.

jshell> int x = 45
x ==> 45
|  created variable x : int

문을 입력하며, 바로 결과가 출력됩니다. 이 결과를 다음과 같이 해석할 수 있니다. “변수 x는 값 45를 갖는다.” JShell이 verbose 모드로 실행되었기 때문에, 수행된 액션에 대한 부가 설명도 출력됩니다. 부가 정보 메시지는 수직 막대(|) 문자로 시작합니다. 이 메시지에서 생성된 변수명과 변수 타입 정보를 확인할 수 있습니다.

입력 완료된 스니펫 끝에 세미콜론이 없다면, 내부적으로 문(statement) 종료를 표시하는 세미콜론(;) 문자가 자동 추가됩니다.

처리 결과를 저장할 변수를 지정하지 않은 식(expression)이 입력되면, 다음에 값을 참조하는 목적으로 스크래치 변수1가 생성됩니다. 그리고 그 스크래치 변수에 실행된 식의 결과가 저장됩니다. 다음 예제는 식과 메서드 실행 결과를 스크래치 변수에 저장하는 것을 설명합니다. 그리고 이 예제에서 하나의 스니펫이 여러줄로 완성할 때 사용되는 연속 프롬프트 (…>)를 확인 할 수 있습니다.

jshell> 2 + 2
$3 ==> 4
|  created scratch variable $3 : int

jshell> String twice(String s) {
   ...>    return s + s;
   ...> }
|  created method twice(String)

jshell> twice("Ocean")
$5 ==> "OceanOcean"
|  created scratch variable $5 : String

정의 변경

코드를 실행하다보면 변수, 메서드 및 클래스가 개발자의 의도와 다르게 잘못 정의될 수 있습니다. JShell에서 이런 문제는 정의를 새로 입력하는 것으로 쉽게 해결 됩니다. 새로 입력된 정의는 이전 정의를 덮어씁니다.

변수, 메서드 및 클래스의 정의를 변경해야 한다면, 단순히 새로운 정의를 입력하면 됩니다. 예를 들어서 앞에 “스니펫 실행하기” 절에서 정의한 twice 메서드는 다음 예제를 실행하면 새로운 정의로 변경됩니다.

jshell> String twice(String s) {
   ...>    return "Twice:" + s;
   ...> }
|  modified method twice(String)

jshell> twice("thing")
$7 ==> "Twice:thing"
|  created scratch variable $7 : String

앞에서 “생성된 메서드(created method)“로 표시된 부분이 이번 피드백에서는 “수정된 메서드(modified method)“로 표시됩니다. 이 메시지는 정의는 변경되었지만, 변경된 메서드가 이전과 같은 서명(signature)을 가지므로, 기존의 메서드 사용법이 여전히 유효합니다.

호화되지 않는 방식으로 정의를 변경할 수도 있습니다. 다음 예제에서 변수 x 타입이 int에서 String 으로 변경되었습니다.

jshell> int x = 45
x ==> 45
|  created variable x : int

jshell> String x
x ==> null
|  replaced variable x : String
|    update overwrote variable x : int

위 예제에서 변수 x의 타입 변경에 대한 피드백 메시지가 “replaced“로 표현되어 있습니다.

피드백 레벨 변경

앞에서 가장 많은 정보와 설명을 제공하는 verbose 모드로 JShell을 실행하였습니다. “/set feedback” 명령으로 피드백 양과 형식을 변경할 수 있습니다. (예 : /set feedback consice) 다른 윈도우의 코드를 복사한 후 붙여 넣기 방식으로 JShell을 사용한다면, 여러분은 프롬프트가 없고 오류 피드백 만을 제공하는 모드를 선호할 것입니다. JShell에 “/set feedback silent” 명령을 실행하면, JShell은 오류 피드백만을 출력합니다.

Forward References (사전 참조)

JShell에서 메소드를 정의할 때 아직 정의하지 않은 메서드, 변수, 클래스를 참조할 수 있습니다. 이 기능은 탐색적인 프로그래밍을 지원하기 위해서 만들어졌습니다. 프로그래밍 과정에서 이런 기능이 필요할 때가 있습니다.

예를 들어, 구의 볼륨을 구하는 메소드를 정의할 때, volume 메소드를 다음 예제와 같이 구현할 수 있습니다.

jshell> double volume(double radius) {
   ...>    return 4.0 / 3.0 * PI * cube(radius);
   ...> }
|  created method volume(double), however, it cannot be invoked until variable PI, and method cube(double) are declared

위 예제의 volume 메소드 정의는 JShell 세션에서 정상적으로 수행됩니다. 그러나, 아직은 volume 메서드가 완전하게 정의된 것이 아니라는 메시지가 출력됩니다. 이 메소드 정의는 참조될 수는 있있습니다. 그러나, 필요한 모든 요소를 정의하기 전에 이 메서드를 실행하면 실폐하고 에러 피드백을 출력합니다.

jshell> double PI = 3.1415926535
PI ==> 3.1415926535
|  created variable PI : double

jshell> volume(2)
|  attempted to call method volume(double) which cannot be invoked until method cube(double) is declared

jshell> double cube(double x) { return x * x * x; }
|  created method cube(double)
|    update modified method volume(double)

jshell> volume(2)
$5 ==> 33.510321637333334
|  created scratch variable $5 : double

필요한 모든 정의가 완료되면, volume 메서드는 정상적으로 작동합니다.

이 volume 메서드를 이용하여 “비호환 교체”를 설명하겠습니다. 다음 예제에서는 PI의 정밀도를 변경2하고, PI 객체에 새로운 값을 입력하였습니다.

jshell> BigDecimal PI = new BigDecimal("3.141592653589793238462643383")
PI ==> 3.141592653589793238462643383
|  replaced variable PI : BigDecimal
|    update modified method volume(double) which cannot be invoked until this error is corrected:
|      bad operand types for binary operator '*'
|        first type:  double
|        second type: java.math.BigDecimal
|          return 4.0 / 3.0 * PI * cube(radius);
|                 ^------------^
|    update overwrote variable PI : double

새롭게 정의된 PI 타입은 volume 메서드 정의에 사용된 타입과 호환되지 않습니다. 현재 JShell은 verbose 모드로 동작하기 때문에, PI 타입 변경에 영향을 받는 다른 요소 정보를 출력합니다. 이 예제는 비호환성을 설명하는 대표적인 사례입니다. verbose 모드는 업데이트 정보를 출력하는 유일한 사전 정의 피드백 모드(Predefined feedback mode)입니다. 다른 피드백 모드에서는 해당 코드가 실행될 때까지 어떠한 경고도 출력하지 않습니다. verbose 모드를 제외한 다른 사전 정의 피드백 모드는 실행 부하를 줄이기 위해서 업데이트 경고를 제공하지 않습니다. 모든 사전 정의 피드백 모드에서 volume 메서드를 실행하면, 다음과 같은 이슈를 출력합니다.

jshell> volume(2)
|  attempted to call method volume(double) which cannot be invoked until this error is corrected:
|      bad operand types for binary operator '*'
|        first type:  double
|        second type: java.math.BigDecimal
|          return 4.0 / 3.0 * PI * cube(radius);
|                 ^------------^

예외(Exceptions)

예외 역추적(Backtrace)에서, 피드백은 예외가 발생한 스니펫과 해당 스니펫 내부의 위치를 출력합니다.

JShell에 입력된 코드의 위치는 “#ID:line-number” 형식으로 출력됩니다. 여기서 스니펫 ID는 “/list” 명령이 제공하는 숫자입니다. “line-number“는 스니펫의 행 번호입니다. 다음 예제에서 예외가 발생한 위치는 스니펫 넘버 #1(devide 메서드)의 두 번째 행입니다.

jshell> int divide(int x, int y) {
   ...> return x / y;
   ...> }
|  created method divide(int,int)

jshell> divide(5, 0)
|  java.lang.ArithmeticException thrown: / by zero
|        at divide (#1:2)
|        at (#2:1)

jshell> /list

   1 : int divide(int x, int y) {
           return x / y;
       }
   2 : divide(5, 0)

스니펫 텝 자동 완성

스니펫을 입력할 때, 텝 키를 이용하여 코드를 자동 완성할 수 있습니다. 현재까지 입력으로 코드를 결정할 수 없는 상황에서는, 가능한 옵션을 모두 제공합니다.

다음 예제는 volume 메서드가 정의된 상태에서, 메서드 명의 첫 번째 3 개 문자(vol)를 입력한 후에 텝 키를 입력한 상태를 설명합니다.

jshell> vol<Tab>

탭 키를 입력하면 입력값이 다음과 같이 변경됩니다.

jshell> volume(

자동 완성 기능을 사용할 때 현재 입력 값을 기준으로 한 개 이상의 경우의 수를 갖는다면, 가능한 모든 코드를 출력합니다.

jshell> System.c<Tab>
class                 clearProperty(        console()             currentTimeMillis()

jshell> System.c

입력한 코드에 공통 문자가 추가되고 커서는 입력 끝부분으로 이동합니다. 아이템을 완성하기 위해 추가 문자를 입력할 수 있습니다.

메소드의 열린 괄호에서 텝 키를 입력하면 매개 변수 유형으로 완료 가능한 형태를 출력합니다.

jshell> "hello".startsWith(<Tab>
Signatures:
boolean String.startsWith(String prefix, int toffset)
boolean String.startsWith(String prefix)

<press tab again to see documentation>

jshell> "hello".startsWith(

텝 키를 다시 입력하면 첫 번째 메서드의 텍스트 버전 문서가 출력됩니다.

jshell> "hello".startsWith(<Tab>
boolean String.startsWith(String prefix, int toffset)
Tests if the substring of this string beginning at the specified index starts with the
specified prefix.

Parameters:
prefix - the prefix.
toffset - where to begin looking in this string.

Returns:
true if the character sequence represented by the argument is a prefix of the substring of this
          object starting at index toffset ; false otherwise. The result is false if toffset is
          negative or greater than the length of this String object; otherwise the result is
          the same as the result of the expression
                    this.substring(toffset).startsWith(prefix)


<press tab to see next documentation>

jshell> "hello".startsWith(

스니펫 변환

JShell은 클래스를 처음 참조할 때 필요한 클래스 임포트(import)를 쉽게 할 수 있습니다. 또한 단축키를 사용하여 식(Expression)을 변수 선언으로 간단하게 변환할 수 있습니다.

아직 가져 오지 않은 식별자를 입력한 다음에 바로 “Shift + Tab i“를 누르면 세션에 import문을 추가하는 옵션이 출력됩니다.

jshell> new JFrame<Shift+Tab i>
0: Do nothing
1: import: javax.swing.JFrame
Choice: 1
Imported: javax.swing.JFrame

jshell> new JFrame

임포트 추가 옵션이 출력되면 사용할 옵션 번호를 입력하면 됩니다. 복수의 import 옵션이 제시될 수 있습니다.

식(Expression)을 입력한 후 “Shift+Tab v“를 눌러 식(Expression) 변수 선언으로 변환할 수 있습니다. 앞에서 입력한 식은 변수 선언의 초기값이 되고, 식의 반환 타입은 변수의 타입으로 선언됩니다. 다음 예제에서 “Shift+Tab v“를 누르면, 세로 막대 (|)로 표시된 커서는 변수 이름을 입력해야 하는 곳에 위치하게 됩니다.

jshell> new JFrame("Demo") <Shift+Tab v>
jshell> JFrame | = new JFrame("Demo")

식(Expression)은 유효해야 하며 그렇지 않으면 변환 요청은 무시됩니다. 이 예제에서 변수를 변환하기 전에 JFrame의 import가 선행되어야 합니다.

앞 예제를 완료하기 위해서, 커서가 위치한 곳에 변수명 frame을 입력하고 Enter 키를 누릅니다.

jshell> JFrame frame = new JFrame("Demo")
frame ==> javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden, ... tPaneCheckingEnabled=true]
|  created variable frame : JFrame

jshell>

식(Expression)의 반환 타입이 아직 import 되지 않은 경우가 있습니다. 이런 상황에서, “Shift+Tab v“을 누르면 import 옵션과 변수 생성 기능 모두가 제공됩니다.

jshell> frame.getGraphics() <Shift+Tab v>
0: Do nothing
1: Create variable
2: import: java.awt.Graphics. Create variable
Choice: 2
Imported: java.awt.Graphics

jshell> Graphics | = frame.getGraphics()

위 예제를 완료하려면, 커서가 위치한 곳에 변수 이름 gc를 입력하고 Enter 키를 누릅니다.

jshell> Graphics gc = frame.getGraphics()
|  created variable gc : JFrame

jshell>

3. 명령

JShell 명령은 JShell 세션에 입력되며, 환경을 제어하고 정보를 출력하는 기능을 제공합니다.

  • 문서 구성
    • JShell 명령 소개
    • JShell 명령의 텝 자동완성
    • 명령어 약어

JShell 명령 소개

JShell 명령은 환경을 제어하고, JShell 세션의 정보를 출력합니다.

JShell 명령은 슬래쉬(/)로 시작하기 때문에 스니펫과 명확하게 구분됩니다. “/var”, “/methods” 그리고 “/types” 명령을 사용하여 현재 세션에 정의된 변수, 메서드 및 타입 정보를 확인할 수 있습니다. “/list” 명령을 사용하면 입력된 스니펫 목록을 확인할 수 있습니다. 다음 예제는 이런 명령의 사용 방법과 출력 결과를 설명합니다.

jshell> /vars
|    int x = 45
|    int $3 = 4
|    String $5 = "OceanOcean"

jshell> /methods
|    twice (String)String

jshell> /list

   1 : System.out.println("Hi");
   2 : int x = 45;
   3 : 2 + 2
   4 : String twice(String s) {
         return s + s;
       }
   5 : twice("Ocean")

변수의 유형과 값 및 메소드의 타입 시그니처(Signature)가 출력됩니다.

JShell에는 JShell이 시작할 때, 기본 시작 스크립트(Default Startup Script)가 자동으로 실행됩니다. 사용자는 별도 부가적인 작업없이 바로 코드 작업을 할 수 있습니다. 시작 스크립트의 실행 항목은 “/list -start” 또는 “/list -all” 명령을 사용하여 확인할 수 있습니다.

jshell> /list -all

  s1 : import java.util.*;
  s2 : import java.io.*;
  s3 : import java.math.*;
  s4 : import java.net.*;
  s5 : import java.util.concurrent.*;
  s6 : import java.util.prefs.*;
  s7 : import java.util.regex.*;
   1 : System.out.println("Hi");
   2 : int x = 45;
   3 : 2 + 2
   4 : String twice(String s) {
         return s + s;
       }
   5 : twice("Ocean")

기본 시작 스크립트는 기본 import 문으로 구성됩니다. “/set start” 명령을 이용하여 시작 항목의 개인화 설정을 할 수 있습니다. 이 명령에 대한 자세한 정보는 “/help /set start” 명령으로 확인 가능합니다. “/save -start” 명령은 현재 시작 스크립트를 자신의 시작 스크립트의 시작점으로 저장합니다.

다른 중요한 명령으로는 JShell을 종료하는 “/exit”, 스니펫을 저장하는 “/save“ 그리고 파일에서 스니펫을 가져오는 “/open“이 있습니다.

JShell 명령 목록은 “/help” 명령으로 확인 가능합니다.

JShell 명령의 텝 자동완성

스니펫을 작성할 때와 마찬가지로, 명령과 명령 옵션을 입력할 때, 텝 키를 사용하여 명령과 명령 옵션의 자동 완성 기능을 사용할 수 있습니다. 현재까지 입력으로 명령과 명령의 옵션의 자동 완성을 결정할 수 없는 상황에서는 가능한 선택 사항을 모두 제공합니다.

다음 예제는 명령 슬래시(/) 다음에 텝 키를 눌렀을 때의 피드백 결과입니다.

jshell> /<Tab>
/!          /?          /drop       /edit       /env        /exit       /help
/history    /imports    /list       /methods    /open       /reload     /reset
/save       /set        /types      /vars

<press tab again to see synopsis>

jshell> /

명령 및 명령 옵션의 자동 완성이 가능한 상황에서는 그 자리에서 완료됩니다. 예를 들어서, /l을 입력하고 Tab(텝 키)을 누르면 그 입력줄에 “/list“이 출력됩니다.

jshell> /l<Tab>

jshell> /list

텝 자동 완성 기능은 명령 옵션도 지원합니다. 다음은 “/list” 명령의 옵션을 출력하기 위해서 텝 키를 사용하는 예제입니다.

jshell> /list -<Tab>
-all       -history   -start     

<press tab again to see synopsis>

jshell> /list -

위 예제서 “명령의 간단한 설명을 출력하려면 텝 키를 다시 입력“과 같은 메세지를 주목하시기 바랍니다. 텝 키를 입력하면 명령에 대한 간단한 설명이 출력됩니다. 텝 키를 3번 입력하면 명령이 도움말 문서가 출력됩니다. 다음 예제는 텝 키를 두 번과 세 번 눌렀을 때의 결과입니다.

jshell> /list -<Tab>
list the source you have typed

<press tab again to see full documentation>

jshell> /list -<Tab>
Show the source of snippets, prefaced with the snippet id.

/list
    List the currently active snippets of code that you typed or read with /open

/list -start
    List the automatically evaluated start-up snippets

/list -all
    List all snippets including failed, overwritten, dropped, and start-up

/list <name>
    List snippets with the specified name (preference for active snippets)

/list <id>
    List the snippet with the specified snippet id

jshell> /list -

고유한 인수의 완성은 제자리에서 수행됩니다. 예를 들어 “/list -a “을 입력하면 -all 옵션이 자동으로 표시됩니다.

jshell> /list -a<Tab>

jshell> /list -all

스니펫 이름도 Tab을 사용하여 완성할 수 있습니다. 예를 들어 JShell 세션에서 이전에 volume 메서드를 정의해다면, 메서드 이름을 일부 입력한 후 Tab 키를 누르면 전체 메서드 이름이 표시됩니다.

jshell> /ed v<Tab>

jshell> /ed volume

명령에 파일명을 인수로 입력해야 하는 위치에서 텝 키를 사용하면 현재 사용 가능한 파일이 표시됩니다.

jshell> /open <Tab>
myfile1      myfile2    definitions.jsh

<press tab again to see synopsis>

jshell> /open

고유한 파일 이름 완성은 제자리에서 수행됩니다.

jshell> /open d<Tab>

jshell> /open definitions.jsh

명령 약어

약어를 사용하여 타이핑 양을 줄일 수 있습니다. 명령, /set subcommand, 명령 인수 및 명령 옵션은 약어가 고유한 경우 모두 축약될 수 있습니다.

/l“로 시작하는 유일한 명령은 “/list“입니다. “/list” 명령 옵션 중에서 “-a“로 시작하는 옵션은 “-all“입니다. 따라서 “/list -all” 명령은 다음 약어로 실행할 수 있습니다.

jshell> /l -a

또한 /se로 시작하는 유일한 명령은 /set이고, fe로 시작하는 유일한 /set 서브 명령은 feedback입니다. 그리고 v로 시작하는 유일한 피드백 모드는 verbose 입니다. (전제 조건: “v”로 시작하는 사용자 정의 피드백 모드가 없는 상황) 따라서 verbose를 피드백 모드로 설정하는 명령은 다음과 같은 약어로 처리할 수 있습니다.

jshell> /se fe v

주의할 점은 s는 약어로 사용할 수 없다는 것입니다. set 명령과 save 명령은 모두 “s” 문자로 시작합니다. 약어가 확실하지 않은 경우, 탭 완성을 사용하여 옵션을 확인할 수 있습니다.

4. 편집(Editing)

JShell은 프롬프트에서 입력된 것을 수정하는 편집 기능을 제공합니다. 또한, 이런 수정 작업에 여러분이 선호하는 외부 편집기를 사용할 수 있습니다.

쉘 편집 기능을 이용하여 이전에 입력한 스니펫과 명령을 입력한 후에, 다시 스니펫과 명령을 편집할 수 있습니다. 이전에 입력했던 스니펫과 명령을 검색하고 변경할 수 있습니다. 또한, 스니펫을 편집하고 생성할 때 외부 편집기를 사용할 수도 있습니다. 외부 편집기 이용은 여러 줄로 구성된 스니펫을 작성할 때 매우 유용합니다.

  • 문서 구성
    • 쉘 편집
    • 외부 편집기 사용

쉘 편집

명령 프롬프트의 입력을 수정하는 기능을 이용하여 여러분의 입력을 손쉽게 고칠 수 있고, 이전에 입력한 명령과 스니펫을 검색하고 수정할 수 있습니다.

JShell의 쉘 편집 기능은 JLine23을 기반으로 만들었습니다. 기능적으로 Emacs 모드의 BSD editlineGNU readline과 유사합니다. 더 자세한 내용은 JLine2 사용자 정보GNU Readline 문서를 참조하십시오.

입력 행 탐색(Input Line Navigation)

쉡 편집은 현재 행 편집을 지원합니다. JShell의 이전 세션에서 만들어진 히스토리에도 접근할 수 있습니다.

입력 행 탐색을 위한 키 조합에 Ctrl 키와 Meta 키를 사용합니다. 키보드에 Meta 키가 없으면, Alt 키가 Meta 키를 대체합니다.

행(line) 안에서 이동은 왼쪽 화살표 방향키(<-)와 오른쪽 화살표 방향키(->)를 사용합니다. 뒤로 이동할 때는 Ctrl+B를, 앞으로 이동할 때는 Ctrl+F를 사용합니다. 히스토리에서 행(line)을 탐색하는 경우에는 위 화살표 방향키아래 화살표 방향키를 사용합니다. 위 화살표 키를 누르면, 현재 행이 이전 명령이나 스니펫 행으로 대체됩니다. 위 화살표 키를 다시 누르면 현재 행은 그 이전 행으로 대체됩니다. 히스토리에는 명령과 스니펫이 모두 기록됩니다. 스니펫이 여러 행으로 구성된 경우, 위 화살표 키와 아래 화살표 키는 스니펫의 개별 행을 탐색하고 출력합니다.

다음 표는 입력 행 탐색에 사용되는 키와 기능을 정리합니다.

액션
Return 현재 행 입력
<–, 왼쪽 화살표 방향키 한 문자 뒤로 이동
–>, 오른쪽 화살표 방향키 한 문자 앞으로 이동
Up arrow, 위 화살표 방향키 한 줄 위로 이동, 히스토리에서 뒤로 한 줄 이동
Down arrow, 아래 화살표 방향키 한 줄 아래로 이동, 히스토리에서 앞으로 한 줄 이동
Ctrl+A 행 시작 부분으로 이동
Ctrl+E 행 끝으로 이동
Meta+B 한 단어 뒤로 이동
Meta+F 한 단어 앞으로 이동

히스토리 탐색(History Navigation)

히스토리에는 여러 JShell 세션의 스니펫과 명령이 기록되고 관리됩니다. 히스토리를 통해서 현재 세션과 이전 세션에서 입력한 항목에 접근할 수 있습니다.

이전애 입력한 것을 다시 입력하거나 수정하려면, 위 혹은 아래 화살표 방향키, 왼쪽 및 오른쪽 화살표 방향키를 사용하여 기록을 탐색한 후 커서가 위치한 곳에 텍스트를 입력합니다. 텍스트를 삭제해야 할 경우 Delete 키를 사용합니다. Enter 키를 눌러 히스토리 행을 재입력합니다.

다음 예제에서, 위쪽 및 아래쪽 화살표 키는 한 번에 한 줄씩 히스토리를 앞뒤로 이동합니다

jshell> class C {
   ...>    int x;
   ...> }
|  created class
jshell> /list

   1 : class C
         int x;
       }

jshell> <up arrow>

위 화살표 방향키를 입력하면 다음과 같이 /list 명령이 출력됩니다.

jshell> /list

위 방향 화살표 키를 다시 입력하면 클래스 정의 마지막 라인이 출력됩니다.

jshell> }

아래 방향 화살표 키를 누르면 “/list” 명령을 반환합니다. 엔터 키를 누르면 “/list” 명령이 실행됩니다.

jshell> /list

   1 : class C {
         int x;
       }

Ctrl+위 화살표 방향키는 이전 스니펫으로 이동합니다. 스니펫이 한 줄이라면 Ctrl+위 화살표 방향키4위 화살표 방향키 와 결과가 같습니다. 클래스 C와 같이 여러 줄로 구성된 스니펫에서 Ctrl+위 화살표 방향키는 해당 스니펫의 첫 번째 행으로 이동합니다. 그 사이에 행은 건너 뜁니다.

입력 행 수정(Input Line Modification)

히스토리로 부터 입력 행을 조회한 후, 필요에 따라서 코드를 변경하고 재입력할 수 있습니다. 이 기능을 사용할 경우, 코드의 일부분을 수정하기 위해서 행 전체를 다시 입력할 필요가 없습니다.

현재 커서가 위치한 곳에서 텍스트를 입력하면 됩니다. 행에서 커서를 움직이는 키에 대해서는 “입력 행 탐색” 절을 확인하시기 바랍니다.

다음 표는 입력 행 수정에 사용되는 키와 기능을 정리합니다.

액션
Delete 커서 위 또는 이후의 문자를 삭제합니다. 이것은 운영체제에 따라서 결정됩니다.
Backspace 커서 앞에 있는 문자를 삭제합니다.
Ctrl+K 커서 위치부터 행의 마지막까지 텍스트를 삭제합니다.
Meta+D 커서에서 워드(Word) 끝까지 텍스트를 삭제합니다.
Ctrl+W 커서에서 이전 공백(White Space)까지 텍스트를 삭제합니다.
Ctrl+Y 행에 가장 최근에 삭제된 문자를 붙여넣습니다.
Meta+Y Ctrl+Y 다음에 Meta+Y 이전에 삭제된 텍스를 순환합니다.

검색과 기타

히스토리 검색은 JShell의 기능으로, 이 기능을 통해서 한 번에 한 줄씩 히스토리를 이동하지 않고도 원하는 줄을 쉽게 찾을 수 있습니다.

검색을 시작하려면 Ctrl-R을 누릅니다. 프롬프트에서 검색 문자열을 입력합니다. 검색은 가장 최근 항목에서 뒤쪽으로 이동하며 처리됩니다. 검색은 JShell의 이전 세션을 포함합니다. 다음 예제는 Ctrl-R을 누른 후에 표시되는 프롬프트를 보여줍니다.

jshell> <Ctrl+R>
((reverse-i-search)`':

히스토리 탐색의 예제에서, class를 입력하면 텍스트 “class”를 포함하는 가장 최근 입력 행을 출력합니다.

(reverse-i-search)`class': class C {

검색은 점증적으로 처리됩니다. 첫 번째 문자 “c”로 검색하고 예제와 같이 결과를 출력합니다. Ctrl+R를 반복적으로 입력해서 히스토리의 이전 결과를 검색할 수 있습니다. Ctrl+S는 현재 위치에서 앞 방향으로 검색을 계속합니다.

Ctrl-x (“를 입력하여 키보드 매크로를 정의할 수 있습니다. 그 다음 텍스트를 입력합니다. 매크로를 종료할 때 “Ctrl-x )“를 입력합니다. “Ctrl + x e“를 입력하면 앞에서 정의한 매크로가 실행됩니다.

다음 표에서는 검색과 매크로 생성에 사용되는 키 조합과 기능을 정리합니다.

액션
Ctrl+R 히스토리 마지막에서 뒤쪽으로 검색
Ctrl+S 히스토리 처음부터 앞 방향으로 검색
Ctrl+X ( 매크로 정의 시작
Ctrl+X ) 매크로 정의 종료
Ctrl+X e 매크로 실행

외부 편집기 사용

JShell 코드 편집에 외부 편집기를 사용할 수도 있습니다. 이 편집기는 스니펫 편집 및 생성에 사용됩니다. 특히 여러 줄로 작성된 스니펫 작업에 유용합니다. 여러분이 선호하는 편집기를 JShell에 지정할 수 있습니다.

기존에 만들어진 모든 스니펫을 편집기에서 한 번에 편집할 경우, 별도 옵션 없이 /edit 명령을 사용합니다. 편집기에서 특정 스니펫을 지정하여 편집할 경우, /edit 명령에 스니펫 이름 혹은 ID를 추가하여 실행합니다. /list 명령을 사용 스니펫 ID를 얻을수 있습니다. 다음 예제를 실행하면 편집기를 열고, 앞에서 정의한 volume 스니펫 코드가 편집기에 출력됩니다.

jshell> /edit volume

편집기에서 새로운 스니펫을 작성할 수 있습니다. 편집기를 저장하면, 변경되거나 새로 작성된 스니펫은 JShell 세션에 입력됩니다. 이때 스니펫 입력에 대한 피드백은 JShell 윈도우에서 확인할 수 있습니다. 그러나 현재 JShell 윈도우에는 프롬프트가 없는 상태입니다. 편집기를 종료한 이후에는 JShell 윈도우에 명령이나 스니펫을 다시 입력할 수 있습니다.

/edit 명령을 실행할 때 편집기를 지정하지 않으면, 환경 변수에 설정된 편집기가 실행됩니다. 환경 변수는 JSHELLEDITOR, VISUAL, 그리고 EDITOR 순서로 참조합니다. 설정된 환경 변수가 없다면, JShell에 포함되어 있는 기본 편집기5를 사용합니다. /set editor 명령을 사용하여, 여러분이 선호하는 편집기를 사용하도록 JShell을 설정할 수 있습니다. /set editor 명령의 매개 변수로 여러분이 사용하고자 하는 외부 편집기를 실행하는 명령을 추가합니다. 다음은 편집기로 “kwrite”를 설정하고 기존의 모든 스니펫을 편집기에 오픈하는 예제입니다.

JShell에 포함된 기본 편집기
그림 1: JShell에 포함된 기본 편집기
jshell> /set editor kwrite
|  Editor set to: kwrite

jshell> /edit

외부 편집기 윈도우에 x 변수를 정의한 다음에, 외부 편집기에 변경을 저장하면, JShell 윈도우에 다음과 메시지가 출력됩니다.

|  created variable x of type int with initial value 6

외부 편집기를 종료하면 JShell 윈도우에 프롬프트가 다시 나타납니다.

jshell>

5. 외부 코드

JShell 세션은 클래스 패스를 이용하여 외부 클래스에 접근할 수 있습니다. 외부 모듈은 모듈 경로, 추가 모듈 설정 및 모듈 내보내기 설정을 통해 접근할 수 있습니다.

  • 문서 구성
    • 클래스 패스 설정
    • 모듈 옵션 설정

클래스 경로 설정

JShell 세션에 클래스 패스를 설정하여 외부 코드에 접근할 수 있습니다.

커맨드 라인에서 클래스 패스는 다음 예제와 같이 설정할 수 있습니다.

 % jshell --class-path myOwnClassPath

접근해야 하는 패키지를 포함하는 디렉터리 혹은 JAR 파일을 클래스 패스로 지정합니다. 코드는 클래스 파일로 컴파일되어 있어야 합니다. 이름이 없는 패키지로 표현되는 디폴트 패키지에 코드는 JShell에서는 접근할 수 없습니다. 클래스 패스를 설정한 상태라면, 이 패스에 포함된 패키지들은 세션에서 임포트 가능합니다.

jshell> import my.cool.code.*

다음 예제와 같이 JShell 세션 아래에서 /env 명령을 사용하여 클래스 패스를 설정할 수 있습니다.

jshell> /env --class-path myOwnClassPath
|  Setting new options and restoring state.

/env 명령은 실행 상태를 재설정하고, 명령으로 입력 한 새로운 클래스 패스 혹은 환경 설정으로 현재 코드 스니펫을 모두 다시 로드합니다.

모듈 옵션 설정

JShell은 모듈을 지원합니다. 모듈 패스를 설정할 수 있고, 지정된 모듈 패스로부터 추가 모듈을 찾고, 모듈을 내보낼 수 있습니다.

다음 예제와 같이 모듈 옵션은 /env 명령이나 커맨드 라인이 옵션으로 제공됩니다.

% jshell --module-path myOwnModulePath  --add-modules my.module

현재 환경 설정은 옵션 없이 /env 명령을 사용하여 확인할 수 있습니다. 다음은 클래스 패스가 설정된 상황에서, 클래스 패스 정보를 출력하는 /env 명령의 사용 예제입니다.

jshell> /env
|     --add-modules my.module
|     --module-path myOwnModulePath
|     --class-path myOwnClassPath

옵션에 대한 자세한 내용을 보려면 다음 명령으로부터 확인할 수 있습니다.

jshell> /help context

6. 피그백 모드

피드백 모드는 JShell에서 프롬프트, 피드백에 대한 정의입니다. 피드백은 JShell과 사용자의 상호작용에 사용됩니다. 피드백 수준이 다른 여러 사전 정의 피드백 모드가 제공됩니다. 필요에 따라 사용자 정의 피드백 모드를 만들 수 있습니다.

  • 문서 구성
    • 피드백 모드 설정
    • 피드백 모드 정의

피드백 모드 설정

피드백 모드는 JShell에서 프롬프트 및 피드백에 대한 정의입니다. 피드백은 JShell과 여러분의 상호작용에 사용됩니다. 사용자 편의를 위해서 여러 사전 정의 피드백 모드(Predefined feedback mode)가 제공됩니다. 필요에 따라 사용자 정의 피드백 모드를 만들 수 있습니다.

사전 정의 피드백 모드는 수정할 수 없습니다. 그러나 사전 정의된 피드백 모드를 사용하여 사용자 정의 모드를 만들 수 있습니다. 사전 정의된 피드백 모드가 제공하는 정보의 양은 verbose, normal, consice, silent 순입니다. 정보양이 가장 많은 것은 verbose 입니다.

다음 표는 사전 정의 피드백 모드에 대한 요약입니다.

Mode 값 스니펫 선언 업데이트 명령 프롬프트
verbose name ==> value (설명) Yes Yes Yes \njshell>
normal name ==> value Yes No Yes \njshell>
concise name ==> value (식만 제공) No No No
jshell>
concise No No No No ->
  • Mode 컬럼은 설명할 피드백 모드를 나타냅니다.
  • 값 스니펫(Value Snippets) 컬럼은 식(expressions), 할당문, 변수 선언과 같은 값을 갖는 스니펫을 표현하는 방식을 설명합니다.
  • 선언(Declaration) 컬럼은 선언 혹은 메서드, 클래스, enum, 인터페이스 그리고 어노테이션 인터페이스에 대해 피드백 제공 여부를 설명합니다.
  • 업데이트 컴럼은 현재 스니펫 이외에 변경 사항의 출력 여부를 설명합니다.
  • 명령 컬럼은 명령에 대한 성공을 나타내는 피드백 제공 여부 설명합니다.
  • 프롬프트 컬럼은 어떤 프롬프트가 사용되는지 설명합니다.

기본 피드백 모드는 “normal“입니다.

피드백 모드는 다음 예제와 같이 커맨드 라인 옵션으로 설정하거나 /set feedback 명령을 사용하여 변경할 수 있습니다.

jshell> /set feedback verbose
|  Feedback mode: verbose

jshell> 2 + 2
$1 ==> 4
|  created scratch variable $1 : int

jshell> /set feedback silent
-> 2 + 2
-> /set feedback normal
|  Feedback mode: normal

jshell> 2 + 2
$3 ==> 4

jshell> /set feedback concise
jshell> 2 + 2
$4 ==> 4
jshell>

피드백 모드로 normal 혹은 verbose로 설정할 경우, 명령 피드백은 설정 모드를 출력합니다.
그러나 피드백 모드로 consise 혹은 silent가 설정될 때는, 명령 피드백으로 설정 모드를 출력하지 않습니다.
또한 식 2+2에 대한 피드백의 3 가지 다른 피드백 형식에 대해서 주의 깊이 살펴보시기 바랍니다. silent로 피드백 모드가 설정되면 식 2+2에 어떤 피드백도 제공하지 않습니다.

현재 및 사용 가능한 피드백 모드는 옵션없이 /set feedback 명령 사용하여 확인할 수 있습니다. 현재 모드는 다음과 같이 피드백 모드를 설정하는 명령으로 표시됩니다.

jshell> /set feedback
|  /set feedback verbose
|
|  Available feedback modes:
|     concise
|     normal
|     silent
|     verbose

피드백 모드 정의

사용자 정의 피드백 모드에서 사용자가 원하는 프롬프트를 정의할 수 있습니다. 또한 JShell에 입력된 요소들에 대해서 수신을 원하는 피드백을 정의할 수 있습니다.

피드백 모드는 다음을 설정을 갖습니다.

  • Prompts: regular 프롬프트 문자, continuation 프롬프트 문자6
  • Truncation: 출력할 값의 최대 길이
  • Format: 제공할 피드백의 포멧

사전 정의 피드백 모드는 변경할 수 없습니다. 그러나 다음 예제와 같이 기존 사전 정의 피드백 모드의 복사본을 만들수 있습니다.

jshell> /set mode mine normal -command
|  Created new feedback mode: mine

새로운 피드백 모드 mine 모드는 normal 모드의 복사본입니다. “-command” 옵션은 명령 피드백을 원한다는 의미입니다. 만약 발생한 액션에 대한 설명을 원하지 않는다면, “-command” 옵션 대신에 “-quiet” 옵션을 사용합니다.

프롬프트 설정

다른 /set 명령과 마찬가지로, 추가 설정이 없는 /set prompt 명령을 실행하면 현제 프롬프트 설정을 출력합니다.

jshell> /set prompt normal
|  /set prompt normal "\njshell> " "   ...> "

앞 예제의 피드백을 보면, 첫번째 문자열이 regulaer 프롬프트이고, 두 번째 문자열이 continuation 프롬프트 입니다. continuation 프롬프트는 여러줄로 스니펫이 구성될 경우에 사용되는 프롬프트입니다. 다음 예제에서는 새로운 모드에서 프롬프트를 변경하는 방법을 소개합니다.

jshell> /set prompt mine "\nmy mode: "  ".......: "

jshell> /set feedback mine
|  Feedback mode: mine

my mode: class C {
.......:    int x;
.......: }
|  created class C

my mode:

프롬프트 문자열은 %s 문자열을 포함할 수 있습니다. 이 문자는 다음 스니펫 ID로 변환됩니다. 그러나 명령이 입력되거나 에러로 스니펫을 반환할 경우, 프롬프트에 사용자가 입력한 값은 ID에 새로운 값이 할당되지 않습니다.

모든 설정은 현재 세션에서만 유지됩니다. /reset 명령으로 재설정되지 않습니다. 미래의 다른 세션에서도 현재 설정이 기본으로 유지되길 원한다면, 설정을 유지하기 위해서 -retain 옵션을 사용해야 합니다. 다음 예제는 사용자 정의 모드를 여러 세션에서 걸쳐서 유지하는 방법을 소개합니다.

my mode: /set mode mine -retain

my mode: /set feedback mine -retain
|  Feedback mode: mine

my mode: /exit
|  Goodbye
% jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

my mode:

Truncation(자름) 설정

출력할 값이 너무 길 경우에, 출력시점에 출력 데이터를 잘라야 합니다. /set truncation 명령을 사용하여 출력할 값의 최대 길이를 설정합니다. 별도의 옵션 없이 /set truncation 명령을 입력하면, 현재 설정을 출력합니다. 다음 예제는 normal 모드를 상속한 mine 모드의 설정을 보여줍니다.

my mode: /set truncation mine
|  /set truncation mine 80
|  /set truncation mine 1000 expression,varvalue

my mode: String big = IntStream.range(0,1200).mapToObj(n -> "" + (char) ('a' + n % 26)).collect(Collectors.joining())
big ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv ... fghijklmnopqrstuvwxyzabcd"

Truncation(절단) 설정이 적용되는 조건은 Truncation(절단) 길이 다음에 입력될 선택자(selector)로 결정됩니다. 온라인 도움말에 따르면 선택자 유형으로 두 가지 타입이 정의되어 있습니다.

  • 케이스 셀렉터는 출력할 값의 스니펫 타입을 표시합니다.
  • 액션 셀렉터는 스니펫에 무슨 일이 발생하는지를 설명합니다.

센렉터에 대한 자세한 설명은 /help /set truncation 명령으로 확인할 수 있습니다.

이전 예제에서의 식의 결과 값(expression case selector) 혹은 변수의 값이 아닌, 변수 명을 입력하여 명시적으로 요청하는 것과 같은 상황이라면, 처럼 값이 식의 값(expression case selector)이거나 변수의 값이 아니라면, 변수 명(varvalue case selector)을 입력하여 명시적으로 출력을 요청할 때 80개 문자로 절단하라는 의미입니다. 이 순서는 중요합니다. 마지막 것이 사용됩니다. 만약에 순서가 반대라면, 모든 값은 80 개 문자에서 절달될 것입니다.7

다음 예제에서 기본 Truncation(절단)을 100으로 설정합니다. 그리고 명시적으로 요청할 때에만 실제 전체 값을 출력합니다.

my mode: /set truncation mine 100

my mode: /set truncation mine 300 varvalue

my mode: big + big
$2 ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi ... yzabcdefghijklmnopqrstuvwxyzabcd"

my mode: big
big ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
vwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl ... jklmnopq
rstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"

my mode: /set mode mine -retain

새로운 설정을 유지하기 위해서, 예제의 마지막에서 처럼 -retain 옵션을 사용하여 변경을 유지합니다.

포멧 설정(Set Formats)

스니펫 출력은 사용자가 변경할 수 있는 설정입니다. normal 모드로 부터 상속한 출력 형식은 import 문에 대해서는 어떤 피드백도 제공하지 않습니다. 값의 유형도 출력하지 않습니다.

my mode: import java.beans.*

my mode: Locale.CANADA.getUnicodeLocaleAttributes()
$5 ==> []

스니펫 출력 형식은 /set format 명령으로 설정할 수 있습니다. /set format 명령을 모드 명만을 추가해서 실행하면 현재 포멧 설정을 출력합니다.

my mode: /set format mine

출력 포멧 설정 명령에 대한 자세한 도움말은 /help /set 명령을 통해서 이용 가능합니다. 포멧을 정의할 때 사용하는 필드를 설명하는 이 절의 나머지 부분에서 이 도움말을 참조로써 사용할 수 있습니다.

피드백에 출력됨은 display 필드로 결정합니다. 출력 필드 정의하는데 돕는 용도로 여러 필드를 정의할 수 있습니다. silent 모드를 제외한 사전 정의 모드는 /help /set format 명령에서 볼 수 있는 필드 중 몇 가지를 정의합니다. 이 필드는 예제 모드에서 상속됩니다. 다음 예제는 import 문의 출력 정의(Display Definition)하는 방법을 설명합니다.

my mode: /set format mine display "{pre}added import {name}{post}" import-added

my mode: /set format mine display "{pre}re-added import {name}{post}" import-modified,replaced

name 필드는 스니펫 이름으로 사전 정의된 필드입니다. 다음 예제는 import 문에 제공되는 피드백입니다.

my mode: import java.beans.*
|  re-added import java.beans.*

표시 정의(Display Definition)에 사용 된 prepost 필드는 피드백 출력의 각 행에 대한 접두어 및 접미어 문자입니다. 다음 예제에서는 세로 막대 접두사를 빈 문자열로 변경하는 설정입니다.

my mode: /set format mine pre ""

my mode: void m() {}
created method m()

my mode: import java.beans.*
re-added import java.beans.*

my mode: /set truncation mine
/set truncation mine 100
/set truncation mine 300 varvalue

접두 문자 변경은 명령 피드백을 포함한 모든 피디백에 영향을 미칩니다.

값을 표시 할 때 타입을 표시하려면, 사전 정의 모드에서 정의 된 결과 필드를 변경하십시오.

my mode: /set format mine result "{type} {name} = {value}{post}" added,modified,replaced-primary-ok

my mode: Locale.CANADA.getUnicodeLocaleAttributes()
Set<String> $11 = []

my mode: 2 + 2
int $12 = 4

이 변경은 새로 추가되거나 업데이트(추가, 수정, 대체)된 경우 입력된 스니펫(primary)에 에러가 없는 경우(ok)에만 결과를 만듭니다.

유지 설정된 모드를 영구적으로 삭제하기 위해서는 -delete 옵션과 함께 -retain 옵션을 함께 사용해야 합니다.

my mode: /set feedback verbose -retain
|  Feedback mode: verbose

jshell> /set mode mine -delete -retain

7. 스크립트

JShell 스크립트는 한 개 파일에 기술된 일련의 스니펫과 JShell 명령이거나 한 줄로 기술된 스니펫 혹은 명령입니다.

스크립트 형태로는 파일과 사전 정의 스크립트8가 있습니다. 다음 표사는 정의 스크립트에 대한 요약입니다.

스크립트 명 스크립트 내용
DEFAULT 일반적으로 사용되는 임포트 문으로 구성됩니다. 이 스크립트는 별도로 시작 스크립트를 지정하지 않을 때 사용됩니다.
PRINTING PrintStream 클래스의 print, println, 그리고 printf 메서드를 직접 참조하는 JShelll 메서드를 정의합니다.
JAVASE java.se 모듈로 정의된 핵심 Java SE API를 임포트합니다. 패키지의 수가 많기 때문에 JShell 시작이 상당히 지연될 수 있습니다.
  • 주제
    • 시작 스크립트 Scripts
    • 스크립트 생성과 로딩

시작 스크립트(Startup Scripts)

시작 스크립트는 JShell 세션이 시작될 때 실행되는 스니펫과 명령으로 구성됩니다. DEFAULT 스크립트는 일반적으로 자주 사용되는 import 문으로 구성되어 있습니다. 필요한 경우 사용자 정의 스크립트를 작성할 수 있습니다.

Jshell이 “reset(재설정)” 될 때마다 시작 스크립트가 실행됩니다. JShell 세션은 처음 시작 및 /reset, /reload, /env 명령이 실행될때 “Reset(재설정)“됩니다. 스크립트를 별도로 설정하지 않으면 기본 시작 스크립트인 DEFAULT 스크립트가 실행됩니다. 이 DEFAULT 스크립트는 일반적으로 사용되는 import 문으로 구성되어 있습니다.

Java는 java.lang 패키지를 자동으로 import 합니다. 따라서 java.lang을 import 문을 사용하여 명시적으로 가져올 필요 없습니다.

시작 스크립트를 설정하는 용도로 /set start 명령을 사용합니다.

jshell> /set start mystartup.jsh

jshell> /reset
|  Resetting state.

모든 /set 명령과 마찬가지로, -retain 옵션을 사용하지 않으면 /set start 명령은 현재 세션에서만 유효합니다. 일반적으로 -retain 옵션은 시작 스크립트 설정을 테스트할 때에는 사용하지 않습니다. 원하는 설정을 찾았을 경우, -retain 옵션을 이용하여 이 설정을 보존합니다.

jshell> /set start -retain

시작 스크립트는 JShell이 시작할 때마다 실헹됩니다.

시작 스크립트는 세션 상태가 재설정(reset) 될 때만 현재 세션에 실행됩니다. 스크립트 내용만 저장되며, 스크립트 파일에 대한 참조는 저장되지 않습니다. 이 스크립트 파일은 /set start 명령이 실행될 때만 읽힙집니다. 사전 정의 스크립트는 참조로 실행되고 새로운 JDK가 릴리즈될 때만 업데이트됩니다.

시작 스크립트는 커맨드 라인 옵션 –startup을 사용하여 지정할 수 있습니다.

% jshell --startup mystartup.jsh

System.out을 사용할 필요 없이 print 메서드를 사용할 수 있다면 매우 편리합니다. 사전정의 PRINTING 스크립트를 사용하면 print, printlnprintf 메서드를 바로 사용할 수 있습니다. /set start 명령을 사용하여 두 개 이상의 시작 스크립트를 지정할 수 있습니다. 다음 예제는 기본 import 문(DEFAULT)과 print 메소드 정의(PRINTING) 모두를 로드하는 시작 설정입니다.

jshell> /set start -retain DEFAULT PRINTING

jshell> /exit
|  Goodbye

% jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

jshell> println("Hello World!")
Hello World!

-retain 옵션을 사용하여 jshell이 실행될 때마다 사전 정의 스크립트가 실행하도록 설정할 수 있습니다. 옵션 없이 /set start 명령을 사용하면 시작 스크립트에서 정의한 내용을 자세하게 확인할 수 있습니다.

커맨드 라인에서 두 개 이상의 시작 스크립트를 설정하려면 각 스크립트에 –startup 플래그를 사용해야 합니다.

% jshell --startup DEFAULT --startup PRINTING

스크립트 생성과 로딩

스크립트를 이용하여 JShell 세션 내에서 사용할 import 문과 코드를 JShell 세션에 설정합니다.

스크립트 생성

스크립트는 외부 편집기를 이용하여 생성할 수 있습니다. 또한 스크립트는 JShell에 입력 한 항목으로부터 생성할 수도 있습니다. 다음 명령 중 하나를 사용하여 JShell 세션의 항목을 이용하여 스크립트를 만듭니다.

jshell> /save mysnippets.jsh

jshell> /save -history myhistory.jsh

jshell> /save -start mystartup.jsh

위 예제의 첫 번째 명령은 현재 활성 상태의 스니펫을 mysnippets.jsh에 저장합니다. 두 번째 명령은 myhistory.jsh에 히스토리에 기록된 모든 스니펫과 명령을 저장합니다. 스크립트에 저장된 스니펫은 현재 유효한 스니펫과 유효하지 않은 스니펫 모두를 포함합니다. 마지막 명령은 현재 시작 스크립트를 mystartup.jsh에 저장합니다. 명령에 사용된 파일명은 유효한 파일 경로 및 이름이어야 합니다.

스크립트 로드

JShell 세션을 시작할 때 커맨드 라인에서 스크립트를 로드할 수 있습니다.

% jshell mysnippets.jsh

JShell 세션 내에 /open 명령을 사용하여 스크립트를 로드 할 수도 있습니다.

jshell> /open PRINTING

  1. [역자주]스크래치 변수(Scratch variable) - 특별한 의미를 갖지 않는 변수로, 값을 잠시 보관하는 용도로 만들어진 임시 변수로, 대개 보유한 값이 얼마 후에 의미가 없어지거나 삭제됨. [return]
  2. [역자주]“정밀도 변경”이란 변수 타입의 변경을 의미하고, “새로운 값을 입력”은 객체 생성 후 할당을 의미합니다. [return]
  3. [역자주]JLine은 콘솔 입력을 처리하기 위한 Java 라이브러리입니다. bash의 명령 편집, 자동완성, 히스토리 기능을 제공합니다. https://github.com/jline/jline2 [return]
  4. Mac 환경에서 Ctrl+위 화살표 방향키 는 Missing Control로 맵핑되어 있습니다. 따라서 Ctrl+위 화살표 방향키 를 사용하기 위해서는 “시스템 환경 설정”에서 Missing Control의 키 맵핑을 변경해야 합니다. [return]
  5. [역자주]JShell은 자바로 개발된 편집기를 표함합니다. JShell은 이 편집기를 기본 편집기로 사용합니다. [return]
  6. [역자주]regular 프롬프트 문자는 일반 프롬프트 문자를 의미하고, continuation 프롬프트 문자는 여려 줄로 스니펫을 작성할 때 출력하는 프롬프트 문자입니다. 기본 regular 프롬프트 문자는 “|“입니다. 기본 continuation 프롬프트 문자는 “__ …>__“입니다. [return]
  7. [역자주]expression과 varvalue 셀렉터를 설정함으로써 두 번째 설정은 범위를 한정하였습니다. [return]
  8. 사전 정의 스크립트는 별도 파일로 존재하지 않습니다. Java JDK의 API 형태로 개발되어 있습니다. [return]
김태완 avatar
작성자: 김태완
1999년 부터 Java, Framework, Middleware, SOA, DB Replication, Cache, CEP, NoSQL, Big Data, Cloud를 키워드로 살아왔습니다. 현재는 빅데이터와 Machine Learning을 중점에 두고 있습니다.
E-mail: taewanme@gmail.com