680
4
부
고급 주제 및 실전 응용
21.1.2
scala
명령행 도구
scala
명령은 인자로 프로그램이 주어진 경우에는 그 프로그램을 실행하고, 그렇지 않은 경우에
는
REPL
을 시작한다. 이 또한
scalac
처럼 셸 스크립트다. 다음과 같이
scala
를 시작할 수 있다.
scala
<
옵션
>
[
<
스크립트
|
클래스
|
객체
|
jar
>
<
인자
>
]
scalac
가 받아들이는 같은 옵션을 여기에 지정할 수 있다. 또한 [표
21
-
4
]에 있는 옵션도 추가로
지정할 수 있다.
표
21-4
scala
명령의추가옵션
옵션 설명
-
howtorun
:
방법
object
,
script
,
jar
,
guess
중어떤방법으로실행할지지정한다(
guess
가기본값임) .
-
i
파일
REPL
을시작하기전에파일의내용을미리읽어들인다.
-
e
문자열 문자열을마치
REPL
에서입력한것처럼실행한다.
-
save
컴파일한스크립트를나중에사용할수있게
JAR
파일에저장한다.따라서재컴파일에드는부
가비용을줄일수있다.
-
nc
컴파일데몬인
fsc
를실행하지않는다.이옵션을지정하지않으면컴파일러를재시작하는데
드는부가비용을줄이기위해
fsc
를자동으로시작한다.
옵션이 아닌 첫 번째 인자가 실행할 프로그램으로 인식된다. 아무 실행 파일도 지정하지 않으면
REPL
을 시작한다. 프로그램을 지정한 경우, 그 프로그램 이름 뒤에 오는 모든 인자는
args
배
열을 통해 대상 프로그램에 전달된다. 앞에서 이미 그런 예를 많이 봤다.
‘
-
howtorun
:
방법
’ 옵션을 지정하지 않은 경우,
scala
는 대상 프로그램의 종류를 추론할 것이
다. 대상 파일이 스칼라 소스 코드라면
scala
는 그 대상을 스크립트로 실행한다. 만약 대상이
main
이 들어 있는 클래스 파일이거나 정상적인
Main
-
Class
가 지정된
JAR
파일이라면, 일반적
인 자바 프로그램과 마찬가지로 대상 파일을 실행한다.
‘
-
i
파일
’ 옵션은 대화식 모드에서 원하는 스칼라 문을 입력하기 전에 대상 파일을 미리 읽어 들
이기 위해 사용한다. 일단
REPL
에 들어왔다면 ‘
:
load
파일이름
’을 사용해서 파일을 읽을 수 있
다. 이런 파일은 여러분이
REPL
을 시작할 때마다 동일한 명령을 반복해서 실행하는 경우에 유용
하다.
681
21
장
스칼라 도구와 라이브러리
REPL
을 사용하는 동안 몇 가지 명령을 쓸 수 있다.
:
help
를 입력하면 모든 명령의 목록을 간
단한 설명과 함께 볼 수 있다. [표
21
-
5
]는 스칼라
2
.
11
.
2
에서 사용 가능한 명령을 보여준다. 내
용을 약간 편집했다.
표
21-5
스칼라
REPL
에서사용가능한명령
명령 설명
:
cp
경로
JAR
나디렉터리를
classpath
에추가한다.
:
edit
번호 또는 줄 과거입력을편집한다.
:
help
[
명령] 이요약이나명령에따른구체적인도움말을표시한다.
:
history
[
개수
]
과거입력을표시한다( 선택적인개수는보여줄명령의개수다 ).
:
h
?
문자열 과거입력을검색한다.
:
imports
[
이름 이
름 ...]
과거임포트내역을보여주며,이름이어디서왔는지식별해준다.
:
implicits
[
-
v
]
현재영역안의암시들을보여준다(
-
v
를선택하면더자세한출력을보여준다) .
:
javap
경로 또는 클래스 파일이나클래스를역어셈블한다.
:
line
번호 또는 줄 지정한번호나줄을과거입력목록의맨뒤로보낸다.
:
load
경로 경로로주어진파일의내용을실행한다.
:
paste
[
-
raw
] [
경로
]
붙여넣기
paste
모드로들어가거나,경로에있는파일을붙여넣는다.
:
power
고급사용자모드로들어간다( 본문의설명을보라 ).
:
quit
인터프리터를종료한다(
Ctrl
-
D
도같은역할을한다) .
:
replay
실행을재설정하고,모든예전명령을재실행한다.
:
reset
REPL
을초기상태로재설정하고,모든세션엔트리를삭제한다.
:
save
경로 세션을나중에실행할수있도록파일에저장한다.
:
sh
명령 인자 셸명령을실행한다(결과는암시적으로
⇒
List
[
String
]
이다).
:
settings
[
+
또는
-
]
옵션 컴파일러옵션플래그를사용가능하게만들거나(
+
)/불가능하게만든다(
-
).
:
silent
결과를자동으로출력하게하거나출력하지않게한다.
:
type
[
-
v
]
식 식을계산하지않고타입만표시한다.
:
kind
[
-
v
]
식 식의타입이속하는계
kind
를표시한다.
:
warnings
경고가발생한행중가장최근에발생한경고를보여준다.
:
power
모드로 활성화할 수 있는 ‘고급 사용자 모드’에서는 추상 구문 트리
abstract
syntax
tree
나 인터
프리터의 프로퍼티 등 메모리상의 데이터를 살펴보거나 컴파일러를 조작할 수 있는 추가 명령을
제공한다.
어떤 스크립트를 자주 사용하는 경우
scala
명령으로 그 스크립트를 실행하는 것이 지겨울 수
있다. 윈도우나 유닉스 종류의 시스템에서는 ‘
scala
스크립트
-
파일
-
이름
’ 방식의 호출을 사용하
지 않아도 독립적으로 실행될 수 있는 스크립트를 만들 수 있다.
682
4
부
고급 주제 및 실전 응용
다음 예제는 유닉스 계열의 시스템에서 독립 실행 스크립트를 만드는 방법을 보여준다.
chmod
+
x
secho
와 같이 파일에 실행 권한을 부여해야 한다는 사실을 기억하라.
#!/
bin
/
sh
#
src
/
main
/
scala
/
progscala2
/
toolslibs
/
secho
exec scala
"$
0
"
"$
@
"
!#
print
("
You entered
:
")
args
.
toList foreach
{
s
=
>
printf
("%
s
",
s
)
}
println
다음은 이 실행 파일을 사용하는 방법을 보여준다.
$
secho Hello World
You entered
:
Hello World
마찬가지로 다음은 윈도우의
.
bat
명령을 보여준다.
::#!
@
echo off
call scala
%
0
%*
goto
:
eof
::!#
print
("
You entered
:
")
args
.
toList foreach
{
s
=
>
printf
("%
s
",
s
)
}
println
scalac
에 대비한
scala
의 한계
소스 파일을
scala
로 실행하는 것은
scalac
로 컴파일하는 것과 비교할 때 몇 가지 한계가 있다.
scala
로 실행할 스크립트 파일은 다음 예제와 같이 그 내용을 익명의 객체에 둘러싼 것과 비슷
하다.
683
21
장
스칼라 도구와 라이브러리
object Script
{
def main
(
args
:
Array
[
String
]):
Unit
=
{
new AnyRef
{
//
스크립트
코드가
여기에
들어간다
.
}
}
}
스칼라
object
에는 패키지 선언이 들어갈 수 없다. 이는 스크립트 안에서 패키지를 선언할 수
없다는 뜻이다. 이 책에서 패키지를 선언하는 예제는 반드시 컴파일해서 별도로 실행해야 하는
이유도 그 때문이다.
반대로, 올바른 스크립트인데 ‘
-
Xscript
객체
’ 옵션을 사용하지 않으면
scalac
로 컴파일할 수
없는 것도 있다. 여기서
객체
는 컴파일할 객체의 이름이며, 앞의 예제에 있는
Script
를 대신한
다. 다른 말로 하면, 이 컴파일러 옵션은
REPL
이 암시적으로 만들어주는 것과 같은 래퍼를 만
든다.
타입의 밖에 함수 정의나 함수 호출이 위치할 수 없기 때문에, 컴파일을 하려면 래퍼 객체가 필
요하다. 다음 예제를
scala
를 사용해서 스크립트로 실행하는 경우에는 잘 작동한다.
//
src
/
main
/
scala
/
progscala2
/
toolslibs
/
example
.
sc
case class Message
(
name
:
String
)
def printMessage
(
msg
:
Message
)
=
println
(
msg
)
printMessage
(
new Message
("
This works fine with the REPL
"))
하지만 이 스크립트를
scalac
로
-
Xscript
옵션 없이 컴파일하면 다음과 같은 오류가 발생한다.
example
.
sc
:
3
:
error
:
expected class or object definition
def printMessage
(
msg
:
Message
)
=
println
(
msg
)
^
example
.
sc
:
5
:
error
:
expected class or object definition
printMessage
(
new Message
("
This works fine with the REPL
"))
^
two errors found
684
4
부
고급 주제 및 실전 응용
대신 다음과 같이 컴파일해서 실행할 수 있다.
scalac
-
Xscript MessagePrinter src
/
main
/
scala
/
progscala2
/
toolslibs
/
example
.
sc
scala
-
classpath
.
MessagePrinter
이 스크립트는 결과적으로 기본 패키지를 사용하기 때문에, 만들어진 클래스 파일은 현재 디렉
터리에 들어 있을 것이다.
MessagePrinter
$$
anon
$
1
$
Message
$.
class
MessagePrinter
$$
anon
$
1
$
Message
.
class
MessagePrinter
$$
anon
$
1
.
class
MessagePrinter
$.
class
MessagePrinter
.
class
javap
-
private
를 사용해서(다음 절에서 설명할 것이다 ) 각 파일을 살펴보면 내부에 들어 있
는 선언을 볼 수 있다.
-
p
또는
-
private
플래그는 비공개나 보호 멤버를 포함하는 모든 멤버를
표시하라는 의미다 (모든 옵션을 보고 싶다면
javap
-
help
를 사용하라 ).
.
class
를 빼고
javap
MessagePrinter
$$
anon
$
1
$
Message
$
처럼 호출해야 한다.
MessagePrinter
와
MessagePrinter
$
는
scalac
가 스크립트를 ‘애플리케이션’으로 만들면서
진입점을 제공하기 위해 생성한 래퍼다.
MessagePrinter
에는 우리에게 필요한
static
main
이
들어 있다.
MessagePrinter
$$
anon
$
1
은 전체 스크립트를 감싸도록 생성된 자바 클래스다. 스크립트의
printMessage
메서드는 이 클래스의 비공개 메서드다.
MessagePrinter
$$
anon
$
1
$
Message
는
Message
클래스다.
MessagePrinter
$$
anon
$
1
$
Message
$
는
Message
동반 객체다.
21.1.3
scalap
와
javap
명령행 도구
스칼라 구성 요소들이
JVM
바이트 코드로 어떻게 구현되는지 이해하려 할 때 디컴파일러
Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.