Java란 무엇인가

코딩하는 포로리·2022년 1월 18일
2

Java

목록 보기
1/3
post-thumbnail

📌 1. Java란?


📎 Java란?

🔥 출처: 위키백과 사전

자바(Java)는 자바로 기술된 프로그램 개발 및 실행을 할 수 있는 소프트웨어 모임의 총칭이다. 자바 프로그램은 운영체제나 하드웨어에 의존하지 않는 바이트 코드(중간 언어)인 추상적인 코드로 구현된다. 따라서, 자바 프로그램을 실행하기 위해서는 자바 가상 머신(JVM)과 개발에 필요한 표준 라이브러리 세트컴파일러의 환경만 맞추면 자바 프로그램은 모든 환경에서 동일하게 동작한다. 이러한 실행환경과 개발환경을 제공하는 것이 자바 플랫폼이다.



📌 2. Java의 장단점


📎 Java 장점

👉 ⭐️객체지향 프로그래밍 언어(OOP:Object Oriented Programming)⭐️

  • 유지보수가 쉽고 직관적인 코드 분석이 가능하다.
  • 설계도인 클래스를 작성하여, 객체와 객체를 연결하여 목적에 맞는 프로그램을 완성한다.

👉 분산 네트워크 기술 지원

  • 자바에는 TCP/IP라이브러리가 기본적으로 포함되어 있고, HTTP 프로토콜을 지원한다.

👉 멀티쓰레드(Multi Thread) 지원

  • 동일한 쓰레드를 동시에 수행할 수 있다.
  • 사용자 인터페이스 쓰레드와 장시간 계산이 필요한 쓰레드가 동시에 필요할 때 효과적이다.

👉 ⭐️이식성이 높음⭐️

  • 자바가상머신(JVM)에서 작동하기 때문에 운영체제(ex: Window, Linux)의 종류에 상관없이 작동한다.

👉 ⭐️자동 메모리 관리(Garbage Collector)⭐️

  • 객체 생성시 자동으로 메모리 영역을 찾아서 할당하고, 사용이 완료된 객체는 쓰레기 수집기(Garbage Collector)를 실행시켜 자동으로 메모리에서 체크하고 반환해준다.
  • 자바는 개발자가 직접 메모리에 접근할 수 없으며, 메모리는 자바가 직접 관리한다.

👉 동적 로딩 지원

  • 프로그램 실행시 모든 클래스가 로딩되지 않고, 필요한 시점에 클래스를 로딩하여 사용할 수 있다.
  • 그러므로 애플리케이션의 변경사항도 비교적 적은 작업만으로 처리할 수 있다.

👉 오픈소스 라이브러리가 풍부하다.

  • 자바는 오픈소스(Open Source)언어이고 자바 프로그램에서 사용하는 라이브러리 또한 오픈소스 양이 방대하다.
  • 고급 기능을 구현하는 코드를 작성하는 대신 검증된 오픈소스 라이브러리를 사용하면 애플리케이션을 다시 컴파일 할 필요가 없다. 따라서 유지보수를 쉽고 빠르게 할 수 있다.

📎 Java 단점

👉 속도가 느림

  • 자바는 실행을 위해 자바 가상 머신을 거쳐야 하므로, 다른 언어에 비해 실행 속도가 느려서 처리 속도가 중요한 애플리케이션에는 적합하지 않다.
  • 하지만 바이트코드(byte code)를 하드웨어의 기계어로 변환해주는 JIT컴파일러와 Hotspot(향상된 최적화 기술)과 같은 기술 적용으로 JVM 기능이 향상되어 속도문제가 개선되었다.

👉 불편함 예외처리

  • 자바는 예외 처리가 잘 되어 있지만, 개발자가 일일이 지정해 줘야 한다는 불편함도 있다. 그렇게 하지 않으면, 컴파일조차 거부된다.

👉 하드웨어 정밀 조정 불가

  • 하드웨어에 연결할 수 없기 때문에 직접 하드웨어를 정밀하게 조정해야 하는 프로그램 개발에는 적합하지 않다.


📌 3. Java is 객체지향 언어


📎 객체지향 언어란?

객체지향언어란, 프로그램을 데이터와 처리방법으로 나누지 않고, 객체를 만들고 조작하며 객체끼리 관계를 맺음으로써 다수의 객체가 서로 상호작용할 수 있게 하는 것이다. 다시 말해, 객체를 조립해서 전체의 프로그램을 만드는 조립식 프로그래밍이다.


📎 객체(Object)란?

물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신과 다른 것을 식별가능한 것을 말한다. 예를 들어, 물리적으로 존재하는 학생, 회원 등과 추상적으로 생각할 수 있는 생산, 주문, 배송 등이 모두 객체가 될 수 있다.


📎 클래스(Class)란?

객체라는 추상적인 개념을 코드화 한 것을 클래스라고 한다. 간단하게 생각하면, 클래스는 붕어빵틀 그리고 객체는 붕어빵 정도로 생각하면 좋다. 이처럼 객체를 만들기 위한 설계도 개념인 클래스는 객체의 속성기능을 표현하는 변수메소드를 포함한다.

👉 상태: 멤버변수

클래스 안에서 선언되는 변수를 멤버 변수라고 하며 객체가 가지는 속성을 표현하는데 사용된다.

👉 동작: 메소드

메소드는 객체 안에서 사용하는 함수로 객체가 제공하는 기능을 구현하는데 사용된다.

👉 멤버변수와 메소드 예시

멤버변수와 메소드를 각각 클래스의 상태와 동작의 역할이라고 생각하면 이해하기 쉽다. 예를 들어, 고양이라는 클래스가 있다고 가정해보자. 고양이를 이루는 여러가지 요소를 크게 나누면 상태(속성)와 동작으로 나눌 수 있다. 고양이의 상태로는 생김새나 이름 몸무게 등이 있다. 반대로 고양이의 동작은 할퀴기나 핡기 그리고 밥먹기 등이 있다. 이런 상태와 동작을 각각 메소드와 클래스로 표현하면 아래와 같이 표현된다.

Class cat {

String name = 'kitty'; 
int weight = 10 ;

void claw() { }

}

Class cat1 = new Cat();

📎 객체지향언어의 특징 4가지

👉 캡슐화(Encapsulation)

  • 그림 설명: 원은 멤버 변수이고, 원을 둘러싸고 있는 것은 멤버 메서드이다. 객체의 필드(속성)와 메소드를 하나로 묶고 실제 구현 내용을 외부로 부터 감추는 형태를 그림으로 표현한 것이다.
  • 캡슐화에 의해, 외부 객체는 객체 내부의 구조를 얻지 못한다. 객체가 일부로 노출해서 제공하는 필드오 메소드만을 이용할 수 있어야 한다.
  • 객체지향 프로그래밍에서는 객체의 데이터를 외부에서 마음대로 읽고 변경할 경우 객체의 무결성이 깨질 수 있기 때문에 일반적으로 외부의 접근을 막는 경우가 많다.
  • JAVA의 접근 제한자 public, private, default, proected 로 캡슐화의 구조를 이해할 수 있다.

👉 상속(Inheritance)

  • 상위 클래스의 모든걸 하위 클래스가 이어 받는 것으로 기존 코드를 재활용할 수 있다.
  • 상속의 대상은 부모의 필드와 메소드이다.
  • 상속의 효과로 4가지 정도를 이야기할 수 있다.
    • 부모 클래스를 재사용해서 자식 클래스의 효율적인 개발을 도모할 수 있다.
    • 반복된 코드의 중복을 줄여준다.
    • 유지보수의 편리성을 제공한다.
    • 객체의 다형성을 구현할 수 있게 한다.

👉 다형성(Polymorephism)

  • 같은 타입이지만 실행 결과가 다양한 객체를 대입할 수 있는 성질을 말한다. 다시 말해, 하나의 이름으로 많은 상황에 대처하다보니 코드가 간결해지는 효과가 있다.
  • 오버로드(Overload)와 오버라이드(Override)가 다형성의 대표적인 예시이다.

👉 추상화(Abstraction)

  • 추상화는 객체의 공통적인 속성과 기능을 추출하여 정의하는 것을 말한다.
  • 사과, 딸기, 배라는 각각의 객체가 있고 이 객체를 하나를 묶기 위해 과일이라는 추상적인 객체로 정의한다고 하면, 이 행위를 추상화라고 할 수 있다.

📎 객체지향의 5원칙

👉 단일책임원칙(SRP Single Responsibility Principle)

  • 하나의 클래스는 하나의 책임만 가져야 한다는 원칙이다. 즉, 어떤 변화(요구사항의 변화) 등에 의해 클래스를 변경해야 하는 이유는 오직 하나여야 한다.
  • 나머지 4원칙의 기초가 되는 원칙이기 때문에 SRP 원칙만 잘 지키면 다른 책임의 변경으로 인한 연쇄작용을 방지 가능하다.

👉 개방 폐쇄 원칙(OCP Open-Closed Principle)

  • SW의 구성요소인 모듈, 컴포넌트, 클래스, 메소드는 확장에는 열려있고, 변경에는 닫혀 있어야 한다.
  • 확장에 열려있다는 뜻은, 새로운 변경사항이 발생했을 때 유연하게 코드를 추가 또는 수정할 수 있어야 한다는 뜻이다.
  • 변경에 닫혀있다는 뜻은, 객체를 직접 수정하지 않고도 변경사항을 적용할 수 있도록 설계해야한다는 뜻이다.
  • 시스템의 아키텍쳐를 떠받치는 원동력이되는 원칙이다.

👉 리스코프 치환 원칙(LIP The Liskov Subsitution Principle)

  • 부모 클래스를 상속한 자식 클래스는 부모 클래스의 역할을 정확히 해내야 한다.
  • 자식 클래스의 상세 내부를 부모 클래스는 알 필요가 없지만, 상속의 과정 중 메소드의 재정의가 필요할 때 자식 클래스가 부모 클래스의 기존 메소드 의미를 해치지 않아야 한다.

👉 인터페이스 분리 원칙(ISP Interface Segregation Principle)

  • 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 즉, 꼭 필요한 인터페이스만 상속해야 한다.
  • 클라이언트 자신이 사용하는 메소드에만 의존해야 하며, 사용하지 않는 인터페이스의 메소드를 의존하면 안된다.
  • 인터펭스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.

👉 의존성 역전의 원칙(DIP Dependency Inversion Principle)

  • 여기서 DI는 의존성 주입으로, 변화하기 쉬운 것 혹은 자주 변화하는 것 보다 변화하기 어려운 것 혹은 변화가 거의 없는 것에 의존해야 하는 원칙이다.
  • 고차원 모듈은 잘 변화하기 않는다.

📎 객체지향언어 장점

  1. 재사용성
  2. 신뢰성 향상
  3. 유지보수의 우수성

📎 객체지향언어 단점

  1. 개발속도가 느림
  2. 실행속도가 느림


📌 4. JAVA의 구성



👉 JDK(JAVA Development Kit)

  • 자바 개발 키트 라는 뜻으로 개발자가 JAVA 프로그램을 개발하기 위한 환경을 제공한다. JDK에는 JRE가 포함되어 있으며, JAVA소스를 JVM이 읽을 수 있는 바이트코드로 변환하는 컴파일러와 같이 개발에 필요한 도구를 포함하고 있다.

👉 JRE(JAVA Runtime Environment)

  • 자바 실행 환경이라는 뜻으로 JAVA 프로그램이 실행되기 위한 최소의 조건을 포함하고 있다. 바로 플랫폼에 알맞는 JVM과 표준 클래스 라이브러리(API)이다.


📌 5. JAVA 실행과정


  1. 프로그램 Runtime시 JVM은 OS로부터 프로그램이 필요로 하는 메로리를 할당받음
  2. 자바 컴파일러(javac)가 java 소스코드를 통해 jvm이 이해할 수 있는 바이트코드(.class)로 변환
  3. 클래스로더(Class Loader)를 통해 Class파일들을 JVM으로 로딩
  4. 로딩된 Class파일들은 실행엔진(Execution Engine)을 통해 해석됨
  5. 해석된 바이트코드는 메모리(Runtime Data Areas)에 배치되어 실질적인 수행이 이루어짐 + 이런 실행과정 동안 JVM은 필요에 따라 GC같은 관리 작업 수행



📌 6. JVM이란?


📎 JVM이란?

JVM이란 JAVA Virtual Machine의 약자이다. JAVA는 하드웨어가 아닌 JVM이라는 가상머신을 통해 작동한다. 이 JVM은 시스템 메모리를 관리하면서 자바 기반 애플리케이션을 위해 이식 가능한 실행 환경(자체 CPU, 메모리, 네트워크 인터페이스 및 스토리지 등...)을 제공한다.


📎 JVM 특징

👉 중개자 역할

  • JVM은 자바 애플리케이션을 클래스 로더를 통해 읽어들여 자바 API와 함께 실행한다. 이 실행된 JVM은 JAVA와 OS 사이에서 중개자 역할을 수행하여 JAVA가 OS나 CPU에 구애받지 않고 재사용을 가능하게 해준다.

👉 메모리 관리자

  • JVM은 메모리를 관리하고 Garbage Collection실행을 통해 메모리를 최적화한다.

📎 JVM 구조

📂 1) 클래스 로더(Class Loader)

Runtime시 JVM내로 클래스(.class)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다.

  • 로딩: .clss를 읽어옴
  • 링크: 코드 내부의 레퍼런스를 연결함
  • 초기화: 클래스에 있는 static값들을 초기화함

📂 2) 메모리(Runtime Data Area)

프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간으로, 힙,메소드는 전체 공유자원으로 분류되고 스택,PC,네이티브메소드 스택은 쓰레드 단위의 자원으로 분류된다.

  • PC(PC Register)
    • 쓰레드(Thread)가 시작될 때 생성되며 생성될 때마다 생성되는 공간으로 쓰레드마다 하나씩 존재함
    • 쓰레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록하는 부분
  • 스택(Stack)
    • 프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 주로 저장하는 영역
    • 메소드 호출때마다 각각의 스택 프레임(그 메서드만을 위한 공간)이 생성되고 메소드 수행이 끝나면 프레임 별로 삭제 수행
    • 에러 났을 때 에러 메시지보면 런타임 스택에 메시지가 쌓여있는 것을 볼 수 있음
  • 네이티브 메소드 스택(Native Method Stack)
    • 자바 프로그램이 컴파일되어 생성되는 바이트코드가 아닌 기계어로 작성된 프로그램을 실행시키는 별도의 스택 영역
    • JAVA Native Interface를 통해 바이트 코드로 전환하여 저장한다.
  • 메소드(Method) = Class Area = Static Area
    • 프로그램 시작 전에 클래스 수준의 정보(클래스 이름, 부모 클래스 이름, 메소드, static 변수, 일반 변수 등...)를 저장하여 프로그램 종료때까지 해당 데이터를 가지고 감
    • 자바는 Main 메소드의 호출에서부터 계속된 메소드의 호출로 흐름을 이어가기 때문에, 메소드의 바이트 코드는 프로그램의 흐름을 구성하는 바이트 코드로 볼 수 있음
    • Runtime Contatnt Pool이라는 별도의 관리 영역이 함께 존재하는데, 여기에 상수 자료형을 저장하여 참조와 중복을 막는 역할을 수행
  • 힙(Heap)
    • 객체를 저장하는 가상 메모리 공간
    • 프로그램 시작 후 데이터가 들어오고 나가는 구역 (어느순간 들어오고, 어느순간 나가는 데이터들)

📂 3) 실행엔진(Execution Engine)

클래스를 실행시키는 역할을 한다. 클래스 로더가 JVM내의 메모리(Runtime Data Area)에 바이트 코드를 배치시키고, 이것은 실행엔진에 의해 실행된다.

  • 인터프리터(Interpreter)
    • 자바 바이트 코드를 명령어 단위(한줄씩)로 읽어서 네이티브 코드로 변환
    • 단, 한줄씩 수행해서 느리다는 단점이 있음
  • JIT(Just In Time)
    • 인터프리터의 단점을 보완하기 위해 도입
    • 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 네이티브 코드로 변환
    • 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행
  • GC(Grabage Collector)
    • 더 이상 참조되지 않는 객체를 모아서 메모리 정리



📖 참고

0개의 댓글