[Java] 김영한의 실전 자바 기본편 - #5 패키지
[김영한의 실전 자바 - 기본편↗️]을 듣고 정리한 글입니다.
1. 패키지 개념
1.1 패키지 개념
자바에서 패키지(package)는 클래스들을 논리적으로 분류하고 그룹화하는 방법이다.
- 프로그램이 작을 때는 모든 클래스를 하나의 폴더에 넣어도 관리가 가능하지만, 규모가 커지면 클래스가 많아지고 복잡해져서 유지보수가 어려워진다.
- 이때 관련 있는 클래스들을 패키지로 묶어서 관리하면 더 체계적이고 효율적인 코드 관리를 할 수 있다.
- 즉, 컴퓨터는 보통 파일을 분류하기 위해 폴더, 디렉토리라는 개념을 제공한다. 자바도 이런 개념을 제공하는데, 이것이 바로 패키지인 것이다.
1.2 패키지 장점
- 코드 분류: 기능별로 클래스를 그룹화하여 코드가 잘 정리된다.
- 이름 충돌 방지: 같은 이름의 클래스를 서로 다른 패키지에서 사용할 수 다.
- 접근 제어: 패키지를 기반으로 접근 제어가 가능하다. (예: default 접근 제어는 같은 패키지에서만 접근 가능)
1.3 패키지가 필요한 이유
작은 프로그램과 큰 프로그램
- 작은 프로그램에서는 몇 개의 클래스만 있어도 문제없지만, 프로그램이 커지면 수십 개의 클래스로 확장될 수 있다.
- 아래처럼 클래스가 많아질 경우 관련된 관련 있는 기능들을 분류해서 관리하기 위해 패키지를 사용한다.
// 작은 프로그램 예시
Order
User
Product
// 큰 프로그램 예시
User
UserManager
UserHistory
Product
ProductCatalog
ProductImage
Order
OrderService
OrderHistory
ShoppingCart
CartItem
Payment
PaymentHistory
Shipment
ShipmentTracker
1.4 패키지의 분류
아래와 같이 카테고리를 만들고 분류해보자.
소핑몰 시스템 예시
* user
* User
* UserManager
* UserHistory
* product
* Product
* ProductCatalog
* ProductImage
* order
* Order
* OrderService
* OrderHistory
* cart
* ShoppingCart
* CartItem
* payment
* Payment
* PaymentHistory
* shipping
* Shipment
* ShipmentTracker
- 위에서
user
,product
등이 바로 패키지이다. 그리고 해당 패키지 안에 관련된 자바 클래스들을 넣으면 된다. - 위처럼 관련 있는 클래스들을 같은 패키지에 그룹화하면 프로그램을 더 쉽게 이해하고 유지보수할 수 있다.
2. 패키지 사용
2.1 패키지 사용 방법
패키지를 사용하려면 패키지를 먼저 만들고 그 다음에 클래스를 만들어야 한다.
- 패키지를 사용하는 경우 항상 코드 첫줄에
package pack
과 같이 패키지 이름을 적어주어야 한다.
패키지 생성 및 클래스 작성 예시
- 먼저,
pack
이라는 패키지를 만들고 그 안에Data
클래스를 작성하자. - 이후에
Data
인스턴스가 생성되면 생성자를 통해 정보를 출력한다.
// 파일: Data.java
package pack;
public class Data {
public Data() {
System.out.println("패키지 pack Data 생성");
}
}
- 그 다음,
pack.a
패키지를 만들고User
클래스를 추가하자. - 이후에
User
인스턴스가 생성되면 생성자를 통해 정보를 출력한다.
// 파일: User.java
package pack.a;
public class User {
public User() {
System.out.println("패키지 pack.a 회원 생성");
}
}
2.2 패키지 사용 예시
이제
PackageMain1
이라는 클래스를 만들어 위에서 만든Data
와User
클래스를 사용해보자
// 파일: PackageMain1.java
package pack;
public class PackageMain1 {
public static void main(String[] args) {
Data data = new Data(); // 같은 패키지 내 클래스 사용
pack.a.User user = new pack.a.User(); // 다른 패키지의 클래스 사용
}
}
위 예시에서, Data
클래스는 pack
패키지에 있으므로 패키지 경로를 생략할 수 있지만, User
클래스는 pack.a
패키지에 있으므로 패키지 경로를 포함해야 한다.
2.3 패키지 경로를 포함한 클래스 사용
서로 다른 패키지에 있는 클래스를 사용할 때는 패키지 경로를 포함해 클래스 이름을 사용해야 한다.
예를 들어, pack.a.User
와 같은 식으로 패키지 경로를 명시한다.
패키지 pack Data 생성
패키지 pack.a 회원 생성
3. 패키지와 import
3.1 import
패키지가 다를 경우 클래스의 패키지 경로를 항상 작성하는 것은 번거로울 수 있다.
이를 해결하기 위해 import
를 사용하면 패키지 이름 없이 클래스 이름만으로도 접근할 수 있다..
package pack;
import pack.a.User; // pack.a 패키지의 User 클래스를 가져옴
public class PackageMain2 {
public static void main(String[] args) {
Data data = new Data(); // 같은 패키지에 있는 클래스는 import 없이 사용 가능
User user = new User(); // import 덕분에 패키지 이름 없이 사용 가능
}
}
실행 결과
패키지 pack Data 생성
패키지 pack.a 회원 생성
이 코드에서 import
문 덕분에 pack.a.User
클래스를 패키지 경로 없이 User
로 간단히 사용할 수 있다.
3.2 모든 클래스 import하기 (* 사용)
특정 패키지 내에 있는 모든 클래스를 사용하고 싶을 때는
*
기호를 사용할 수 있다.
이는 해당 패키지에 있는 모든 클래스를 자동으로 import하게 해준다.
package pack;
import pack.a.*; // pack.a 패키지의 모든 클래스를 가져옴
public class PackageMain2 {
public static void main(String[] args) {
Data data = new Data();
User user = new User(); // pack.a의 User 클래스
}
}
- 이처럼
*
를 사용하면 해당 패키지에 속한 모든 클래스를 사용할 수 있지만,*
는 남용하지 않도록 주의하는 것이 좋다. - 필요한 클래스만 명시적으로
import
하는 것이 더 권장되기 때문이다.
3.3 클래스 이름 중복 문제
서로 다른 패키지에 같은 이름의 클래스가 있을 수 있다. (ex:
pack.a.User
와pack.b.User
)
이때 import
는 하나의 User
클래스만 선택할 수 있으며, 다른 User
는 패키지 경로 전체를 명시해서 사용해야 한다.
package pack;
import pack.a.User; // pack.a의 User 클래스만 import
public class PackageMain3 {
public static void main(String[] args) {
User userA = new User(); // pack.a.User
pack.b.User userB = new pack.b.User(); // pack.b.User는 경로를 명시하여 사용
}
}
이 경우, pack.a.User를 자주 사용하므로 import로 가져오고, pack.b.User는 패키지 전체 경로를 사용하여 명시적으로 사용한다.
4. 패키지의 규칙
4.1 패키지 규칙
- 패키지 이름과 디렉토리 구조 일치: 패키지 이름과 실제 파일의 디렉토리 구조가 동일해야 한다.
- 패키지 이름 소문자 사용: 패키지 이름은 일반적으로 소문자로 작성하는 것이 관례이다.
- 도메인 이름을 활용한 패키지 네이밍: 큰 프로젝트나 외부 라이브러리를 제공할 때는 충돌 방지를 위해 도메인 이름을 거꾸로 사용한다. (ex: com.company.project)
4.2 패키지의 계층 구조
패키지는 계층 구조로 구성될 수 있지만, 계층이 깊다고 해서 패키지 간에 특별한 연결이 있는 것은 아니다. 모든 패키지는 서로 독립적인 존재이다.
계층 구조 예시
a
a.b
a.c
- 위와 같이 a 패키지와 그 하위 패키지인 a.b, a.c가 존재할 수 있다.
- 하지만 자바는 패키지가 계층 구조로 되어 있다고 해서 하위 패키지를 자동으로 인식하지는 않으며, 필요한 패키지나 클래스를 직접 import해야 한다.
5. 패키지의 활용
5.1 패키지 활용 예시
패키지를 사용하여 프로젝트를 구성하는 것은 큰 애플리케이션에서 필수적이다.
쇼핑몰 애플리케이션의 구조를 예시로 패키지를 어떻게 사용할 수 있는지 살펴보자.
com.helloshop
├── user
│ ├── User
│ └── UserService
├── product
│ ├── Product
│ └── ProductService
└── order
├── Order
├── OrderService
└── OrderHistory
- 이 구조에서 com.helloshop이라는 상위 패키지 아래에 user, product, order 패키지가 있고, 각각의 패키지에 해당 도메인과 관련된 클래스들이 있다.
- 이와 같이 프로젝트의 기능별로 패키지를 나누는 것이 일반적이다.
5.2 com.helloshop.user 패키지
사용자 관련 기능들을 담당하는
user
패키지이다.
User
클래스
package com.helloshop.user;
public class User {
String userId;
String name;
public User(String userId, String name) {
this.userId = userId;
this.name = name;
}
// 사용자 정보 출력 메서드
public void printUserInfo() {
System.out.println("User ID: " + userId + ", Name: " + name);
}
}
UserService
클래스
package com.helloshop.user;
public class UserService {
public void createUser() {
User user = new User("123", "John Doe");
user.printUserInfo();
}
}
- UserService는 사용자 생성과 관련된 서비스 로직을 처리하는 클래스이다.
- 주로 사용자 등록, 수정, 삭제 등의 로직이 여기에 포함될 수 있다.
5.3 com.helloshop.product 패키지
제품 관련 기능들을 담당하는
product
패키지이다.
Product
클래스
package com.helloshop.product;
public class Product {
String productId;
int price;
public Product(String productId, int price) {
this.productId = productId;
this.price = price;
}
// 제품 정보 출력 메서드
public void printProductInfo() {
System.out.println("Product ID: " + productId + ", Price: " + price);
}
}
ProductService
클래스
package com.helloshop.product;
public class ProductService {
public void createProduct() {
Product product = new Product("A001", 20000);
product.printProductInfo();
}
}
ProductService는 상품 생성, 수정, 삭제 등의 기능을 담당하는 서비스 클래스이다.
5.4 com.helloshop.order 패키지
주문 관련 기능들을 담당하는
order
패키지이다. 이 패키지는 사용자와 상품을 기반으로 주문을 처리한다.
Order
클래스
package com.helloshop.order;
import com.helloshop.product.Product;
import com.helloshop.user.User;
public class Order {
User user;
Product product;
public Order(User user, Product product) {
this.user = user;
this.product = product;
}
// 주문 정보 출력 메서드
public void printOrderInfo() {
System.out.println("Order placed by: " + user.name + " for product: " + product.productId);
}
}
OrderService
클래스
package com.helloshop.order;
import com.helloshop.product.Product;
import com.helloshop.user.User;
public class OrderService {
public void order() {
User user = new User("123", "John Doe");
Product product = new Product("A001", 20000);
Order order = new Order(user, product);
// 주문 정보 출력
order.printOrderInfo();
}
}
- 이 클래스는 사용자와 제품을 기반으로 주문을 생성하는 서비스 로직을 처리한다.
- OrderService는 User, Product, Order 클래스를 사용하여 주문을 생성한다.
5.5 OrderHistory 클래스
OrderHistory는 주문 내역을 관리하는 클래스이. 주문 기록을 저장하고 조회하는 기능이 여기에 포함될 수 있다.
OrderHistory
클래스
package com.helloshop.order;
public class OrderHistory {
// 주문 내역을 관리하는 클래스
}
이처럼 패키지를 구성할 때 서로 관련된 클래스는 하나의 패키지에 모으고, 관련이 적은 클래스는 다른 패키지로 분리하는 것이 좋다.
댓글남기기