본문 바로가기
Java/Java Basic

[Java Basic] 50 - Jar 명령어로 기본 archive 만들기(Windows CMD)

by Rosmary 2023. 1. 10.
728x90
반응형

 

 

 

 

 

간만에 진행하는 Java 포스팅이다. Java 기초 포스팅은 되도록이면 진행하지 않으려 했는데, 정리가 필요한 내용이 생겨 추가 포스팅을 작성하게 되었다. 매번 자료를 찾아서 기억을 복구하기도 어려워서 아예 정리를 할 겸 말이다(요즘 들어 기억력이 점점 금붕어의 그것이 되는 것 같아 걱정이다).

 

이번 포스팅의 주제는 jar 라고 불리는, 아카이브를 위한 일종의 압축 파일이다. 본 포스팅은 java의 패키지와도 연관이 있는 내용이기 때문에, 관련 내용에 대한 배경 지식이 필요하신 분들은 이 포스팅을 먼저 확인하고 오면 된다.

 

 

1.  폴더로만 구성된 패키지에서의 에러사항

 

필자가 아이디와 패스워드를 입력하여 로그인을 하는 프로그램을 하나 만든다고 가정해보자. 입력한 비밀번호는 탈취되는 경우에 대비하여 암호화를 진행한 String 값을 반환하도록 하려 한다. 

 

기능적으로 나누면 크게 계정 정보를 입력받는 클래스와, 비밀번호의 암호화 문자열을 반환하는 클래스 크게 두 가지를 만들 수 있을 것이다. 우선, 두 클래스를 호출할 수 있는 Main 클래스를 간단히 아래와 같이 만들고, 

 

 

계정 정보를 입력하는 InputAccount.java와 비밀번호를 암호화하는 EncryptSHA를 아래와 같은 Java 코드로 작성하였다.

 

 

필자가 개인 프로젝트에 쓴다고 예전에 만든건데, 코드 치기 귀찮아서 재활용한다... 반복해서 직접 쳐봐야 실력이 늘텐데...

 

모든 java 파일을 컴파일하고, Main 클래스를 java 명령어로 호출하면 아래와 같이 정상적인 결과가 나타나는 것을 확인할 수 있다.

 

 

이제, class 파일이 위치한 폴더를 보자. 서로 다른 기능을 가진 클래스 파일이 한 폴더 안에 어우러져있으니 한 눈에 보기에도 어지럽다. 

 

 

따라서 필자는 EncryptSHA 클래스 파일과 InputAccount 클래스 파일을 각각 별도의 폴더를 만들어 넣고, 이들 클래스를 참조할 수 있도록 package 키워드를 추가하려 한다.

 

 

 

그런데, 한 가지 문제가 생겼다. InputAccount의 경우, 기존에 동일한 경로에 위치하던 EncryptSHA를 참조했었기에, EncryptSHA 역시 import 문으로 코드를 작성해야 하나, import는 상위 경로 지정이 안된다는 치명적인 단점이 있다. 예를 들어, 필자가 InputAccount 클래스 코드에서 EncryptSHA를 import 하기 위해 아래와 같이 코드를 작성하면 JVM이 필자의 의도를 전혀 못 알아먹는다는 이야기다.

 

** import ...encrypt.EncryptSHA; (참고로 명령창에서 상위 폴더를 의미하는 기호가 ".."이다. 현재 폴더는 "."로 표기한다)

 

 

import 문의 경우, 기본적으로 클래스 파일이 위치한 경로에서 하위 경로만을 탐색할 수 있도록 만들어졌기 때문에 일어나는 일이다. 

 

이 문제를 해결하기 위해서, Main 클래스 파일이 위치하는 경로를 최상위 절대 경로로 지정해주면 좋은데... 일반적인 Java 코드는 이를 지원하는 기능이 없다. 이러한 문제를 해결하기 위해 jar 파일을 사용한다.

 

 

 

 

2. Jar 파일

 

jar 파일은 JSP 포스팅을 보셨던 분들이라면 낮이 꽤 익을 것이다. 패키지에 포함된 클래스들에 대해 소개할 때, jar 파일 내부의 어떤 위치에 있는 클래스를 사용하는지 언급하면서 보여주었다.

 

 

 

자신이 만든 클래스 파일이 폴더로 구조화되어 있고, 내부 클래스 파일 역시 패키지 구조 내 다른 클래스 파일을 참조해야할 경우, 참조해야 할 클래스가 포함된 폴더를 jar 파일로 변환할 때, 패키지의 최상위 경로를 절대 경로로 지정하는 효과를 낼 수 있다. 실제로 JSP와 Servlet 파일을 작성할 때도, 생전 만들어본 적 없는 HttpSession 같은 클래스 파일을 사용할 수 있는 것도 이 jar 파일의 존재 덕분이다. 

 

Jar 파일을 사용하기 위해, 아래와 같은 절차를 거친다.

 

-  사용하고자 하는 클래스 파일을 폴더로 구조화 한다.

-  구조화된 폴더 중 참조가 필요한 폴더를 jar 확장자로 압축한다. 

-  압축된 jar 파일을 OS 환경 변수에 등록하여, java 사용 시 생성한 jar 파일을 참조할 수 있도록 한다.

 

하나씩 진행해보자.

 

(1) 폴더(패키지) 구조화

 

패키지 구조화는 이미 끝나 있다. 필자의 경우 inputAccount는 inputinfo 폴더에, EncryptSHA는 encrypt 폴더에 넣어놓음으로써 구조화를 완료했다.  cmd에서 tree 명령어로 본 최종 폴더의 형태는 아래와 같다.

 

 

 

(2) Jar 파일 압축

 

이제 패키지화 된 폴더인 jartest를 jar 파일로 압축해보자. jar 파일 압축은 Zip과 같은 프로그램을 사용하지 않고, java 설치 시 같이 딸려오는(?) jar 라는 명령어를 사용한다. jar --help 를 cmd 창에 입력했을 때, 뭔가 말이 많다면 이 명령어를 사용할 수 있는 상태다.

 

 

마치 리눅스 명령어처럼(실제 리눅스 명령어도 동일하다..), 사용 방법에 대해 세세하게 설명해놓았다. 가장 주요하게 보아야 하는 옵션은 -c와 -f인데, -c는 jar 파일의 신규 생성 시 사용하는 옵션이고, -f는 생성할 jar 파일의 이름을 지정할 때 사용하는 옵션이다.

 

 

--help 명령어의 결과 중 최 상단에 jar 명령어의 사용 예시가 나와 있는데, 이를 토대로 현재 만든 jartest 폴더를 jar 파일로 압축해보려 한다. 우선 manifest니 뭐니 어려운 말은 다 건너뛰고, 단순히 압축을 해보려한다.

 

명령어는 아래와 같다.

 

jar  [옵션]  [-f 옵션 사용 시 jar 파일명]  [압축할 폴더의 경로]

 

필자는 단순히 encrypt 폴더만 jar로 압축할 예정이므로, 위의 명령어 포맷을 적용하면 아래와 같은 결과가 나타난다. 

ex1)  jar -cf encrypt.jar ./encrypt

ex2) jar --create --file=encrypt.jar ./encrypt

 

 

 

 

 

생성된 jar 파일을 열어보면, 실제 encrypt 폴더와 동일하게 EncryptSHA.class 파일이 존재하고 있음을 확인할 수 있다. 이제 InputAccount 클래스 파일은 이 jar 파일을 참조하여 EncryptSHA 클래스 파일을 호출하는 것이 가능한 단계에 한 발 짝 다가섰다(아직 된다는 의미가 아니다..)

 

 

(3) classpath 환경변수에 생성한 jar 파일 등록

 

이렇게 만들어진 jar 파일은 컴퓨터가 당장 인식하는데에 어려움이 있다. Main 클래스에 의해 InputAccount 클래스 파일이 호출되고 내부의 encrypt.EncryptSHA.class 파일을 호출하는 코드가 나타나는데, 이 encrypt는 encrypt.jar의 최상위 폴더를 의미한다. jar 파일을 만든 필자야 이를 이해하지만, 컴퓨터는 

 

"encrypt가 뭐야?? 먹는거야?"

 

라며 여전히 에러를 뿜어낼 것이다.

 

 

 따라서 encrypt는 encrypt.jar라는 것을 컴퓨터에게 이해시킬 필요가 있는데, 이를 위해 classpath라는 시스템 환경 변수를 등록해주어야 한다. 

 

classpath는 말 그대로 class 파일의 경로를 의미한다. java에서는 jar 파일 내부 또는 단독 클래스 파일의 위치를 JVM에게 알려주기 위해 사용한다. JSP/Servlet 사용 시  혹은 DB 연동을 위한 JDBC 사용 시에도 이러한 jar 파일을 classpath에 등록하는데, "이러이러한 패키지, 클래스 파일을 사용할 때, 여기에 등록한 경로를 JVM은 참조해라" 라고 알려주는 것이라 보면 된다. 

 

윈도우 검색창에서 "시스템 환경 변수"라고 입력하면 아래와 같은 아이콘이 나타난다.

 

 

이 아이콘을 클릭하면 우측 하단에 환경 변수 편집이라는 버튼이 있는데 클릭해보자. 클릭하면 상단의 사용자 변수에 여러 내용이 등록된 것이 보일 것이다. 

 

 

필자처럼 classpath 변수가 등록된 분들도 있을 것이고 아닌 분들도 있을 것인데, 이 변수가 없는 경우 새로 만들기 버튼을, 그렇지 않은 경우 classpath 변수를 선택하고 편집 버튼을 누르자.

 

그럼 각 변수에서 참조하는 경로가 목록 형태로 나타나는데, 여기에 생성한 jar 파일의 경로를 입력해주자. 입력이 완료되면 확인 및 적용 버튼을 눌러 변경 사항을 저장하자.

 

 

 

여기까지 작업이 완료되었다면 OS를 재부팅하자(되도록이면 재부팅 없이 변수 등록을 하고 싶은데 마땅한 방법이 없다. 경로가 일반적인 곳이 아니라 그런가...). 재부팅 후, cmd 창에서 아래의 명령어로 classpath에 생성한 jar 파일 경로가 잘 들어가 있는지 확인하자. 

 

 

이제 InputAccount.java 파일이 위치한 곳으로 이동하여 javac 명령어로 다시 컴파일을 진행해보자. 재부팅 전에는 컴파일이 불가하던 것이 말끔하게 해결되었음을 확인할 수 있다.

 

 

 

다시 Main 클래스를 실행하면, 패키지 폴더 구성 전과 동일한 형태의 결과가 나타남을 확인할 수 있다. 이미 환경변수로 등록한 jar 파일에 encrypt 패키지가 포함되어 있는 상태이기 때문에 기존의 jartest 폴더의 encrypt 폴더는 삭제하더라도 동작에 문제가 없다(당연한 이야기지만 encrypt.jar 파일이 삭제되는 순간 동작에 문제가 생긴다).

 

 

 


 

 

jar 파일은 자주 참조되는, 그리고 기능별로 묶인 패키지를 아카이브 형태로 압축한 것이라 보면 된다. 자주 사용하는 기능이면서 제대로 동작하는 파일들이 jar에 포함되어 있다면 단순히 jar 파일을 참조하도록 만들기만 해도, 여러 프로그램을 단 시간에 만드는 것도 가능하게 된다.

 

jar 파일을 생성하면 manifest라는 파일이 자동으로 생성되는데, 시간이 된다면 다음 번에는 jar 파일의 manifest 파일에 대해 알아보려 한다. 

 

 

 

Fin.

반응형

댓글