본문 바로가기
코딩 이야기/자바 코딩

자바(Java) 기초 마스터: 클래스와 함수(메서드) 만들기

by 안개소리 2026. 4. 13.
자바 기초 마스터: 클래스와 함수 만드는 법 완벽 가이드

자바(Java) 기초 마스터: 클래스와 함수(메서드) 만들기

안녕하세요! 최고의 퍼포먼스를 내는 백엔드 개발자를 꿈꾸는 여러분. 자바 프로그래밍의 세계에 발을 들인 것을 환영합니다. 자바는 전 세계적으로 가장 많이 사용되는 언어 중 하나이며, 그 중심에는 객체 지향 프로그래밍(Object-Oriented Programming, OOP)이라는 강력한 개념이 자리 잡고 있습니다.

OOP를 이해하는 것은 자바 정복의 절반이라고 해도 과언이 아닙니다. 그리고 OOP의 가장 기초적인 벽돌이 바로 '클래스(Class)''함수(Method, 메서드)'입니다. 이 개념을 제대로 잡지 못하면 앞으로 배울 상속, 다형성 같은 고급 기술들은 모래 위에 쌓은 성이 될 뿐입니다.

오늘 이 포스팅에서는 단순한 이론 설명을 넘어, 실제 동작하는 예제 코드를 한 줄 한 줄 뜯어보며 자바에서 클래스와 함수를 어떻게 설계하고 구현하는지, 그리고 왜 그렇게 해야 하는지 아주 깊이 있게 다뤄보겠습니다. 이 글을 끝까지 읽으시면 여러분도 자신 있게 나만의 자바 객체를 만들어낼 수 있을 것입니다.


1. 클래스(Class)란 무엇인가?: 객체의 설계도

자바에서 클래스는 '객체를 만들기 위한 설계도' 또는 '틀'입니다. 붕어빵 틀을 생각해보세요. 틀(클래스) 자체는 먹을 수 없지만, 그 틀에 반죽을 부어 구워내면 맛있는 붕어빵(객체)이 만들어집니다.

클래스는 객체의 상태(속성)를 나타내는 '필드(변수)'와 객체의 행동을 나타내는 '메서드(함수)'로 구성됩니다.

예제로 보는 클래스 선언

우리는 주변에서 흔히 볼 수 있는 '자동차'를 주제로 클래스를 만들어보겠습니다.

// Car.java 파일
public class Car {
    // 1. 필드 (Fields) - 자동차의 속성
    String company; // 제조사
    String model;   // 모델명
    String color;   // 색상
    int maxSpeed;   // 최고 속도
    int currentSpeed; // 현재 속도

    // 2. 생성자 (Constructor) - 객체 초기화 틀
    public Car(String company, String model, String color, int maxSpeed) {
        this.company = company;
        this.model = model;
        this.color = color;
        this.maxSpeed = maxSpeed;
        this.currentSpeed = 0; // 초기 속도는 0
    }

    // 3. 메서드 (Methods) - 자동차의 행동
    void accelerate() {
        System.out.println("가속합니다.");
        currentSpeed += 10;
    }
}

클래스 구성 요소 상세 설명

  • public class Car: public은 접근 제한자로, 누구나 이 클래스를 사용할 수 있음을 의미합니다. 클래스 이름(Car)의 첫 글자는 관례적으로 대문자로 씁니다.
  • 필드(Field): 객체의 데이터를 저장하는 변수들입니다. 클래스 블록 바로 아래 선언됩니다.
  • 생성자(Constructor): 클래스 이름과 동일하며 리턴 타입이 없습니다. new 연산자로 객체가 생성될 때 딱 한 번 호출되어 필드들을 초기화합니다. this 키워드는 현재 객체 자신을 가리킵니다.

2. 함수(Method)란 무엇인가?: 객체의 기능 구현

자바에서는 다른 언어의 '함수(Function)'를 메서드(Method)라고 부릅니다. 메서드는 클래스 내부에 정의되어 객체가 할 수 있는 행동을 구현한 코드 블록입니다. 데이터를 입력받아(매개변수) 처리하고, 결과를 반환(리턴값)할 수 있습니다.

메서드의 구조와 예제

가장 기본적인 메서드 구조를 Car 클래스에 추가해보겠습니다.

// ... Car 클래스 내부

// [접근제한자] [리턴타입] [메서드명]([매개변수...]) { ... 실행코드 ... }

// 예제 1: 리턴값도 없고 매개변수도 없는 메서드
public void showInfo() {
    System.out.println("--- 자동차 정보 ---");
    System.out.println("제조사: " + this.company);
    System.out.println("모델: " + this.model);
    System.out.println("현재 속도: " + this.currentSpeed + "km/h");
}

// 예제 2: 매개변수가 있는 메서드 (속도를 입력받아 설정)
public void setSpeed(int speed) {
    if (speed < 0 || speed > maxSpeed) {
        System.out.println("잘못된 속도입니다. 설정할 수 없습니다.");
        return; // 메서드 실행을 종료
    }
    this.currentSpeed = speed;
    System.out.println("속도를 " + speed + "km/h로 설정했습니다.");
}

// 예제 3: 리턴값이 있는 메서드 (현재 속도가 최고 속도인지 확인)
public boolean isAtMaxSpeed() {
    return this.currentSpeed >= this.maxSpeed;
}

메서드 작성 시 핵심 포인트

  • 리턴 타입: 메서드가 실행을 마치고 돌려주는 데이터의 종류입니다. 돌려줄 게 없다면 void를 씁니다. 값을 돌려줄 때는 return 키워드를 사용합니다.
  • 매개변수(Parameter): 메서드 실행에 필요한 외부 입력값입니다. 없을 수도 있고 여러 개일 수도 있습니다.
  • 이름: 메서드가 하는 일을 명확히 나타내는 동사형 이름이 좋습니다. (예: setSpeed, calculateArea)

3. 클래스로부터 객체 생성하고 사용하기 (Main 메서드)

설계도(클래스)를 만들었으니, 이제 실제 자동차(객체)를 만들어서 달려보겠습니다. 이를 위해 프로그램의 시작점인 main 메서드가 필요합니다.

// Main.java 파일
public class Main {
    public static void main(String[] args) {
        // 1. Car 객체 생성 (myCar라는 이름의 인스턴스)
        // new 연산자와 생성자를 호출
        Car myCar = new Car("현대", "아이오닉6", "흰색", 200);

        // 2. 객체의 메서드 사용
        myCar.showInfo(); // 초기 정보 출력

        myCar.accelerate(); // 가속 (현재속도 0 -> 10)
        myCar.accelerate(); // 가속 (현재속도 10 -> 20)

        myCar.setSpeed(100); // 속도 직접 설정

        // 3. 리턴값이 있는 메서드 활용
        boolean maxCheck = myCar.isAtMaxSpeed();
        System.out.println("현재 최고 속도인가요? " + maxCheck);

        myCar.showInfo(); // 최종 정보 출력
    }
}

실행 결과 분석

--- 자동차 정보 ---
제조사: 현대
모델: 아이오닉6
현재 속도: 0km/h
가속합니다.
가속합니다.
속도를 100km/h로 설정했습니다.
현재 최고 속도인가요? false
--- 자동차 정보 ---
제조사: 현대
모델: 아이오닉6
현재 속도: 100km/h

핵심: new Car(...)를 통해 메모리(Heap 영역)에 구체적인 자동차 데이터가 만들어집니다. 우리는 myCar라는 변수를 통해 이 객체에 접근하고 메서드를 호출하여 상태를 변경하거나 값을 가져옵니다. 이것이 바로 OOP의 기본 흐름입니다.


4. 함수(메서드)의 강력함: 오버로딩(Overloading)

자바에서는 하나의 클래스 내에 이름은 같지만 매개변수의 타입이나 개수가 다른 메서드를 여러 개 정의할 수 있습니다. 이를 메서드 오버로딩이라고 합니다. 이는 사용자에게 편리함을 제공하고 코드의 일관성을 유지하게 해줍니다.

System.out.println()이 대표적인 오버로딩 예시입니다. 우리는 문자열, 정수, 실수 등 어떤 데이터든 println() 하나로 출력할 수 있는데, 이는 내부적으로 각 타입에 맞는 println` 메서드가 오버로딩되어 있기 때문입니다.

우리의 Car 클래스에도 `setSpeed`를 오버로딩해 보겠습니다.

// ... Car 클래스 내부

// 오버로딩 예제 1: 정수형 속도를 받음
public void setSpeed(int speed) {
    // ... 기존 코드 ...
}

// 오버로딩 예제 2: 문자열로 된 속도를 받음 (예: "120")
public void setSpeed(String speedStr) {
    try {
        int speed = Integer.parseInt(speedStr); // 문자열을 정수로 변환
        this.setSpeed(speed); // 정수형 setSpeed 호출 (코드 재사용)
    } catch (NumberFormatException e) {
        System.out.println("속도 형식이 잘못되었습니다.");
    }
}

이렇게 하면 호출하는 쪽에서 myCar.setSpeed(100) 또는 myCar.setSpeed("100") 모두 사용할 수 있게 되어 매우 유연합니다.


FAQ: 자주 묻는 질문 3가지

Q1. 클래스와 객체, 인스턴스의 차이는 무엇인가요?
  • 클래스: 설계도 (코드 자체).
  • 객체: 설계도로부터 만들어진 실체 (메모리에 존재).
  • 인스턴스: 특정 클래스로부터 만들어진 객체를 관계 중심으로 부를 때 사용. "myCar는 Car 클래스의 인스턴스이다."
Q2. 메서드를 만들 때 `public`, `private`는 왜 붙이나요?
이를 접근 제한자라고 합니다. 객체의 중요한 필드나 데이터가 외부에서 함부로 변경되는 것을 막기 위해 `private`으로 숨기고, 안전한 메서드(`public`)를 통해서만 접근하도록 설계하는 것(캡슐화)이 OOP의 기본 원칙이기 때문입니다.
Q3. 클래스 안에 메서드 없이 필드만 있어도 되나요?
네, 가능합니다. 그런 클래스는 단순히 데이터를 묶어두는 역할(DTO, VO)을 합니다. 하지만 일반적인 OOP 설계에서는 상태와 행동을 함께 정의하는 것이 좋습니다.