학교에서 Java를 배울 때, 교수님이 어렴풋이 말씀하셨던 기억이 납니다. 이번 프로젝트에서의 문제를 반영하면서, 새벽 대기와 이른 출근에도 해결되지 않아 답답했던 기억이 남아 이 글을 작성해봅니다.
현재 제가 참여 중인 프로젝트에서 소스 코드 반영 시나리오는 아래와 같습니다.
.class 파일을 배포.class 파일을 반영이런 수기 배포 프로세스에서 static 변수의 사용은 굉장히 위험할 수 있습니다.
간단한 예제를 통해 살펴보겠습니다.
// StaticVariables.java
public class StaticVariables {
public static final String API_URL = "www.test.com";
public static final String API_KEY = "ㄱㄴㄷㄹㅁ12345abcde";
}
// Main.java
public class Main {
public static void main(String[] args) {
System.out.println(StaticVariables.API_URL);
System.out.println(StaticVariables.API_KEY);
}
}
이제 위 소스 코드를 빌드한 후, 디컴파일하여 내용을 확인해 보겠습니다.
IntelliJ IDEA에서 Build > Build Project 메뉴를 통해 프로젝트를 빌드한 후, /out/production/ 디렉터리로 이동하면 빌드된 파일을 볼 수 있습니다.
디컴파일된 StaticVariables.class 파일:
public class StaticVariables {
public static final String API_URL = "www.test.com";
public static final String API_KEY = "ㄱㄴㄷㄹㅁ12345abcde";
}
그리고 Main.class 파일도 확인해 보면:
public class Main {
public static void main(String[] args) {
System.out.println("www.test.com"); // 상수가
System.out.println("ㄱㄴㄷㄹㅁ12345abcde"); // 하드코딩 되어있다!
}
}
static 변수의 참조는 컴파일 시점에 이루어지기 때문에, API_KEY 값을 변경하고 StaticVariables.java만 수정 후 빌드해도 StaticVariables.class만 배포하면 다른 클래스에서는 변경 사항이 반영되지 않습니다. Main.java와 같이 참조하는 클래스도 함께 빌드하고 배포해야 합니다.
이처럼, static 변수의 참조는 컴파일 시점에 확정되기 때문에 static 변수를 포함하는 클래스뿐 아니라 이를 참조하는 모든 클래스도 동일하게 다시 컴파일 되어야 합니다.
static 변수 클래스를 참조하는 클래스가 더 많다면 어떨까요. 예를 들어, StaticVariables에 100개 이상의 변수가 있고 여러 파일에서 이를 참조한다고 가정해 봅시다. 참조 클래스가 1000개에 달할 경우, 모든 파일을 매번 수동으로 FTP 배포하는 것은 현실적으로 어려울 것입니다. 수정할 static 변수는 하나로, StaticVariables.class만 수정하면 될 거라고 예상할 수 있습니다. 그렇지만 사실 참조하는 클래스 모두 한데모아 빌드해야 하니 배포 효율성이 떨어질 수 밖에 없습니다.
이를 해결하기 위해 아래 두 가지 방안을 고려할 수 있습니다.
현재 프로젝트에서는 배포 환경을 바꾸기 쉽지 않기 때문에 static 변수 사용하는 클래스에 1차적으로 하드코딩하고, 이후 배포에서 Property로 관리하기로 결정했습니다.
static 변수가 암의 초기 종양처럼 느껴졌으며, 사용이 적을 때 수정할 수 있어 다행이라 생각했습니다. 지금의 배포 환경에 프로젝트 구석구석에 있다고 생각하면.. 정말 아찔합니다. enum도 컴파일 시 값이 고정된다하니, 유의해야겠습니다.
감사합니다.