2017년 7월 4일 화요일

[Java] 패키지(Package)의 개념

자바에서 패키지(Package)란 클래스들의 모음이다. 패키지를 통해 편리하게 프로젝트를 관리할 수 있고 내 코드들을 다른 라이브러리로부터, 또 다른 라이브러리들끼리 서로 구분가능하다. 기본적인 자바 라이브러리 또한 java.lang, java.util. java.net java.awt와 같은 다양한 패키지들를 통해 분류된다. 자바 라이브러리는 우리가 일반 폴더 구조에서 볼수있는 계층적 패키지구조를 가지고 있다. 상위 패키지에 하위패키지가 종속되는 형식이다. 그래서 모든 자바 패키지들은 가장 상위 패키지인 java와 javax 패키지에 종속되어 있다.

패키지(Package)를 사용하는 가장 큰 이유는 클래스명의 고유성을 보장하기 위해서이다. 만약 다른 두 프로그래머가 서로 다른 목적을 가진 클래스를 생성했는데 이름 같다 가정할 때, 서로 다른 패키지를 사용함으로써 충돌을 피할수 있다. 그리고 패키지 이름의 고유성을 보장하기 위해 최상위 패키지명에 "com.muckycode"와 같은 방식으로 인터넷 도메인 주소를 꺼꾸로 사용하기도 한다. 인터넷 도메인은 이미 고유성을 가지고 있기때문에 다른 충돌을 걱정할 필요가 없기 때문이다.

클래스는 같은 패키지내 모든 클래스들과 다른 패키지내 모든 public 클래스들을 사용할수있다. 다른 클래스를 사용하는데는 2가지 방법이 있다.
하나는 클래스 선언전 import 키워들 이용해서 패키지 전부 또는 클래스 1개만을 가져와 사용하는것과, 패키지 전체 주소를 가져와 사용하는것이다.


// 패키지 주소 전체를 이용하는 방식

java.util.Date today = new java.util.Date();
java.util.Date yesterday = new java.util.Date();
위방식은 클래스 사용시마다 매번 주소를 입력해야되기 때문에 엄청 귀찮다. 그래서 보통은 import 방식을 쓰게된다.


// import 키워드를 이용하는 방식

import java.util.*
import java.math.BigInteger;

public class Test {
...
}

import 방식은 하나의 클래스에만 적용가능하지만, * 문자를 이용해서 패키지의 모든 하위 클래스에도 적용이 가능하다.
import 방식을 이용하는것은 편리하지만, 만약 서로다른 패키지가 같은 이름을 가진 클래스를 가지고 있다면 이는 컴파일시 에러로 이어진다. 컴파일러가 무슨 클래스를 로드해야될지 모르기 때문인데, 이를 피할려면 특정 클래스의 주소를 import하는 방식을 사용해야한다. 만약 같은 이름을 가진 클래스들을 모두 사용해야한다면 패키지 전체 주소를 이용하는 방식을 사용해야한다. 예를들면 Date라는 클래스는 java.util 패키지에도 존재하고, java.sql 패키지에도 존재한다. 두 패키지를 모두 사용한다는 가정하에 import 방식을 이용하면


import java.util.*;
import java.sql.*;

public class Test {

 public static void main(String[] args) {
  Date newDate = new Date();
 }
}
// Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
// The type Date is ambiguous
// The type Date is ambiguous

위와 같은 컴파일 에러를 얻게된다. 그래서 이럴때는 import 방식 말고 전체 주소를 이용하는 방식을 이용해야한다.


java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(0);
}

import 방식은 static 클래스, 메소드, 데이터 필드들도 적용이 가능하다.
자주쓰는 System.out 객체는 static 클래스인 System을 import 하거나, static 객체인 System.out을 import하여 간소화할수 있다.


import static java.lang.System.out;
import static java.lang.Math.*;
public class Test {

 public static void main(String[] args) {
  out.println("Test"); //Test
  double x = sqrt(2); // Math.sqrt(2)가 간소화됐다.
  out.println(x); // 1.4142135623730951
 }
}
}

클래스를 패키지에 종속시키려면 클래스 선언전에 package 키워드를 이용해 어떤 패키지에 속해있는지 정해줘야한다. 만약 정해주지 않는다면, 클래스는 기본적으로 "default package"에 속하게 되고 "default package"는 아무런 패키지 이름을 가지지 않는다. 그리고 해당 클래스를 파일 디렉토리상으로도 패키지 구조와 일치하게 이동해야 한다.


package com.muckycode.java.app

public class myMathApp {
...
}

위 클래스는 com.muckycode.java.app 패키지에 속하게 되고, com폴더 -> muckycode폴더 -> java폴더 -> app폴더 내에 존재해야한다.

댓글 3개: