Java 명령줄 인수 설명: 기본부터 실용적인 디자인 패턴까지

目次

1. 소개

이 장의 목적

Java 명령줄 인수는 프로그램이 실행 시 외부 값을 받아 동작을 변경할 수 있게 해 주는 기본적인 기능입니다. 이 문서에서는 String[] args의 의미부터 실제 애플리케이션에서 사용되는 설계 패턴까지 모두 설명합니다. 이 장에서는 먼저 명령줄 인수가 할 수 있는 일과 어떤 상황에서 유용한지를 명확히 합니다.

명령줄 인수란 무엇인가?

Java 애플리케이션은 일반적으로 다음 시그니처를 가진 main 메서드에서 시작됩니다:

public class App {
    public static void main(String[] args) {
        // args is an array of strings passed at runtime
    }
}

args문자열 배열이며, 프로그램을 실행할 때 제공된 값을 저장합니다. 예를 들어:

javac App.java
java App Tokyo 2025 debug

이 경우 args["Tokyo", "2025", "debug"] 를 포함합니다.
인수가 제공되지 않으면 args.length0 입니다.

일반적인 사용 사례

  • 환경 또는 대상 전환 : 프로덕션 vs 테스트 모드, 지역 코드, 언어, 로그 레벨.
  • 외부에서 처리 대상 지정 : 입력 파일 이름, 디렉터리, URL, ID 목록.
  • 배치 처리 및 자동화 : 스케줄된 작업에 날짜나 범위를 전달하거나 CI/CD 파이프라인에서 매개변수를 주입.

모든 경우에 재컴파일 없이 동작을 변경할 수 있어, 명령줄 인수는 쉘 스크립트와 cron 같은 작업 스케줄러와 함께 사용하기에 이상적입니다.

주요 설계 고려 사항

  • 필수 인수와 선택 인수 구분 : 필수 인수가 누락되면 명확한 도움말 출력이나 종료 코드를 통해 실패하도록 합니다.
  • 조기 검증 : 가능한 한 빨리 숫자나 날짜 값을 변환하고, 잘못된 입력에 대해 명확한 안내를 제공합니다.
  • 기본값 설계 : 선택 인수는 안전한 기본값을 가져야 하며, 그래야 프로그램이 계속 실행될 수 있습니다.
  • 가독성 및 유지보수성 : 직접 배열에 접근하는 코드를 퍼뜨리지 말고, 인수를 구조화된 객체(DTO 또는 설정 클래스)로 파싱합니다.

인수, 환경 변수, 설정 파일 중 선택하기

  • 명령줄 인수 : 일시적인 오버라이드나 작업별 설정에 가장 적합합니다(우선순위 최고, 로컬화된 구성).
  • 환경 변수 : 비밀키나 배포 환경마다 달라지는 엔드포인트에 적합합니다.
  • 설정 파일 (properties/JSON/YAML) : 여러 설정을 체계적으로 관리하고 재사용 및 버전 관리를 할 때 이상적입니다.

실제로는 설정 파일 + 환경 변수 + 명령줄 인수의 3계층 설계가 잘 작동하며, 명령줄 인수가 가장 높은 우선순위를 가집니다.

최소 예제: 모든 인수 나열하기

public class ArgsEcho {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("No arguments were provided.");
            System.out.println("Example: java ArgsEcho input.txt debug");
            return;
        }
        System.out.println("Received arguments:");
        for (int i = 0; i < args.length; i++) {
            System.out.printf("args[%d] = %s%n", i, args[i]);
        }
    }
}

이 문서에서 다음에 다룰 내용 (로드맵)

  • String[] args에 대한 기본 연산 (길이 확인, 요소 접근)
  • 형 변환 (int/double/boolean 및 예외 처리)
  • -v, --help, --mode=prod와 같은 옵션 형식
  • IDE 설정 및 테스트 중 인수 전달 방법
  • 오류 처리 및 보안 고려 사항 (잘못된 입력, 예외 관리)
  • 실용 예제 (파일 처리, 모드 전환, 로그 레벨 제어)

먼저 기억할 핵심 원칙: 모든 인수는 문자열로 전달되며, 사용하기 전에 안전하게 변환하고 검증해야 합니다. 다음 장에서는 구체적인 코드 예제를 통해 기본 구문과 일반적인 패턴을 살펴봅니다.

2. 명령줄 인수란?

main 메서드와 String[] args의 관계

Java 애플리케이션의 진입점은 다음과 같이 정의된 main 메서드입니다:

public static void main(String[] args)

여기서 args는 “인수”를 의미하며, 프로그램이 시작될 때 외부에서 전달된 값을 저장하는 문자열 배열입니다.
프로그램을 실행할 때 java ClassName 뒤에 공백으로 구분하여 지정한 값들이 순차적으로 args에 저장됩니다.

예시: 인수를 사용한 실행

javac Sample.java
java Sample apple orange banana

이 경우 args의 내용은 다음과 같습니다:

IndexValue
args[0]“apple”
args[1]“orange”
args[2]“banana”

즉, args가변 길이 문자열 리스트와 같이 동작하여 원하는 만큼의 값을 전달할 수 있습니다.
인수가 지정되지 않으면 args.length0이 되며(null이 되지는 않습니다).

실행 예시 및 출력

public class Sample {
    public static void main(String[] args) {
        System.out.println("Number of arguments: " + args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}
java Sample dog cat

출력:

Number of arguments: 2
args[0] = dog
args[1] = cat

여기서 중요한 점은 모든 인수가 문자열로 전달된다는 것입니다.
숫자나 boolean 값으로 사용하려면 나중에 명시적으로 변환해야 합니다.

언제 명령줄 인수를 사용해야 할까요?

명령줄 인수는 다음과 같은 상황에서 일반적으로 사용됩니다:

  • 운영 모드 전환 예: java Server startjava Server stop을 사용해 서로 다른 동작 수행.
  • 파일 경로나 설정 값 지정 예: java ReportGenerator /data/input.csv
  • 스크립트 실행 중 임시 매개변수 전달 예: 날짜, 사용자 이름 등, 환경 변수의 가벼운 대체물로 사용.

이러한 사용 사례는 유연성을 높이고 프로그램을 재컴파일 없이 외부 입력으로 제어할 수 있게 합니다.

인수가 제공되지 않을 때의 동작

Java의 main 메서드는 인수가 전달되지 않더라도 항상 String[] args를 포함합니다.
프로그램을 인수 없이 실행하면 args.length == 0이 되므로, 다음과 같은 조건 검사를 추가하는 것이 권장됩니다:

if (args.length == 0) {
    System.out.println("No arguments were specified. Exiting.");
    return;
}

이는 명령줄 인수의 핵심 특징을 보여줍니다: 프로그램이 시작 시점에 유연하고 외부적인 입력을 받을 수 있게 해줍니다.

요약

  • String[] args는 프로그램 실행 시 전달된 인수 목록을 보관합니다.
  • 모든 인수는 문자열로 처리됩니다.
  • 인수가 제공되지 않더라도 argsnull이 아니라 빈 배열입니다.
  • 인수를 사용하면 프로그램이 유연하고 재사용 가능하며 자동화하기 쉬워집니다.

다음 장에서는 이 기반 위에 구축하여 args에서 값을 추출하고 사용하는 기본 사용 패턴 및 구체적인 코드 예시를 보여줍니다.

3. 기본 사용법 및 코드 예시

명령줄 인수의 기본 구문

명령줄 인수를 사용하려면 먼저 main 메서드에 전달된 String[] args에서 값을 추출합니다.
args는 배열이므로 인덱스로 각 요소에 접근할 수 있습니다.

public class CommandExample {
    public static void main(String[] args) {
        System.out.println("Number of arguments: " + args.length);
        if (args.length > 0) {
            System.out.println("First argument: " + args[0]);
        } else {
            System.out.println("No arguments were specified.");
        }
    }
}

프로그램을 다음과 같이 실행합니다:

javac CommandExample.java
java CommandExample hello

출력:

Number of arguments: 1
First argument: hello

위와 같이 args[0]는 전달된 첫 번째 값을 저장합니다.
여러 인수가 제공되면 args[1], args[2] 등으로 접근할 수 있습니다.

한 번에 모든 인수 처리

인수의 개수가 가변적일 때는 일반적으로 루프를 사용해 처리합니다.
다음 예제는 전달된 모든 인수를 순차적으로 출력합니다.

public class PrintArgs {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("No arguments were provided.");
            System.out.println("Example: java PrintArgs apple orange banana");
            return;
        }

        System.out.println("Argument list:");
        for (int i = 0; i < args.length; i++) {
            System.out.printf("args[%d] = %s%n", i, args[i]);
        }
    }
}

실행:

java PrintArgs apple orange banana

출력:

Argument list:
args[0] = apple
args[1] = orange
args[2] = banana

루프를 사용하면 프로그램이 어떤 개수의 인수든 처리할 수 있습니다.
베스트 프랙티스로, 요소에 접근하기 전에 항상 배열 길이를 확인하세요.

인수 순서에 따른 의미 부여

인수의 순서에 따라 특정 의미를 부여할 수 있습니다.
예를 들어, 파일 이름, 모드, 그리고 덮어쓰기 플래그를 받는 프로그램을 생각해 보세요.

public class FileProcessor {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: java FileProcessor <file> <mode> <overwrite>");
            System.out.println("Example: java FileProcessor data.txt verbose true");
            return;
        }

        String fileName = args[0];
        String mode = args[1];
        boolean overwrite = Boolean.parseBoolean(args[2]);

        System.out.println("File name: " + fileName);
        System.out.println("Mode: " + mode);
        System.out.println("Overwrite enabled: " + overwrite);
    }
}

실행 예시:

java FileProcessor data.txt simple false

출력:

File name: data.txt
Mode: simple
Overwrite enabled: false

인수 위치에 역할을 할당함으로써 유연한 프로그램 제어가 가능합니다.

예시: 인수를 숫자로 취급하기

모든 인수가 문자열로 전달되므로, 숫자로 취급하려면 타입 변환이 필요합니다.
다음 프로그램은 두 개의 정수를 받아 합을 출력합니다.

public class SumArgs {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Please specify two integers.");
            return;
        }

        int a = Integer.parseInt(args[0]);
        int b = Integer.parseInt(args[1]);
        int sum = a + b;

        System.out.println("Sum: " + sum);
    }
}

실행:

java SumArgs 7 13

출력:

Sum: 20

"abc"와 같은 비숫자 값이 전달되면 NumberFormatException이 발생합니다.
프로그램을 보다 견고하게 만들려면 예외 처리를 추가해야 합니다.

예외 처리를 포함한 안전한 구현

public class SafeSum {
    public static void main(String[] args) {
        try {
            if (args.length < 2) {
                throw new IllegalArgumentException("Insufficient arguments. Please specify two integers.");
            }
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            System.out.println("Sum: " + (a + b));
        } catch (NumberFormatException e) {
            System.out.println("One or more arguments cannot be interpreted as numbers.");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}

적절한 예외 처리를 통해 잘못된 인수가 제공될 때 프로그램이 갑자기 종료되는 대신 명확한 메시지를 반환할 수 있습니다.

요약

  • 명령줄 인수는 args 배열에 문자열로 전달됩니다.
  • 요소에 접근하기 전에 항상 args.length를 확인하세요.
  • 가변 개수의 인수를 처리하려면 루프를 사용하세요.
  • Integer.parseInt()와 같은 메서드를 사용해 숫자 값을 변환합니다.
  • 사용자 친화적인 동작을 위해 예외 처리를 구현합니다.

다음 장에서는 일반적인 실수와 중요한 주의사항을 검토하고, 더 안전하고 재사용 가능한 코드를 작성하는 방법을 설명합니다.

4. 일반적인 실수와 주의사항

명령줄 인수는 간단한 메커니즘이지만, 초보자들이 흔히 마주치는 여러 함정이 있습니다.
이 장에서는 전형적인 실수와 이를 방지하기 위한 실용적인 대책을 소개합니다.

배열 인덱스 오류 (ArrayIndexOutOfBoundsException)

가장 흔한 실수는 존재하지 않는 인덱스에 접근하는 것입니다.
args는 배열이므로 범위를 벗어난 인덱스를 지정하면 다음과 같은 예외가 발생합니다.

예시: 잘못된 코드

public class ErrorExample {
    public static void main(String[] args) {
        System.out.println(args[0]); // Error occurs if no arguments are provided
    }
}

실행:

java ErrorExample

출력:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

대책

배열 요소에 접근하기 전에 항상 args.length를 확인하세요.

if (args.length == 0) {
    System.out.println("No arguments were specified.");
    return;
}
System.out.println("First argument: " + args[0]);

핵심 포인트:
args는 절대 null이 아닙니다.
인수가 전혀 제공되지 않더라도 길이가 0인 배열로 존재합니다.

모든 인수는 문자열입니다

명령줄 인수는 항상 문자열로 전달됩니다.
따라서 숫자 계산을 수행하려면 타입 변환이 필요합니다.

int num = Integer.parseInt(args[0]);

"abc"와 같은 비숫자 문자열이 전달되면 NumberFormatException이 발생합니다.

대책: 예외 처리 추가

try {
    int num = Integer.parseInt(args[0]);
    System.out.println("Input value: " + num);
} catch (NumberFormatException e) {
    System.out.println("The argument cannot be interpreted as a number. Please provide a valid value.");
}

핵심 포인트:
인수를 직접 숫자로 사용하는 것은 위험합니다.
항상 사용자가 제공한 입력이 유효하지 않을 수 있다고 가정하세요.

공백이 포함된 인수

명령줄에서는 공백이 인수 구분자로 처리됩니다.
공백이 포함된 문자열을 전달하려면 큰따옴표로 묶어야 합니다.

예시:

java Message "Hello World"

결과:

args[0] = Hello World

프로그램을 큰따옴표 없이 실행하면 "Hello""World"가 별개의 인수로 처리됩니다.

멀티바이트 문자 처리

비ASCII 텍스트와 같은 멀티바이트 문자를 전달할 때 문자 인코딩 문제가 발생할 수 있습니다.
특히 Windows 시스템에서는 콘솔 인코딩이 종종 MS932(Shift_JIS)이며, 이는 UTF-8 기반 Java 프로그램과 충돌할 수 있습니다.

대책:

  • 실행 전에 명령 프롬프트를 UTF-8로 설정합니다 (chcp 65001).
  • IDE 실행 설정(Eclipse / IntelliJ IDEA)에서 인코딩을 UTF-8로 통일합니다.
  • Java 시작 옵션 -Dfile.encoding=UTF-8을 지정합니다.
    java -Dfile.encoding=UTF-8 Sample Hello
    

너무 많거나 너무 긴 인수

운영 체제에 따라 명령줄 인수 전체 길이에 제한이 있습니다.
Windows에서는 대략 8,000자, Linux에서는 약 128KB가 제한입니다.
대량의 데이터를 처리해야 한다면 명령줄 인수 대신 파일 입력이나 표준 입력을 사용하세요.

특수 문자와 이스케이프

셸이나 명령 프롬프트에서는 <, >, &와 같은 특정 문자가 특수한 의미를 가집니다.
이를 리터럴 인수로 전달하려면 따옴표로 묶거나 이스케이프해야 합니다.

예시:

java SymbolTest "<tag>" "&value"

이는 셸이 이러한 문자를 리다이렉션이나 파이프 연산자로 오해하는 것을 방지합니다.

인수 순서 오류

인수 순서가 중요한 경우, 사용자가 값을 잘못된 순서로 지정할 수 있습니다.
특히 입력 파일과 출력 파일 이름과 같은 쌍에서 흔히 발생합니다.

대책:

  • --input=input.txt와 같은 명명된 옵션을 사용하세요(후속 장에서 다룹니다).
  • 사용법을 명확히 설명하는 help 옵션을 제공하세요.

요약

Error TypeCauseCountermeasure
Out-of-range accessAccessing arguments without checking countValidate with args.length
Number conversion errorDirect conversion of invalid stringsHandle with try-catch
Incorrect splittingNo quotation marks for spaced valuesUse double quotation marks
Encoding issuesCharacter set mismatchUnify to UTF-8
Special character errorsShell interpretationQuote or escape characters
Incorrect orderUser input mistakesNamed options or help output

다음 장에서는 타입 변환, 옵션 형식 및 기본값을 활용한 실용적인 설계 패턴을 소개하여 보다 견고한 명령줄 도구를 만드는 방법을 다룹니다.

5. 실용 사용법: 타입 변환, 옵션 인수 및 기본값

이 장에서는 명령줄 인수를 보다 유연하고 프로덕션에 적합한 방식으로 처리하는 기술을 살펴봅니다.
타입 변환, 옵션 스타일 인수, 그리고 기본값 설계를 적용함으로써, 사용자에게 더 안전하고 사용하기 쉬운 프로그램을 만들 수 있습니다.

인수를 숫자 및 불리언 타입으로 변환하기

모든 명령줄 인수는 String 값으로 전달되지만, 산술 연산 및 조건 로직에는 적절한 데이터 타입이 필요합니다.

숫자로 변환하기

int count = Integer.parseInt(args[0]);
double rate = Double.parseDouble(args[1]);

불리언으로 변환하기

boolean debugMode = Boolean.parseBoolean(args[2]);

예시: 숫자 계산 프로그램

public class Multiply {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java Multiply <number1> <number2>");
            return;
        }

        try {
            double a = Double.parseDouble(args[0]);
            double b = Double.parseDouble(args[1]);
            System.out.println("Result: " + (a * b));
        } catch (NumberFormatException e) {
            System.out.println("One or more arguments are not numeric.");
        }
    }
}

실행:

java Multiply 4.5 3

출력:

Result: 13.5

핵심 포인트:

  • 변환은 항상 try-catch 블록으로 감싸서 잘못된 입력을 안전하게 처리하세요.
  • Boolean.parseBoolean()는 값이 "true"와 정확히 일치할 때만 true를 반환하며, 대소문자를 구분하지 않습니다.

명명된 옵션 인수 설계

인수 순서에 의존하는 설계는 사람의 실수에 취약합니다.
--key=value와 같은 명명된 옵션이나 -v와 같은 플래그를 사용하면 프로그램이 더 직관적이 됩니다.

예시: 명명된 옵션 파싱

public class OptionParser {
    public static void main(String[] args) {
        boolean verbose = false;
        String mode = "normal";
        String file = "default.txt";

        for (String arg : args) {
            if (arg.equals("-v") || arg.equals("--verbose")) {
                verbose = true;
            } else if (arg.startsWith("--mode=")) {
                mode = arg.substring("--mode=".length());
            } else if (arg.startsWith("--file=")) {
                file = arg.substring("--file=".length());
            }
        }

        System.out.println("Mode: " + mode);
        System.out.println("File: " + file);
        System.out.println("Verbose output: " + verbose);
    }
}

실행:

java OptionParser --mode=debug --file=log.txt -v

출력:

Mode: debug
File: log.txt
Verbose output: true

핵심 포인트:

  • startsWith()을 사용하면 --key=value 형식을 쉽게 감지할 수 있습니다.
  • 인수를 어떤 순서로든 지정할 수 있습니다.
  • 셸 스크립트와 자동화 작업에 적합합니다.

기본값 제공

인수가 누락될 경우를 대비해 안전한 기본값을 정의하는 것이 중요합니다.
이를 통해 프로그램은 최소한의 입력으로도 실행될 수 있으며, 예기치 않은 종료를 방지합니다.

예시: 기본값을 가진 프로그램

public class Greeting {
    public static void main(String[] args) {
        String name = "Guest";
        String lang = "ja";

        if (args.length > 0) name = args[0];
        if (args.length > 1) lang = args[1];

        if (lang.equals("en")) {
            System.out.println("Hello, " + name + "!");
        } else if (lang.equals("fr")) {
            System.out.println("Bonjour, " + name + "!");
        } else {
            System.out.println("Hello (default), " + name + "!");
        }
    }
}

Execution:

java Greeting Taro en

Output:

Hello, Taro!

Execution without arguments:

java Greeting

Output:

Hello (default), Guest!

Key points:

  • Safely handles missing arguments.
  • Behavior adapts based on the number of provided arguments.

Generalizing Option Parsing

For more complex tools, creating a dedicated option parser improves maintainability compared to manually processing args.

Example: Simple Option Parser

import java.util.HashMap;

public class SimpleParser {
    public static void main(String[] args) {
        HashMap<String, String> options = new HashMap<>();

        for (String arg : args) {
            if (arg.startsWith("--") && arg.contains("=")) {
                String[] pair = arg.substring(2).split("=", 2);
                options.put(pair[0], pair[1]);
            }
        }

        System.out.println("Parsed options:");
        for (String key : options.keySet()) {
            System.out.println(key + " = " + options.get(key));
        }
    }
}

Execution:

java SimpleParser --user=admin --port=8080 --mode=test

Output:

Parsed options:
user = admin
port = 8080
mode = test

Key points:

  • HashMap allows flexible storage of key-value pairs.
  • The parser can serve as a reusable foundation for CLI tools.

Practical Design Patterns

  • Few arguments : positional arguments are sufficient.
  • Many configuration values : use named options ( --key=value ).
  • Many optional values : define default values.
  • System integration and scripting : adopt consistent option conventions (e.g., --help , --config ).

Summary

FeatureApproachBenefit
Numeric/boolean conversionparseInt, parseDouble, parseBooleanEnables calculations and conditions
Named arguments--key=value formatOrder-independent and flexible
Default valuesVariable initialization and branchingSafe and user-friendly
Generic parserStore in HashMapEasy to extend and maintain

In the next chapter, we introduce real-world usage patterns, including file operations, batch processing, and mode switching commonly used in production environments.

6. Applied Examples: Common Real-World Patterns

This chapter demonstrates how command-line arguments are used in real-world scenarios.
By flexibly specifying arguments, you can build highly reusable tools for file operations, mode switching, and logging control.

Processing Files Specified by Command-Line Arguments

The most common use case is receiving a target file as a command-line argument.
This pattern is especially useful for automating file read/write operations.

Example: Reading and Displaying File Contents

import java.nio.file.*;
import java.io.IOException;

public class FileReaderTool {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java FileReaderTool <filePath>");
            return;
        }

        String filePath = args[0];
        try {
            String content = Files.readString(Paths.get(filePath));
            System.out.println("=== Contents of " + filePath + " ===");
            System.out.println(content);
        } catch (IOException e) {
            System.out.println("Failed to read file: " + e.getMessage());
        }
    }
}

Execution example:

java FileReaderTool data.txt

Sample output:

=== Contents of data.txt ===
Sample data line 1
Sample data line 2

Key points:

  • Always include file existence checks and exception handling.
  • Easy to extend for batch processing of multiple files.

Switching Program Behavior by Mode

Using arguments to switch behavior allows a single program to serve multiple roles.

Example: Mode-Based Execution

public class ModeSelector {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java ModeSelector <mode>");
            System.out.println("Available modes: test / prod / debug");
            return;
        }

        String mode = args[0].toLowerCase();

        switch (mode) {
            case "test":
                System.out.println("Running in test mode...");
                break;
            case "prod":
                System.out.println("Running in production mode...");
                break;
            case "debug":
                System.out.println("Running in debug mode with detailed logging...");
                break;
            default:
                System.out.println("Unknown mode: " + mode);
        }
    }
}

Execution:

java ModeSelector debug

Output:

Running in debug mode with detailed logging...

Key points:

  • Useful for switching between development, testing, and production environments.
  • Widely used in automation scripts and batch jobs.

Automating Calculations with Multiple Arguments

In batch processing and scheduled scripts, arguments are often used to pass parameters dynamically.
The following example shows a simple calculator tool that operates on two numeric values.

public class Calculator {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: java Calculator <num1> <num2> <op>");
            System.out.println("Example: java Calculator 10 5 add");
            return;
        }

        double a = Double.parseDouble(args[0]);
        double b = Double.parseDouble(args[1]);
        String op = args[2];

        switch (op) {
            case "add": System.out.println(a + b); break;
            case "sub": System.out.println(a - b); break;
            case "mul": System.out.println(a * b); break;
            case "div":
                if (b == 0) {
                    System.out.println("Division by zero is not allowed.");
                } else {
                    System.out.println(a / b);
                }
                break;
            default:
                System.out.println("Unknown operation.");
        }
    }
}

Execution:

java Calculator 8 2 mul

Output:

16.0

This approach allows you to create small, script-friendly tools that integrate easily with automation workflows.

Specifying Configuration with Option Arguments

For more flexible operation, option-style arguments such as --key=value are extremely useful.

public class ConfigLoader {
    public static void main(String[] args) {
        String config = "default.conf";
        boolean verbose = false;

        for (String arg : args) {
            if (arg.startsWith("--config=")) {
                config = arg.substring("--config=".length());
            } else if (arg.equals("--verbose")) {
                verbose = true;
            }
        }

        System.out.println("Configuration file: " + config);
        System.out.println("Verbose logging: " + (verbose ? "ON" : "OFF"));
    }
}

Execution:

java ConfigLoader --config=prod.conf --verbose

Output:

Configuration file: prod.conf
Verbose logging: ON

Key points:

  • Named options reduce human error because order does not matter.
  • Commonly used for configuration paths and execution modes.

Practical Example: File Processing Tool with Logging

import java.nio.file.*;
import java.io.*;

public class FileCopyTool {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java FileCopyTool <input> <output> [--verbose]");
            return;
        }

        String input = args[0];
        String output = args[1];
        boolean verbose = (args.length > 2 && args[2].equals("--verbose"));

        try {
            Files.copy(Paths.get(input), Paths.get(output), StandardCopyOption.REPLACE_EXISTING);
            if (verbose) {
                System.out.println("File copied successfully: " + input + " → " + output);
            }
        } catch (IOException e) {
            System.out.println("Copy failed: " + e.getMessage());
        }
    }
}

Execution:

java FileCopyTool report.txt backup.txt --verbose

Output:

File copied successfully: report.txt → backup.txt

Key points:

  • Logging can be toggled via options for development or production use.
  • This structure is reusable as a foundation for real-world scripts.

Summary

Use CaseTypical Argument PatternScenario
File specification<file>Input/output processing, automated backups
Mode switching<mode> or --mode=debugEnvironment-specific execution
Configuration selection--config=xxx.confSystem configuration and runtime parameters
Option control--verbose, --dry-runLogging and safe test runs
Batch processing<startDate> <endDate>Scheduled jobs and data aggregation

In the next chapter, we cover how to pass command-line arguments in IDEs and testing environments, including Eclipse and IntelliJ IDEA, along with debugging tips.

7. Testing and Debugging Tips / Configuring Arguments in IDEs

Programs that use command-line arguments can be executed and tested not only from the terminal, but also within development environments such as Eclipse and IntelliJ IDEA.
This chapter explains how to configure arguments during development and introduces tips for efficient debugging.

Setting Arguments in Eclipse

In Eclipse, you can configure command-line arguments using Run Configurations.
This allows you to run programs with predefined arguments without manually typing commands each time.

Steps:

  1. From the menu bar, select Run → Run Configurations… .
  2. From the list on the left, choose the target Java Application.
  3. Open the Arguments tab.
  4. Enter arguments in the Program arguments field, separated by spaces. Example: data.txt debug true
  5. Click Apply , then Run .

The same arguments will be reused the next time you run the program.
You can also save multiple configurations to switch between different test scenarios.

Tips:

  • Arguments may be written on separate lines; Eclipse treats them as space-separated values.
  • Strings containing spaces must be enclosed in double quotation marks (e.g., "Hello World" ).
  • To change character encoding, specify -Dfile.encoding=UTF-8 in the VM arguments field.

Setting Arguments in IntelliJ IDEA

IntelliJ IDEA provides an even more streamlined configuration process.

Steps:

  1. Open Run → Edit Configurations… .
  2. Select the configuration for the target class.
  3. Enter arguments in the Program arguments field. Example: --mode=debug --file=log.txt --verbose
  4. Click OK or Apply , then run the program.

Tips:

  • Run configurations are saved per project.
  • The same configuration is used for both Run and Debug executions.
  • You can define environment variables alongside arguments to closely simulate production environments.

Understanding Differences from Command-Line Execution

There may be differences between running a program in an IDE and running it directly from the terminal, particularly regarding environment variables and working directories.

AspectIDE ExecutionTerminal Execution
Working directoryProject root (configurable)Current shell directory
Environment variablesDefined per run configurationInherited from the shell
EncodingIDE default or configuredDepends on OS and console

Being aware of these differences helps prevent issues that only occur after deployment.

Debugging Tips for Argument-Based Programs

  • Print all received arguments at startup to verify correct input.
  • Log parsed values after validation and type conversion.
  • Use breakpoints at argument parsing logic to inspect runtime values.
  • Test edge cases such as missing arguments, invalid values, and empty strings.

Summary

  • Command-line arguments can be tested efficiently within IDEs.
  • Eclipse and IntelliJ IDEA provide built-in support for argument configuration.
  • Be mindful of differences between IDE and terminal environments.
  • Effective debugging starts with validating and logging argument values.

이러한 기술을 사용하면 명령줄 인수를 활용하는 Java 프로그램을 자신 있게 개발, 테스트 및 디버깅할 수 있으며, 개발 및 운영 환경 전반에 걸쳐 일관된 동작을 보장합니다.