24 May 2019
|
POJO
POJO란
POJO란 Plain Old Java Object의 첫 글 자를 따서 만든 약자다. 간단한 자바오브젝트라는 뜻이다.
그러면 POJO 프로그램이란 무엇인가? 특정 프레임워크의 클래스를 상속하지 않으면 POJO인것인가?단순하게 보면 그냥 평범한 자바 오브젝트라고 할 수 있지만, 좀 더 명확하게 말하면, 적어도 조건을 충족해야 한다.
특정 규약에 종속되지 않는다
POJO는 자바언어와 꼭 필요한 API외에는 종속되지 않아야 한다. 따라서 특정 규약을 따라 비즈니스 컴포넌트를 만들어야 하는 경우는 POJO가 아니다. 또한 특정 클래스를 상속해서 만들어야 하는 규약이 있는 경우도 마찬가지다.
특정 규약을 따라서 만들게 하는 경우는 대부분 규약에서 제시하는 특정 클래스를 상속하도록 요구한다. 그럴 경우 자바의 단일 상속 제한 때문에 더이상 해당 클래스에 객체지향적인 설계 기법을 적용하기가 어려워지는 문제가 생긴다. 또한 규약이 적용된 환경에 종속적이 되기 때문에 다른 환경으로 이전이 힘들다는 문제점이 있다.
즉 별다른 가치를 주지도 못하는 규약 따위에 종속되지 않아야 하고, 객체지향 설계에서 자유로운 적용이 가능한 오브젝트 여야만 POJO라고 불릴 수 있다.
특정 환경에 종속적이지 않는다
순수한 애플리케이션 로직을 담고 있는 오브젝트 코드가 특정환경에 종속되게 만드는 경우라면 그것 역시 POJO라고 할 수 없다. POJO는 환경에 독립적이어야 한다.
특히 비즈니스 로직을 담고 있는 POJO 클래스는 웹이라는 환경정보나 웹 기술을 담고 있는 클래스나 인터페이스를 사용해서는 안 된다. 설령 나중에는 웹 컨트롤러와 연결되서 사용될 것이 뻔하다고 할지라도 직접적으로 웹 이라는 환경으로 제한해버리는 오브젝트나 API에 의존해서는 안된다. 그렇게 할 경우 웹 의외의 에서는 사용을 할 수가 없다.
그럼 결국 특정환경과 특정규약에 종속되지 않으면, 모두 POJO인가?
POJO의 가장 중요한 점은 객체지향적인 자바 언어의 기본에 충실하게 만들어져야 한다.
자바가 객체지향 프로그래밍을 가능하게 해주고, 스프링이 자바의 객체지향프로그래밍을 기반으로 재사용성을 높여준다고 해서, 객체지향에 설계에 맞게 자동으로 적용이 되는게 아니다.
책임과 역할이 각기 다른 코드를 한 클래스에 몰아넣어 덩치 큰 만능 클래스로 만드는 경우, 재사용이 불가능한 정도로 다른 레이어와 영역의 코드와 강한 결합을 가지고 만들어지는 경우, 상속과 다형성의 적용으로 처리하면 되는것을 if/switch문이 가득 찬 길고 긴 메소드로 작성해놓은 경우라면, 과연 그것이 객체지향적인 자바오브젝트라고 할 수 있을까?
결론
- 거창하게 이야기했지만 결론은 POJO의 정의는 환경과 기술에 종속되지 않고, 객체지향적인 원리에 충실하게 설계된 자바 오브젝트를 말한다.
09 May 2019
|
AOP
DI
DI 컨테이너란?
프레임워크에서 컨테이너란?
예를 들면, 애플리케이션에서 코드를 작성할 때 특정기능이 필요하면 이미 기능이 구현되어 있는 라이브러리를 호출하여 사용하곤 합니다.
프로그램의 흐름을 사용자가 제어합니다. 하지만 프레임워크 기반 개발에서는 프레임워크가 흐름의 주체가 되어 필요할때마다 코드를 호출하여 사용합니다.
즉 프레임워크에서 이 제어권을 가지는 것이 바로 컨테이너입니다. 객체에 대한 제어권이 개발자로부터, 컨테이너에게 넘어가면서 객체의 생성부터 생명 주기 관리까지 모든 것을 컨테이너가 도맡아서 하게 됩니다.
DI(Dependency Injection)란?
DI는 클래스 사이의 의존관계를 빈 설정 정보를 바탕으로, 컨테이너가 자동적으로 연결해주는것을 얘기합니다. 개발자들은 제어를 담당할 필요없이, 빈 설정 파일에 의존관계가 필요하다는 정보만 추가해주면 됩니다.
한마디로 뭔가 필요한 인스턴스가 있으면, 내가 가서 찾아오던가 직접 만드는 대신 무엇이 필요한지 선언만 하면 외부에서 자동으로 제공해준다는 뜻입니다.
AOP란?
AOP는 애플리케이션 전체에 걸쳐 사용되는 기능을 재사용 하도록 지원하는 것입니다.
기존에 OOP에서 바라보던 관점을 다르게 하여 부가기능적인 측면에서 보았을때 공통된 요소를 추출하자는 것입니다. 이때 가로(횡단) 영역의 공통된 부분을 잘라냈다고 하여, AOP를 크로스 컷팅(Cross-Cutting) 이라고 불리기도 합니다.
요약하자면 아래와 같습니다.
-
OOP : 비지니스 로직의 모듈화
모듈화를 하는 핵심단위는 비지니스 로직
-
AOP : 인프라 혹은 부가기능의 모듈화
로깅, 트랜잭션, 보안 등등
그렇게 하는 이유는, DI는 컨테이너가 할테니 나머지
서비스 / 컴포넌트 / 비즈니스에 신경써라.
프로그래머는 비지 니스 로직에나 집중해라. 이걸 정제해서 얘기하면 관심의 분리라고도 이야기합니다.
결국 AOP는 기존 OOP의 방식으로는 깔끔하게 중복된 코드를 제거하고 모듈화를 하기 어려운 공통된 기능을 재사용하기 편하게 한 기법입니다.
AOP의 장점은 크게 2가지입니다.
- 어플리케이션 전체에 흩어진 공통 기능이 하나의 장소에서 관리된다는 점
- 다른 서비스 모듈들이 본인의 목적에만 충실하고, 그외 사항들은 신경쓰지 않아도 된다는 점
05 May 2019
|
JVM
자바 메모리 구조
- JVM이란?
- JVM(Java Virtual Machine, 자바 가상 머신)은 자바 바이트 코드를 실행할 수 있는 주체이다.
- JVM의 역할
- Java와 OS를 연결하며, Java가 OS에 독립적으로 실행되도록 한다.
- Java 애플리케이션을 Class Loader를 통해서 읽어들여 Java API와 함께 실행한다
- GC를 실행한다
- JVM 실행과정
- 프로그램이 실행되면 OS에서 JVM에 메모리를 할당한다. JVM은 할당받은 메모리를 용도에 따라 여러 영역으로 나누어서 관리한다.
- 자바 컴파일러가 자바소스를 읽어들여 자바 바이트코드로 변환시킨다
- 자바 바이트코드를 Class Loader를 통해 JVM 메모리 영역으로 로딩한다
- 자바 바이트코드는 Execution engine을 통해 해석된다
- 해석된 바이트코드는 Runtime Data Areas에 배치되어 실질적인 수행이 이루어진다. 이러한 과정에서 JVM은 필요에 따라 Thread Synchronization과 GC같은 관리작업을 수행한다.
![image](https://t1.daumcdn.net/cfile/tistory/0139C94D51A4557F39)
- JVM 내부모듈
- 클래스로더
- JVM 내로 클래스를 Load 해서 Runtime Data Areas에 배치, 동적으로 클래스를 로드(컴파일 타임이 아닌 런타임에 클래스를 참조할 때 해당 클래스를 로드)
Runtime Data Area
- JVM 이라는 프로그램이 OS에서 실행되면서 할당받는 메모리 영역
- PC Register, JVM Stack, Native Method Stack은 스레드마다 생성, Heap, Method Area는 모든 스레드가 공유
PC Register
- Thread가 생성될때마다 생성되는 영역으로, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. 이것을 이용해서 쓰레드를 돌아가면서 수행할 수 있게 한다.
Native Method Stack
- 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다. 보통 C/C++등의 코드를 수행하기 위한 스택이다(JNI)
Method Area( Class Area, Code Area, Static Area )
-
하나의 JAVA파일은 크게 필드, 생성자, 메소드로 구성된다. 그중 필드 부분에서 선언된 변수(전역 변수)와 각 클래스와 인터페이스에 대한 런타임 상수 풀, 필드와 메소드 static 변수, 메서드의 바이트 코드등을 보관한다.
-
Method 영역의 데이터는 프로그램의 시작부터 종료가 될 때까지 메모리에 남아있게 된다. 다르게 말하면 전역변수가 프로그램이 종료될때까지 어디서든 사용될 수 있는 이유이기도 하다. 모든 스레드가 공유하고 있으며, jvm이 시작될 때 생성된다.
-
따라서 전역변수를 무분별하게 선언하다보면, 메모리가 부족할 우려가 있어 필요한 변수만을 사용할 필요가 있다
Stack Area( 스택 메모리 영역 )
-
우리가 현재까지 작성하던 메소드 내에서의 정의하는 기본 자료형(int, double, byte,long, boolean 등)에 해당하는 지역변수( 매개 변수 및 블럭문 내 변수 포함)의 데이터값이 저장되는 공간이 stack 영역이다.
-
해당 메소드가 호출 될 때 메모리에 할당되고 종료되면 메모리가 해제된다. 예시로, main 메소드 호출될 때 Stack 영역에 할당되고 종료시 해제된다. 또한 예시로 a라는 변수에 5,4,3,2 순으로 값을 할당한 후 마지막에 a를 출력할 경우 2의값이 나온다. 이전 데이터는 지워진 것이고, 2라는 값만 출력되는 것은 이전의 값이 지워지는 구조라는 것이다.
-
즉 Stack 영역은 LIFO(Last In First Out)의 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워진다는 것을 알 수 있습니다.
Heap Area( 힙 메모리 영역 )
-
힙 영역에는 참조형의 데이터 타입을 갖는 객체(인스턴스), 배열 등은 Heap 영역에 저장된다. 이때 변수( 객체, 객체변수, 참조 변수 )는 Stack 영역의 공간에서 실제 데이터가 저장된 Heap 영역의 참조값(reference value, 해시코드 / 메모리에 저장된 주소를 연결해주는 값)을 new 연산자를 통해서 리턴받는다.
-
다시 말하면 실제 데이터를 갖고 있는 Heap 영역의 참조 값을 Stack 영역의 객체가 갖고 있다. 이렇게 리턴 받은 참조 값을 갖고 있는 객체를 통해서만 해당 인스턴스를 핸들 할 수 있다.
public class HeapArea {
public static void main(String[] args) {
String str1 = new String("joker");
String str2 = new String("joker");
if(str1 == str2){
System.out.println("같은 주소값 입니다.");
} else {
System.out.println("다른 주소값 입니다.");
}
}
}
-
예시로, 위 코드를 실행하면 다른 주소값이 나온다. 이유는 무엇일까? 데이터가 저장된 heap 영역의 참조 값을 리턴 받아서 가지고 있다는 것이다. 그렇기 때문에 저장된 주소가 다른 값을 “==”으로 비교시 다른 주소값이 나오는 것이다.
-
참고로 Heap에 저장된 데이터가 더 이상 사용이 불필요 하다면, 메모리 관리를 위해 JVM에 의해서 알아서 해제된다. 이러한 기능을 GC( 가비지 컬렉터 ) 라고 한다.
Runtime Constant Pool
- Method Area 내부에 존재하는 영역, 어떤 메소드나 필드를 참조할 때 런타임 상수 풀을 통해 해당 메소드나 필드의 실제 메모리상 주소를 찾아서 참조하여 중복을 막는 역할
Execution Engine
Load된 클래스의 바이트코드를 실행하는 Runtime Module Class Loader를 통해 JVM 내의 Runtime Data Areas에 배치된 바이트 코드를 기계어로 변환 후 실행