자바에서 메소드(method)는 필요할 때마다 실행 가능한, 재사용 가능한 코드 조각입니다.
메소드는 종종 함수(function)라고도 불리며, 이 두 단어가 동일한 의미로 사용되는 것을 볼 수 있습니다.
메소드 또는 함수 사용의 중요성
소프트웨어 개발자들은 복잡한 문제를 더 작은 하위 문제로 분할하고, 각 하위 문제를 해결함으로써 전체 문제를 해결하는 방식을 취합니다. 이러한 접근 방식은 모듈식 아키텍처(modular architecture)라는 개념으로 이어집니다. 모듈식 아키텍처에서는 개발자들이 더 큰 문제를 해결하기 위해 코드를 이동 및 실행 가능한 여러 조각으로 나눕니다.
메소드는 전체 애플리케이션의 여러 부분에서 재사용될 수 있다는 장점이 있습니다. 예를 들어, 문장에서 불필요한 공백을 제거하는 유틸리티 메소드를 만들고 싶다고 가정해 봅시다. 애플리케이션의 여러 곳에서 이 로직이 필요할 때마다 코드를 반복해서 작성하는 것이 합리적일까요?
그보다는 메소드를 한 번만 정의해두고, 애플리케이션의 여러 위치에서 다른 입력값을 사용하여 동일한 메소드를 호출하는 것이 훨씬 효율적일 것입니다. 후자가 분명히 더 효율적이고 효과적인 방법입니다.
또한, 자바에서는 접근 제어자(access modifier)를 사용하여 애플리케이션에서 실제로 공유할 수 있는 메소드와 그렇지 않은 메소드를 제어할 수 있습니다. 이는 코드를 더욱 읽기 쉽고, 조직적이며, 구조화된 형태로 만드는 데 도움이 됩니다.
자바의 메소드 유형
자바에는 크게 두 가지 유형의 메소드가 있습니다. 사용자 정의 메소드(user-defined methods)와 미리 정의된 메소드(predefined methods)입니다. 이름에서 알 수 있듯이, 사용자 정의 메소드는 프로그래머가 직접 정의하는 메소드입니다. 다음은 사용자 정의 메소드의 예시입니다.
public int sum(int a, int b) { return a + b; }
반면에 미리 정의된 메소드 또는 내장 메소드(built-in methods)는 자바 프로그래밍 언어 자체에 이미 포함되어 있는 메소드입니다. 다음은 내장 메소드의 예시입니다.
String text = "Hello World"; text.toLowerCase();
여기에서 toLowerCase
는 코드의 어느 곳에서든 호출할 수 있는 자바 내장 메소드입니다.
자바 메소드의 구조
이제 자바에서 메소드의 이상적인 구조를 살펴보겠습니다.
[access_modifier] [return_type] method_name(...parameters) { // method body }
메소드를 구성하는 각 요소들은 반드시 위와 같은 순서대로 배치해야 합니다. 예를 들어, 반환 유형(return type)은 메소드 이름보다 먼저 정의되어야 합니다. 메소드를 구성하는 각 요소의 기능과 작동 방식을 알아보겠습니다.
#1. 접근 제어자
자바에서 접근 제어자(access modifier)는 메소드, 클래스, 인터페이스, 변수 등의 가시성(visibility)을 정의하는 키워드입니다. 자바에는 기술적으로 5가지의 접근 제어자가 있습니다.
public
: 모든 클래스에서 접근 가능합니다.private
: 해당 메소드가 속한 클래스 내부에서만 접근 가능합니다.default
: 기본 접근 제어자로, 동일한 패키지 내에서만 메소드에 접근할 수 있는protected
제어자와 유사합니다.protected
: 하위 클래스 또는 특정 패키지 내에서 접근 가능합니다.
public int sum(int a, int b) { return a + b; }
위 예시에서 sum
메소드는 접근 제어자가 public
이므로, 어디에서든 접근할 수 있습니다.
#2. 반환 유형
함수의 반환 유형(return type)은 함수가 반환할 데이터의 자료형(data type)을 정의합니다. 만약 함수가 아무 값도 반환하지 않는다면, 반환 유형으로 void
를 지정해야 합니다. void
유형이 지정된 경우, return
키워드를 사용할 수 없습니다. 함수를 정의할 때 반환 유형을 지정하는 것은 필수입니다.
public void log(String text) { System.out.println(text); }
위의 log
메소드는 아무 값도 반환하지 않습니다. 단순히 콘솔에 텍스트를 출력하는 기능을 수행하므로, 반환 유형이 void
입니다.
#3. 메소드 이름
메소드 이름은 클래스 내에서 메소드를 식별하고, 객체(object)에서 메소드를 호출하는 데 사용됩니다.
class Print { void log(String text) { System.out.println(text); } } Print p = new Print(); p.log("hello world"); // outputs "hello world"
#4. 매개변수
메소드에 정의된 매개변수(parameter)에 따라 메소드에 인수(argument)를 전달할 수 있습니다. 예를 들어, 메소드에 두 개의 매개변수가 정의되어 있다면, 해당 데이터 유형에 맞는 두 개의 인수를 전달해야 합니다. 인수는 정의된 순서대로 전달해야 합니다.
class Calc { int sum(int a, int b) { return a + b; } } Calc cal = new Calc(); cal.sum(3, 7); // will return 10
#5. 메소드 본문
메소드 본문(method body)에는 특정 결과를 반환하는 데 사용되는 프로그래밍 로직이 포함됩니다. 메소드가 수행해야 하는 실제 기능을 정의합니다. 중괄호({}
)로 둘러싸여 있으며, 종종 코드 블록(code block)이라고도 불립니다.
class Calc { int sum(int a, int b) { return a + b; } }
위 예시에서 중괄호 안의 return
문이 sum
메소드의 본문에 해당합니다.
자바에서 메소드 호출
자바에서 메소드를 호출하는 것은 매우 간단합니다. 메소드가 정의된 클래스의 인스턴스(instance)를 생성한 후, 해당 인스턴스에서 메소드 이름으로 메소드를 호출할 수 있습니다.
정적 메소드(static method)는 해당 메소드가 속한 클래스의 객체 인스턴스 없이도 직접 호출할 수 있습니다. 반면, 비정적 메소드(non-static method)는 반드시 클래스의 인스턴스, 즉 객체에서 호출해야 합니다.
정적 메소드의 호출 예시는 다음과 같습니다.
class Math { public static int sum(int a, int b) { return a + b; } } public class Main { public static void main(String[] args) { int add = Math.sum(5, 2); System.out.println(add); } }
위 코드에서 Math
클래스 내부의 sum
메소드는 정적 메소드입니다. 따라서 Math
클래스의 객체(인스턴스)를 생성할 필요 없이, 클래스 자체에서 메소드를 직접 호출할 수 있습니다.
반대로, 비정적 메소드의 호출 예시는 다음과 같습니다.
class Math { public int sum(int a, int b) { return a + b; } } public class Main { public static void main(String[] args) { int add = new Math().sum(5, 2); System.out.println(add); } }
여기서는 Math
클래스의 새 객체를 생성한 후, 해당 객체에서 sum
메소드를 호출합니다. 비정적 메소드는 클래스가 인스턴스화되기 전에는 메모리에 생성되지 않기 때문입니다.
이것이 바로 자바에서 메소드를 호출하는 기본적인 방법입니다.
마지막 말
자바뿐만 아니라 모든 프로그래밍 언어에서 메소드는 코드를 체계화하고 여러 위치에서 재사용할 수 있도록 하는 매우 유용한 방법입니다. 메소드는 모듈식 구성 요소 기반 아키텍처의 핵심적인 구성 요소입니다.
자바를 사용하고 있다면, 자바의 예외 처리(exception handling)에 대해서도 자세히 알아보는 것이 좋습니다.