https://github.com/VSFe/Tech-Interview/blob/main/05-ETC.md 의 면접질문들에 대한 답을 나름대로 정리한 포스팅
가상화
하나의 물리적인 하드웨어 시스템에서 여러개의 독립된 컴퓨팅 환경을 만들어내는 기술
독립된 컴퓨팅 환경은 모두 소프트웨어로 구현된다.
가상 머신
도커는 컨테이너 기반 가상화를 이용한다.
일반적으로 가상머신을 사용하는 이유는 프로세스에 있다.
프로세스를 호스트 머신과는 독립되는 환경에서 구동하고 싶은 마음에 가상머신을 사용한다.
그러나 전통적인 가상머신은 프로세스 뿐 아니라 OS, Virtual NIC과 같은 컴퓨팅 환경 구성요소를 실행하기 위해 많은 리소스를 사용한다.
반면 컨테이너 기반 가상화는 프로그램과 프로그램을 실행하기 위한 라이브러리, 바이너리 파일만을 하나의 컨테이너로 묶은 뒤 독립된 환경에서 실행한다.
도커 엔진이 OS, Virtual NIC과 같은 동작을 대신해준다.
따라서 컨테이너가 여러개더라도 여러개의 OS, Virtual NIC이 생기지 않아 리소스가 절약된다.
각 컨테이너는 공통 운영 체제 커널을 공유한다.
도커 컨테이너를 관리하고 실행하는 백그라운드 서비스인 도커 데몬이 각각의 컨테이너가 정해진 논리 공간에 배정될 수 있도록 한다.
프로세스 격리 기본 단위인 네임스페이스를 사용하여 시스템 리소스 범위를 한정하여 각 컨테이너가 자신만의 독립된 환경을 가지도록 한다.
각 컨테이너에 할당된 리소스를 제한하고 관리하는 cgroups(Control Groups)를 통해, 한 컨테이너가 과도하게 리소스를 사용하여 다른 컨테이너의 성능에 영향을 미치는 것을 방지한다.
도커 데몬은 호스트 운영체제에서 실행된다.
Continuous Integration
지속적 통합
애플리케이션의 새로운 코드 변경 사항이 정기적으로 빌드 및 테스트되어 공유 레포지토리에 통합되는 것
Continuous Deployment
CodeDeploy와 S3, Github Action을 사용하여 CI/CD를 구축하였다.
GitHub-hosted runner에서 테스트 및 빌드 진행
S3에 빌드 파일 업로드
S3에 업로드 된 빌드 파일을 EC2에 가져와서 실행
자바 기준
static 키워드는 정적이라는 의미를 가지며, 객체 인스턴스에 종속되지 않는다는 의미를 갖는다.
static 키워드가 붙은 변수는 Method Area에 저장된다.
반면 일반적인 멤버 변수들은 객체 인스턴스가 생성되었을 때 Heap 공간에 생성된다.
멤버 메서드, static 메서드는 키워드 상관없이 Method Area에 생성된다.
static 변수들은 GC에 의해 수집되지 않고 프로그램 실행부터 종료까지 유지된다.
static 변수에 의해 참조되는 static 객체들은 참조 변수를 가진 클래스가 언로드되면 GC의 대상이 된다.
언로드는 동적으로 로드된 클래스를 JVM에서 해재하는 것으로 흔히 일어나진 않는다.
표준 자바 애플리케이션에서는 클래스가 한 번 로드되면 프로그램이 종료될 때까지 JVM에 남아 있는다.
클래스 멤버 변수에 붙은 static 키워드
멤버 변수가 특정 객체에 종속되지 않고 클래스 자체에 속함을 의미한다.
객체가 생성되지 않아도 해당 멤버 변수에 접근할 수 있다.
클래스 내의 메서드에 붙은 static 키워드
해당 메서드가 객체 인스턴스가 아닌 클래스 자체에 속함을 의미한다.
객체 인스턴스가 아닌 클래스 변수를 사용해 static 메서드에 접근할 수 있다.
중첩 클래스에 붙은 static 키워드
중첩 클래스가 외부 클래스에 종속되지 않고 독립적인 클래스임을 의미한다.
static 키워드가 붙은 중첩 클래스는 외부 인스턴스에 대한 참조가 없다.
자바 기준
static 키워드가 붙은 변수, 함수는 모드 Method Area에 저장되어, 인스턴스를 생성하지 않아도 언제든 호출할 수 있다.
프로그램을 실행하면 Class Loader가 프로그램 실행에 필요한 클래스 파일들을 JVM위에 적재한다.
Loading 과정에서 클래스의 바이트코드를 Method Area에 저장하는데, 이때 static 메서드들도 저장된다.
Linking 과정에서 클래스 변수들을 기본값(0 또는 null)으로 초기화시킨다.
Initialization 과정에서 클래스 변수들을 코드에서 지정한 값들로 초기화시킨다.
static final
클래스 전체에서 공유되는 불변 값
클래스가 로드될 때 초기화되고 이후 변경할 수 없다.
static만 붙은 경우엔 변경할 수 있다.
final만 붙은 경우엔 특정 인스턴스에 종속된 불변값을 나타내고, 클래스 전체에서 공유되지 않는다.
객체는 상태와 행동을 가지는 복합적인 존재로 스스로 판단하고 행동하는 자율적인 존재이다.
객체지향 프로그래밍이란 이러한 객체들의 협력을 통해 기능을 구현하는 프로그래밍 패러다임이다.
Single Responsibility Principle
단일 책임 원칙
클래스는 단 한가지의 변경 이유만을 가져야 한다.
Open-Closed Principle
개방-폐쇄 원칙
소프트웨어는 확장에 대해 열려있어야 하고, 수정에 대해서는 닫혀있어야 한다.
기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있어야 한다.
Liskov Substitution Principle
리스코프 치환 원칙
부모 클래스를 자식 클래스로 대체하더라도 시스템이 문제없이 동작할 것임을 보장해야 한다.
코드의 변경 없이 새로운 자식 클래스와 협력할 수 있어야 한다.
Interface Segregation Principle
인터페이스 분리 원칙
비대한 인터페이스는 응집도있는 특화된 인터페이스로 분리해야 한다.
Dependency Inversion Principle
의존성 역전 원칙
상위 수준 클래스는 하위 수준 클래스에 의존해선 안된다.
전통적인 소프트웨어 개발에선 상위 수준 모듈이 하위 수준 모듈에 의존한다.
상위 모듈, 하위 모듈 모두 추상화에 의존함으로써 전통적인 의존성 구조를 뒤집는다.
많은 형태를 가질 수 있는 능력
하나의 추상 인터페이스에 대해 서로 다른 구현을 연결할 수 있는 능력
메시지 전송 객체는 동일한 메시지를 전송하지만, 실제로는 어떤 메서드가 실행될 것인지는 메시지 수신 객체의 클래스가 무엇이냐에 따라 달라지는 특성
메시지를 전송한다는 것은 메시지 수신 객체의 메서드를 호출한다는 것을 의미한다.
정적 다형성
컴파일 시점에 결정되는 다형성
메서드 오버로딩이 대표적
같은 이름의 메서드지만 매개변수의 타입이나 개수로 각 메서드를 구별할 수 있다.
어떤 메서드가 호출될지는 컴파일 시점에 결정된다.
동적 다형성
런타임 시점에 결정되는 다형성
메서드 오버라이딩이 대표적
부모 클래스의 메서드를 자식 클래스에서 재정의하는 것
어떤 메서드가 호출될지는 런타임 시점에 주입된 실제 인스턴스 타입에 의해 결정된다.
오버로딩은 정적 다형성의 대표적인 예시로 컴파일 시점에 어떤 메서드가 호출될 지 결정된다.
오버라이딩은 동적 다형성의 대표적인 예시로 런타임 시점에 어떤 메서드가 호출될 지 결정된다.
객체지향 언어를 만족하기 위해선 3가지 기능이 있어야 한다.
캡슐화
상속성
다형성
따라서 클래스 지원 여부와 상관없이 다음의 기능을 만족한다면 객체지향 언어, 만족하지 않는다면 객체지향 언어가 아니다.
자바스크립트의 경우 클래스가 없지만 기존 객체를 복사하여 새로운 객체를 만들어내는 프로토타입이라는 개념을 사용하여 객체지향을 위한 기능들을 만족하는 객체지향 언어이다.
프레임워크
애플리케이션 개발자가 요구사항에 맞게 커스터마이징 할 수 있는 애플리케이션 골격
부분적으로 구현된 추상 클래스, 인터페이스 집합, 다양한 컴포넌트들을 제공
프레임워크가 개발자가 구현한 서브클래스를 사용하는 제어의 역전이 일어난다.
애플리케이션 개발에 필요한 기본적인 기능들과 설계를 제공함으로써 개발 속도를 높이고 재사용성과 일관성을 높일 수 있도록 도와준다.
라이브러리
특정 기능을 수행하는 독립적인 코드들의 집합
개발자가 필요한 기능을 사용하고 싶을 때 필요한 라이브러리를 호출하여 사용한다.
개발자가 애플리케이션의 흐름을 제어하며, 필요한 라이브러리를 호출한다.
개발자는 다양한 라이브러리를 사용함으로써 시간을 절약하고, 품질과 안전성을 높이고 기능을 쉽게 확장할 수 있다.
프레임워크와 라이브러리의 가장 큰 차이는 제어의 역전 여부이다.
프레임워크는 애플리케이션의 흐름을 프레임워크가 정하고 제어한다.
라이브러리는 애플리케이션의 흐름을 개발자가 정하고 제어한다.
Call By Value
메서드를 호출할 때 값을 넘겨주는 것
호출자의 변수와 파라미터로 넘어간 변수는 복사된 서로 다른 변수이다.
메서드에서 값을 변경해도 호출자의 변수에 영향을 주지 않는다.
Call By Reference
메서드를 호출할 때 참조값을 넘겨주는 것
호출자의 참조값과 파라미터로 넘어간 참조값은 완전히 같은 변수이다.
메서드에서 참조값을 변경하면 호출자의 참조값 변수도 변경된다.
자바는 Call By Reference를 지원하지 않는다.
호출자가 가진 객체에 대한 참조값이 파라미터로 넘어갈 때 복사되어 전달된다.
즉, 호출자의 참조값과 파라미터로 넘어간 참조값의 내용물은 같고, 같은 객체를 가리키지만 같은 변수는 아니다.
메서드 안에서 복사된 참조값을 통해 객체의 상태를 변경할 순 있지만,
메서드 안에서 참조값을 변경하더라도 호출자의 참조값이 영향을 받지 않는다.
자바가 Call By Reference를 지원하지 않는 이유
메모리 관리를 개발자가 아닌 가비지 컬렉션을 통해 하기 위해서 메모리 관리가 복잡해지도록 하지 않기 위해서
기본 데이터 타입, 참조 타입 모두 동일하게 Call By Value로 동작함으로써 일관성을 유지하기 위해
C++의 복잡성을 줄이고 객체지향 프로그래밍 언어의 특성에만 집중하기 위해서
함수형 프로그래밍
부작용이 없는 순수 함수를 사용하는 프로그래밍 패러다임
시스템의 다른 부분에 영향을 주지 않으므로 유지보수가 쉽다.
메서드가 서로 간섭하지 않으므로 lock을 사용하지 않고 쉽게 멀티스레드로 동작할 수 있다.
순수 함수
부작용이 없고 참조 투명성을 갖는 함수
부작용이란, 함수 내에 포함되지 않고 시스템의 다른 부분에 영향을 미치는 기능을 말한다.
참조 투명성이란, 같은 인수로 함수를 호출했을 때 항상 같은 결과를 반환하는 함수를 말한다.
Side Effect (부작용)란, 함수 내에 포함되지 않고 시스템의 다른 부분에 영향을 미치는 기능을 말한다.
외부의 자료구조를 고치거나 객체 필드에 값을 할당 & 변경하는 것
예외를 발생시키는 것
I/O 동작을 수행하는 것 모두 Side Effect에 해당한다.
Side Effect는 프로그램의 상태를 예측하기 어렵게 만들어 버그를 유발하기에 가능한 한 줄이는 것이 좋다.
그러나 이를 제거하는 것이 불가능하거나 성능상 비효율적일 수도 있다.
애플리케이션 동작을 위해 필요한 I/O 동작(외부 API, DB, 파일 입출력, 사용자 입력)을 전부 제거할 수 없다.
사용자 세션 정보나 애플리케이션 설정 값과 같은 상태를 기록하거나 변경해야 할 수도 있다.
불변 객체를 계속해서 생성하는 방식은 객체를 재사용하는 것보다 성능에 부정적일 수 있다.
시스템의 다른 부분에 영향을 주지 않으므로 유지보수가 쉽고 버그 발생이 적다.
메서드가 서로 간섭하지 않으므로 lock을 사용하지 않고 쉽게 멀티스레드로 동작할 수 있다.
동시성 문제는 여러 스레드가 동시에 공유 변수를 참조하거나 조작할 때 발생한다.
그러나 순수함수는
참조 투명성을 지키기 위해 변경되는 공유 변수를 참조하지 않는다.
부작용을 없애기 위해 공유 변수를 변경하지도 않는다.
따라서 순수함수는 Thread Safe하다 할 수 있다.
일급 함수
일반 값처럼 취급할 수 있는 함수를 일급 함수라 한다.
함수를 파라미터로 전달할 수 있고
함수를 메서드의 결과값으로 반환할 수 있고
함수를 자료구조에 저장할 수 있다.
함수를 인자로 받거나 함수를 결과로 반환하는 함수를 고차 함수라 한다.
서블릿
자바 웹 애플리케이션에서 동적인 웹 페이지를 생성하기 위한 자바 클래스
WAS에서 동작
HTTP 요청을 받아 생성한 동적인 컨텐츠를 HTTP 메시지에 담아 응답한다.
서블릿이나 JSP (템플릿 엔진, HTML내에 자바 코드를 삽입하여 동적인 웹 페이지 생성) 가 비즈니스 로직과 뷰 렌더링을 모두 처리하면 하나의 클래스가 너무 많은 역할을 갖기에 유지보수가 어려워진다.
또한 비즈니스 로직과 뷰 렌더링의 수정 주기는 다르고 서로 독립적인 이유로 발생한다.
MVC란 역할에 따라 소프트웨어 구성요소를 Model, View, Controller로 나눔으로써 유지보수가 편해지는 디자인 패턴
Model
데이터와 관련된 부분 (Entity, DTO, VO, Domain Object..)
Controller와 View를 제어해선 안된다.
View
사용자에게 보여지는 부분
Model에만 의존해야 한다.
Controller
Model과 View를 이어주는 부분
Model과 View에 의존해도 된다.
View가 Model로부터 데이터를 받기 위해서는 반드시 Controller를 통해 받아야 한다.
MVP (Model - View - Presenter)
MVC 패턴은 Controller가 사용자 Input을 받아 Model의 상태를 변경하고, 필요한 Model을 View에게 넘기는 등 하는 일이 많다.
MVP 패턴은
View가 사용자 Input을 받고, 사용자 Input을 Presenter에게 넘기고, Presenter에게 결과물 Model을 받아 View를 그린다.
Presenter는 사용자 Input을 받아 Model의 상태를 변경하고, 필요한 Model을 View에게 다시 건넨다.
View에 맞는 Presenter가 하나만 있는 1대1 관계
MVVM (Model - View - ViewModel)
MVP 패턴은 View와 Presenter가 일대일 관계이기에 번거롭다.
MVVM 패턴은
View가 사용자 Input을 받고, 사용자 Input을 ViewModel에게 넘긴다.
ViewModel은 사용자 Input을 받아 Model의 상태를 변경하고, 자신의 상태를 변경하기만 한다.
여러개의 View가 하나의 ViewModel을 관찰할 수 있는 다대일의 관계
MVP와 MVVM은 비즈니스 로직과 사용자 입력을 분리함으로써 비즈니스 로직의 테스트 용이성을 높인다.
MVC는 비교적 간단한 구조를 가진다.
소프트웨어 디자인 과정에서 자주 발생하는 문제들을 해결하기 위한 일반적인 해결책 혹은 청사진
많이 시도되고 검증된 해결책들이므로 이를 참고하여 다양한 문제들을 해결하는 데 적용할 수 있다.
빌더 패턴
프록시 패턴
데코레이터 패턴
싱글톤 패턴
하나의 인스턴스만 생성하여 재사용함으로써 메모리를 효율적으로 사용할 수 있다.
하나의 인스턴스만 생성하도록 구현하는 것이 까다롭다.
생성자를 막아버리기에 테스트 환경에서 mocking이 어렵고, 상속이 어려워 다형성을 활용하기 어렵다.
내부 static 클래스 (LazyHolder) 가 JVM에 로드 & 초기화 될때 싱글톤 인스턴스를 생성하게 함으로써 다중 스레드에서의 인스턴스가 1개 이상 생성되는 문제를 해결할 수 있다.
프로그래머가 동적으로 할당한 메모리 영역 중 더이상 쓰이지 않는 영역을 자동으로 찾아내어 해제하는 기능
Tracing Garbage Collection 방식
프로그램을 실행하다가 특정 타이밍에 현재 할당된 모든 메모리를 조사하여 현재 접근 가능한지 불가능한지 분류한 뒤, 접근 불가능한 메모리를 쓰레기로 간주하여 해제시키는 방식
항상 접근 가능한 메모리 (root)를 기준으로 참조가능한 메모리를 반복 접근하여 접근 가능/불가능한 메모리를 분류한다.
불가능한 메모리는 전부 할당 해제한다.
mark and sweep 방식
stop the world가 발생한다.
Reference Counting Based Garbage Collection
다른 메모리가 어떤 메모리를 얼마나 많이 참조하는지 횟수를 세어서 접근 가능과 불가능을 나누는 방식
참조 횟수가 0이되면 해당 메모리에 아무도 접근을 못하는 것이므로 해당 메모리를 해제한다.
구현이 쉽지만 모든 대입문마다 참조 횟수를 변경해야 하므로 오버헤드가 발생한다.
순환 참조 문제가 발생하면 해당 객체들이 해제되지 않아 메모리 누수가 발생한다.
자바는 Tracing Garbage Collection 방식을 사용한다.
주로 힙 영역에 있는 데이터를 관리한다.
힙 영역은 다음과 같이 세분화된다.
Young Generation
Eden, Survivor Spaces (S0, S1)
새로 생성된 객체는 Eden에 할당된다.
Eden이 가득차면 Minor GC가 발생하여, 참조되는 객체들이 Survivor Spaces로 옮겨진다.
Old Generation
Young Generation에서 오랫동안 살아남은 객체가 이동되는 영역
영역이 가득차면 Major GC가 발생한다.
장점
메모리 관리 자동화
메모리 안전성
개발 생산성 향상
단점
GC 실행 시 애플리케이션 속도 저하
추가적인 CPU 사용
CPU가 데이터를 처리할 때 사용하는 레지스터의 크기를 의미한다.
32비트 시스템에서는 주소 레지스터가 32비트 크기이므로 최대 4GB 메모리 공간에 대한 주소를 지정할 수 있다.
64비트 시스템에서는 주소 레지스터가 64비트 크기이므로 무한에 가까운 메모리 공간 주소를 가질 수 있다.
인증 (Authentication)
인가 (Authorization)
Open Authorization
OAuth의 주 목적은 인가이다.
사용자가 로그인을 하여 자신을 증명하는 것은 인증이지만
인증된 사용자가 자원에 대한 접근 권한을 애플리케이션에게 부여하기 위한 인가 프로토콜이다.
애플리케이션 서버는 자신의 id, password, 사용자로 부터 받은 인가코드를 권한 서버로 보내 액세스 토큰을 받아오고 (권한 서버로부터 인가)
액세스 토큰을 리소스 서버에 보내 자원을 받아온다. (리소스 서버로부터 인가)
JSON Web Token
JSON의 형태로 된 데이터를 네트워크롤 통해 안전하게 주고 받기위해 사용한다.
Header, Payload, Signature로 구성된다.
Header는 JWT가 어떤 알고리즘으로 디지털 서명되었는지 알려준다.
Payload는 주고받고 싶은 데이터가 들어간다.
Signature는 Header와 Payload를 Header에 명시한 알고리즘으로 암호화 한 전자 서명이다.
Header와 Payload는 Base64로 인코딩되어 있다.
Header와 Payload를 Header에 명시한 알고리즘으로 암호화 한 전자 서명이다.
Header와 Payload는 Base64 인코딩값을 그대로 사용하고, 둘은 .으로 구분하여 합친다.
Access Token의 사용 정지를 위해 블랙 리스트를 생성하여 관리하거나
Access Token이 탈취될 것을 대비해 유효 시간을 짧게 설정할 수 있다.
Access Token과 마찬가지로 블랙 리스트를 생성하여 관리하거나
Refresh Token Rotation 방식을 통해 발급받은 Refresh Token을 1회용으로 만들어 탈취되더라도 무용하게 만들 수 있다.
단방향 암호화
암호화는 가능하지만 복호화가 불가능한 암호화 기법
사용자 비밀번호와 같이 서버가 알아서는 안되는 정보를 암호화할 때 사용된다.
주로 해싱 알고리즘을 사용한다.
양방향 암호화
복호화가 가능한 암호화 기법
대칭키 방식과 비대칭키 방식이 있다.
대칭키 방식은 하나의 키를 사용해 암호화/복호화를 수행하며 속도가 빠르다. (AES)
비대칭키 방식은 암호화와 복호화에 각각 다른 키를 이용하며 속도가 느리다. (RSA)
일반적으로 혼합하여 사용한다.
현존하는 많은 문자열들을 어떤 바이너리 형태로 나타낼 것인지 약속한 규격
컴퓨터는 숫자로만 정보를 처리할 수 있기에 텍스트 데이터를 숫자로 변환하기 위해 다양한 인코딩 방식이 사용된다.
Base64 인코딩
64개의 문자를 사용하여 데이터를 인코딩한다.
원본 데이터를 6비트씩 나누어 하나의 ASCII 문자로 변환한다.
ASCII 문자 하나는 8비트이기에 Base64 인코딩은 데이터 크기를 증가시킨다.
=
를 추가한다.초기 HTTP 프로토콜이 ASCII 기반으로 개발되었기 때문에 사용하였다.
Web에서 사용하는 HTML문서는 ASCII로 구현되어 있는데, 이런 문서에 ASCII로 표현할 수 없는 바이너리 데이터를 포함하고자 할 때 사용할 수 있다.
데이터가 전송될 때 수정되지 않고 온전히 전송될 수 있도록 도와준다.
ex) 작은 이미지와 같은 바이너리 데이터를 Base64로 인코딩하여 HTML 문서에 포함하기
소스코드 버전 관리 시스템
소프트웨어 개발에서 소스코드의 변경 사항을 추적하거나 협업을 위해 사용한다.
Merge
Fast-Forward Merge: 대상 브랜치가 현재 브랜치의 부모인 경우, 단순히 대상 브랜치를 앞으로 이동시킨다.
Three-Way Merge: 두 브랜치가 공통 조상을 가지는 경우, 병합 커밋을 생성하며 합친다.
Squash Merge: 여러 커밋을 하나의 커밋으로 압축하여 병합한다.
Rebase
Standard Rebase: 병합할 브랜치의 커밋을 현재 브랜치 위로 재배치한다.
Interactive Rebase: 커밋을 편집하거나 스쿼시하면서 합칠 수 있다.
출처
https://www.youtube.com/watch?v=zh0OMXg2Kog
https://velog.io/@zsmalla/%EA%B0%80%EC%83%81%ED%99%94%EC%99%80-%EB%8F%84%EC%BB%A4-Virtualization-Docker#-%EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4-docker%EB%8A%94
가상화https://www.youtube.com/watch?v=O6Y4vSrWrUI
https://limdevbasic.tistory.com/28
https://www.youtube.com/watch?v=dG4FrwfRTdM
statichttps://www.youtube.com/watch?v=B8b0WHwYJgk
call by value, call by referencehttps://www.youtube.com/watch?v=-YLSKwZaCUM&t=2s
자바와 call by valuehttps://www.youtube.com/watch?v=ogaXW6KPc8I
MVChttps://www.youtube.com/watch?v=bjVAVm3t5cQ
MVC, MVP, MVVM