여러 사람들과 함께 Java 프로젝트를 공유하여 개발할 경우, JavaSE와 Maven 버전을 고정해둘 필요가 있다. 버전을 고정하지 않으면 빌드 자체가 실행되지 않거나 빌드 중 컴파일 오류를 겪을 수 있다.
우선 오래 전에 개발된 Java 프로젝트에서 로컬 개발 환경을 구축하는 과정에서 동료들이 제각각 어려움을 겪을 수 있는 상황을 가정한다. 이 프로젝트에서는 JDK 1.7과 Maven 3.0.3을 사용한다고 가정하겠다. 물론 어지간한 프로젝트라면 JDK 11로 마이그레이션할 수 있지만, 일단 프로젝트는 가급적 크게 건드리지 않으려고 한다.
brew install zulu7
이 밖에도 OpenJDK 계열의 JavaSE로 추천할만한 런타임은 다음과 같다. JavaSE 11이 현행으로는 가장 많이 쓰이는 버전이다.
brew install temurin11
brew install temurin8
brew install temurin17
굳이 Oracle JDK 1.6을 사용해야 한다면, 다음 명령도 가능하다.
brew install java6
jenv를 이용한다. pyenv와 유사하여 pyenv에 익숙한 개발자라면 쉽게 사용할 수 있다.
(zsh을 사용한다고 가정함)
brew install jenv
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(jenv init -)"' >> ~/.zshrc
source ~/.zshrc
설치된 JavaSE 목록을 확인해본다.
jenv versions
* system (set by /Users/terzeron/.jenv/version)
jenv와 별개로 사용할 수 있는 (시스템에 설치된) JavaSE에 해당하는 "system"을 제외하고는 아무 것도 나오지 않는데, 정상이다.
jenv는 전역적으로 또는 특정 디렉토리에서만 지역적으로 사용할 JavaSE를 설정하는 역할을 수행하므로 설치되어 있는 JavaSE를 사전 등록하는 작업이 필요하다.
jenv add /Library/Java/JavaVirtualMachines/zulu-7.jdk/Contents/Home
jenv rehash
jenv versions
* system (set by /Users/terzeron/.jenv/version)
1.7
1.7.0.332
zulu64-1.7.0.332
이 세 가지 JavaSE가 모두 동일한 런타임을 가리킨다. 현재 프로젝트 디렉토리에서 사용할 버전으로 1.7을 고른다.
jenv local 1.7
JavaSE 버전을 확인해본다.
java -version
자신이 사용하려던 JavaSE가 정상적으로 설정되어 있는지 확인한다.
openjdk version "1.7.0_332"
OpenJDK Runtime Environment (Zulu 7.52.0.11-CA-macosx) (build 1.7.0_332-b01)
OpenJDK 64-Bit Server VM (Zulu 7.52.0.11-CA-macosx) (build 24.332-b01, mixed mode)
이후에 이 디렉토리에 진입할 때마다 jenv가 JavaSE를 1.7로 설정해준다. 이 효과는 .java-version이라는 파일 때문에 영구적으로 나타나는데, 이 파일을 삭제하게 되면 다시 설정해줘야 한다. 프로젝트 git repository에 이 파일을 추가해주는 게 좋다.
macOS의 경우, JavaSE를 설치하면 /Library/Java/JavaVirtualMachines/ 디렉토리에 설치된다. 예를 들어, temurin11을 사용하려면 다음과 같은 명령을 실행해야 한다.
jenv add /Library/Java/JavaVirtualMachines/temurin-11.jdk/Contents/Home
jenv rehash
jenv local 11
maven은 이미 설치되어 있다고 가정한다. 혹시 설치되어 있지 않다면 다음 명령으로 설치 가능하다.
brew install maven
maven wrapper는 maven의 버전을 고정해주는 역할을 한다.
mvn wrapper:wrapper -Dmaven=3.0.3
Java 1.6이나 1.7에서는 Maven도 구 버전이 필요하여 이 예제에서는 일부러 Maven 3.0.3을 사용했는데, 현행 프로젝트에서는 이 버전이 너무 낮으니 좀 더 최신 버전을 사용할 필요가 있다.
이후에는 mvn 대신에 ./mvnw 명령을 사용하면 되고, IntelliJ에는 mvn 대신에 mvnw를 사용할 수 있도록 지원해주는 플러그인도 있다.
./mvnw clean package
mvnw 파일이나 mvnw.cmd 파일 등을 git repository에 추가해주는 게 좋다.
maven wrapper를 설치하는 명령은 길어서 기억하기 쉽지 않다. 이런 경우 bash나 zsh의 alias로 만들어두면 편리하다.
alias init_mvnw="mvn wrapper:maven:wrapper"
zsh의 경우, ohmyzsh의 mvn 플러그인을 이용하면 mvn과 mvnw를 편리하게 사용할 수 있다. mvn이라는 이름의 alias가 등록되어 있어서 이걸 실행하면 mvn-or-mvnw 함수를 실행하고, mvnw가 있으면 우선 실행하고 없으면 mvn을 실행하는 방식이다.
안타깝지만 mvnw는 jenv가 PATH 환경변수로 설정한 java executable에 의존하지 않고 JAVA_HOME 환경변수에 의존하기 때문에, mvnw가 실행될 때 jenv와 맞지 않는 다른 JavaSE를 사용할 가능성이 있다.
./mvnw --version
Apache Maven 3.0.3 (r1075438; 2011-03-01 02:31:09+0900)
Maven home: /Users/terzeron/.m2/wrapper/dists/apache-maven-3.0.3-bin/5qc5295i0tgpqqq0db6bfsr5ld/apache-maven-3.0.3
Java version: 17.0.2, vendor: Eclipse Adoptium
Java home: /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
Default locale: ko_KR, platform encoding: UTF-8
OS name: "mac os x", version: "12.2", arch: "aarch64", family: "mac"
jenv가 이 문제를 해결하기 위해 제공하고 있는 방법은 다음과 같다. export 플러그인을 이용해서 환경변수를 노출시키고 현재 shell에 반영한다.
jenv enable-plugin export
exec $SHELL -l
./mvnw --version
Apache Maven 3.0.3 (r1075438; 2011-03-01 02:31:09+0900)
Maven home: /Users/terzeron/.m2/wrapper/dists/apache-maven-3.0.3-bin/5qc5295i0tgpqqq0db6bfsr5ld/apache-maven-3.0.3
Java version: 1.7.0_332, vendor: Azul Systems, Inc.
Java home: /Library/Java/JavaVirtualMachines/zulu-7.jdk/Contents/Home/jre
Default locale: ko_KR, platform encoding: UTF-8
OS name: "mac os x", version: "10.16", arch: "x86_64", family: "mac"
JavaSE 버전을 확인할 때, 다음과 같이 에러가 발생할 수 있다.
/Users/terzeron/.jenv/shims/java: line 21: /usr/local/Cellar/jenv/0.5.4/libexec/libexec/jenv: No such file or directory
java라는 이름의 wrapper executable이 jenv를 정상적으로 찾지 못해서 발생하는 에러이다. M1 맥북에서 Intel 바이너리를 참조하기 때문에 생기는 문제로서, homebrew 구조에 대한 이해갸 필요하다.
M1 맥북이 등장함에 따라 homebrew의 설치 경로가 나뉘었는데 Intel 맥북은 /usr/loca/Cellar 하위에 패키지가 설치되고, M1 맥북은 /opt/homebrew/Cellar 하위에 패키지가 설치된다. 그러므로 M1 맥북이라면 /usr/local/Cellar를 사용하지 않고 /opt/homebrew/Cellar를 사용해야 마땅하다.
이 문제를 해결하려면, 번거롭지만 ~/.jenv 디렉토리를 삭제하고 jenv를 재설치해야 한다.
rm -rf ~/.jenv
brew uninstall jenv
brew install jenv
그리고 위에서 설명했던대로 JavaSE 런타임을 다시 등록해줘야 한다.
jenv add <JavaSE 설치 경로>
jenv rehash