11장. 매번 만들기 귀찮은데 누가 만들어 놓은 거 쓸 수 없나요?

공부하는 감자·2023년 12월 3일
0

자바의 신 3판

목록 보기
11/30

들어가기 전

『자바의 신 3판』 을 읽고 내용 정리 및 공부한 내용을 정리한 글입니다.
서적: 자바의 신 3판 구입처

내용 정리

API

Application Programming Interface의 약자로 “애플리케이션에 선언되어 있는 클래스와 메소드에 대한 상세한 설명이 포함된 문서”를 말한다.

JDK에는 많은 클래스와 메소드들이 포함되어 있다. 이렇게 많은 클래스를 사용할 때 참조하는 문서가 바로 API라는 것이다.

자바의 API는 HTML로 구성되어 있다(웹이다). JDK에 포함되어 있는 문서도 API라고 부르며, 다른 여러 자바 관련 프레임웍에서 제공하는 문서도 API라고 부른다.

💡 이 책에서 설명하는 API 기준은 Java 7 이상 버전의 기준이다.

💡 API 문서 만들기
소스 내에 클래스 및 메소드를 선언하기 전이나 후에 API에 명시되도록 하기 위한 주석을 상세하게 달아두고, javac와 java 명령어가 있는 jdk/bin 디렉터리에 있는 javadoc라는 명령어를 실행만 해주면 자동으로 API 문서인 HTML 파일이 생성된다.
부록에서 확인할 수 있다.

Java API 문서

Java API 문서가 최근에 많이 변경되었다. 가장 큰 변화는 3개의 화면으로 나뉜 Frame 버전을 사용할 수 없고, 다운로드하기가 매우 어렵게 되어있다. 그래서 온라인으로 API 문서를 활용해야만 한다.

API 문서는 크게 OpenJDK와 Oracle 문서로 나눠서 볼 수 있다.

  1. OpenJDK 19 버전의 API를 확인하려면 구글에서 “openjdk 19 api doc”로 검색하면 다음의 링크가 나온다.

    https://devdocs.io/openjdk~19

  2. 오라클 문서는 “openjdk 19 api doc”로 검색하면 다음의 링크가 나온다.

    우측 상단의 검색 창에서 클래스를 찾아갈 수 있다.

화면 정보

이 상세 정보 화면에서 클래스 및 인터페이스는 다음의 순서로 정보가 제공된다.

  • 패키지와 클래스/인터페이스 이름
  • 클래스 상속 관계 다이어그램 (Class Inheritance Diagram)
    • 오라클 자바 API 문서는 부모 클래스에 선언되었지만, 자식 클래스에서 별도로 Overriding을 하지 않은 메소드는 자세한 설명이 제공되지 않는다.
    • 따라서, 사용가능한 메소드가 있는데 그 클래스의 API에 없다면 부모 클래스들의 메소드를 살펴봐야만 한다.
  • 직속 자식 클래스 (Direct Known Subclasses)
    • 현재 보고 있는 클래스를 확장한 클래스들의 목록.
  • 알려진 모든 하위 인터페이스 목록 (All Known Subinterfaces) : 인터페이스에만 존재함.
    • 인터페이스를 상속받은 인터페이스 목록
  • 알려진 모든 구현한 클래스 목록 (All Known Implementing Class) : 인터페이스에만 존재함.
    • 해당 인터페이스를 구현한 클래스들의 목록
    • 어떤 인터페이스로 선언된 매개 변수를 메소드에 넘겨줘야 할 때, 여기에 구현된 클래스의 객체를 넘겨주면 된다.
      ex) Runnable 인터페이스를 매개 변수로 사용하는 메소드가 있으면 Thread 객체를 생성해서 넘긴다.
  • 구현한 모든 인터페이스 목록 (All Implemented interfaces) : 클래스에만 존재함
    • 클래스에서 구현한 모든 인터페이스의 목록
  • 클래스/인터페이스의 선언 상태(Class/Interface Declaration)
  • 클래스/인터페이스의 설명 (Class/Interface Description)
    • 클래스에 대한 상세한 설명을 볼 수 있다.
    • 클래스가 JDK에 추가된 버전을 명시한 Since와, 그 클래스와 관련있는 모든 클래스나 인터페이스, 메소드 등의 링크를 제공하는 See also를 확인할 것.
  • 내부 클래스 종합 (Nested Class Summary)
    • 내부 클래스를 public하게 선언할 경우 그에 대한 내용이 이 목록에 제공된다.
  • 상수 필드 종합 (Field Summary)
    • 클래스에는 public static으로 선언한 상수 필드가 존재할 수 있다.
  • 생성자 종합 (Constructor Summary)
  • 메소드 종합(Method Summary)
    • 클래스에 선언되어 있는 모든 public 및 protected 메소드에 대한 종합 정보를 제공한다.
    • 참고로 우리가 API 문서를 생성할 때 private 메소드를 보이고 말고하는 것은 따로 설정할 수 있다.
  • 부모 클래스로부터 상속받은 메소드들 (Methods inherited from parent)
  • 상수 필드 상세 설명 (Field Detail)
    • 클래스에 선언된 상수 필드가 어떤 내용을 제공하는지에 대한 상세한 설명을 나열한다.
  • 생성자 상세 설명 (Constructor Detail)
    • 생성자를 어떻게 사용하고, 매개 변수에 어떤 값들이 제공되어야 하는지, 어떤 리턴 값ㅇ르 제공하는지, 이 생성자에서 던지는 예외는 언제 발생하는지를 확인할 수 있다.
  • 메소드 상세 설명 (Method Detail)

Deprecated

“디프리케이티드”라고 읽으며, 이제 이건 사용하지 않는 것이라고 선언한 것이다. 이 Deprecated는 생성자, 상수 필드, 메소드에 선언되어 있다.

JDK를 처음 만들었을 때에는 필요에 의해 만들었는데, 나중에 쓰다 보니 문제를 야기시키거나 혼동을 가져와서, 혹은 더 이상 가치가 없을 때 Deprecated로 처리한다.

삭제하지 않고 Deprecated시키는 이유는 호환성 때문이다.

💡 호환성 Compatibility
버전이 올라갔을 때, 이전 버전에서 문제가 생기지 않도록 한다.

Deprecated된 메소드를 사용하면 Warning을 띄워준다.

Note: ~ uses or overrides a deprecated API.

-Xlint:deprecation이라는 옵션을 주고 컴파일하면 상세 경고를 볼 수 있다.

이렇게 컴파일 시 알려주는 이유는 사용자들이 그 클래스가 Deprecated되었다는 사실을 알 수가 없기 때문이다.

이클립스 등의 툴은 Deprecated 여부를 체크하여 보여주지만, 그냥 일반 에디터에서 자바 코드를 작성하는 사람들은 알 수가 없다. 따라서 이러한 Deprecated 된 것들을 알려준다.

기타

책에서는 화면별 상세 설명을 해주는데, 이건 책을 직접 참고해서 보는 편이 좋을 것 같다.

직접해 봅시다. (정답 제공X)

BigDecimal (Java Platform SE 8 )

Q. BigDecimal 클래스의 용도가 무엇인지 확인해 보자.

Me: 불변하는 임의의 정밀 부호가 있는 십진법 숫자. BigDecimal 클래스는 산술, 스케일 조작, 반올림, 비교, 해싱 및 포맷 변환을 위한 연산을 제공합니다.

Q. BigDecimal 클래스의 생성자가 몇 개인지 확인해 보자.

Me: 16개

Q. BigDecimal 클래스에 있는 메소드 중 abs() 메소드의 용도는 무엇인가?

Me: BigDecimal의 절대값을 반환한다.

Q. BigDecimal 클래스에 있는 메소드 중 현재 값에서 특정 값을 빼는 연산을 수행하는 메소드는 어떤 것인가?

Me: subtract(BigDecimal subtrahend)

Q. BigDecimal 클래스에 있는 메소드 중 나누기와 관련된 메소드에는 어떤 것들이 있는지 확인해 보자.

Me: divide 라는 이름으로 선언되어 있다. 그리고 scale을 따로 설정할 수도 있고.

질문

💡 책에 있는 내용이 아닙니다.

책을 읽으며 설명이 더 필요하거나, 추가로 궁금한 점에 대해 질문 형식으로 작성 후, 답을 구해보고 있습니다.
참고한 사이트나 영상은 [출처]로 달아두었으며, 오류 지적은 언제나 환영합니다.

Q. API란 무엇인가?

자바 API라는 문구가 낯설어서 정의를 찾아보고 정리해봤다. 지금까지 API라면 웹 API를 떠올렸는데, 찾아보니 좀 더 넓은 의미로 사용되는 단어였다.

API란

Application Programming Interface의 약자로, 위키백과에서는 다음과 같이 정의하고 있다.

컴퓨터나 컴퓨터 프로그램 사이의 연결이다. 일종의 소프트웨어 인터페이스이며 다른 종류의 소프트웨어에 서비스를 제공한다.

사용자 인터페이스가 컴퓨터와 사람을 연결시킨다면, API는 컴퓨터나 소프트웨어를 서로 연결시킨다.

즉, 응용 프로그램 간에 상호작용하기 위한 규약이다. 특히 외부 응용 프로그램에서 서비스를 요청하고 데이터를 교환하는데 사용된다.

API의 종류는 크게 다음과 같이 나눌 수 있다.

  • 표준 라이브러리 API
    • 대부분의 프로그래밍 언어는 표준 라이브러리에 대한 API를 제공한다. 이는 언어에 내장된 함수, 클래스, 모듈 등을 개발자가 활용할 수 있도록 도와준다.
  • 외부 라이브러리 및 프레임워크 API
    • 외부에서 개발된 라이브러리나 프레임워크에 대한 API이다.
  • 웹 API
    • 서버와 클라이언트 간에 데이터를 주고받기 위한 규칙을 정의한다. 대개 HTTP 프로토콜을 통해 통신하며, 주로 JSON이나 XML 형식으로 데이터를 교환한다. 대표적인 웹API로는 RESTful API가 있다.
  • 데이터베이스 API
    • 데이터베이스와 상호작용하기 위한 API로, 데이터베이스에 연결하고 쿼리를 실행하는 등의 작업을 수행할 수 있도록 한다. 예로는 JDBC가 있다.

API와 라이브러리

API는 다른 소프트웨어와 상호작용하기 위한 규칙의 집합이며, 라이브러리는 구현된 코드의 모음이다.

위키백과에서 자바 API는 다음과 같이 정의된다.

자바를 사용하여 쉽게 구현할 수 있도록 한 클래스 라이브러리의 집합이다.

java에서 제공하는 java.lang 혹은 java.util 등과 같은 클래스들은 오라클 Java가 제공해주는 라이브러리라고 볼 수 있다.

그렇다면 왜 자바 API라고 부를까?

API는 라이브러리를 포함하는 개념이다. 라이브러리는 특정 작업을 수행하는 함수, 클래스, 모듈 등으로 구성되어 있고 이 구성 요소들은 API를 통해 노출된다.

위에서 말한 java.util 패키지는 유용한 자료구조와 알고리즘을 제공하는 라이브러리로, 개발자가 클래스와 메소드들을 사용할 수 있도록 API를 통해 노출된다.

정리하자면, 외부에서 사용할 수 있도록 인터페이스를 정의하는 것을 API라고 하는 것 같다. 이때, API를 통해 제공되는 것이 라이브러리일 수도 있는 것이다.

Q. BigDecimal을 사용하는 이유

부동소수점 방식의 한계

float와 double은 IEEE 754 표준의 부동소수점 방식을 사용한다. 부동 소수점 방식은 다음과 같은 구조를 가지고 있다.

  • 부호 비트(Sign bit): 1비트
  • 지수 부분(Exponent): 고정된 비트 수
    • 숫자의 크기를 나타낸다. 이진 부동소수점에서는 지수를 2의 보수로 표현한다.
  • 가수 부분(Fraction or Mantissa): 고정된 비트 수
    • 실제 숫자의 유효 숫자 부분을 나타낸다. 이진 소수로 표현되며, 소수점 이하의 비트도 포함된다.

32비트 이진 부동소수점에서는 부호비트1비트+지수부분8비트+가수부분23비트=32비트부호 비트 1비트 + 지수 부분 8비트 + 가수 부분 23비트 = 32비트 이다.

IEEE 754 표준의 부동 소수점 수학적 수식은 다음과 같다.

±(1.M)×2E127±(1.가수부)×2지수부127±(1.M) × 2^{E-127} \\ ±(1.가수부) × 2^{지수부-127}

부동소수점을 계산하는 방법은 이 사이트 에서 상세히 설명해준다.

부동소수점 방식으로 실수를 표현하면 큰 범위의 값을 표현할 수 있다. 하지만, 정밀한 십진수를 표현하려고 할 때 발생하는 한계와 부동소수점 정밀도 문제가 있다.

  • 2진수 실수로 변환 시, 끝자리가 5가 아니면 무한 소수가 된다. 그래서 특정 부분에서 끊어 반올림을 한다.
    • 즉, 컴퓨터의 메모리는 한정적이기 때문에 실수의 소숫점을 표현할 수 있는 수의 제한이 있다. 그리고 이는 곧 부정확한 실수의 계산값을 초래하게 된다.

따라서 금융권과 같은 정확한 십진수 계산이 필요한 경우에는 BigDecimal을 사용한다.

BigDecimal 클래스

BigDecimal은 소수를 십진수로 다루머 가변 소수점 연산을 수행한다. 또한 가변 크기의 정수를 표현하는 데 필요한 메모리를 동적으로 할당한다. 즉, 사용되는 값의 크기에 따라 메모리의 크기가 달라진다.

내부적으로 정수 부분과 소수 부분으로 값을 표현한다.

  • 정수 부분 (intVal)
    소수점 왼쪽에 위치한 정수 부분을 BigInteger 객체(java.math.BigInteger)로 저장한다. BigInteger는 임의의 크기의 정수를 다룰 수 있는 클래스로, 정밀한 정수 연산을 지원한다.
  • 소수 부분 (intCompact): 소수 부분의 정수 표현을 담당한다. 내부적으로 정수로 저장되며, scale 변수의 값에 따라 소수점 이하의 위치가 결정된다. 이를 통해 정밀한 십진수 연산이 가능하게 된다.
  • Scale
    소수점 이하의 자릿수를 나타내는 값(int)이다. 예를 들어, "123.456"에서는 소수 부분의 스케일이 3이 된다.

BigDecimal의 단점

  1. 부동 소수점 연산에 비해 상대적으로 느릴 수 있다.
  2. 임의의 정밀도 정수를 처리할 때 BigInteger를 내부적으로 사용하므로, 메모리 사용량이 큰 객체를 생성할 수 있으며 대량의 데이터를 다룰 때 메모리 효율성에 영향을 줄 수 있다.
  3. 부동 소수점을 사용할 때보다 코드가 길어질 수 있다.
  • 산술 연산 메서드를 호출하고 scale을 조절하는 등의 작업이 추가될 수 있다.
  1. BigDecimal은 불변(immutable)한 객체이기 때문에 산술 연산 시마다 새로운 객체가 생성된다. 이는 많은 객체가 생성되면 메모리 할당이 많아질 수 있다.
  2. 십진수를 다루기 위한 클래스이기 때문에 비트 연산을 지원하지 않는다. 이는 특정 종류의 계산에서 다른 자료형에 비해 효율성이 떨어지게 만들 수 있다.

BigDecimal 사용 시 주의할 점

소수부 표현이 정확하다고 BigDecimal foo = new BigDecimal(0.1);을 넣어버리면 생성자 내부에 자바가 0.1을 근사한 값을 넣어버려 실제로는 0.1과는 완전히 다른 값인 0.1000000000000000055511151231257827021181583404541015625을 저장해버린다.

따라서 BigDecimal을 사용해 소수연산을 할 때는 반드시 String으로 변환하여 근사할 여지가 없게끔 처리해야 한다.

precision과 scale

precision은 유효숫자 개수를 의미하며 scale은 소수 자리의 개수를 의미한다. 즉, 예를 들어 12.345는 precision이 5이고 scale이 3이 된다.

참고 사이트

ChatGPT

API와 API 문서 보는 법 - Java

☕ 실수 표현(부동 소수점) 원리 한눈에 이해하기

Java float, double, BigDecimal - 부동소수점 오차

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글