소개
효과적인 프로젝트 구조는 성공적인 Java 개발에 매우 중요합니다. 이 포괄적인 가이드는 Java 프로젝트를 구성하는 기본 원리를 탐구하여, 개발자에게 확장 가능하고, 유지 관리 가능하며, 잘 구조화된 소프트웨어 솔루션을 만드는 데 대한 실질적인 통찰력을 제공합니다.
기본 Java 프로젝트 구조 생성
Java 프로젝트는 개발자가 코드를 효과적으로 관리하는 데 도움이 되는 특정 조직 규칙을 따릅니다. 이 단계에서는 기본 구성 요소를 이해하기 위해 간단한 Java 프로젝트 구조를 수동으로 생성합니다.
Java 프로젝트 구성 요소 이해
Java 프로젝트는 일반적으로 다음을 포함합니다.
- 소스 코드 파일 (
.java) - 컴파일된 바이트코드 파일 (
.class) - 리소스 파일 (구성, 이미지 등)
- 문서
간단한 프로젝트 구조 생성
작업 공간에서 기본 프로젝트 구조를 생성하는 것으로 시작해 보겠습니다. 개념을 설명하기 위해 간단한 "HelloWorld" 애플리케이션을 빌드합니다.
먼저, LabEx 환경에서 터미널을 엽니다. 터미널은 이미
/home/labex/project디렉토리에 있어야 합니다.Java 애플리케이션을 위한 프로젝트 디렉토리를 생성합니다.
mkdir -p hello-java-app/src
cd hello-java-app
src디렉토리 내에 간단한 Java 클래스 파일을 생성합니다.
mkdir -p src/com/example/app
- 이제 첫 번째 Java 클래스를 생성해 보겠습니다. 코드 편집기를 열고
hello-java-app/src/com/example/app/경로에HelloWorld.java라는 새 파일을 생성합니다.
package com.example.app;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java Project World!");
}
}
- 이 Java 코드를 컴파일해 보겠습니다. 터미널에서 프로젝트 루트로 다시 이동하여 다음을 실행합니다.
cd /home/labex/project/hello-java-app
mkdir -p bin
javac -d bin src/com/example/app/HelloWorld.java
컴파일이 성공하면 출력에 오류가 표시되지 않아야 합니다.
- 이제 컴파일된 Java 애플리케이션을 실행합니다.
java -cp bin com.example.app.HelloWorld
다음 출력을 볼 수 있습니다.
Hello, Java Project World!
프로젝트 구조 이해
생성한 내용을 검토해 보겠습니다.
hello-java-app/
├── bin/ ## 컴파일된 바이트코드 (.class 파일)
│ └── com/
│ └── example/
│ └── app/
│ └── HelloWorld.class
└── src/ ## 소스 코드 (.java 파일)
└── com/
└── example/
└── app/
└── HelloWorld.java
이 구조는 다음 원칙을 따릅니다.
- 소스 코드 분리: 모든 Java 소스 파일은
src디렉토리에 있습니다. - 패키지 구조:
com.example.app패키지는com/example/app/디렉토리에 해당합니다. - 컴파일된 코드 분리: 바이트코드 파일은 별도의
bin디렉토리에 있습니다.
핵심 개념
- 패키지 (Packages): Java 는 클래스를 구성하고 이름 충돌을 방지하기 위해 패키지를 사용합니다.
- 디렉토리 구조 (Directory structure): 패키지 이름은 디렉토리 구조에 직접 매핑됩니다.
- 클래스패스 (Classpath):
-cp플래그는 Java 에 컴파일된 클래스를 찾을 위치를 알려줍니다.
이제 기본 Java 프로젝트 구조를 수동으로 생성했습니다. 이 기반은 실제 애플리케이션에서 사용되는 더 복잡한 프로젝트 구조를 이해하는 데 도움이 됩니다.
패키지를 사용하여 Java 코드 구성
이 단계에서는 패키지를 사용하여 Java 코드를 구성하고 여러 클래스를 사용하여 더 구조화된 애플리케이션을 만드는 방법을 배웁니다. 유지 관리 가능한 Java 프로젝트를 위해서는 적절한 패키지 구성이 필수적입니다.
패키지 규칙 이해
Java 패키지는 계층적 명명 규칙을 따릅니다.
- 도메인 이름으로 시작 (예:
com.example) - 프로젝트 또는 조직 이름 추가 (예:
com.example.project) - 기능 영역 추가 (예:
com.example.project.model)
프로젝트에서 이 구조를 구현해 보겠습니다.
다중 패키지 프로젝트 생성
다양한 관심사를 위한 별도의 패키지를 사용하여 간단한 도서관 관리 시스템을 구축합니다.
- 프로젝트 디렉토리로 이동합니다.
cd /home/labex/project
mkdir -p library-app/src
cd library-app
- 구조화된 패키지 레이아웃을 생성합니다.
mkdir -p src/com/example/library/model
mkdir -p src/com/example/library/service
mkdir -p src/com/example/library/util
- 먼저, 모델 클래스를 생성합니다. 코드 편집기를 열고
library-app/src/com/example/library/model/경로에Book.java라는 새 파일을 생성합니다.
package com.example.library.model;
public class Book {
private String title;
private String author;
private int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
// Getters
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getYear() {
return year;
}
@Override
public String toString() {
return "Book{title='" + title + "', author='" + author + "', year=" + year + "}";
}
}
- 다음으로,
library-app/src/com/example/library/service/BookService.java에 서비스 클래스를 생성합니다.
package com.example.library.service;
import com.example.library.model.Book;
import java.util.ArrayList;
import java.util.List;
public class BookService {
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
public List<Book> getAllBooks() {
return new ArrayList<>(books);
}
public Book findBookByTitle(String title) {
for (Book book : books) {
if (book.getTitle().equalsIgnoreCase(title)) {
return book;
}
}
return null;
}
}
library-app/src/com/example/library/util/BookFormatter.java에 유틸리티 클래스를 생성합니다.
package com.example.library.util;
import com.example.library.model.Book;
public class BookFormatter {
public static String formatBookInfo(Book book) {
return String.format("'%s' by %s (%d)",
book.getTitle(), book.getAuthor(), book.getYear());
}
}
- 마지막으로,
library-app/src/com/example/library/LibraryApp.java에 메인 애플리케이션 클래스를 생성합니다.
package com.example.library;
import com.example.library.model.Book;
import com.example.library.service.BookService;
import com.example.library.util.BookFormatter;
public class LibraryApp {
public static void main(String[] args) {
// Create service
BookService bookService = new BookService();
// Add some books
bookService.addBook(new Book("The Great Gatsby", "F. Scott Fitzgerald", 1925));
bookService.addBook(new Book("To Kill a Mockingbird", "Harper Lee", 1960));
bookService.addBook(new Book("1984", "George Orwell", 1949));
// Display all books
System.out.println("Library Catalog:");
for (Book book : bookService.getAllBooks()) {
System.out.println(BookFormatter.formatBookInfo(book));
}
// Find a specific book
Book foundBook = bookService.findBookByTitle("1984");
if (foundBook != null) {
System.out.println("\nFound book: " + foundBook);
}
}
}
- 모든 Java 파일을 컴파일합니다.
mkdir -p bin
javac -d bin src/com/example/library/model/Book.java src/com/example/library/service/BookService.java src/com/example/library/util/BookFormatter.java src/com/example/library/LibraryApp.java
- 애플리케이션을 실행합니다.
java -cp bin com.example.library.LibraryApp
다음 출력을 볼 수 있습니다.
Library Catalog:
'The Great Gatsby' by F. Scott Fitzgerald (1925)
'To Kill a Mockingbird' by Harper Lee (1960)
'1984' by George Orwell (1949)
Found book: Book{title='1984', author='George Orwell', year=1949}
패키지 구조 이해
생성한 구조를 살펴보겠습니다.
library-app/
├── bin/ ## 컴파일된 바이트코드
└── src/ ## 소스 코드
└── com/
└── example/
└── library/
├── model/ ## 데이터 구조
│ └── Book.java
├── service/ ## 비즈니스 로직
│ └── BookService.java
├── util/ ## 유틸리티 함수
│ └── BookFormatter.java
└── LibraryApp.java ## 메인 애플리케이션
패키지 구성 원칙
이 구조는 중요한 설계 원칙을 따릅니다.
관심사 분리 (Separation of Concerns):
model패키지: 데이터 구조를 포함합니다.service패키지: 비즈니스 로직을 포함합니다.util패키지: 유틸리티 함수를 포함합니다.
논리적 그룹화 (Logical Grouping): 관련 클래스는 동일한 패키지에 함께 그룹화됩니다.
직관적인 탐색 (Intuitive Navigation): 패키지 구조를 통해 특정 기능을 쉽게 찾을 수 있습니다.
Import 관리: 클래스는 import 를 통해 서로 참조하여 종속성을 명확하게 합니다.
이러한 방식으로 코드를 구성하면 이해하고 확장하기 쉬운, 더 유지 관리 가능하고 확장 가능한 애플리케이션을 만들 수 있습니다.
Maven 을 사용한 프로젝트 관리
이 단계에서는 Apache Maven 을 사용하여 Java 프로젝트를 관리하는 방법을 배웁니다. Maven 은 프로젝트 설정 및 유지를 단순화하는 강력한 빌드 자동화 및 종속성 관리 도구입니다.
Maven 이해
Maven 은 다음을 제공합니다.
- 표준 프로젝트 구조
- 종속성 관리
- 빌드 자동화
- 프로젝트 정보 관리
- 프로젝트 간 일관된 빌드 프로세스
Maven 프로젝트 설정
Maven 을 사용하여 새 프로젝트를 만들어 보겠습니다.
- 먼저, Maven 이 설치되었는지 확인합니다.
mvn --version
다음과 유사한 출력을 볼 수 있습니다.
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-1036-azure", arch: "amd64", family: "unix"
- 프로젝트 디렉토리로 이동합니다.
cd /home/labex/project
- archetype (프로젝트 템플릿) 을 사용하여 새 Maven 프로젝트를 생성합니다.
mvn archetype:generate \
-DgroupId=com.example.calculator \
-DartifactId=simple-calculator \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
이 명령은 표준 디렉토리 구조를 가진 새 프로젝트를 생성합니다.
- 프로젝트 구조를 검토합니다.
cd simple-calculator
ls -la
다음과 유사한 출력을 볼 수 있습니다.
total 24
drwxr-xr-x 4 labex labex 4096 ... .
drwxr-xr-x 6 labex labex 4096 ... ..
-rw-r--r-- 1 labex labex 174 ... .gitignore
-rw-r--r-- 1 labex labex 720 ... pom.xml
drwxr-xr-x 4 labex labex 4096 ... src
여기서 핵심 파일은 프로젝트 구성을 정의하는 pom.xml (Project Object Model) 입니다.
- Maven 표준 디렉토리 레이아웃을 검토합니다.
find src -type d
다음과 같은 출력을 볼 수 있습니다.
src
src/main
src/main/java
src/main/java/com
src/main/java/com/example
src/main/java/com/example/calculator
src/test
src/test/java
src/test/java/com
src/test/java/com/example
src/test/java/com/example/calculator
이것이 Maven 표준 디렉토리 레이아웃입니다.
src/main/java: 소스 코드src/main/resources: 리소스 파일src/test/java: 테스트 코드src/test/resources: 테스트 리소스
- 생성된
App.java파일을 살펴보겠습니다.
cat src/main/java/com/example/calculator/App.java
간단한 "Hello World" 클래스를 볼 수 있습니다.
package com.example.calculator;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
Maven 프로젝트 향상
더 많은 클래스를 추가하여 계산기 프로젝트를 향상시켜 보겠습니다.
src/main/java/com/example/calculator/에Calculator.java라는 새 파일을 생성합니다.
package com.example.calculator;
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
public int multiply(int a, int b) {
return a * b;
}
public double divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
return (double) a / b;
}
}
- 이제 기존
App.java파일을 수정하여 Calculator 클래스를 사용합니다.
package com.example.calculator;
/**
* Simple Calculator Application
*/
public class App
{
public static void main( String[] args )
{
Calculator calculator = new Calculator();
// Perform some calculations
System.out.println("Addition: 5 + 3 = " + calculator.add(5, 3));
System.out.println("Subtraction: 10 - 4 = " + calculator.subtract(10, 4));
System.out.println("Multiplication: 6 * 7 = " + calculator.multiply(6, 7));
System.out.println("Division: 20 / 4 = " + calculator.divide(20, 4));
System.out.println("Calculator application completed successfully!");
}
}
- Maven 을 사용하여 프로젝트를 빌드합니다.
mvn compile
다음으로 끝나는 출력을 볼 수 있습니다.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
- 애플리케이션을 JAR 파일로 패키징합니다.
mvn package
이 명령은 코드를 컴파일하고, 테스트를 실행하고, 애플리케이션을 패키징합니다.
- 패키징된 애플리케이션을 실행합니다.
java -cp target/simple-calculator-1.0-SNAPSHOT.jar com.example.calculator.App
다음 출력을 볼 수 있습니다.
Addition: 5 + 3 = 8
Subtraction: 10 - 4 = 6
Multiplication: 6 * 7 = 42
Division: 20 / 4 = 5.0
Calculator application completed successfully!
Maven POM 파일 이해
Project Object Model (POM) 파일에는 프로젝트 구성이 포함되어 있습니다. 편집기에서 pom.xml 파일을 열고 구조를 검토합니다.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.calculator</groupId>
<artifactId>simple-calculator</artifactId>
<version>1.0-SNAPSHOT</version>
<name>simple-calculator</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Build configuration... -->
</project>
POM 파일의 주요 요소:
groupId: 조직 또는 프로젝트 식별자artifactId: 프로젝트 이름version: 프로젝트 버전dependencies: 프로젝트에서 사용되는 외부 라이브러리build: 프로젝트 빌드 구성
Maven 주요 명령어
다음은 몇 가지 필수 Maven 명령어입니다.
mvn compile: 소스 코드 컴파일mvn test: 테스트 실행mvn package: 배포 가능한 패키지 생성 (JAR, WAR)mvn install: 로컬 저장소에 패키지 설치mvn clean: 빌드 아티팩트 제거 (target 디렉토리)mvn clean install: clean 및 install 의 조합
Maven 은 규칙, 종속성 관리 및 빌드 자동화를 제공하여 Java 프로젝트 관리를 크게 단순화했습니다. 이 표준화된 접근 방식은 개발자가 프로젝트 구조를 관리하는 대신 코드 작성에 집중할 수 있도록 돕습니다.
요약
이 Lab 에서는 실습을 통해 Java 프로젝트 구조를 관리하기 위한 필수적인 전략을 배웠습니다.
먼저, 소스 디렉토리, 패키지 및 컴파일된 코드 구성의 기본 구성 요소를 이해하면서 기본 Java 프로젝트 구조를 수동으로 생성하는 것으로 시작했습니다.
그런 다음, 모델, 서비스 및 유틸리티 패키지로 기능을 분할하여 관심사 분리를 구현하면서 적절한 패키지 구성으로 더 복잡한 프로젝트를 생성하는 단계로 나아갔습니다.
마지막으로, 종속성 관리 및 자동화된 빌드 프로세스를 통해 표준화된 Java 프로젝트를 생성하고 관리하기 위해 강력한 빌드 자동화 도구인 Maven 을 사용하는 방법을 배웠습니다.
이러한 기본적인 기술은 향후 Java 개발 작업의 견고한 기반이 될 것이며, 잘 구성되고 유지 관리 가능하며 확장 가능한 애플리케이션을 만들 수 있도록 해줍니다. 프로젝트 구조에 대한 확립된 규칙과 모범 사례를 따르면 다른 개발자와 보다 효과적으로 협업하고 더 높은 품질의 코드를 생성할 수 있습니다.



