[SpringBoot] Command line is too long. 문제 원인/해결법
스프링부트에서 테스트 코드를 작성하던 중
갑자기 이전엔 발새하지 않던 Command line is too long. 라는 에러가 발생했다.
원인
This error occurs when the classpath gets too long or have many VM arguments. Most operating system has a limited number of characters for command line.
에러와 직면한 이후, 문제 해결을 위한 래퍼런스 탐색 도중 baeldung에서 에러의 원인을 발견할 수 있었다.
baeldung에서 확인한 내용을 해석해보자면
"이 에러는 classpath가 너무 길거나 가상머신 인수가 많을 때 발생하며, 대부분의 운영 체제는 커맨드 라인 글자의 글자수 제한을 가진다" 라는 것이다.
나는 가상머신 인수가 많은 문제는 사실 테스트 코드 작성 전에는 발생하지 않던 문제이기도 했고 예측이 가지 않아서
먼저 classpath가 너무 길다는 내용에 집중해보았다.
classpath 길이 관련으로 발생하는 문제는 주로 Windows 환경에서 발생하며, 명령 줄(command line)의 길이가 운영 체제에서 허용하는 최대 길이를 초과할 때 나타난다고 한다.
그럼 classpath를 줄여야할텐데 어떻게하면 클래스패스를 줄일 수 있을까??
해결방법
문제 해결법은 생각보다 간단했다.
그냥 사용하던 classpath를 dynamic classpath, 즉 동적 클래스패스로 사용하도록 변경해주면 되는 것이다.
설정방법1. /.idea/workspace.xml 수정
<component name="PropertiesComponent">
<property name="dynamic.classpath" value="true" />
" 루트 디렉토리 - .idea - workspace.xml " 에 있는 <component name="PropertiesComponent"> 태그에
위처럼 'dynamic.classpath' property 태그를 추가하고 value 속성을 'true'로 설정해주면 해결된다.
.idea는 IntelliJ의 프로젝트별 프로젝트 세팅 파일이고,
workspace.xml에 있는 PropertiesComponent 태그는 환경변수를 관리하는 컴포넌트 태그로
내부에 IDE의 프로퍼티 값을 설정할 수 있다.
이 설정은 PropertiesComponent 구성 요소 내에 dynamic.classpath 속성을 정의하여 문제를 해결하는 것인데,
이 속성의 값을 true로 설정하여 클래스패스를 동적으로 관리하도록 지정한다.
동적 클래스패스 설정을 사용하면,
IDE나 빌드 도구가 긴 클래스패스 대신 클래스패스 매니페스트 파일(manifest file)을 생성할 수 있게 되는데
이 파일은 클래스패스에 포함된 모든 JAR 파일과 디렉토리의 목록을 포함하고 실제 명령 줄에는 이 매니페스트 파일의 경로만 포함된다.
java -cp "C:\path\to\project\lib\library1.jar;C:\path\to\project\lib\library2.jar;...;C:\path\to\project\lib\libraryN.jar" com.example.Main
예를 들어 이렇게 길었던 클래스패스를 dynamic classpath 설정을 통해 manifest 파일을 만들어 관리함으로써
java -cp "@C:\path\to\project\classpath.txt" com.example.Main
이렇게까지 줄일 수 있게 된다는 것이다.
이렇게 명령 줄의 길이를 크게 줄임에 따라 Command line is too long. 과 같은 오류를 해결할 수 있었다.
설정방법2. Application Configuration 설정
반면 IDE 설정을 몇 번의 버튼 클릭을 통해 변경하는 방법도 존재한다.
Application의 Edit Configurations 를 클릭한다.
그리고 Build and run 파트의 Modify options를 클릭해주면
Shorten command line 이라는 옵션이 있는데 선택해준다.
Shorten command line에는 JAR manifest, @argfile (Java 9 이상부터 생김) 두 가지 옵션이 있다.
JAR manifest 방식은 IDE가 classpath.jar 을 통해 길이가 긴 classpath를 전달하는 방식이고
@argfile 방식은 명령줄에서 인수(argument)를 파일에 저장한 후, 해당 파일을 참조하여 인수를 제공하는 방식이다.
결론
개발을 하면서 꽤나 다양한 오류 상황에 마주하게 되는 것 같다.
그 중에는 간단해보였지만 꽤 오랜 시간을 투자해야했던 트러블 슈팅이 종종 있었는데
과거에는 트러블슈팅에 오랜 시간을 투자하고 있으면 무력함이 느껴지고 개발에 대한 재능을 다시 한 번 의심하고는 했다.
하지만 지금은 그렇지않다.
그 과정에서 원인을 분석하고 지금처럼 기록해나가는 과정이 정말 큰 배움의 순간이라고 생각한다.
오류가 발생한다는 것은 내가 제대로 알지 못하고 기술을 사용하고 있다는 것이고, 오류의 발생은 학습의 과정으로 이어진다.
항상 배움의 자세로 개발에 임하자.
에러? 오히려 좋다:)
실무에서 터뜨릴 것들까지 지금 다 터뜨려서 많이 성장해두자.