ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바컴파일 - javac 명령어/옵션 사용법 및 문제해결 (Feat. 스프링부트)
    IT/Java 2019. 12. 8. 20:30

    #잡설

     

    요즘은 컴파일 이라고하면 IDE툴[이클립스,인텔리제이...]이 멋지게, 그리고 부가기능까지 합쳐져서 사용자의 입맛에 따른 모양새로 컴파일을 해서 빌드해준다. Jar든 War든 runnable Jar든...

    그러나 자바의 컴파일은 원초적으로 이클립스든 뭐가됐든 IDE툴에서 PC에 설치된 JAVA의 경로에서 javac라는 파일을 가져다가 툴 내부적으로 javac라는 명령어를 이용해서 컴파일한다.

     

    우리는 모두 IDE툴을 이용해서 빌드를 통해 컴파일을 하지만, 운영유지를 하다보면 이미 리눅스에 톰캣으로 올려 서비스중인 SpringBoot 프로젝트의 소스를 수정해야하는 상황이 생기기 마련이다.

    사실 원론적으로는 단 한 하나의 문자열을 수정하더라도 IDE툴을 이용해 수정하고, git과 같은 버전관리프로그램에 기록한 뒤 재 빌드를 하여 정식적으로 소스를 새로 배포하는게 맞는 구조이고, 또 그렇게 하길 권장하며, 아주 복잡한 체계가 잡힌 회사에서는 단 하나의 문자열을 바꾸는것 조차 리뷰와 컨펌을 받아야만 반영할 수 있는 회사도 많다.

     

     

    그러나, 일반적으로는 그러지 못하는 순간들이 많다.

    여러가지 여건 상황으로 인해 리눅스에 직접 접근하여 vi를 이용해 JAVA파일을 수정하고 재컴파일을 해야하는 순간들이 존재하는데, 그때 javac를 사용하기 위해 간단한 예시들을 찾아보면 아래처럼 설명한다.

    vi편집기나 메모장을 통해 HelloWorld.java 를 만들어서 리눅스에 갖다놓고, javac HelloWorld.java 라고 입력하면  HelloWorld.java 파일 내 문법적인 오류가 없을 시 HelloWorld.class 라는 파일이 만들어 집니다.

     

    그!러!나 우리 신입이들이 실제 회사에서 서비스하고있는 소스에다가 javac 명령어로 컴파일을 해보려하면 분명히 문법상 오류가 없는 파일인데도 불구하고 온갖 에러가 발생하며 컴파일되지 않는다. (나만 그랬나...?)

    왜그런지, 어떤 에러는 무엇이 잘못된건지 차근차근 살펴보자.

     

     


    #본론

    우선 javac의 생김새는 아래처럼 생겼다.

    javac <option> <source files>

     

    option 중에서는 가장 중요한 classpath 하나에 대해서만 작성한다.

    그외의 옵션은 써본적도 없고 필요할때 찾아보면 된다.

     

    -classpath (-cp) :

    컴파일러가 컴파일 할때 필요로하는 라이브러리나 클래스들의 경로를 지정해주는 옵션이다.

     

    스프링 프로젝트에서  리눅스에서 직접 javac로 컴파일 할 때 classpath를 설정해주지 않으면 아래와 같이 does not exist 라며 뭐가 자꾸 없다고한다.

    ...
    error: package ????.????? does not exist
    error: package ???.????.?????? does not exist
    error: package ???.??.????? does not exist
    ....

     

    보통 스프링인 경우 gradle이나 maven 등으로 외부라이브러리 등을 의존하는 프로젝트가 대부분이므로 java파일 최상단에 외부라이브러리를 import 하고 있기 때문에 classpath 옵션을 이용해서 컴파일할때 필요한 클래스들의 경로를 지정해주지 않으면 위와같은 에러들이 발생하며 컴파일되지 않는다.

     

    그럴땐 javac -classpath lib경로/* java파일 로 입력해주면 된다.

    아래 예시를 참조.

    javac -classpath 프로젝트경로/WEB-INF/lib/* 프로젝트경로/WEB-INF/classes/SomeFile.java

    절대경로로 입력하든, 상대경로로 입력하든 시스템이 찾아갈수있게끔만 지정해주면 된다.

     

     

     

     

     

    위와 별개로 아래와 같은 에러가 발생한다면...

    error: package javax.servlet does not exist
    error: package javax.servlet.annotation does not exist
    error: package javax.servlet.http does not exist

    해당 클래스들은 tomcat의 lib 안에 있는 server-api.jar 에 포함된 클래스들이다.

    위 classpath 옵션에 프로젝트의 lib 경로와 톰캣의 lib 경로를 모두 참조시켜주면 되는데 : 문자로 이어나간다.

    아래의 예시를 참조.

    javac -classpath 프로젝트경로/WEB-INF/lib/*:톰캣경로/lib/* 프로젝트경로/WEB-INF/classes/SomeFile.java

     

     

     

     

     

    만약 classpath까지 다 설정해주어 대부분의 에러가 사라졌는데, 맨 마지막까지 아래 에러가 남아있다면...

    error: cannot find symbol

     javac 커맨드를 입력하는 위치를 잘 살펴보아야 한다.

    위 에러는 변수같은게 선언되지 않았을때 발생하는 에러이다.

    만약 프로젝트의 경로가 아래와 같이 되어있다고 가정해보자.

     

     

     

    즉 위 환경에서 service 파일인 SomeService.java 파일을 수정하려고 하는데 해당 파일안에 controller파일을 import 하는 import com.test.controller.SomeController  라는 소스가 있을 경우, javac를 입력해야 하는 위치는 classess 폴더상에서 입력해야 소스상의 com.test.... 라는 경로가 올바른 경로가 되는것이다.

     

    개발을 하다보면 수많은 에러와 접견하겠지만, 우선 기본적으로 이 classpath만 잘 이해하고 입력해줘도 어지간하면 에러를 해결하고 문제를 해결할것이다.

     

     


    댓글

다치지 말고 운동하자.