티스토리 뷰

Java+Spring/Java

[Java]Java17, System.err.println()

Vagabund.Gni 2023. 6. 11. 16:18
728x90
반응형

목차

     

    언젠가 언급했지만, 뜻하지 않게 자바 17과 웹플럭스를 이용한 웹 개발을 하게 되었다.

     

    리액티브 프로그래밍 자체에 흥미가 있어 웹플럭스는 공부도 하고 써보기도 했지만,

     

    갑작스러운 자바 17 사용은 당황이 될 수밖에 없었다.

     

    물론 자바 자체가 강력한 하위호환을 지원해서 당장 힘든 일은 없었지만,

     

    레거시 코드를 구성하신 개발자 분들께 물어봐도 왜 자바 17을 선택했는지 아는 분이 계시지 않아 아쉬웠다.

     

    그렇다고 한참 전에 틀을 잡은 개발자분의 연락처를 물어보기도 그렇고...

     

    해서 처음부터 정리하고 싶었지만 미루고 미뤘던 자바 17의 특징에 대해 가볍게 정리하려고 한다.

     

    추가로 에러메시지를 출력하는 System.err.println()까지.

     

    Java 17

     

    기존에 사용하던 자바 11과의 비교보다는 17의 특징과 추가된 기능 위주로 정리한다.

     

    물론 내가 사용하면서 와닿은 부분 위주이기 때문에 라인업이 다양하진 않다.

     

    LTS(Long-Term Support)

     

    자바 17은 2021년 9월 발표된, 가장 최신 버전으로 2029년까지 지원이 예정되어 있다.

     

    2030년까지 지원하는 자바 8 보다는 짧지만, 2026년으로 끝나는 자바 11보다는 길다.

     

    물론 이 지원 기간은 언제라도 늘어날 가능성이 있기 때문에, 자바 8보다 오래 지원할 가능성도 없지는 않다.

     

    Text Block

     

    자바 17에서는 파이썬과 비슷하게 텍스트 블록을 지원한다. 큰따옴표 세 개로 문자열을 감싸 입력하면

     

    가독성이 좋고 형식도 정해줄 수 있는 코드를 작성할 수 있다.

     

    예를 들면 우리 프로젝트에선 SQL 쿼리문을 아래와 같이 따로 관리한다.

    public static final String FIND_USER_WITH_ROLE_BY_ID = """
    	 SELECT u.USER_SEQ as seq,
    	 		u.USER_PASSWORD as password,
    			u.USER_ID as id,
    			u.USER_NAME as name,
    			r.USER_ROLE as role
    	   FROM AU_USER_MASTER u
    	   LEFT OUTER JOIN AU_USER_ROLE r
    	     ON u.USER_ID = r.USER_ID
    	  WHERE u.USER_ID = :id
    """;

     

    Helpful NullPointerExceptions

     

    이 기능은 NPE를 쉽게 다루기 위해 추가된 기능이다.

     

    역할은 NPE가 정확히 어떤 변수에서 발생했는지 알려주는 것인데, 이게 굉장히 편하다.

     

    코드로 예를 들면 아래와 같다.

    public class Example {
    
    	public static void main(String[] args) {
    
    		Person person = null;
    		System.out.println(person.getName());
    	}
    }
    
    class Person {
    	String getName() {
    		return "GNI";
    	}
    }

    위 코드에서 person 객체를 null로 초기화했기 때문에 person.getName()은 NPE를 발생시킨다.

     

    이 경우 자바 17에서는 아래와 같은 에러 메시지를 출력한다.

     

    이게 별 거 아닌 것 같아도 코딩할 때 굉장히 편하다.

     

    record

     

    record 키워드는 불변 데이터를 담는 클래스를 굉장히 간결하게 작성할 수 있도록 도와준다.

     

    기존 자바 11에서는 POJO(Plain Old Java Object)를 이용해 해당 클래스를 작성했으나 각종 설정이나 애너테이션을

     

    반복해서 붙여야 하는 번거로움이 있었다.

     

    예를 들어 아래와 같은 코드를 보자.

    import java.util.Objects;
    
    public class Person {
    	private final String name;
    	private final int age;
    
    	public Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	@Override
    	public boolean equals(Object o) {
    		if (this == o) return true;
    		if (o == null || getClass() != o.getClass()) return false;
    		Person person = (Person) o;
    		return age == person.age && Objects.equals(name, person.name);
    	}
    
    	@Override
    	public int hashCode() {
    		return Objects.hash(name, age);
    	}
    
    	@Override
    	public String toString() {
    		return "Person{" +
    			"name='" + name + '\'' +
    			", age=" + age +
    			'}';
    	}
    }

    코드의 대비를 위해 다소 장황하게 풀어쓴 감이 있지만 일단 넘어가자.

     

    record 키워드를 사용하면 위와 같은 클래스 생성을 아래와 같이 간단하게 끝낼 수 있다.

    public record Person(String name, int age) { }

    물론 위에서 강조했던 대로 해당 키워드는 불변 객체를 생성하기 위한 기능이므로

     

    모든 변수가 final로 선언되며 setter() 메서드는 지원하지 않는다.

     

    Sealed Classes

     

    기존에는 클래스가 final로 선언되지 않은 한 누구나 해당 클래스를 상속받을 수 있었다.

     

    하지만 자바 17에서 추가된 sealed 키워드를 사용하면 허용된 클래스에서만 상속이 가능해진다.

     

    코드로 바로  보면 아래와 같다.

    public sealed class Cat
    permits Gni, Dinger, Dodan { }

    위 코드에서 Cat 클래스는 Gni, Dinger, Dodan 세 개의 클래스 이외는 상속이 불가능하다.

     

    추가로 상속을 받을 세 개의 클래스는 각각 'final', 'sealed', 'non-sealed'중 하나로 선언되어야 한다.

     

    Stream.toList()

     

    자바 11에서 스트림을 리스트로 변환하려면 아래와 같이 Collectors 클래스에서 기능을 찾아야 했다.

    List<Integer> numbers = List.of(1, 2, 3, 4, 5);
    List<Integer> doubledNumbers = numbers.stream()
            .map(n -> n * 2)
            .collect(Collectors.toList());

    하지만 자바 17에서 toList() 메서드가 Collectors 클래스의 정적 메서드로 추가되어서

     

    아래와 같이 간단하게 리스트를 생성할 수 있다.

    List<Integer> numbers = List.of(1, 2, 3, 4, 5);
    List<Integer> doubledNumbers = numbers.stream()
            .map(n -> n * 2)
            .toList();

    개인적으로 이 부분도 별거 아니지만 꽤 꿀이라고 생각한다.

     

    System.err.println()

     

    system.err.println()는 아주 오래된 메서드이다. 무려 Java 1.0부터 존재해 온 문법인데,

     

    이번에 레거시 코드를 읽다가 발견했고, 신기해서 따로 정리한다.

     

    해당 메서드는 이름대로 에러 메시지를 출력하기 위한 명령어이며, 대략 다음과 같은 특징을 가진다.

     

    • 버퍼링: 표준 출력과 다르게 버퍼링 없이 출력된다. 이는 에러 메시지를 가능한 한 빨리 출력하기 위함이다.
    • 색상: system.out.println()과 다르게 system.err.println()는 콘솔에서 빨간색으로 출력된다.
    • 스트림 분리
      system.out.println()과 system.err.println()는 서로 다른 출력 스트림을 사용하기 때문에
      일반 출력과 에러 출력을 각각 다른 곳으로 보내줄 수 있다.

    코드로 예시를 보면 아래와 같다.

    public static void main(String[] args) {
    
    	try {
    		int result = divide(10, 0);
    	} catch (ArithmeticException e) {
    		System.err.println("An error occurred: " + e.getMessage());
    	}
    }
    
    private static int divide(int a, int b) {
    	return a / b;

    위와 같이 입력하면 10을 0으로 나누려 시도하기 때문에 에러가 나며,

     

    메시지는 아래와 같이 출력된다.

     

    역시 인텔리제이로 개발할 때 은근 써먹게 되는 기능인 것 같다.

     

    추가로 해당 메시지를 따로 파일에 저장하려면 아래와 같이 입력하면 된다.

    public static void main(String[] args) {
    
    	try {
    		System.setErr(new PrintStream(new FileOutputStream("errors.txt")));
    	} catch (FileNotFoundException e) {
    		System.err.println("Could not open file for writing: " + e.getMessage());
    	}
    
    	try {
    		int result = divide(10, 0);
    	} catch (ArithmeticException e) {
    		System.err.println("An error occurred: " + e.getMessage());
    	}
    }
    
    private static int divide(int a, int b) {
    	return a / b;

    위와 같이 입력해 주면 기본 src 경로에 errors.txt가 생기며 에러메시지가 저장되는 것을 확인할 수 있다.

    반응형
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/06   »
    1
    2 3 4 5 6 7 8
    9 10 11 12 13 14 15
    16 17 18 19 20 21 22
    23 24 25 26 27 28 29
    30
    글 보관함