
벡엔드 개발자 면접 질문(기술면접) 질문 정리 모음 - CS
2021-04-08 01:00 시에 저장한 글입니다.
백엔드 면접 질문용 공부 후 정리 자료입니다. 정확하지 않을 수 있으니 꼭 다시 책이나 자료를 참고하여 공부하세요
CS 관련 지식
1) 네트워크
2) Long-Polling과 Websocket, Server-Sent Event
(1) Polling
- 클라이언트가 서버에서 HTTP Request를 주기적으로 요청하고, 서버가 응답하는 방식
- 클라이언트가 주기적으로 요청을 하기 때문에 클라이언트의 수가 증가하면 요청의 수도 함께 증가하기 때문에 서버의 부담이 커짐
- 또한, 요청과 응답후에는 연결이 끊어지기 때문에 요청할 때마다 항상 연결을 맺는 과정이 필요
- 이 부분에서 많은 비용이 소모.
(2) Long Polling
- 클라이언트가 서버에 HTTP Request를 요청하면, 서버는 대가하고 있다가 이벤트가 발생했을 때, 클라이언트에게 응답을 하는 방식이다.
- Polling 처럼 불필요한 요청에 계속 응답하는 것이 아니기 때문에 요청에 따른 커넥션 맺는 과정에서 발생하는 비용이 줄어듦
- 클라이언트의 수가 증가하면 그에 따른 응답을 해야하는 수도 증가하기 때문에 Polling과 큰 차이는 없게 됨
- 다수의 클라이언트가 동시에 이벤트가 발생할 경우 서버는 각 클라이언트에게 응답을 하게 되고, 그 다수의 클라이언트는 서버에게 곧바로 요청을 하기 때문에 이 순간 서버의 부담이 커짐
(3) Streaming
- 클라이언트와 서버 사이의 연결을 끊지 않고 필요한 메세지를 계속 전달하여 커넥션을 맺는 과정에서 발생하는 부담 경감
(4) WebSocket
- 클라이언트와 서버간의 전이중 통신을 지원하기 위한 통신 프로토콜
(1) 클라이언트와 서버간에 전이중 통신을 수행하려면 클라이언트가 서버로 HTTP UPGRADE 요청을 보내야 한다. 이를 웹 소켓 프로토콜 핸드 쉐이크라고한다.
(2) 서버가 커넥션을 UPGRADE 할 수 있는 경우, HTTP 101 응답을 클라이언트에게 보냄
서버는 핸드 쉐이크가 성공적으로 수행되었다고 판단하고, 서버와 클라이언트 사이의 커넥션을 웹 소켓 프로토콜로 UPGRADE 한다.
클라이언트와 서버 사이의 HTTP 101 응답이 전달되는 순간, 서버와 클라이언트 사이의 커넥션은 HTTP 프로토콜이라고 하지 않는다.
그리고 이순간 양방향 통신이 가능해진다.
(3) 웹 소켓으로 연결된 모든 클라이언트는 다른 클라이언트에게 커넥션을 끊는 요청을 전송
2) TCP와 UDP
- TCP와 UDP : 전송 계층에서 패킷을 보내기 위한 프로토콜
(1) TCP (Transmission Control Protocol)
- 연결형 서비스
- 3-way handshaking 과정을 통해 연결을 설정하고, 4-way handshaking을 통해 해제
- 높은 신뢰성과 전송 순서를 보장
- 1:1 통신에서 사용
- UDP보다는 속도가 느림
- 파일전송과 같은 신뢰성이 중요한 서비스에 사용
(2) UDP (User Datagram Protocol)
- 비연결형 서비스.
- 패킷을 주고 받을 때 신호 절차를 거치지 않음
- 신뢰성이 낮으며 전송 순서가 바뀔 수 있음
- 1:N 이나 N:N 통신에서 사용
- TCP보다 속도가 빠름
- UDP도 개발자가 직접 신뢰성을 보장하도록 할 수 있음. HTTP/3은 QUIC이라는 프로토콜을 기반으로 하는데, QUIC은 UDP를 기반으로 함
- 스트리밍, RTP와 같이 연속성이 더 중요한 서비스에 사용
(3) TCP 3, 4 way handshake
TCP 3way handshake- 가상회선을 수립하는 단계
- 클라이언트는 서버에 요청을 전송할 수 있는지, 서버는 클라이언트에게 응답을 전송할 수 있는지 확인하는 과정
- SYN, ACK 패킷을 주고받으며, 임의의 난수로 SYN 플래그를 전송하고, ACK 플래그에는 1을 더한값을 전송
- 장치들 사이의 접속을 성립하기 위한 절차로 양 장치 모두 데이터 통신 준비가 되었다는 것을 보장
- SYN(n) -> ACK(n + 1) / SYN(m) -> ACK(m + 1) (SASA)
(4) TCP 4way handshake
- 연결을 해제하는 단계
- 클라이언트는 서버에게 연결해제를 통지하고 서버가 이를 확인하고 클라이언트에게 이를 받았음을 전송해주고 최종적으로 연결 해제
- 단, 서버에서 소켓이 닫혔다고 통지해도 클라이언트 측에서는 일정시간 대기하는데, 혹시나 패킷이 나중에 도착할 수 있기 때문
- 장치들 사이의 통신을 종료하기 위한 절차
- FIN (Client) -> ACK (Server) -> FIN (Server) -> ACK(Client) (FAFA)
4) HTTP와 HTTPS
- 웹 프로토콜 : 웹에서 쓰이는 통신규약
- 민감한 정보가 있는 페이지의 경우 Https 그렇지 않으면 http
- Http 1.1과 2.0: 속도의 차이 : 2.0같은 경우는 헤더를 압축해서 보내기도하고, 한번의 연결로 동시에 여러 메시지를 주고 받음
(1) HTTP
- 웹 프로토콜중 하나로 HTTP가 가장 많이 쓰임. 요청과 응답으로 이루어져 있어 어떤 데이터를 요청하면, 어느 데이터를 준다고 응답
- 따로 암호화 과정을 거치지 않음
- http방식이 https방식보다 빠름
- 중간에 패킷을 가로챌 수 있고, 수정할 수 있어 보안이 취약. 민감한 정보를 다룰 때 항상 변조, 해킹 가능성을 생각해야 함
- 네트워크상에서 정보를 누군가가 마음대로 열람, 수정이 가능
(2) HTTPS
- HTTP에 보안 계층을 추가한 것
- 누가 볼수 없도록 막음. 중간에 암호화 계층을 거쳐서 패킷을 암호화. 제3자 인증, 공개키 암호화, 비밀키 암호화를 사용
- Https는 설치 및 인증서를 유지하는데 추가적인 비용이 발생
(3) 암호화
- 제3자 인증은 믿을 수 있는 인증기관에 등록된 인증서만 신뢰하는 것
공개키 암호화: 비밀키를 공유하기 위해 사용비밀키 암호화: 통신하는 데이터를 암호화하는데 사용
6) GET과 POST의 차이점
(1) GET
- 서버에 존재하는 정보를 요청
- 이 때 반환되는 정보는 정보 자체가 아니라 정보의 표현
- Request Body는 입력하지 않는 것이 일반적이며, 레거시 시스템의 경우 요청을 받아들이지 않을 수 있음
- 캐싱을 수행하기 때문에 캐싱되지 않는 요청은 GET 요청이 맞지 않을 수 있음
(2) POST
- 서버에 정보를 생성하는 것을 요청
- 예전 HTTP 통신은 POST 요청으로 데이터 삭제, 수정도 form 요청으로 같이 수행
- POST 요청은 서버의 상태를 변경시키기 때문에 멱등성이 유지되지 않음
- Request Body에 요청하는 데이터를 담아 전송
7) HTTP 메서드
1) GET
- 서버에 존재하는 데이터를 요청하는 것 (CRUD의 R)
- 요청된 자원을 수정할 때, 자원내 필드를 전체 수정할 때 사용 (만약 일부만 전달할 경우, 그외 필드들은 NULL or 초기값 처리).
- Http Request Message의 Header 부분의 URL에 담겨서 전송되며, BODY는 비어있는 상태 URL에 ?뒤에 데이터를 가져오기 위한 조건이 포함
- URL에 조건이 포함되었기 때문에 데이터의 제한이 존재하며, URL에 노출되기 때문에 보안의 위험존재
2) POST
- 서버에 데이터를 생성하는 것을 요청 (CRUD의 C)
- Http Request Message의 BODY 부분에 클라이언트의 요청을 처리하기 위한 데이터가 존재
- URL에 노출되지 않기 때문에 보안의 위험이 존재하지 않으며 보내는 데이터의 제한이 없음
3) PUT
- 서버에 존재하는 데이터를 수정하거나 존재하지 않으면 생성 (CRUD의 C,U)
4) DELETE
- 서버에 데이터를 제거할 것을 요청. 존재하지 않아도 동일하게 동작합 (CRUD의 D)
5) PATCH
- 서버에 존재하는 데이터를 일부 수정(CRUD의 U)
- GET과 POST를 상황에 따라 써야하는 이유는, GET 요청은 캐싱이 된다. 그뜻은 웹 서버에 요청이 전달되지 않고, 캐시에서 데이터를 전달해준다는 것
- 만약 글작성을 GET으로 처리한다면, 똑같은 요청을 처리했을 때, 캐싱으로 인해 두번째부터의 동일한 글작성은 서버에 전달되지 않고 첫번째 캐싱된 결과를 계속 전달받을 수 있기 때문에 METHOD를 명확하게 구분해서 써야 함
8) RESTful
- HTTP URI를 통해 자원을 표시하고 HTTP Method를 통해 자원에 대한 처리를 표현
- 사람이 읽을 수 있는 API라는 것이 특징
- HTTP를 사용하기 때문에 HTTP의 특성을 그대로 반영하고 별도의 인프라 구축이 필요없음
- URI로 접근가능하고 내용이 JSON,XML 등으로 표현된 자원에 대한 행위를 HTTP Method로 정의
- RESTful하다라는 것은 REST API의 설계의도를 명확하게 지켜주는 것
- 슬래시를 통해 계층관계를 표시한다던가 숫자는 id를 나타낸다든가 동사보단 명사를 위주
(1) 장점
- 검색엔진에 최대한 많은 페이지가 인덱싱되기를 원하는 경우 REST로 설계하고 html을 서버사이드 렌더링하여 sitemap을 형성하는 것이 쉬움
- API 명세서를 읽지 않고도 요청을 알아보기 쉬움
(2) 단점
- 이 말은 공식화된 레퍼런스가 없기 때문에, 사람마다 다르게 해석하여 사용할 수도 있음
- 특정 클라이언트에서는 HTTP Method나 상태코드 중에 사용할 수 없는 것들이 있음
- 실제 API를 개발할 때 REST로 디자인하면 굉장히 복잡한 비즈니스가 있음
(3) HATEOAS
- 동적인 API를 제공할 수 있음(모든 관련된 동작을 URI를 통해 알려줌)
- 클라이언트가 API의 변화에 일일이 대응하지 않아도 됨
9) CORS
- 서로 다른 도메인간에 자원을 공유하는 것
- 도메인 또는 포트가 다른 서버의 자원을 요청하면 발생 하는 문제
- 웹 프론트 측에서 request header에 CORS 관련 옵션을 넣어주고, 서버에서는 해당 프론트 요청을 허용
- 대부분의 브라우저에서는 이를 기본적으로 차단하며 서버측에서 헤더를 통해서 사용가능한 자원을 알려줌
- preflight request는 실제 요청을 보내도 안전한지 판단하기 위해 사전에 보내는 요청
- OPTIONS 메서드로 요청하며 CORS를 허용하는지 확인
- CORS가 허용된 웹서버라면 사용 가능한 리소스를 헤더에 담아 응답
10) OSI 7 Layer
- 네트워크에서 통신이 일어나는 과정을 7단계로 캡슐화하여 서로 다른 동작을 각 layer에서 담당하는 것
- 통신이 일어나는 과정을 단계적으로 파악할 수 있으며 layer 별로 각기 다른 동작을 수행하기에 오류 탐지가 용이
(1) 물리 계층(Physical layer)
- 전기적, 기계적 특성을 바탕으로 비트 흐름을 전송. 이 계층은 데이터를 전달만 할 뿐, 데이터가 무엇인지 전혀 신경쓰지 않음(케이블, 리피터, 허브 등)
(2) 데이터 링크 계층(DataLink layer)
- 안전한 정보 전달을 보장. 물리 계층에서 전달 받은 프레임의 오류를 찾고 필요시 재전송을 요청
(3) 네트워크 계층(Network layer)
- 오류 없는 패킷을 목적지까지 안전하고 빠르게 전달하는 경로(라우팅)를 찾는 계층
(4) 전송 계층 (Transport layer)
- 전송을 통해 통신을 활성화하는 계층. 패킷의 전송이 유효한지 확인하고 실패한 패킷을 재전송. end-to-end 통신의 신뢰성을 보장
- 오류 검출, 흐름제어, 중복 검사를 수행
(5) 세션 계층(Session layer)
- 포트를 연결하여 논리적인 통신을 가능하게 하는 계층
(6) 표현 계층(Presentation layer)
- 응용 프로그램을 위해 형식상 차이를 갖는 데이터를 인코딩하여 일관된 형태의 데이터를 표현하는 계층
(7) 응용 계층(Application layer)
- 사용자와 직접 상호작용하는 계층(크롬, 파이어폭스)
(11) CSR / SSR
(1) CSR의 과정
- 서버가 브라우저에게 응답을 보냄
- 브라우저는 JS를 다운 받음
- 브라우저는 리액트를 실행
- 페이지가 보여지고 상호작용
(2) SSR의 과정
- 서버가 브라우저에게 HTML 응답, 랜더링하기 위한 준비가 되었다고 보냄
- 브라우저가 페이지랜더링, 페이지가 보여지고 브라우저는 JS 다운받음
- 브라우저 리액트 실행
- 페이지 상호작용 가능
(3) CSR과 SSR의 차이
- CSR은 마지막 단계 전까지 화면에 보여지지가 않고 로딩중 / SSR은 미리 페이지가 보여짐
- CSR은 초기로딩속도가 느리긴하지만, 화면전환에 있어서 클라이언트에서 이루어져서 빠른 전환이 가능
- SSR은 초기로딩속도가 빨라서 사용자가 느끼기엔 좋지만, 동작은 하지않음
- 화면전환에 있어서 서버에 요청해야하므로 서버에 부담을 줄 수 있음. 서비스마다 사용자의 요구마다 다름
(12) FOUC(Flash of Unstyled Content)
- 브라우저로 웹문서에 접근했을때 미처 CSS의 스타일이 모두 적용되지 못한 상태에서 화면이 표시되어 발생하는 화면 깜박임 스타일의 적용 전과 적용 후가 그대로 화면에 노출된 상태로 변경되는 현상
- FOUC를 최소화하기 위해서는 기본적으로 <head> 요소안에 CSS를 링크하고, @import의 사용을 자제
- 자바스크립트의 선언순서, 위치를 변경 (성능을 위해 </body> 요소 앞에 자바스크립트를 위치시키곤 하는데 이를 <head> 안으로 위치를 변경)
- FOUC를 유발하는 구역을 숨겼다가 문서의 스타일이나 스크립트가 모두 적용되면 보여줌
2) 운영체제
1) 가비지 컬렉터
(1) 가비지와 가비지 컬렉터
- Garbage : 정리되지 않은 메모리, 유효하지 않은 객체의 메모리
- Garbage collector (GC) : 프로그램이 사용할 수 있는 메모리 용량이 부족할 때 가비지들을 메모리에서 해제하는 기능
(2) 메모리
- 메모리 할당 : 자바스크립트는 값을 선언할 때 자동으로 메모리를 할당한다.
- 메모리 사용 : 메모리를 읽고 쓰는 것을 의미. 메모리가 할당된 변수를 사용하면 읽기와 쓰기 작업이 이루어짐
- 메모리 해제 : 더 이상 필요하지 않은 메모리를 해제하여 재사용 할 수 있도록 함
(3) 레퍼런스 카운팅(Reference Counting)
- 해당 값이 얼마나 많이 참조되었는지 추적
- 변수를 선언하고 참조값이 할당되면 레퍼런스 카운트는 1이 됨
- 다른 변수가 같은 값을 참조하면 레퍼런스 카운트가 늘어남
- 마찬가지로 해당 값을 참조하는 변수에 다른 값을 할당하면 레퍼런스 카운트가 줄어듦
let objectA = {}; // 레퍼런스 카운트 1
let objectB = objectA; // 레퍼런스 카운트 2
objectA = null; // 레퍼런스 카운트 1
objectB = null; // 레퍼런스 카운트 0- 값의 레퍼런스 카운트가 0이 되면 해당 값에 접근할 방법이 없으며 메모리를 회수해도 안전
- 순환 참조 문제 : 객체가 두 개일 때 함수 실행이 끝날 때 두 객체는 모두 스코프를 벗어나게 될 것이고, 두 객체는 불필요해지므로 할당된 메모리는 회수되어야 하지만 함수 실행이 끝난 뒤에도 레퍼런스 카운트가 0이 되지 않으므로 두 객체는 계속 존재
- 이런 함수를 여러 번 호출하면 메모리를 회수하지 못하고 낭비되는 메모리가 많이 늘어남
(4) 마크 앤 스위프(Mark and sweep)
- 메모리 해제 여부를 결정하기 위해 루트(roots, 자바스크립트의
window객체)부터 해당 객체까지 닿을 수 있는지를 판단 - 루트부터 시작하여 루트가 참조하는 객체들과 그 객체가 참조하는 또 다른 객체들을 추적
- 객체를 추적하면서 닿을 수 있는 객체는 표시(mark) 한 후, 표시가 없는 객체들은 메모리를 해제(sweep)
2) Call-by-value, Call-by-reference, Call-by-assignment
(1) call-by-value(cbv):
- 변수의 값을 복사하여 함수의 인자로 전달
- 복사된 인자는 함수 내에서만 사용되는 local variable의 특성을 가짐
- 함수 안에서 인자의 값이 변경되어도 외부의 변수의 값은 변경되지 않음
(2) call-by-reference(cbr)
- 변수의 주소값을 복사하여 함수의 인자로 전달
- 함수 안에서 값이 인자의 값이 변경된다면 전체 코드에서 해당 변수의 값이 변경
(3) call-by-assignment (cba)(python)
- 전달받는 객체에 따라 참조 방식이 결정.
- immutable object : (int, float, tuple)이 함수의 인자로 넘어갈 땐 call-by-value로 전달
- mutable object : (list, dic, set)이 함수의 인자로 넘어갈 땐 call-by-reference로 전달
- list, dic, set이 mutable object 인 이유 : 객체의 크기가 아주 큰 경우 복사 참조만 된다면 메모리 공간이 낭비
3) 가상 메모리와 페이지 폴트
(1) 가상 메모리
- 프로그램 실행에 필요한 메모리 용량 전체를 RAM에서 할당받는 것이 아니라, 최소한의 메모리를 RAM에서 할당받아 저장하고 나머지는 HDD (가상 메모리 공간)에 저장하는 것
- 요구 페이징 : 페이지 폴트가 발생하면 운영 체제가 가상 메모리에서 해당 페이지를 찾아 물리 메모리의 불필요한 페이지와의 교체를 요구. 그리고 이 과정 동안은 모든 스레드가 대기
(3) 페이지 교체 알고리즘
- 요구 페이징이 발생했을 때 교체할 물리 메모리의 페이지를 선정하는 알고리즘
FIFO (First In First Out): 물리 메모리에 적재된지 가장 오래된 페이지를 교체. 페이지의 사용 빈도를 무시하기 때문에 활발하게 사용하는 페이지가 교체될 수 있다는 문제점이 있음. 페이지가 적재된 순서를 Queue에 저장하는 방식을 사용LRU (Least Recently Used): 가장 오랜 기간 사용되지 않은 페이지를 교체. 많은 운영체제가 사용하는 알고리즘LFU (Least Frequently Used): 참조 횟수가 가장 적은 페이지를 교체. 만약 교체 대상이 여러 개일 경우에 LRU를 사용LFU는 초기에 한 페이지를 집중적으로 참조하다가 이후에 참조하지 않는 경우에 메모리에 계속 남아있을 수 있음MFU (Most Frequently Used): LFU와 반대로 참조 횟수가 가장 많은 페이지를 교체하는 알고리즘
(4) 메모리 단편화 (Memory Fragmentation)
- 내부 단편화 : 교체된 페이지의 크기 < 할당된 공간의 크기
- 외부 단편화 : 교체된 페이지의 크기 > 할당된 공간의 크기
(5) 페이징과 세그먼테이션
- 메모리 단편화를 해결할 수 있는 기법
-
페이징
- 페이지가 연속적인 물리 메모리 공간에 들어가야하는 제약을 해결하기 위한 방법
- 가상 메모리는 페이지, 물리 메모리는 프레임이라는 고정 크기의 블록으로 나눈 후, 페이지 테이블의 매핑을 통해 1:1 대응
- 페이지 단위를 작게하면 내부 단편화(Internal fragmentation) 역시 해결할 수 있지만 페이지에 공간을 할당한 후, 남는 공간이 적어지기 때문에 그 만큼 page mapping 과정이 증가
-
세그멘테이션
- method, function, object, variables 등 프로그램의 논리적 단위를 바탕으로 서로 다른 크기의 블록으로 나누는 방법
- 세그먼트들의 크기가 서로 다르기 때문에 메모리를 페이징 기법처럼 미리 분할해 둘 수 없고, 메모리에 적재될 때 빈 공간을 찾아 할당하는 사용자 관점의 가상 메모리 관리 기법
- 각 세그먼트 별로 길이 값을 가지고 있어 내부 단편화를 해결
4) 프로세스와 스레드
(1) 프로세스
- 실행 중인 프로그램, 운영체제로부터 자원을 할당, 한 프로세스 안에 여러개의 스레드가 생성될 수 있음
- 운영체제로부터 프로세서, 주소 공간, 메모리과 같은 시스템 자원을 할당받는 작업의 단위로 실행된 프로그램
- 프로세스는 실행될 때 운영 체제로부터 독립된 메모리 영역 (Code, Data, Heap, Stack)을 할당
- 다른 프로세스의 자원에는 접근할 수 없음
(2) 프로세스 관련 용어
- PCB : 프로세스 제어 블록, 프로세스에 대한 중요한 정보를 저장
- PC : 프로그램 카운터, 프로세스 실행을 위한 다음 명령의 주소를 표시
- 캐시메모리 : 자주 사용되는 데이터가 저장되는 공간으로 CPU의 레지스터와 메모리 사이에서 병목 현상을 완화하는 장치
(3) 스레드
- 실행 제어만 분리한 것, 프로세스 내에서 동작되는 실행의 단위
- Stack 외에 프로세스가 할당받은 자원 (Code, Data, Heap)을 스레드끼리 공유하면서 실행
- 컨텍스트 스위칭도 캐시 메모리를 비우지 않아도 되는 스레드쪽이 빠름
- 자원 공유로 인해 문제가 발생할 수 있음
- 하나의 프로세스가 실행되면 기본적으로 하나의 메인 스레드가 생성
(4) 멀티 프로세스
- 하나의 프로그램을 프로세스 여러 개로 구성하여 Context switching을 통해 실행하는 것
- 하나의 프로세스에 문제가 생기더라도 다른 프로세스에 영향을 미치지 않음
(5) 멀티 스레드
- 하나의 프로그램을 한 프로세스 내에 여러 개의 스레드로 구성하여 실행하는 것
- 하나의 프로세스에서 여러개의 스레드를 만들어 자원의 생성과 관리의 중복을 최소화하는 것
-
장점
- 멀티 프로세스에 비해 메모리 자원소모가 줄어듬
- 힙 영역을 통해서 스레드간 통신이 가능해서 프로세스간 통신보다 간단
- 스레드의 컨텍스트 스위칭은 프로세스의 컨텍스트 스위칭보다 빠름
-
단점
- 힙 영역에 있는 자원을 사용할 때는 동기화를 해야 함
- 동기화를 위해서 락을 과도하게 사용하면 성능이 저하
- 하나의 스레드가 비정상적으로 동작하면 다른 스레드도 종료
(6) Thread-safe
- 두 개 이상의 스레드가 race condition에 들어가거나 같은 객체에 동시에 접근해도 연산결과의 정합성이 보장될 수 있게끔 메모리 가시성이 확보된 상태를 의미
- java.util.concurrent 패키지 하위의 클래스를 사용
- 인스턴스 변수를 두지 않음
- Singleton 패턴을 사용(이 때, 일반적으로 구현하는 Singleton Pattern은 Thread-safe 하지 않습니다.)
- 동기화(syncronized) 블럭에서 연산을 수행
(7) ThreadLocal
- 스레드 내부에서 사용되는 지역변수
- 각각의 thread scope 내에서 공유되어 사용될 수 있는 값으로 다른 스레드에서 공유 변수에 접근할 시 발생할 수 있는 동시성 문제의 예방을 위해 만들어짐
(8) 컨텍스트 스위칭
- 한 Task가 끝날 때까지 기다리는 것이 아니라 여러 작업을 번갈아가며 실행해서 동시에 처리될 수 있도록 하는 방법
- 프로세서가 멀티 프로세싱을 구성하여 어떤 하나의 프로세스를 실행하고 있는 상태에서 인터럽트 요청에 의해 다음 우선 순위의 프로세스가 실행되어야 할 때, 기존 프로세스의 상태 또는 레지스터 값 (context)을 저장하고 다음 프로세스를 수행하도록 새로운 프로세스의 상태 또는 레지스터 값을 교체하는 작업.
- 인터럽트가 발생하면 현재 프로세스의 상태를 PCB에 저장하고 새로운 프로세스의 상태를 레지스터에 저장하는 방식으로 동작
- CPU는 아무런 일을 하지 않으므로 잦은 컨텍스트 스위칭은 성능저하 원인
- 스레드는 캐시메모리나 PCB에 저장해야하는 내용이 적고 비워야 하는 내용도 적기때문에 상대적으로 더 빠른 컨텍스트 스위칭 가능
- 멀티 프로세싱을 Computer multitasking을 통해 빠른 속도로 Task를 바꿔 가며 실행하여 실시간 처리에 근사하도록 하는 기술
(9) 프로세스 동기화
- 다중 프로세스 환경에서 자원등에 한 프로세스만이 접근가능하도록 하는 것
- 프로세스 동기화를 하지 않으면 데이터의 일관성이 깨지기 때문에 연산결과가 잘못 반환될 가능성이 존재
-
경쟁 상태(Race Condition)
- 여러 프로세스나 스레드가 동기화 메커니즘 없이 자원에 접근하려는 상황
- 공유된 자원에 대한 접근 순서에 따라 실행 결과가 달라질 수 있는 상황
-
임계 구역(Critical Section)
- 여러 스레드가 동시에 접근해서는 안되는 공유자원에 접근하는 코드 블럭
- 한 임계구역에 하나의 스레드 혹은 프로세스만 접근이 가능
- 임계 구역에 접근하는 것을 제어하기 위해 세마포어, 뮤텍스와 같은 매커니즘을 사용
-
임계 구역 문제를 해결하기 위한 조건
- 상호 배제(Mutual Exclusion): 한 프로세스가 임계구역에서 동작중이면 다른 프로세스는 접근할 수 없다.
- 진행(Progress): 임계구역에서 작업중인 프로세스가 없다면 입계구역으로 진입하려는 프로세스를 적절히 선택해서 진입할 수 있도록 합니다.
- 유한 대기(Bounded Waiting): 한 프로세스가 임계영역으로 진입을 요청한 후 다른 프로세스는 진입이 유한한 횟수로 제한되어야 합니다. (기아상태 방지)
6) 동기, 비동기 / 블로킹/논블로킹
(1) 동기 방식
- 메서드 리턴과 결과를 전달받는 시간이 일치하는 명령 실행 방식
- 동기 방식은 한 함수가 끝나는 시간과 바로 다음의 함수가 시작하는 시간이 같음
(2) 비동기 방식
- 여러 개의 처리가 함께 실행되는 방식
- 동기 방식에 비해 단위시간 당 많은 작업을 처리할 수 있음
- CPU나 메모리를 많이 사용하는 작업을 비동기로 처리하게 되면 과부하가 걸릴 수 있고 프로그램의 복잡도도 증가
(3) 블로킹 / 논블로킹 방식
- 블로킹 : 대상의 작업이 끝날 때 까지 제어권을 대상이 가지고 있음
- 논블로킹 : 대상의 작업 완료여부와 상관없이 새로운 작업을 수행
(4) 동기 논블로킹
- 계속해서 polling을 수행하기 때문에 컨텍스트 스위칭이 지속적으로 발생해 지연이 발생
7) RISC와 CISC
(1) RISC(Reduced Instruction Set Computer)
- 축소 명령어 세트 컴퓨터(명령어의 개수가 적은 것)
- 핵심적인 명령어를 기반으로 최소한의 명령어 세트를 구성함으로써 파이프라이닝 이라는 획기적인 기술을 도입할 수 있어 빠른 동작 속도와 하드웨어의 단순화와 효율화를 시킬 수 있었고, 가격 경쟁력에서도 우위를 점함
-
특징
- 적은 명령어 세트
- 간단한 명령어로 빠른 실행속도
- 고정적인 명령어 길이
- 워드, 데이터 버스 크기가 동일하고 실행 사이클도 모두 동일
- 회로 구성이 단순
- 프로그램을 구성할 때 상대적으로 많은 명령어가 필요
- 파이프 라이닝을 사용함
- 명령어 개수가 적어서 컴파일러가 단순하게 구현
(2) CISC(Complex Instruction Set Computer)
- 연산을 처리하는 복잡한 명령어(명령어가 할 수 있는 일의 양이 RISC 대비하여 많다는 것)들을 수백개 이상 탑재하고 있는 프로세서
- CISC는 명령어 개수 증가에 따라 프로세서 내부구조가 매우 복잡해지고, 고속으로 작동되는 프로세서를 만들기 힘들어짐
- 명령어마다 길이가 다르고 실행에 필요한 사이클 수도 다르기 때문에 파이프 라이닝설계가 어려움
-
특징
- 명령어의 개수가 많음
- 명령어 길이가 다양하며, 실행 사이클도 명령어 마다 다름
- 회로구성이 복잡함
- 프로그램을 만들 때 적은 명령어로 구현 가능
- 다양한 명령어를 사용하기 때문에 컴파일러가 복잡
-
사용 이유
- 아직 너무도 많은 프로세서가 CISC 모델로 구축되어 있고 이것을 전부 바꾸는 것은 비용이 큼
- CISC 성능의 취약점은 RISC와 같은 파이프라인을 일부 사용하고 집적도는 더 높임으로써 부분적으로 보완이 가능
- RISC에 비해 호환성이 좋음
7) 교착상태(Deadlock)
- 서로 다른 프로세스가 서로의 자원을 요구하며 무한정 기다리는 현상
(1) 상호배제 (Mutual exclusion)
- 한번에 한 프로세스만이 자원을 점유할 수 있음
- 하나의 프로세스가 자원을 사용할 경우 다른 프로세스는 그 자원을 사용할 수 없는 것
(2) 점유와 대기, 보유 및 대기(Hold and wait)
- 프로세스가 이미 자원을 점유하는 상태에서 다른 자원을 무한정 기다림
- 프로세스가 자신이 가질 수 있는 자원은 가지고 있으면서 다른 자원이 오기를 기다리고 있는 것
(3) 비선점(No Preemption)
- 프로세스가 어떤 자원의 점유를 끝낼 때까지 그 자원을 뺏을 수 없음
- CPU 할당뿐만 아니라 모든 자원에 의해서 비선점이 된다는 것
- 임의의 프로세스가 자원을 할당 받은 상태에서 다른 프로세스는 이 자원을 뺏어서 사용할 수 없는 형태
(4) 환형대기(Circular wait)
- 각 프로세스들이 원형으로 구성되어 순환적으로 자원을 요구
- 선형이 아니고 원형을 이루게 되어 프로세스의 자원 할당에서 첫 번째 프로세스와 마지막 프로세스의 자원할당이 겹치게 되어 원형에 있는 모든 프로세스가 자원 할당을 받고자 기다리는 형태가 만들어지는 것
(2) 교착 상태 해결방법
- 예방 : 4가지 조건 중 하나라도 만족되지 않도록 함
- 회피 : 알고리즘을 데드락이 발생하지 않도록 함
- 회복 : 교착상태가 발생할 때 해결
- 무시 : 회복과정의 성능저하가 심하다면 그냥 무시
(3) 기아상태(Starvation)
- 여러 프로세스가 부족한 자원을 점유하기 위해 경쟁할 때, 특정 프로세스가 영원히 자원 할당이 되지 않는 경우
- 우선순위를 수시로 변경하거나 오래 기다린 프로세스의 우선순위를 높여주거나, Queue를 사용
(3) 세마포어와 뮤텍스
- 뮤텍스와 세마포어 : 다수의 프로세스나 스레드가 공유 자원에 동시에 접근하는 것을 제어하는 것
(1) 세마포어
- 여러개의 프로세스가 접근 가능한 공유자원을 관리하는 방식
- 뮤텍스가 될 수 있음
- 다른 프로세스가 세마포어를 해제할 수 있음
- 현재 공유 자원에 접근할 수 있는 스레드, 프로세스의 수를 나타내는 값을 두는 상호 배제 기법.
- 그 값만큼 동시에 스레드가 해당 공유 자원에 접근 가능
(2) 뮤텍스
- 한 번에 한 개의 프로세스만 접근 가능하도록 관리하는 방식
- 뮤텍스는 세마포어가 될 수 없음
- 락을 획득한 프로세스만 락을 반환할 수 있음
- 한 스레드, 프로세스에 의해 소유될 수 있는 Key를 기반으로 한 상호배제 기법
- 한 스레드가 임계 영역에 들어갈 때 lock을 걸어 다른 스레드가 접근하지 못하도록 하고 임계 영역에서 나올 때 unlock
(4) 가상 메모리
- Swap 영역. 실제 메모리에서 공간이 부족한 경우 보조 기억 장치(auxiliary storage, secondary storage)에서 임시로 사용하는 영역
- OS 에서 관리하며 프로세스는 이것이 실제 메모리인지 Swap 영역인지 모름
- 실제 메모리가 아니기 때문에 지연시간이 많이 발생하며 가급적이면 swap메모리를 사용하지 않도록 설계하는 것이 좋고 만약 계속해서 사용하는 양이 증가한다면 메모리 누수 의심
(5) 캐시의 지역성
- 시간 지역성 : 최근에 접근한 데이터에 다시 접근하는 경향
- 공간 지역성 : 최근 접근한 데이터의 주변 공간에 다시 접근하는 경향
3) 데이터베이스
(1) 데이터베이스 인덱스
- 검색성능을 향상시키기 위함
- 검색성능을 실질적으로 향상시키기 위해서는 해당 쿼리가 index를 사용하는지, 카디널리티, Selectivity 같은 요소들이 고려된 인덱스가 생성되어야 함
장점: 빠른 검색 성능단점: 인덱스를 구성하는 비용 즉, 추가, 수정, 삭제 연산시에 인덱스를 형성하기 위한 추가적인 연산이 수행
(2) 트랜잭션
- 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위
- 트랜잭션에는 여러개의 연산이 수행될 수 있음
- 트랜잭션은 수행중에 한 작업이라도 실패하면 전부 실패하고, 모두 성공해야 성공
(3) 트랜잭션의 특성(ACID)
(1) Atomicity (원자성)
- 트랜잭션과 관련된 일은 모두 실행 혹은 모두 실행되지 않음
- Transaction은 최소 작업 단위로 더이상 나눌 수 없음
- ex) 송금 transaction은 출금(A 계좌로 부터)과 입금(B 계좌로)이라는 두 가지 작업을 수행하고 있음, 하지만 이는 하나의 transaction으로 묶여있기 때문에 위의 두 작업은 나눠질 수 없음
- 출금만 실행되고 입금이 수행되지 않는다면 이는 transaction이라 부를 수 없음
- 출금만 실행되고 입금이 실행되지 않는다면 돈이 증발해버리는 심각한 문제가 발생
- 이러한 문제를 방지하기 위해 출금과 입금을 하나의 transaction으로 정의하고 입금이 실행되지 않으면 출금 또한 취소해버림으로Tj(rollback) 출금과 입금 과정을 마치 하나의 작업처럼 실행
(2) Consistency(일관성)
- 트랜잭션이 성공했다면, 데이터베이스는 그 일관성을 유지.
- 일관성은 특정한 조건을 두고, 그 조건을 만족하는지를 확인하는 방식으로 검사
- 일관성 : DBMS에서 제공하는 제약조건을 어기지 않고 데이터의 논리적 오류가 없음을 의미
- ex) 송금 예제에서, A가 만원을 이체했는데 B에서 오천원만 받았다면 이는 논리적 오류
(3) Isolation(독립성)
- 트랜잭션을 수행하는 도중에 다른 연산작업이 끼어들지 못하도록 함
- 임계영역을 두는 것으로 달성할 수 있음
- ex ) A 계좌에서 B계좌로 이체하는 transaction이 실행되는 도중 A 계좌의 모든 잔액을 출금하는 transaction이 실행되었다고 가정
- 만약 첫 번째 transaction이 A의 계좌에서 이체 금액을 출금한 상태에서 두 번째 transaction이 잔액을 조회하고 이를 출금하려고한다면 문제가 발생할 수 있음
- 아직 첫 번째 transaction은 완료된 상태가 아니기 때문에 만약 도중에 문제가 생겨 이체가 취소된다면 두 번째 transaction이 조회한 금액은 잘못된 금액(이체 금액이 빠져있는)이기 때문
- table, 혹은 해당 row에 lock을 걸어버리는 것이지만 이러한 방법은 동시성을 떨어뜨려 성능에 악영향을 미칠 수 있음
(5) Durability (지속성)
- 성공적으로 트랜잭션이 수행되었다면, 그 결과는 완전히 반영
- 완전히 반영되면 로그를 남기게 되는데 이 로그를 이용해서 트랜잭션 수행전 상태로 되돌릴 수 있어야 함
- 트랜잭션은 로그저장이 완료된 시점에서 종료가 되어야 함
(2) 트랜잭션 격리 수준(Transaction Isolation Levels)
- 고립도와 성능의 트레이드 오프를 조절
READ UNCOMMITTED: 다른 트랜잭션에서 커밋되지 않은 내용도 참조READ COMMITTED: 다른 트랜잭션에서 커밋된 내용만 참조REPEATABLE READ: 트랜잭션에 진입하기 이전에 커밋된 내용만 참조SERIALIZABLE: 트랜잭션에 진입하면 락을 걸어 다른 트랜잭션이 접근하지 못하게 함- 정규화 : 데이터의 중복방지, 무결성을 충족시키기 위해 데이터베이스를 설계하는 것
(3) RDBMS / NOSQL
(1) RDBMS
- 데이터베이스를 이루는 객체들의 릴레이션을 통해서 데이터를 저장하는 데이터베이스
- 수정 (update)에 좋음
- SQL을 사용해 데이터의 저장, 질의, 수정, 삭제를 할 수 있으며 데이터를 효율적으로 보관하는 것을 목적으로 하고 구조화가 중요
-
명확한 데이터 구조를 보장, 중복을 피할 수 있음. 중복 데이터가 존재하지 않아 저장 공간을 절약할 수 있으며, 데이터 수정 (update)이 용이
- 테이블 간의 관계를 통해서 큰 규모의 데이터를 여러 개의 테이블 (ex. user, item, buying)에 분산 저장 가능.
- 분산 저장을 통해 보안을 철저히 하고, 테이블를 구조적으로 도식화하여 효율적으로 관리
- 테이블 관계가 복잡해 질수록 JOIN이 많은 SQL 쿼리가 만들어 질 수 있음
- 데이터 수정 (update)가 자주 발생하는 시스템이거나, 명확한 스키마가 중요한 경우
(2) NOSQL
- 자유로운 형태로 데이터를 저장
- 쓰기 (write)와 읽기 (read)에 좋음
- 수평확장을 할 수 있고 분산처리를 지원
- key-value store, bigtable, dynamo, document db, graph db
-
스키마없이 유연하게 데이터를 저장/관리할 수 있는 데이터베이스
- 데이터 중복이 허용되기에 수정 (update)을 위해서는 중복으로 저장된 데이터를 검색하여 모두 수정해야하는 번거로움이 있으며, 엄격한 스키마가 없다보니 데이터에 대한 규격화된 결과 값을 얻을 수 없음
- 정확한 데이터 구조를 알지 못하거나, 데이터 수정 (update)보다는 쓰기 (write)와 읽기 (read)가 더 자주 발생하는 경우 NoSQL이 적합
5) 소프트웨어 공학
1) 절차 지향과 객체 지향
(1) 절차 지향 프로그래밍 (Procedural Programming)
- 물이 위에서 아래로 흐르는 것처럼 순차적인 처리가 중요시되는 프로그래밍 기법
- C가 대표적인 절차 지향 프로그래밍 언어
- 컴퓨터의 처리구조와 유사해 실행속도가 빠르지만 디버깅이 어려움
(2) 객체 지향 프로그래밍 (Object Oriented Programming)
- 실제 세계를 표방하여 데이터와 절차를 하나의 덩어리로 처리하는 프로그래밍 기법
- Java, Python, C++이 대표적인 객체 지향 프로그래밍 언어
- 객체 지향 프로그래밍은 기존에 짜여진 코드를 재사용하기 용이하며 디버깅이 쉬움
- 단, 처리 속도가 느리며 설계에 많은 노하우와 시간이 필요
(3) 객체 지향 프로그래밍 특징
- 추상화: 객체가 가진 공통의 속성이나 기능을 묶어 명시적인 이름을 부여하는 것
- 캡슐화: 관련된 데이터와 코드를 하나로 묶은 것으로 데이터를 감추고 외부와의 상호작용은 메소드를 통하는 방법
- 상속: 이미 작성된 클래스를 이어 받아서 새로운 클래스를 생성하는 것으로, 기존 코드를 재활용하는 것
- 다형성 (Polymorphism): 같은 코드로 다른 행위를 하는 것(Overriding과 Overloading)
2) 오버로딩과 오버라이딩
- 객체 지향 프로그래밍의 다형성을 지원하는 방법
(1) 오버라이딩 (Overriding)
- 부모 클래스가 가지고 있는 메소드를 자식 클래스가 재정의해서 사용.
- 즉, 메소드의 이름/매개변수/반환형이 같은 상속 받은 메소드를 덮어쓰는 것
- 부모 클래스의 메소드는 무시하고 자식 클래스가 필요로하는 메소드를 추가하여 사용하는 것
(2) 오버로딩 (Overloading)
- 같은 이름의 메소드 (함수)를 여러개 정의하되, 매개 변수의 유형과 개수를 달리하여 다양한 유형의 호출에 응답하는 것
3) 점진적 향상법 / 우아한 성능저하법
(1) 점진적 향상법 (Progressive enhancement)
- 많은 테스트를 통해 말그대로 기능을 점진적으로 향상시키는 것
- 기초부터 차곡차곡 쌓아서 발전해 나가는 방법. 노력과 시간이 필요
- ex ) 웹 페이지를 구성할 때 HTML로 마크업을 구성 / CSS로 스타일을 입힘 / JS로 사용자 경험을 향상
(5) 우아한 성능 저하법 (graceful degradation)
- 최신 기술을 기반 또는 최신 기기에서 동작하는 기능을 만들고 나서, 오래된 기술 또는 오래된 기기에서 동작하게 하기 위해 유사한 기능을 만들어 동작하게 하는 것
- 사용자들의 기기를 위해 별도의 버전을 만들어 놓는 것.
- ex) 사용자의 브라우저가 javascript를 지원하지 않을 때 js를 지원하지 않는 기기를 위해
4) 디자인 패턴
(1) 싱글톤 (Signleton)
- 코드 내 어디서든, 오직 하나의 인스턴스만 사용할 수 있도록 객체를 생성하는 방법
- 객체는 여러 번 생성되지 않고 최초 하나의(Single) 인스턴스만 생성하고 이후에는 이 인스턴스를 참조
- 전역적으로 하나의 인스턴스만 사용, 참조해야하는 경우에 사용
# 보통, 싱글톤 객체의 .get_instance() 로 인스턴스를 받아온다.
singleton_1 = Singleton.get_instance()
singleton_2 = Singleton.get_instance()
# 이렇게 받아온 두 인스턴스는 동일한 인스턴스다.
singleton_1 == singleton_2 # True- 활용 예시 : DB 커넥션과 Pool 을 담당하는 인스턴스, 시스템 전역의 로깅을 담당하는 로거
(2) 프로토타입 (Prototype)
- 기존의 인스턴스를 그대로 복제(clone) 하여 새로운 객체를 생성하는 방법
- 하나의 인스턴스를 사용하는 싱글톤과는 반대되는 개념
# 보통, 프로토타입 객체의 .clone() 으로 인스턴스를 복사한다.
original = Prototype()
prototype = original.clone()
# 이렇게 받아온 두 인스턴스는 동일한 객체는 아니지만, 내부 데이터는 같다.
original == prototype # False
original.data == prototype.data # True- 활용 예시 : DB 로부터 얻어온 데이터 인스턴스를 동일하게 하나 더 만들어야 하는 경우
(3) 팩토리 (Factory)
- 인스턴스를 만들어내는 공장(Factory) 를 통해 객체를 생성하는 방법
- 인스턴스를 직접 생성해내지 않고, 공장에서 제공하는 메소드를 통해 생성
- 사용자는 객체를 생성하고 싶을 때, 공장에서 제공하는 메소드만 알고 있으면 되고, 구체적으로 인스턴스가 어떻게 생성되는지 신경 쓰지 않음
- 한 집합 내에 있는 클래스들의 생성을 한 곳에서 처리하고 싶을 때
# 보통, Factory 객체의 `get` 메쏘드의 파라미터로 생성할 객체의 타입을 넘겨준다.
samsung_keyboard = KeyboardFactory.get_keyboard("samsung")
lg_keyboard = KeyboardFactory.get_keyboard("lg")
# 생성된 객체는 다음과 같이 구체적인 클래스 인스턴스다.
samsung_keyboard # SamsungKeyboard
lg_keyboard # LgKeyboard- 활용 예시 : 삼성, LG 키보드를 만드는 키보드 팩토리
(4) 추상 팩토리 (Abstract Factory)
- 공장을 만들어내는 상위 공장을 먼저 정의하고 여기서 구체적인 공장을 만든 후, 이 공장에서 객체를 생성하는 방법
- 팩토리의 위에 이 팩토리를 만드는 팩토리가 있음
# 키보드 팩토리의 팩토리(추상 팩토리)를 통해 키보드 팩토리를 얻는다.
CommonKeyboardFactory = AbstarctKeyboardFactory.get_keyboard_factory("common")
# 이후는 팩토리 패턴과 동일하다.
samsung_common_keyboard = CommonKeyboardFactory.get_keyboard("samsung")
lg_common_keyboard = CommonKeyboardFactory.get_keyboard("lg")
samsung_keyboard # SamsungCommonKeyboard
lg_keyboard # LgCommonKeyboard- 활용 예시 : 기계식 키보드 공장와 일반 키보드공장을 만드는 키보드 추상 팩토리
(5) 빌더 (Builder)
- 객체를 생성할 때 필요한 파라미터가 많은 경우, 각 파라미터가 무엇을 의미하는지 알기 힘들 수 있음
- 빌더라는 형태를 통해 파라미터 의미를 명확히 하여 생성할 수 있음
# 빌더 패턴 사용 전 (경우 1)
WebBrowser browser = WebBrowser(True, FlashPlugin(), True, 10);
# 사용 후
WebBrowser browser = BrowserBuilder().
with_ssl(True).
with_flash_plugin().
with_cookie_support().
set_timeout(10).
build()- 활용 예시 : 파라미터가 너무 많아서 의미를 파악하기 힘들 때
6) 보안
1) 로컬 스토리지, 세션 스토리지, 쿠키
(1) 로컬 스토리지(LocalStorage)
- 유통 기한 없이 저장할 수 있는 데이터 공간
- 자바스크립트 또는 브라우저 캐시 삭제 등을 통해서만 데이터 삭제 가능
- SessionStorage 와 Cookie 에 비해 저장 공간이 큼.
- 클라이언트 사이드에서만 저장 가능함
(2) 세션 스토리지(SessionStorage)
- 한 세션에만 저장되는 데이터로 브라우저/탭/앱을 껐을 때 데이터가 사라짐
- 서버로 데이터 이전은 불가능
- 쿠키보다 최소 5MB 더 큰 저장 공간 확보 가능
- 클라이언트 사이드에서만 저장 가능
(3) 쿠키(Cookie)
- 다음에 이어지는 요청과 함께 서버로 보내지는 데이터를 저장
- 보통 서버에서 데이터 유통기한을 세팅하고 관리
- 쿠키는 4KB 이하의 아주 작은 데이터를 보관
- 쿠키는 클라이언트에서도 읽을 수 있지만, 보통 서버 사이드에서 읽는 데이터
- 보안을 위해 httpOnly 플래그를 true 로 설정하여 클라이언트에서 쿠키 접근을 방지
(4) 사용 예시
- 로컬 스토리지 : 자동 로그인
- 세션 스토리지 : 입력 폼 정보, 비로그인 장바구니
- 쿠키 : 다시 보지 않음 팝업 창
(5) 가져오기
-
로컬 스토리지
- localStorage.A (Key == A)
- localStorage.getItem(“A”)
-
세션 스토리지
- sessionStorage.A (Key == A)
- sessionStorage.getItem(“A”)
-
쿠키
- getCookie(“A”) (Key == A)
(6) 세팅하기
-
로컬 스토리지
- localStorage.A = 1 (Key == A, Value = 1)
- localStorage.setItem(“A”, 1)
-
세션 스토리지
- sessionStorage.A = 1 (Key == A, Value = 1)
- sessionStorage.setItem(“A”, 1)
-
쿠키
- setCookie(“A”, 1, 7) (Key == A, Value == 1, 유효기간 == 7초)
