CodeGym /행동 /JAVA 25 SELF /Java 프로젝트 구조: src, package, classpath

Java 프로젝트 구조: src, package, classpath

JAVA 25 SELF
레벨 5 , 레슨 4
사용 가능

1. 폴더 src — 여러분의 코드가 있는 곳

만약 Java 프로젝트가 집이라면, 폴더 src는 모든 주요 거주자(여러분의 클래스)가 모이는 아늑한 거실과 같습니다. 바로 여기에 코드가 담긴 모든 소스 파일을 넣어야 하며, 프로젝트 루트나 설정 폴더, 또는 바탕화면(아무리 그러고 싶어도)에는 넣지 않습니다.

왜 소스 코드를 나머지와 분리해야 할까요?

  • 폴더 src에는 여러분이 직접 작성한 파일만 저장됩니다: .java.
  • 빌드 과정에서 생성되는 모든 것(예: .class 파일, 임시 파일)은 다른 폴더(out, build, target 등)에 들어갑니다.
  • 이렇게 하면 탐색이 쉬워지고 프로젝트가 더 깔끔해지며 IDE — 도 더 행복해집니다.

간단한 프로젝트 구조 예:

MyFirstProject/
├── .idea/           # IntelliJ IDEA 내부 파일, 건드리지 마세요
├── out/             # 여기에는 컴파일된 .class 파일이 생성됩니다
├── src/             # 여기에 여러분의 소스 코드가 있습니다!
│   └── Main.java
├── MyFirstProject.iml
└── README.md

중요:
여러분이 직접 작성하는 모든 것 — 클래스, 패키지, 인터페이스 — 은 반드시 src 폴더에 있어야 합니다. 그곳에 이미지, 음악, 비밀 레시피를 넣지 마세요 — 그런 용도는 다른 폴더를 사용하세요.

2. 패키지 package

Java에서는 클래스를 “패키지”로 묶는 것이 일반적입니다 — 파일 시스템의 폴더처럼, 다만 클래스용 폴더라고 생각하면 됩니다. 패키지는 다음에 도움이 됩니다:

  • 이름 충돌을 피할 수 있습니다. 프로젝트에 Main이라는 클래스가 두 개 있어도 서로 다른 패키지에 있으면 충돌하지 않습니다.
  • 코드를 논리적으로 구조화할 수 있습니다(예: com.codegym.tasks, com.mycompany.utils).
  • 클래스와 메서드에 대한 접근을 제어할 수 있습니다.

패키지 선언 문법

각 Java 파일의 시작 부분(모든 importclass 선언 이전)에 다음과 같은 줄을 작성합니다:

package com.codegym.lesson05;

이는 이 파일의 클래스가 패키지 com.codegym.lesson05에 속한다는 뜻입니다.

중요:
파일 시스템의 폴더는 패키지 이름과 일치해야 합니다! package com.codegym.lesson05;라고 되어 있다면 파일 경로는 다음과 같습니다:

src/com/codegym/lesson05/Main.java

IntelliJ IDEA에서 패키지 만드는 방법

  1. 프로젝트 패널에서 src 폴더를 마우스 오른쪽 버튼으로 클릭합니다.
  2. New → Package를 선택합니다.
  3. 예를 들어 com.codegym.lesson05와 같이 이름을 입력합니다(IDE가 자동으로 하위 폴더를 생성합니다).
  4. 이제 해당 패키지 안에 새 클래스를 만드세요. com.codegym.lesson05 폴더를 마우스 오른쪽 버튼으로 클릭하고 New → Java Class를 선택한 다음 이름을 입력합니다.

예:

src/
└── com/
    └── codegym/
        └── lesson05/
            └── User.java

왜 모든 것을 src에 그냥 넣으면 안 될까요?

모든 클래스를 뒤섞어 넣으면 프로젝트는 금세 “쓰레기장”이 되어, 필요한 파일을 찾는 일이 기숙사에서 노트북 충전기를 찾는 것보다 어려워질 것입니다. 패키지를 사용하세요 — 그러면 프로젝트 확장이 쉬워지고, 서드파티 라이브러리를 연결하거나 여러 팀 간에 코드를 나누기도 수월해집니다.

3. 클래스의 전체 이름

Java의 모든 클래스는 반드시 어떤 패키지에 속합니다. 패키지는 클래스 라이브러리 안의 “폴더”일 뿐입니다. 예를 들어:

  • System 클래스는 java.lang 패키지에 있습니다. 전체 이름은 java.lang.System입니다.
  • Scanner 클래스는 java.util 패키지에 있습니다. 전체 이름은 java.util.Scanner입니다.
  • ArrayListjava.util에 있으므로 전체 이름은 java.util.ArrayList입니다.

즉, 클래스의 전체 이름 = 패키지 이름 + 점 + 클래스 이름입니다.

코드에서 이를 사용해 봅시다:

java.util.Scanner sc = new java.util.Scanner(System.in);
String name = sc.nextLine();
System.out.println("안녕하세요, " + name);

여기서 우리는 java.util.Scanner를 명시적으로 적었습니다. 프로그램에 Scanner라는 이름의 다른 클래스가 있더라도, 컴파일러는 어떤 클래스를 의미하는지 정확히 이해합니다.

이 점은 매우 중요합니다: 클래스 이름은 같을 수 있지만, 전체 이름은 항상 고유합니다.

왜 전체 이름이 필요할까요?

서로 다른 두 Date 클래스가 있다고 가정해 봅시다:

  • java.util.Date (날짜 작업을 위한 오래된 클래스),
  • java.sql.Date (데이터베이스 작업을 위한 날짜).

그런데 다음과 같이 작성하면:

Date d = new Date();

컴파일러는 어떤 Date를 사용하려는 것인지 알 수 없습니다. 하지만 전체 이름을 쓰면:

java.util.Date d1 = new java.util.Date();
java.sql.Date d2 = new java.sql.Date(System.currentTimeMillis());

— 혼동이 사라집니다.

4. 연산자 import

매번 클래스의 전체 이름을 쓰는 것은 번거롭습니다. 바로 그래서 Java에는 import 연산자가 있습니다.

다음과 같이 작성하면:

import java.util.Scanner;

의미는 다음과 같습니다: “이 프로그램에서는 java.util 패키지의 Scanner 클래스를 사용하겠다.” 그 다음에는 이렇게 간단히 쓸 수 있습니다:

Scanner sc = new Scanner(System.in);

그러면 컴파일러는 이것이 바로 java.util.Scanner를 의미한다는 것을 이해합니다.

일반적인 import(단일 클래스)

가장 흔한 방식입니다. 특정 클래스를 지정합니다:

import java.util.Scanner;
import java.util.ArrayList;

이제 Scanner, ArrayList처럼 짧은 이름을 사용할 수 있습니다.

패키지 전체 import *

때로는 하나의 패키지에서 많은 클래스를 사용할 때가 있습니다. 이때 다음과 같이 쓸 수 있습니다:

import java.util.*;

의미는 다음과 같습니다: “java.util 패키지의 모든 클래스를 전체 이름 없이 사용할 수 있게 한다.”

이제 다음과 같이 쓸 수 있습니다:

Scanner sc = new Scanner(System.in);
ArrayList<String> list = new ArrayList<>();

하지만 중요하게 기억해야 할 점이 있습니다: import java.util.*;java.util 패키지의 클래스만 가져오며, 하위 패키지의 클래스는 포함하지 않습니다. 예를 들어 java.util.concurrent.ConcurrentHashMap은 포함되지 않습니다. 별도로 import해야 합니다.

import로 할 수 없는 것

  • import는 메서드 내부에서 사용할 수 없으며, 파일의 시작 부분에만 작성합니다.
  • import는 클래스를 메모리에 로드하지 않습니다. 단지 컴파일러에게 클래스를 어디서 가져올지 알려줄 뿐입니다.
  • import는 동일한 이름의 클래스가 둘 이상 있을 때 전체 이름을 대체할 수 없습니다.

5. Classpath — Java가 클래스를 찾는 방법

Classpath는 프로그램을 실행할 때 Java가 여러분의 클래스를 찾는 “경로”입니다. Java가 필요한 .class 파일(여러분의 .java를 컴파일한 결과)을 찾을 위치 목록이라고 생각하면 됩니다.

기본적으로 IDE는 src 폴더(또는 컴파일된 클래스가 있는 폴더, 예: out/production/ProjectName)를 classpath에 자동으로 추가합니다. 따라서 com.codegym.lesson05 패키지에 클래스를 작성했다면, Java는 다음 경로에서 이를 찾습니다:

out/production/ProjectName/com/javarush/lesson05/Main.class

IntelliJ IDEA에서 classpath는 어떻게 동작할까요?

  • IDE에서 프로그램을 실행하면, 필요한 classpath가 자동으로 지정됩니다.
  • 명령줄에서 프로그램을 실행할 경우, -cp 또는 -classpath 플래그로 classpath를 명시해야 합니다.
  • 프로젝트의 모든 클래스와 연결된 라이브러리의 클래스는 classpath에 지정된 폴더 안에 있어야 합니다.

6. 프로젝트 내 코드 구성

하나의 클래스 — 하나의 파일

Java에서는 각 public 클래스가 클래스와 동일한 이름의 별도 파일에 있는 것이 관례입니다. 예를 들어 클래스가 Person이라면 파일 이름은 Person.java여야 합니다.

예:

src/com/javarush/lesson05/Person.java
package com.codegym.lesson05;

public class Person {
    String name;
}

파일 이름과 클래스 이름은 동일해야 합니다

클래스 이름이 MySuperClass라면 파일 이름은 MySuperClass.java여야 합니다. 이는 단순한 취향이 아니라 Java 컴파일러의 요구 사항입니다. 일치하지 않으면 — 컴파일 단계에서 오류가 발생합니다.

리소스(이미지, 텍스트 파일)는 어디에 보관하나요?

  • 리소스는 보통 별도의 폴더(예: resources 또는 res)를 만들어 보관합니다.
  • IntelliJ IDEA에서는 폴더를 마우스 오른쪽 버튼으로 클릭하고 Mark Directory as → Resources Root로 지정할 수 있습니다.
  • Java 코드는 classpath를 통해 이러한 파일에 접근할 수 있습니다.

구조 예:

MyFirstProject/
├── src/
│   └── com/javarush/lesson05/
│       └── Main.java
├── resources/
│   └── config.txt

8. 프로젝트 구조에서 흔한 실수

폴더 구조와 패키지가 불일치
파일 시작 부분에 package com.codegym.lesson05;라고 되어 있는데 파일이 src/Main.java에 있으면, 컴파일러는 "package does not exist" 또는 "class not found" 오류를 발생시킵니다. 항상 폴더가 패키지 이름과 일치하는지 확인하세요!

파일 이름과 클래스 이름 불일치
클래스 이름이 Person인데 파일 이름이 People.java라면, "class Person is public, should be declared in a file named Person.java" 오류가 발생합니다.

패키지를 업데이트하지 않은 채 파일을 수동으로 이동
파일을 다른 폴더로 옮겨 놓고 package 줄을 바꾸지 않으면 프로그램은 컴파일되지 않습니다. IDE의 Project 창에서 이 작업을 수행하세요 — IDE가 package를 자동으로 업데이트합니다!

리소스가 classpath에 추가되지 않음
예를 들어 텍스트 파일을 resources 폴더 밖에 두고 해당 폴더를 Resources Root로 표시하지 않으면, 프로그램은 classpath를 통해 해당 파일을 찾을 수 없습니다.

1
과제
JAVA 25 SELF, 레벨 5, 레슨 4
잠금
마법의 돌 더미 🤖🧑
마법의 돌 더미 🤖🧑
1
과제
JAVA 25 SELF, 레벨 5, 레슨 4
잠금
두 머리 드래곤과의 전투 🐉⚔️
두 머리 드래곤과의 전투 🐉⚔️
1
과제
JAVA 25 SELF, 레벨 5, 레슨 4
잠금
전체 경로로 도구 사용하기 🛠️
전체 경로로 도구 사용하기 🛠️
1
과제
JAVA 25 SELF, 레벨 5, 레슨 4
잠금
두 달력 시스템의 처리: 다른 차원의 시간 ⏳
두 달력 시스템의 처리: 다른 차원의 시간 ⏳
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION