JAVA 및 전반적인 기술 질문들
java
primitive type과 레퍼런스 타입의 차이점
- Primitive type 은 자바에서 제공하는 기본형 데이터 타입으로 타입별 데이터 사이즈가 정해져 있으며 stack 영역에 값이 바로 저장된다. primitive type 은 byte(1), short(2), int(4), long(8), float(4), double(8), char(2), boolean(1) 으로 총 8가지가 있다.
Reference type 은 primitive type 을 제외한 모든 데이터이다. 대표적으로 String 타입이 있으며 데이터 사이즈가 정해져있지 않고 가변적이며 stack 에는 데이터의 주소값이 저장되며 실제 데이터는 heap 영역에 저장된다.
접근 제한자
- private : 현재 객체 내에서만 사용
default : 같은 패키지에 있는 객체들만 사용
protected : 같은 패키지에 있는 객체와 상속관계의 객체들만 사용
public : 모든 접근을 허용
Overloading & Overriding
- Overloading 은 동일한 메소드 명을 활용하여 다양한 기능을 구현하여 사용할 수 있는 방식이다. 매개변수의 개수 및 매개변수의 타입을 다르게 하여 다른 기능을 수행하는 메소드를 만들 수 있다. Overriding은 클래스의 상속 및 구현과 연관이 있다. 부모 클래스에 구현, 선언되어 있는 메소드를 상속받아 동일한 메소드명, 매개변수, 리턴타입을 그대로 활용하여 자식 클래스의 기능을 구현할 수 있다. 이런 Overriding 을 통해 객체지향의 특징인 다형성을 표시한다.
java reflection
- 구체적인 클래스 타입을 알지 못해도, 그 클래스의 메소드, 타입, 변수들을 접근할 수 있도록 해주는 자바 API이다. 스프링에서 BeanFactory 라는 Spring Container가 있는데, 어플리케이션이 실행한 후 객체가 호출 될 당시 객체의 인스턴스를 생성하게 되는데 이 때 필요한게 reflection이다. 이클립스나 인텔리제이 같은 IDE 에서도 동적 바인딩을 이용하여 자동완성등의 기능을 제공한다.
자바의 클래스 파일은 바이트 코드로 컴파일되어 static 영역에 위치하게 되는데, 그래서 class 이름만 알고 있다면 static 영역을 뒤져서 클래스에 대한 정보를 가져올 수 있다.
i/o 의 디자인 패턴은?
- 데코레이터 패턴. 객체를 동적으로 서브 클래스를 이용해 확장한다. 기본 클래스가 존재하며 해당 클래스를 데코레이팅, 즉 꾸며주는 클래스들을 구현하여 기본 객체는 유지한채로 다양한 데코레이팅을 통해 객체에 추가 기능을 더할 수 있는 패턴 방식으로 대표적으로 자바 I/O에서 InputStream, OutputStream 을 FilterInputStream, FilterOutputStream 클래스를 통해 데코레이팅 한다.
자바8 신규 기능?
- lambda : 모든 걸 컴파일러의 추론에 의지하고 코드로 표현하는 건 다 없애버려 코드를 간결하게 만든 게 람다 표현식.
stream : 컬렉션 데이터를 처리하며, 별다른 설정없이 병렬 처리 할 수 있도록 해줌. 연속적인 데이터 집합의 처리 도구, filter, map, reduce, find, match, sort 등으로 데이터를 조작할 수 있다. 중간 연산과 종료 연산으로 구분 할 수 있으며 중간 연산은 stream을 리턴하고 종료연산이 수행되면 비 스트림 객체를 반환한다.
optional : NPE를 피하기 위해 만든 클래스. 선택형 값을 캡슐화하는 클래스이다. 값이 존재하면 그 값을 감싼다. 값이 없는 경우에는 Optional.empty 메소드로 Optional을 반환한다. 잠재적으로 null이 될 수 있는 대상을 Optional 로 감싼다.
자바 8 의 스트림 콜렉션
heap 메모리 설명
- Heap 메모리는 프로그램에서 생성된 객체의 데이터가 저장되는 메모리영역이다. 메모리 내부는 new, survive, old, perm, native 로 구성되어 있다. 새로 생성되는 객체는 new 영역 중 eden 영역에 값이 저장되며 gc 에 의해 지속적으로 참조되고 있는 객체는 survive, old 영역으로 이동하며 살아남게 된다.
new 에서 survive, old 로 객체가 이동될때 minor gc,
old 에서 참조되지 않는 객체가 삭제되면서 메모리가 반환될때 major GC .
perm 영역에는 힙에 저장되는 객체의 클래스 메타 정보, 메소드의 메타정보, static object 등이 저장된다.
native heap 영역은 native Object 가 저장되는 영역이다.
heap 영역은 모든 스레드에서 공유한다.
자바 8에선 perm 영역과 native 영역이 합쳐져 metaspace 영역이 새로 생성되었다.
https://yckwon2nd.blogspot.com/2015/03/java8-permanent.html
perm영역은 어디에 있는지?
- heap 영역 안에서 존재하며 perm 영역에는 힙에 저장되는 객체의 클래스 메타 정보, 메소드의 메타정보, static object 등이 저장된다.
metaspace는?
- java 8 에서 새로 생성된 메모리 영역으로 8버전 이하에서 perm 영역과 native 영역이 합쳐져 생성된 메모리영역이다. 클래스의 메타 정보, 메소드의 메타 정보 등이 metaspace 에 저장되며, 기존에 저장되던 static object, string object 등이 heap 영역에 저장되도록 변경되어 gc 에 의해 메모리가 반환될 수 있도록 변경되었다.
쉽게 말해 정말 수정될 일 없는 데이터 들이 metaspace 영역으로 저장되며 저장공간은 자동으로 조정되도록 개선된 것이다.
gc 종류 및 설명
- serial GC : 하나의 CPU를 사용하여 연속적으로 수행되는 collector.
major GC 수행 시 mark-sweep-compact 알고리즘으로 수행된다.
1. old 영역중 살아있는 객체를 식별한다. (mark)
2. old 영역의 객체들을 훑는 작업을 수행하여 쓰레기 객체를 식별한다. (sweep)
3. 필요없는 객체들을 지우고 살아 있는 객체들을 한 곳에 모은다. (compact)
일반적으로 클라이언트 장비에서 사용되며 대기 시간이 길어도 문제 없을 경우 사용된다.
parallel GC : throughput collector 라고도 알려졌다. serial collector와는 달리 minor GC 를 수행할 때 병렬로 수행하며 많은 cpu를 사용하여 GC의 부하를 줄이고 어플리케이션의 처리량을 증가시킬 수 있다. major GC 는 serial GC 와 동일하게 mark-sweep-compact 알고리즘을 사용한다.
parallel compacting GC : minor GC 알고리즘은 parallel GC 와 동일하며 major GC 에서의 알고리즘이 아래와 같이 변경됐다.
1. old 영역 중에 살아있는 객체를 식별한다. mark
2. 이전 GC를 수행하여 컴팩션된 영역에 살아있는 객체의 위치를 조사한다. sweep
3. 컴팩션을 수행하며 컴팩션된 영역과 비어있는 영역으로 나눈다. compact
CMS(Concurrent mark and sweep) : low-latency collector 라고 알려졌다. 힙 영역이 클 때 적합하며 minor GC 는 parallel GC 와 동일하며 major GC 의 알고리즘은 아래와 같다.
1. mark : 매우 짧은 대기 시간으로 살아 있는 객체를 찾음.
2. sweep : 서버 수행과 동시에 살아 있는 객체에 표시를 해놓음.
3. remark : concurrent 표시 단계(sweep)에서 표시 후 변경된 객체에 다시 표시하는 단계
4. concurrent sweep : 표시되어 있는 쓰레기를 정리하는 단계
G1 GC : garbage first GC. jdk 7 에서부터 기본이 됨. jvm의 heap 영역을 1MB 정도의 크기를 region 으로 나눠서 region 별로 generation을 지정하여 효율이 좋다. CMS 콜렉션과 유사한 방식으로 수행되며 객체의 유효화를 결정하는 동시에 마킹 단계를 수행하며 마킹 단계를 완료하고 나면 대부분 비어있는 영역을 알고 있음
바둑판 영역에 메모리를 할당하고 GC를 실행하는 데 해당영역이 꽉 차게 되면 다른 빈 영역에 메모리를 할당하는 방식
장점 : 긴 GC 에 의한 pause time 이 없는 compact 한 빈공간
GC 의 pause time 예측 가능
처리 성능 향상
Java Heap 을 많이 사용하지 않음
spring
dispatcherservlet?
- Servlet Container 에서 HTTP 프로토콜을 통해 들어오는 모든 요청을 프레젠테이션 계층 제일 앞에 둬서 중앙집중식으로 처리해주는 프론트 컨트롤러. 모든 요청의 진입점으로 공통 처리 작업을 먼저 수행한 후 적절한 세부 컨트롤러로 작업을 위임해준다. 컨트롤러가 작업을 완료하면 dispatcherServlet으로 모델과 뷰를 전달한다. 보통의 뷰의 이름을 전달해주면 dispatcherServlet 의 뷰 리졸버가 이를 이용해 뷰 오브젝트를 생성한다. 뷰 리졸버를 통해 뷰 오브젝트에게 모델을 전달하고 클라이언트에게 돌려줄 최종 결과물을 생성해달라고 한다. 뷰의 처리 결과가 dispatcherServlet 으로 전달되면 httpServletResponse오브젝트에 담아서 클라이언트로 넘긴다.
결국 dispatcherServlet 은 가장 앞 단에서 모든 요청에 대해 우선 처리를 하며 또한 가장 끝 단에서 클라이언트에게 결과물을 전달하는 역할을 한다.
interceptor, filter 의 역할
- interceptor 와 filter 모두 컨트롤러가 수행되기 전, 수행되고 나서 수행된다. filter 는 dispatcherServlet이 수행되기 전에 호출된다. 또한 filter 는 J2EE 표준 스펙에 정의되어 있는 기능이다. interceptor는 dispatcherServlet 을 거치고 나서 controller 가 호출 되기 전에 수행된다. spring framework 자체적으로 제공하는 기능이다.
일반적으로 filter 는 인코딩이나 보안과 같은 web app 전반적으로 처리해야 하는 로직을 구현하고, 클라이언트에서 들어오는 디테일한 처리, 인증 및 권한 등을 주로 interceptor에서 처리한다.
rest api?
- REpresentational State Transfer API(Application Programming Interface) 의 약자로 웹의 장점을 최대한 활용할 수 있는 네트워크 기반의 아키텍쳐. 리소스, 메소드, 메세지의 3가지의 구성요소를 가진다. 이를 REST 형태로 표현해보면
HTTP POST http://myweb/users/
{
"users": {
"name" : "Terry"
}
}
와 같은 형태로 표현되며, 메소드는 HTTP POST, 리소스는 http://myweb/users/라는 형태의 URI로 표현되며, 생성하고자 하는 디테일한 메세지는 json 형태로 표현하였다.
HTTP method : get(select), put(update), post(create), delete(delete) CRUD 네가지의 메소드를 가진다.
: Uniform Interface - REST 는 HTTP 표준만 따른다면 어떠한 기술이라도 사용이 가능하다. 예를 들어 HTTP - JSON 으로 REST 를 정의했다면 플랫폼에 종속되지 않고 어디서든 사용이 가능하다.
: Stateless - 무상태성으로 상태를 저장하지 않으며 각 API 서버는 들어오는 요청만을 들어오는 메시지로만 처리하면 된다.
웹 요청시 흐름
- 1. 웹 요청시 dns 서버를 통해 실제 주소를 읽음
2. http 요청 메세지를 서버로 TCP/IP를 통해 전송
3. 서버 내부 처리가 수행됨. (Spring으로 구현된 서버라면 dispatcherServlet 을 통과해 Controller 에서 로직을 수행하여 view 와 model 을 전달하게 됨)
4. 정상 처리 혹은 에러 처리 에 대한 응답 코드를 내려줌.
웹서버와 Spring 관계
-
HTTP keep-alive
- socket 에서 IN/OUT 의 access 가 마지막으로 종료된 시점으로부터 정의된 시간까지 access가 없더라도 대기하는 구조. 즉 정의된 시간 내에 access 가 이뤄지면 계속 연결된 상태를 유지할 수 있다.
connection time out 과 socket time out 의 차이
- Connection timeout 은 연결이 일정시간동안 연결이 이뤄지지 않은 경우에 발생한다. TCP 연결의 경우 3-way handshake가 이뤄지는 데 일정시간동안 최종 ack 값이 전달되지 않았다는 의미이다.
Socket timeout은 일반적으로 데이터를 전송할 때 여러 패킷으로 나누어서 데이터를 전달하게 되는데 마지막 데이터 패킷이 전달하지 않아 일정시간동안 계속 대기상태에 있을 때 발생하는 timeout 이다.
transaction과 isolation
- Transaction이 보장해야 하는 ACID
Atomicity : 원자성 한 트랜잭션 내에서 실행된 작업들은 하나의 작업으로 간주하여 모두 성공하거나 모두 실패하여야 한다.
Consistency : 일관성 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지한다. 이를테면 DB에서 정한 무결성 조건을 항상 만족.
Isolation : 격리성 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리되어야 한다.
Durability : 지속성 트랜잭션을 성공적으로 마치면 그 결과가 항상 저장되어야 한다.
이 중 격리성에 대한 이슈가 있는데, 격리성을 완벽히 보장하기 위해 모든 트랜잭션을 순차적으로 실행하면 동시성 처리 이슈가 발생한다. 반대로 동시성을 높이기 위해 여러 트랜잭션을 병렬처리하게 되면 데이터의 무결성이 깨질 수 있다.
interface
- 일종의 추상 클래스로, 추상메소드를 갖지만 기능이 구현된 메소드 또는 멤버변수를 구성원으로 가질 수 없다. 추상메소드와 상수만을 멤버로 가질 수 있다. 객체와 객체 사이에서 일어나는 일들의 상호 작용의 매개로 쓰인다. 클래스의 기본 틀을 제공하면서 다른 객체 사이에서의 중간 매개 역할도 담당한다. interface 를 상속하여 구현된 클래스들을 다양하게 정의하여 다형성을 구현할 수 있다. 또한 특정 객체에 종속하지 않도록 해준다.
DI 장점
- Dependency Injection. 의존성 주입. 특정 객체를 사용하기 위해 객체를 생성하게 되는데 이때 Spring은 직접 생성하는 것이 아니라 외부 IoC 컨테이너에서 생성된 객체를 주입시켜 setter나 생성자를 통해 사용할 수 있도록 해준다. 이렇게 외부의 설정에 의해 의존성을 주입하게 되면 사용하고 있는 객체를 변경하거나 해야 할 때 소스 코드를 수정할 필요 없이 외부 설정 값을 통해 의존성을 주입하면 된다.따라서 확장성과 유지보수가 용이해진다.
DL(Dependency Lookup)
- IoC 내에 저장되어 있는 빈에 접근하기 위하여 컨테이너에서 제공하는 API를 이용하여 사용하고자 하는 빈을 Lookup 하는 것. 컨테이너 API와 의존 관계를 많이 가지면 가질수록 어플리케이션에 종속되는 단점이 있다.
IoC(Inversion of control)
- 객체를 생성하고 객체간의 의존관계를 연결시키는 등의 제어권을 개발자가 아니라 컨테이너가 가지게 되었다. 객체의 생명주기를 관리하는 권한 또한 컨테이너들이 전담할 수 밖에 없게 되었다. 이처럼 객체의 생성에서부터 생명주기의 관리까지 모든 객체에 대한 제어권이 바뀐것을 의하는 것이 바로 제어권 역전.
AOP
- Aspect Orient Programming(관점 지향 프로그래밍). OOP 에서 객체를 재사용하면서 반복되는 코드는 많이 줄일 수 있었지만 로그, 권한 체크, 인증, 예외 처리 등 필수적으로 해야하는 소스는 반복될 수 밖에 없었다. 이런 부분을 해결한 게 AOP 이다. 로직이 수행되면서 사용되는 공통 모듈을 만들어서 코드 밖에서 비지니스 로직에 삽입하는 방식이라고 볼 수 있다.
정규화와 비정규화
- 정규화란 데이터베이스의 설계에서 중복을 최소화하여 데이터를 구조화하는 프로세스를 정규화라고 한다. 이상이 있는 관계를 재구성하여 작고 잘 조직된 관계를 생성한다. 일반적으로 정규화란 크고, 제대로 조직되지 않은 테이블들과 관계들을 작고 잘 조직된 관계들로 나누는 것을 포함한다.
비정규화. 되도록 중복된 데이터를 제거하여 성능을 향상할 목적으로 정규화를 수행하나, 과도한 정규화로 인해 테이블의 수가 증가하여 다수의 JOIN으로 오히려 성능의 저하가 발생 할 수 있다. 이럴 때는 비정규화를 통해 성능향상을 기대할 수 있다.
보통 정규화 과정을 모두 거친 다음 마지막으로 비정규화를 실시한다. 단순 테이블을 합치는 것만을 의미하진 않고, 합계와 같은 값을 미리 계산하여 테이블에 저장하거나, 자주 사용되는 행과 그렇지 않은 행들을 분리하거나, 다른 테이블에 의존적이지만 자주 JOIN 하여 사용하는 컬럼을 중복하여 테이블 안에 하나 더 생성하는 등의 비정규화 방법이 있다.
checked exception, unchecked exception
- checked exception : 컴파일 단계에서 확인이 되며 반드시 예외 처리를 해야 한다. 대표적으로 IOException, SQLException이 존재한다. 주로 외부의 영향으로 발생할 수 있는 것들로, 프로그램의 사용자들에 의해서 발생하는 경우가 많다. 존재하지 않는 파일을 처리하려하던가, 실수로 클래스의 이름을 잘못 적었다던가, 입력한 데이터의 형식이 잘못되었다던가, 하는 경우에 발생한다. 이런 경우에는 반드시 예외 처리를 해주어야 한다.
unchecked exception : 실행 단계에서 확인되며 명시적인 처리를 강제하지 않음. RuntimeException의 하위 Exception 들로 NullPointerException, IllegalArgumentException, IndexOutOfBoundException, SystemException 등이 있다.
주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들로 배열의 범위를 벗어난다던가, Null을 참조한다던가, 클래스 형변환을 잘못한다던가, 정수를 0으로 나누는 등으로 인해 발생한다.