소개
효과적인 프로젝트 구조는 성공적인 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
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!");
}
}
cd /home/labex/project/hello-java-app
mkdir -p bin
javac -d bin src/com/example/app/HelloWorld.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
이 구조는 다음 원칙을 따릅니다.
src 디렉토리에 있습니다.com.example.app 패키지는 com/example/app/ 디렉토리에 해당합니다.bin 디렉토리에 있습니다.-cp 플래그는 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);
}
}
}
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 를 통해 서로 참조하여 종속성을 명확하게 합니다.
이러한 방식으로 코드를 구성하면 이해하고 확장하기 쉬운, 더 유지 관리 가능하고 확장 가능한 애플리케이션을 만들 수 있습니다.
이 단계에서는 Apache Maven 을 사용하여 Java 프로젝트를 관리하는 방법을 배웁니다. 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
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) 입니다.
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!" );
}
}
더 많은 클래스를 추가하여 계산기 프로젝트를 향상시켜 보겠습니다.
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!");
}
}
mvn compile
다음으로 끝나는 출력을 볼 수 있습니다.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
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!
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 명령어입니다.
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 개발 작업의 견고한 기반이 될 것이며, 잘 구성되고 유지 관리 가능하며 확장 가능한 애플리케이션을 만들 수 있도록 해줍니다. 프로젝트 구조에 대한 확립된 규칙과 모범 사례를 따르면 다른 개발자와 보다 효과적으로 협업하고 더 높은 품질의 코드를 생성할 수 있습니다.