[ASAC 3기 개발일지] JAVA

배규리·2023년 11월 9일
0
post-thumbnail

Spring을 잘하는 개발자는

  • Spring 프레임워크에 대한 구성 및 원리를 이해한 개발자
  • JAVA 언어를 잘 작성하는 개발자 = 디자인 패턴 및 SOLID 원칙

따라서 이번 게시물에서는 Java언어에 대해서 공부할 것이다!

Java 파일을 생성해서 코딩하고 컴파일하고 실행되는 과정까지의 과정을 한번 살펴보자.

Java 컴파일과 런타임

컴파일 과정(Compile Time)

Java 코드 (.java) -> Bytecode (.class)
위의 과정으로 javac 컴파일러를 통해 이루어진다.

런타임 과정(Runtime Time)

Bytecode (.class) -> 기계어 (OS에 따라 다름)
위의 과정으로 JVM에 의해 이루어진다.

컴파일 에러와 런타임 에러

맨날 우리가 겪는 컴파일 에러,,,런타임 에러,,,이게 다 여기서 나온 것들!
컴파일 에러는 구문 에러!
런타임 에러는 객체 사용시 잘못된 프로그래밍으로 발생한 에러!

컴파일 에러

  • Checked Exception
  • 반드시 예외 처리를 해야한다.
    • try-catch 또는 throw문 사용!

런타임 에러

  • Unchecked Exception
    • 예외 처리를 강제하지 않는다.

이렇게 생각하면 쉽다😊

Java 런타임: JVM

JVM의 역할 = 런타임 = 바이트 코드를 OS에 특화된 기계어로 바꾼다.
JVM은 아래의 3개만 기억하면 된다!
1. Class Loader
2. Runtime Data Area(JVM 메모리)
3. Execution Engine(JVM 엔진)

Class Loader

.class 파일을 메모리로 Load하고 클래스를 인스턴스화 한다!

동적 로딩으로 필요한 클래스만 Runtime 데이터 영역에 적재
🤷‍ 동적 로딩이란 "필요한 Byte Code만을 Runtime Data Area에 적재"하는 과정이다.
Class Loader는 아래와 같은 과정을 거친다.

1. Loading
.class 파일을 JVM 메서드 영역에 가져오는 것
특이한 점은 static변수나 사용하지 않는 클래스는 로드하지 않는다는 점👌
메서드와 변수 그리고 Class, Interface, Enum을 구분해서 저장한다.
로딩이 끝나면 해당 클래스 타입의 객체를 생성하여 메모리의 Heap 영역에 저장

2. Linking
.class파일의 정확성 보장(예를 들어 파일이 적절히 포맷되었는지, 유효한 컴파일러에 의해 생성되었는지 ...)
JVM은 메모리를 기본 값으로 초기화한 후, 클래스 변수들을 위한 메모리에 할당

3. Initialization
모든 정적 변수들이 정의된 값으로 초기화

Runtime Data Area(JVM 메모리)

프로그램 수행을 위해 OS로부터 할당받는 메모리 영역
즉 JVM이 프로그램을 실행하는 동안 데이터를 저장하는 메모리 영역

아래와 같이 5개의 영역으로 분류된다!

  • 공유 영역
    • Heap: 모든 객체들의 정보를 저장
    • Method: 전역 변수를 포함하는 모든 클래스 정보 저장
  • Thread 영역
    • Stack: 메소드의 모든 지역 변수 저장
    • PC Register: Thread의 현재 실행 명령의 주소 저장
    • Native Method Stack: Native 메소드 정보 저장

Execution Engine(JVM 엔진)

적재된 byte code 실행
Byte code를 한줄씩 읽고, 다양한 메모리 영역에 나타난 데이터와 정보를 사용하고 명령을 실행

여기도 3개의 영역으로 분류된다!

  • Interpreter(인터프리터): Byte code를 한줄씩 실행하여 해석
  • JIT(Just-In-Time): 전체 Byte code를 컴파일하고 네이티브 코드를 변경하여 메소드의 반복 호출을 확인할 때마다 JIT는 직접 네이티브 코드로 제공
    -> 재해석으로 요구하지 않으므로 효율성이 증가
  • Garbage Collector: 참조되지 않는 객체 소멸

디자인 패턴 및 객체지향 설계원칙 SOLID

Java는 객체 지향 프로그래밍 언어이다!
OOP는 Object Oriented Programming
객체 지향이라는 것의 목표는 분업화와 모듈화이다.
이를 위해서 특정 객체는 특정 타입의 업무만을 수행해야 한다!

  • 추상화
  • 다형성
  • 캡슐화
  • 상속

위의 것들을 잘 활용하면 객체 지향 프로그래밍 만랩 가능😎
객체 지향 프로그래밍 관점에서 아래의 3개를 잘 지키면 좋은 코드이다.

  1. 중복의 최소화: 하나의 수정이 다른 하나의 수정을 동반해서는 안된다.
  2. 코드 변경의 용이성: 요구사항이 계속해서 바뀔 수 있기 때문에 필요하다.
  3. 재사용성: 정돈된 코드는 전혀 다른 요구사항 및 비슷한 경우에도 그대로 사용이 가능하다.

디자인 패턴의 목표는 재사용성
디자인 패턴을 위한 원칙 2가지
1. 구현보다 인터페이스에 맞춰서 코딩한다.
2. 상속보다는 인터페이스 구성(Composite)을 사용하자.

객체 지향 설계 원칙 SOLID

High Cohesion, Loose Coupling을 위한 원칙

S, Single Responsibility: 단일 책임

하나의 모듈(한 클래스 or 메소드)는 하나의 책임/역할만 가진다.

O, Open-Closed: 개방 폐쇄

확장에 열려있고, 수정에 닫혀있다.

L, Liscov Substitution: 리스코프 치환

상속 시 부모 클래스에 대한 가정 그대로 자식 클래스 동일
즉 하위 타입은 항상 상위 타입을 대체할 수 있어야 한다.

I, Interface Segregation: 인터페이스 분리

인터페이스 내에 메소드는 최소한 개수로

하나의 일반적인 인터페이스보다 여러 개의 구체적인 인터페이스가 낫다.

D, Dependency Inversion: 의존성 역전

인터페이스로 구현체를 연결

참고 문헌
https://coding-factory.tistory.com/828
https://inkyu-yoon.github.io/docs/Language/Java/ClassLoader
https://mygumi.tistory.com/115

profile
백엔드 개발은 취미인 AI 개발자🥹

4개의 댓글

comment-user-thumbnail
2024년 2월 26일

asac관련해서 여쭤보고싶은게 있는데 혹시 가능할까요?

1개의 답글