자바 기술 면접에 필요한 지식들을 간단하게 요약해 봤습니다.
기초부터 심화까지 다양한 질문들을 담았습니다.
독립적 운영 JVM에서 동작하기 때문에, 운영체제에 독립적이다. 객체지향 프로그래밍 OOP - Object Oriented Programing 계층 구조, 캡슐화, 상속, 추상화, 다형성 등을 구현한 객체지향 언어다. 메모리를 자동으로 관리 Garbage Collection을 통해 불필요한 메모리를 자동으로 제거해 준다. 오픈 소스 오픈 소스로 풍부한 라이브러리가 제공된다. 오라클에 인수된 후에는 사용 목적에 따라 일부 유료화가 진행됐다. 멀티스레드 구현 공통 스레드 API를 제공해서 운영체제에 관계없이 멀티스레드를 쉽게 구현할 수 있다. 추상화 (Abstraction) 공통의 속성이나 기능을 묶어서 표현하는 방법 예) 동물을 대표하는 Animal Class 캡슐화 (Encapsulation) 높은 응집도(동일 클래스만 변경)와 낮은 결합도(다른 클래스 간섭 배제)를 유지하는 설계 방법 데이터 캡슐화 : 필드와 메소드를 클래스로 묶는 방법 은닉화 : 외부에서 객체 상태 변경에 제한을 두는 방법 (접근 제어) 예) Animal Class는 Human Class에서 접근 불가 상속 (Inheritance) 또는 일반화 (Generalization)자식 클래스가 부모 클래스를 물려받고 확장하는 개념 예) Animal Class를 Dog Class에서 상속해서 부모 클래스의 변수와 메서드를 사용 다형성 (Polymorphism) 동일 요청에 대해 서로 다른 방식으로 응답할 수 있는 방법 Overriding : 상속 받은 메소드를 재정의 Overloading : 동일 클래스의 동일한 메소드가 매개 변수의 타입이나 개수에 따라 다르게 동작 예) Animal Class의 Bark Method를 Cat Class의 Bark Method가 Overriding 해서 사용 흔히 OOP의 5대 원칙으로 불리며, 줄여서 SOLID라고 합니다.
S : 단일 책임 원칙 SRP : Single Responsibility Principle 객체는 단 하나의 책임만 가져야 한다. O : 개방-폐쇄 원칙OCP : Open Closed Principle 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계해야 한다. L : 리스코프 치환 원칙LSP : Liskov Substitution Principle 자식 클래스는 자신의 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다. I : 인터페이스 분리 원칙ISP : Interface Segregation Principle 클래스는 자신과 관련 없는 인터페이스는 구현하지 않는다. D : 의존 역전 원칙DIP : Dependency Iversion Principle 상위 모듈은 하위 모듈에 종속 되면 안되고, 둘 다 추상화에 의존해야 한다. 예) 상위 모듈인 자동차를 만드는데 하위 모듈인 스노우 타이어를 참조하지 말고, 상위 모듈인 타이어를 추상화 해서 사용한다. 코드의 재사용성 증가 유지보수 용이성 간결한 코드 높은 확장성 강한 응집력과 약한 결합력 보안성 향상 소프트웨어 생산성 향상 접근 제어는 객체의 변수, 함수, 클래스에 대한 접근 범위를 제한하는 용도입니다.
접근 제어를 사용하는 이유는 객체의 보안과 안정성 때문입니다.
그리고 접근 제어자를 명시하지 않으면, 기본으로 default 제어가 적용됩니다.
제어자 동일 클래스 동일 패키지 자식 클래스 전체 public O O O O protected O O O default O O private O
Method Area 클래스가 로딩될 때 할당된다. 패키지, 클래스, 인터페이스, 생성자, 메소드, 필드, Static 변수 등을 저장한다. 모든 스레드가 공유한다. Heap Area 런타임 시에 동적으로 할당된다. new 키워드로 생성된 객체와 배열이 저장되는 영역이다. Heap 영역에 생성된 객체와 배열은 Stack 영역의 변수에서 참조한다. Garbage Collector가 참조하지 않는 메모리를 제거한다. Stack Area 스레드마다 존재하며, 스레드가 시작될 때 할당된다. 지역변수, 파라미터, 리턴값, 연산에 사용되는 값 등이 생성되는 영역이다. 메소드를 호출할 때마다 개별적으로 스택이 생성되며 종료시 해제된다. 선입후출의 구조를 가진다. 기본 타입 변수는 Stack 영역에 직접 값을 가진다. 참조 타입 변수는 Method 영역이나 Heap 영역의 참조 주소를 가진다.
Runtime Data Area
static 클래스당 하나의 멤버가 생성되며, 클래스 멤버라고 부른다. 클래스 로딩 시에 자동으로 멤버가 생성된다. Method 메모리 영역에 저장된다. 동일 클래스의 모든 객체들에 공유된다. 전역 변수와 함수를 만들 때 활용된다. non-static 객체마다 멤버가 생성되며, 인스턴스 멤버라고 부른다. 객체 생성 시에 멤버가 생성된다. Heap 메모리 영역에 저장된다. 객체 내에서만 멤버가 활용된다. 추상 클래스는 추상 메서드가 하나 이상 포함된 클래스로 상속을 통해 사용합니다.
추상 클래스에는 일반 변수와 메서드도 정의가 가능합니다.
인터페이스는 추상 메서드로 구성되고 다중 상속이 가능합니다.
추상 클래스는 일부 구현된 설계도로 상속 받아서 확장을 하게 됩니다.
반면 인터페이스는 기본 설계도로 구현은 모두 따로 해줘야 합니다.
List 순서와 중복이 허용된다. 배열 크기가 가변적이다. 데이터가 커지면 속도 이슈가 있다. 인덱스로 원소에 접근한다. Map Key, Value 한 쌍으로 저장되고 순서가 없다. Key는 중복될 수 없다. Value는 중복이 허용된다. 별도 인덱스가 없다. 검색 속도가 빠르다. Set 순서가 없고 중복도 허용되지 않는다. 인덱스를 사용하지 않는다. 검색 속도가 빠르다. 먼저 프로그램이란 어떤 작업을 하기 위해 실행할 수 있는 파일을 의미합니다.
프로그램이 실행되면 메모리에 올라가며, 프로세스와 스레드에서 작업이 됩니다.
그래서 프로그램 > 프로세스 > 스레드 순으로 실행이 됩니다.
프로세스 (Process)컴퓨터에서 실행되고 있는 프로그램 메모리에서 실행되고 있는 프로그램의 인스턴스 운영 체제로 부터 시스템 자원을 할당 받는 단위 스레드 (Thread)프로세스가 할당 받은 자원을 이용하는 실행 단위 하나의 프로세스에 여러 스레드가 존재하며, 힙을 통해 공유 가능 자바 스레드 (Java Thread)자바 스레드는 JVM에 의해 실행되는 단위 코드 블록 멀티 스레드 구현을 통해 성능 향상 멀티 프로세스 (Multi Process)하나의 프로그램을 여러 개의 프로세스로 구성하여, 각각의 프로세스가 개별 작업을 빠르게 처리 문제 발생 시에 다른 프로세스에 영향을 주지 않음 프로세스 간에 통신 비용이 크고 복잡함 멀티 스레드 (Multi Thread)하나의 프로그램을 여러 개의 스레드로 구성하여, 각각의 스레드가 개별 작업을 빠르게 처리 자원의 효율성 증대 처리 비용 감소 및 응답 시간 단축 자원을 공유하면서 동기화 문제 발생 가능 어플리케이션이 시작될 때 한 번만 메모리에 할당되고 인스턴스가 생성됩니다.
이후 어플리케이션 전체에서 하나의 인스턴스를 사용하는 디자인 패턴입니다.
하나의 자원으로 전체에서 사용하므로 효율성이 올라갑니다.
반면, 사용성이 떨어지는 인스턴스는 메모리를 낭비할 수 있습니다.
멀티스레드 환경에서는 중복 생성을 방지하기 위해, 별도의 추가 설정이 필요합니다.
각각의 객체가 나눠진 이유는 디비 로직과 비즈니스 로직을 분리하고,
효율적으로 데이터를 처리하기 위해서 입니다.
EntityDB 테이블에 존재하는 컬럼들을 필드로 가지는 객체 Entity 클래스와 DB 테이블은 1대 1로 매칭 DAO Data Access Object 데이터베이스에 접근하는 객체 효율적인 디비 커넥션 관리와 보안성 DTO Or VOData Transfer Object Or Value Object 계층간 데이터를 교환하기 위한 자바 객체 DTO와 VO는 유사하지만, VO는 읽기만 가능 자바 서블릿은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버 프로그램입니다.
이후 여러 프레임워크에 다양한 용도로 사용되면서, 웹서비스를 위한 필수 기술로 자리 잡았습니다.
클라이언트 요청에 동적으로 응답 Java Thread를 이용해서 동작 HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속 Spring MVC는 DispatcherServlet을 통해, 클라이언트의 HTTP 요청을 Controller로 연결 서블릿 컨테이너 서블릿을 관리하고 웹서버와 통신해서 실행하는 역할 Tomcat, Jetty, WebLogic, Jeus 등 직렬화자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에서도 사용할 수 있도록, 바이트 형태로 데이터를 변환하는 기술 객체 데이터를 파일로 저장하거나 Stream 데이터로 전송 역직렬화직렬화된 데이터를 다시 자바 객체의 형태로 만드는 과정 저장된 파일을 읽거나 전송된 Stream 데이터를 원래 형태로 복원 병렬 처리(Parallel Operation)는 멀티 코어 환경에서 하나의 작업을 각각의 코어가 분할해서 처리하는 방법입니다.
작업을 분산해서 처리하기 때문에 빠른 처리가 가능합니다.
동시성 싱글 코어를 이용한 멀티 작업은 멀티 스레드가 번갈아 가며 실행되고 병렬 처리는 아니다. 싱글 코어에서는 병렬 처리 보다는 순차 처리가 유리하다. 병렬성 멀티 코어를 이용해서 동시에 멀티 작업을 처리한다. 데이터 병렬성 : 전체 데이터를 서브 데이터로 나눠서 병렬 처리하는 방법 작업 병렬성 : 서로 다른 작업을 병렬로 처리하는 방법 String메모리 영역에 생성되면 변경이 불가능하다. 문자열이 변경되면, 기존 객체는 남아있고 새로운 인스턴스가 생성된다. 잦은 문자열 변경은 성능 저하를 불러와서, 변경이 적은 경우에 주로 사용한다. 멀티 스레드 환경에서 동기화가 가능하다. StringBuffer / StringBuilderString과 달리 가변적으로 사용할 수 있다. 문자열 변경이 발생하면, 기존의 버퍼 크기를 늘린다. 잦은 문자열 변경에 유효하다. StringBuffer는 멀티 스레드 환경에서 동기화를 지원하지만, StringBuilder에 비해 성능이 떨어진다. 사용 결론String : 문자열 변경이 적은 경우 StringBuffer : 문자열 변경이 잦은 멀티 스레드 환경 StringBuilder : 문자열 변경이 잦은 싱글 스레드 환경 클래스나 메서드 등의 타입을 지정하지 않고, 외부에서 유동적으로 지정합니다.
제네릭을 활용하면 효율적이고 안정적인 프로그래밍이 가능합니다.
용도에 맞는 객체 생성이 가능하다. 타입을 별도로 변환할 필요가 없다. 컬렉션 클래스에서 제네릭을 사용해서, 컴파일 과정에서 미리 타입 체크가 가능하다. 자바의 기본 자료형(Primitive Type)에는 Wrapper Class가 있습니다.
기본 자료형을 객체로 사용하기 위해, 포장하는 클래스가 바로 Wrapper Class입니다.
그리고 컬렉션, 제네릭 등에서는 Wrapper Class만 사용이 가능합니다.
기본 자료형을 Wrapper Class로 변경 하면 박싱, 반대면 언박싱입니다.
기본 자료형 Wrapper Class boolean Boolean byte Byte char Character short Short int Integer long Long float Float double Double
IoC Inversion of Control (제어의 역전) 이전 : 자바 프로그램에서 개발자가 직접 객체의 생명 주기를 관리했다. 변경 : 객체의 생명 주기를 스프링 컨테이너가 관리한다. DI Dependency Injection (의존성 주입) 컨테이너에서 빈 객체를 생성해서 사용하는 방식이다. 빈 객체는 싱글턴 패턴으로 컨텐이너에서 하나만 생성된다. 개별 클래스에서 별도로 객체를 생성할 필요가 없다. AOPAspect Oriented Programming (관점지향 프로그래밍) 공통의 관심사를 모듈화 해서 제공하는 프로그래밍 방법 트랜잭션, 보안, 인증 등 공통 모듈이 대상 Spring IoC 컨테이너가 관리하는 자바 객체를 빈이라고 부릅니다.
개별 클래스에서 생성하는 객체는 빈이 아닙니다.
스프링에서 빈은 ApplicationContext에서 관리하는 객체를 의미합니다.
BeanFactory스프링 설정 파일에 등록된 Bean 객체를 생성하고 관리하는 역할 클라이언트의 요청이 있을 때 빈 객체를 생성 (Lazy Loading) ApplicationContext에서 대부분의 기능을 제공하므로 직접 사용은 거의 안함 ApplicationContextBeanFactory를 상속 받아서, 빈 객체를 생성하고 관리 컨테이너가 구동되는 시점에 빈 객체를 생성 (Pre Loading) IoC, DI 등 객체 생명 주기 전반을 관리 필터 (Filter)Dispatcher Servlet에 요청이 전달되기 전후로 작업을 진행한다. 보통 web.xml에 등록해서 인코딩, 보안 등 공통 처리를 담당한다. 인터셉터 (Interceptor)Dispather Servlet이 컨트롤러를 호출하기 전후로 작업을 진행한다. 로그인, 권한, 실행 시간, 로그 등 스프링 공통 기능들을 구현한다. AOP비즈니스 로직의 특정 시점이 수행되는 순간의 전후로 작업을 진행한다. 로깅, 트랜잭션, 에러 등 공통 모듈 기능을 주로 수행한다.
Spring MVC Request Lifecycle
람다식은 수학에서 차용한 함수로 프로그래밍에서는 익명의 함수를 의미합니다.
함수를 하나의 식으로 표현했고, 일급 객체에 해당합니다.
자바에서는 1.8부터 도입됐습니다.
단점재사용 불가 디버깅 어려움 많이 사용하면 오히려 중복 코드 양성 스트림은 자바 1.8부터 추가됐습니다.
배열 또는 컬렉션 데이터를 람다식으로 간편하게 다룰 수 있습니다.
또한 간단하게 병렬 처리가 가능합니다.
스트림은 데이터를 변경하지 않는다. 스트림은 일회용이다. 스트림은 작업을 내부 반복으로 처리한다. 스프링에서는 어노테이션 방식으로 트랜잭션 처리를 지원합니다.
@Transactional이 선언되면 프록시 객체가 생성되고, PlatformTransactionManager를 통해 트랜잭션 처리가 됩니다.
자바에서 리플렉션은 런타임 중인 클래스의 정보에 접근하는 프로그래밍 기법입니다.
리플렉션을 통해 클래스의 타입, 메소드, 변수 등 클래스의 상세 정보를 알수 있습니다.
동적 클래스를 사용할 때 필요하고, 어플리케이션 보다는 프레임워크나 라이브러리 개발에 많이 사용됩니다.
스프링의 어노테이션이 리플렉션을 이용한 대표적인 기능입니다.
Class c = Class.forName("클래스명");
Class s = c.getSuperclass();
Class[] it = c.getInterfaces();
Constructor[] cs = c.getConstructors();
Mehtod[] m = c.getMethods();
Field[] f = c.getFields();
var변수 재선언, 재할당 모두 가능 유연한 변수 사용이 가능 하지만, 코드가 많아지면 오류 가능성 높음 let변수 재선언은 불가능 하지만 재할당은 가능 ES6 부터 도입 const변수 재선언, 재할당 모두 불가능 ES6 부터 도입 클래스형 컴포넌트로직과 상태를 컴포넌트 안에 구현 state, lifeCycle 관련 기능 사용 가능 초기 리액트에서 많이 사용하던 방식 함수형 컴포넌트v16.8 부터 추가 state, lifeCycle 관련 기능 사용이 불가능 하지만, Hook을 통해 지원 컴포넌트 선언이 편리하고 메모리 효율이 높음 공식적으로 함수형 컴포넌트 + Hook 조합을 권장 대규모 트래픽을 처리하는 방법의 핵심은 분산입니다.
거기에 어플리케이션과 디비, 서버 등의 성능 향상도 필수입니다.
서버 분산로드 밸런싱 : 스위치를 통해 여러대의 서버로 분산 (온프레스미 환경) 오토 스케일링 : 어플리케이션을 모니터링 해서 서버 용량을 자동으로 조정 (클라우드 환경) 서버 성능Scale Up : 서버의 CPU, Memory 등 성능을 향상 Scale Out : 서버의 대수를 증가 어플리케이션 개선뷰나 데이터 등 서비스 기능에 따른 캐싱 설정 코드 품질 개선 및 비효율 프로세스 제거 디비 개선레플리카 : Master DB에는 쓰기, Slave DB에는 읽기 기능을 부여해서 분산 디비 정규화, 쿼리 튜닝, 설정 개선 로그나 통계 등 빅데이터는 Elastic, MongoDB 등 활용 파일 서버Staic : Image, JS, CSS 등 정적 파일 별도 서버 구성 (CDN) Upload : 별도 업로드 서버 구성 (CDN) 마이크로 서비스Rest API 시스템을 구축해서 서비스별로 트래픽을 분산 분산 캐시 서버 활용Memcached, Redis 등으로 요청 분산 Akamai CDN을 적용해서 캐싱 웹페이지 제공 부하 테스트 정책코드나 쿼리를 작성 후에 일정 수준의 부하 테스트를 통과하지 못하면 배포 금지 TPS(Transaction Per Second)나 응답 시간 등을 기준 자바의 핵심 기능 중에 하나가 바로 JVM을 통한 메모리 관리입니다.
가비지 컬렉션 기능을 통해서 사용하지 않는 메모리 공간을 자동으로 해제합니다.
보통의 프로젝트에서는 기본 가비지 컬렉터를 사용합니다.
하지만, 기능이나 성능 이슈가 있는 프로젝트는 가비지 컬렉터를 선택할 수 있습니다.
예전의 가비지 컬렉션의 동작 단계는 아래와 같습니다.
이후에 나온 가비지 컬렉터는 다른 방식으로 수행이 됩니다.
Mark메모리 영역을 스캔하면서 사용하지 않는 객체를 식별 Sweep사용하지 않는 객체의 메모리를 수거하고, 사용하는 객체만 남겨둔 상태 Compaction사용하는 객체들을 모으는 단계, 메모리 단편화와 오버헤드 방지를 위한 작업 Stop the world일시 정지 상태에서 가비지 컬렉션 작업을 진행 가비지 컬렉터의 종류는 아래와 같습니다.
Serial GC하나의 스레드가 메모리 관리를 순차적으로 수행 메모리와 CPU 리소스가 부족할 때 사용 Mark-Sweep-Compaction 단계를 수행 처리 속도가 느리고 Stop-the-world 상태가 길어서 상용 서비스에 비추천 Parallel GC멀티코어를 지원하고 여러 스레드에서 수행 Mark-Sweep-Compaction 단계를 여러 스레드에서 빠르게 수행 Stop the world 시간 단축 Parallel Old GCParallel GC에서 Old 영역의 방식을 차별화 Old 영역은 Mark-Summary-Compaction 단계를 수행 CMS GC (Concurrent Mark Sweep)어플리케이션의 응답 속도가 중요한 경우 사용 중간중간 Stop the world를 해제해서 정지 시간 최소화 다른 GC 방식 보다 메모리와 CPU 사용량 증가 Initial Mark -> Concurrent Mark -> Remark -> Concurrent Sweep Compaction은 메모리 단편화가 심한 경우에만 수행 G1 GC (Garbage First)Java 7부터 사용 가능 대용량 메모리와 멀티코어 환경에서 효율적으로 동작 CMS GC를 대체하기 위한 용도 메모리를 동일 사이즈의 여러 리전으로 구분해서 사용 자바는 컴파일 언어입니다.
그래서 코드를 작성한 후에 컴파일러로 바이트 코드를 생성해서 실행합니다.
Java Compile
JVM이 실행되면 Class Loader에서 필요한 클래스들을 메모리에 저장합니다.
이후에 Memory, Execution Engine, JNI에서 이벤트에 따라 처리가 됩니다.
JVM Process
면접은 늘 어렵습니다. 간혹 쉬운 면접도 있지만, 언제나 아쉬움은 남습니다.
그래도 성공한 면접이든 실패한 면접이든 항상 배움은 있습니다.
중요한 건 면접을 통해 한 발 더 나아가는 자세입니다.
면접은 자신의 부족한 부분을 채울 수 있는 좋은 기회이기 때문입니다.
그리고 회사도 인연이라는 생각을 합니다.
정말 가고 싶었던 회사도 막상 나와 맞지 않으면 소용이 없습니다.
반대로 기대가 없던 회사였는데, 면접에서 좋은 느낌을 받는 경우도 종종 있습니다.
면접은 나와 좋은 인연을 이어갈 회사를 찾는 과정입니다.
그 과정 속에서 최선을 다한다면, 분명 좋은 결과를 얻을 수 있을 겁니다.