[면접대비 예상꼬리질문] 프론트엔드 개발자 취업 면접 질문 총정리 (장문, 꼬리에꼬리를 무는 질문 포함)

임정민·2022년 4월 5일
7
post-thumbnail

웹 통신/네트워크 관련

HTTP가 뭔가요?

HTML 문저 혹은 JSON과 같은 문서들을 교환할 수 있도록 하는 프로토콜입니다.
일반적으로 웹 브라우저와 웹 서버간의 소통하기 위해 사용되고 있지만 모바일 어플리케이션이나 ioT 소통과 같은 목적으로도 사용됩니다.

(😒)HTTP의 동작 방식에 대해서 알려주세요.

Client가 서버에게 Request 하면 서버에서 Response하는 형태로 동작합니다.

HTTP 요청 메서드에 대해서 알려주고 어떤 역할을 하는 지 알려주세요.

POST, GET, PUT, DELETE
POST는 서버로 데이터를 전송할 때 사용합니다. (CRUD의 Create)
GET은 서버로부터 데이터를 받을 때 사용합니다. (CRUD의 Read)
PUT은 일부 업데이트에 사용합니다. (CRUD의 Update)
DELETE는 특정 데이터를 제거하는 데 사용합니다.(CRUD의 Delete)

HTTP와 WebSocket은 어떤 차이점이 있죠?

HTTP와 HTTPS의 차이점에 대해서 알려주세요.

두 프로토콜의 차이점은 SSL 인증서입니다. HTTPS는 HTTP 프로토콜에 보안 기능을 추가한 것입니다

SSL은 웹사이트와 브라우저 사이에 전송되는 데이터를 암호화하여 인터넷 연결을 보호하기 위한 표준 기술입니다.

TLS는 SSL의 향상된 버전입니다.

SSL 인증서 암호화 기법인 대칭키 암호화 기법, 공개키 암호화 기법에 대해서 설명해주세요.

REST API에 대해서 설명해주세요.

`REST`란, REpresentational State Transfer 의 약자이다. 여기에 ~ful 이라는 형용사형 어미를 붙여 ~한 API 라는 표현으로 사용된다. 즉, REST 의 기본 원칙을 성실히 지킨 서비스 디자인은 'RESTful'하다라고 표현할 수 있다.

`REST`가 디자인 패턴이다, 아키텍처다 많은 이야기가 존재하는데, 하나의 아키텍처로 볼 수 있다. 좀 더 정확한 표현으로 말하자면, REST 는 `Resource Oriented Architecture` 이다. API 설계의 중심에 자원(Resource)이 있고 HTTP Method 를 통해 자원을 처리하도록 설계하는 것이다.
* Uniform Interface
* Stateless
* Caching
* Client-Server
* Hierarchical system
* Code on demand  
  _cf) 보다 자세한 내용에 대해서는 Reference 를 참고해주세요._

### RESTful 하게 API 를 디자인 한다는 것은 무엇을 의미하는가.(요약)

1.  리소스와 행위를 명시적이고 직관적으로 분리한다.

* 리소스는 `URI`로 표현되는데 리소스가 가리키는 것은 `명사`로 표현되어야 한다.
* 행위는 `HTTP Method`로 표현하고, `GET(조회)`, `POST(생성)`, `PUT(기존 entity 전체 수정)`, `PATCH(기존 entity 일부 수정)`, `DELETE(삭제)`을 분명한 목적으로 사용한다.

2.  Message 는 Header 와 Body 를 명확하게 분리해서 사용한다.

* Entity 에 대한 내용은 body 에 담는다.
* 애플리케이션 서버가 행동할 판단의 근거가 되는 컨트롤 정보인 API 버전 정보, 응답받고자 하는 MIME 타입 등은 header 에 담는다.
* header 와 body 는 http header 와 http body 로 나눌 수도 있고, http body 에 들어가는 json 구조로 분리할 수도 있다.

3.  API 버전을 관리한다.

* 환경은 항상 변하기 때문에 API 의 signature 가 변경될 수도 있음에 유의하자.
* 특정 API 를 변경할 때는 반드시 하위호환성을 보장해야 한다.

4.  서버와 클라이언트가 같은 방식을 사용해서 요청하도록 한다.

* 브라우저는 form-data 형식의 submit 으로 보내고 서버에서는 json 형태로 보내는 식의 분리보다는 json 으로 보내든, 둘 다 form-data 형식으로 보내든 하나로 통일한다.
* 다른 말로 표현하자면 URI 가 플랫폼 중립적이어야 한다.

### 어떠한 장점이 존재하는가?

1.  Open API 를 제공하기 쉽다
2.  멀티플랫폼 지원 및 연동이 용이하다.
3.  원하는 타입으로 데이터를 주고 받을 수 있다.
4.  기존 웹 인프라(HTTP)를 그대로 사용할 수 있다.

### 단점은 뭐가 있을까?

1.  사용할 수 있는 메소드가 4 가지 밖에 없다.
2.  분산환경에는 부적합하다.
3.  HTTP 통신 모델에 대해서만 지원한다.

위 내용은 간단히 요약된 내용이므로 보다 자세한 내용은 다음 Reference 를 참고하시면 됩니다 :)

Session과 Cookie에 대해서 알려주세요.

HTTP 프로토콜의 약점을 보완하기 위해 쿠키 또는 세션을 이용합니다.
HTTP 환경은 Connectionless, Stateless 특성을 가지기 때문에 쿠키과 세션이 필요하다

Connectionless : 클라이언트가 응답을 받으면 연결을 끊어버림
Stateless : 통신이 끝나면 상태를 유지하지 않음

Cookie란?
	1. 쿠키는 Client 로컬에 저장되는 키와 값이 들어있는 데이터 파일
    2. 쿠키는 클라이언트 상태 정보를 로컬에 저장했다가 참조
    3. Client에 300개의 쿠키 저장 가능, 도메인별로 20개의 값만 가질 수 있음
    4. Response Header에 Set-Cookie 속성을 이용하면 클라이언트에 쿠키를 만들 수 있음
    5. 쿠키는 사용자가 따로 요청하지 않아도 브라우저가 Request시 자동으로 서버로 전송
   
Cookie의 구성요소
	이름, 값, 유효시간, 도메인, 경로
  
Cookie 동작 방식
	1. Client가 Request 요청
    2. 서버에서 쿠키 생성
    3. HTTP 헤더에 쿠키 넣어서 Response
    4. 브라우저가 종료되어도 쿠키 만료 시간이 있다면 보관
    5. 같은 요청을 할경우 쿠키 보냄

Cookie 사용 예
	방문 사이트에서 로그인 시 "아이디와 비밀번호를 저장하시겠습니까?"
    쇼핑몰의 장바구니 기능
    자동 로그인 등
    
Session이란?
	1. Client가 아닌 서버 측에서 관리
    2. 세션 ID를 부여하여 브라우저를 종효랄 때 까지 인증상태를 유지
    3. 서버에 사용자의 정보를 두어 보안이 좋지만 서버 메모리를 많이 차지할 수 있다.

Session 동작 방식
	1. Client가 서버 접속 시 세션 ID 발급 받음
    2. Client는 세션 ID에 대해 쿠키를 사용하여 저장하고 가짐
    3. Client는 서버에 요청할 때, 이 쿠키의 세션 ID를 서버에 전달해서 요청
    4. 서버는 세션 ID를 전달 받아서 Client 정보를 활용
    5. Client 정보를 가지고 서버 요청을 처리하여 클라이언트 응답

Session 특징
	1. 각 클라이언트에게 고유 ID 부여
    2. 세션 ID로 Client 구분해서 클라이언트 요구에 맞는 서비스 제공
    3. 보안에서 쿠키보다 우수
    4. 사용자가 많으면 서버 메모리 부족 현상 생길 수 있음
    
Session 사용 예
	로그인과 같이 보안상 중요한 작업을 수행할 때 사용
    
    
Cookie와 Session의 차이
	1. 사용자의 정보가 저장되는 위치가 Cookie는 사용자, Session은 서버
    2. 보안면에서 세션이 더 우수하고 요청속도는 쿠키가 세션보다 빠르다. 세션은 서버의 처리가 필요하기 때문
    **3. Life Cycle : 쿠키는 브라우저가 종료되어도 정보가 남아있을 수 있지만 세션은 삭제됨**

Cache는 뭔가요?

캐시는 불필요한 데이터 전송을 줄이기 위해서 캐시라는 저장공간에 데이터를 저장해두고 사용하는 것입니다. Cookie와 Session과 다른 개념입니다.

그렇다면 Token기반 인증 방식은 뭘까요?

JWT는 인증에 필요한 정보들을 암호화 시킨 토큰을 의미합니다. 세션/쿠키 방식과 유사하게 사용자는 Access Token을 HTTP 헤더에 실어서 서버에 전송합니다. 토큰은 임의로 생성된 비밀번호 같이 동작합니다. 제한된 수명을 가지고 새로운 토큰은 한번 만료되면 새로 생성되어야 합니다.

JWT 인증절차

1. 사용자가 로그인을 합니다.
2. 서버에서는 계정 정보를 읽어 사용자를 확인 후, 사용자의 고유 ID 값을 부여한 후 기타 정보와 함께 Payload에 집어넣습니다.
3. JWT 토큰의 유효기간을 설정합니다.
4. 암호화할 Secret Key를 이용해 Access Token을 발급합니다.
5. Access Token을 받아 저장 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냅니다.
6. 서버에서는 해당 토큰을 검증한 후 조작 여부, 유효기간을 확인합니다.
7. 검증이 완료되었을 경우, Payload를 디코딩하여 데이터를 가져옵니다.

JWT기반 인증 방식의 장단점에 대해서 말씀해주세요.

장점 

1. 간편하다
- 별도의 추가 저장소 없이 JWT는 발급후 검증과정만 거치기 때문에 간편
2. 확장성이 뛰어나다
- Facebook, Google 로그인 등은 모두 토큰 기반 인증을 받기 때문입니다.

단점

1. 이미 발급된 JWT에 대해서느 유효기간이 완료될 때 까지는 계속 사용이 가능합니다.
- 쿠키세션 인증방식은 악의적으로 이용될 경우 쿠키를 삭제하면되지만 JWT는 유효기간이 지나기 전까지 활용 가능
- (해결책) Access Token 유효기간을 짧게하고 Refresh Token을 발급한다.
2. Payload 정보가 제한적입니다.
- Payload는 따로 암호화되지 않기 대문에 유저의 중요한 정보는 Payload에 넣을 수 없습니다.
3. JWT의 길이가 길어 요청이 많아지면 서버의 자원낭비 발생
   

OAuth에 대해서 설명해주시겠어요?

오쓰는 공개(open) 표준에 기반을 둔 인증 프로토콜, 도는 프레임워크로, 최초의 싱글 로그인 크리덴셜을 공유하지 않아도 관련 없는 서버와 서비스의 자산에 대한 접근을 인증할 수 있게 해준다. 인증 분야의 용어로 표현하자면 안전하고, 써드파티이며, 사용자 에이전트인 동시에 위임(Delegated) 인증 방식이라고 표기될 수 있다.

특정 웹사이트에 방문해 로그인 하려 할 때, 해당 웹사이트는 다른 하나 이상의 웹사이트/서비스의 로그인을 이용해 로그인할 기회를 준다. 다른 웹사이트에 링크된 버튼을 클릭하면, 이 웹사이트가 사용자를 인증한다. 그러면 최초 로그인 하려 했던 웹사이트가 다른 웹사이트의 승인을 사용, 사용자를 로그인시킨다.

또 다른 사용 사례도 있다. 사용자가 이메일로 다른 사용자에게 클라우드에 저장한 파일을 전송하는 경우이다. 여기에서 클라우드 스토리지와 이메일 시스템은 서로 관련이 없는 것들이다. 구글 지메일을 이용해 마이크로소프트 원드라이브 파일을 공유하는 사례가 여기에 해당된다.


초기 도입자 중 한 명은 오쓰를 자동차 발레 파킹 키에 비유했다. 잠시 차를 운전해 주차할 때 사용할 수 있지만, 일반 키처럼 제약 없이 사용하는 것은 불가능한 키를 의미한다. 짧은 거리는 운전할 수 있지만, 트렁크나 글로브 박스를 열 수 없다. 즉 오쓰는 성공적으로 인증을 제공했던 인증 공급업체를 통해 사용자에게 다른 웹사이트/서비스에 제약 없이 액세스 해 리소스를 이용할 수 있는 액세스 인증 토큰을 제공할 뿐이다.

(😒) OAuth의 작동원리에 대해서 알고 계신가요?

사용자가 이미 특정 웹사이트나 서비스에 로그인 했다고 가정해봅시다. 참고로 오쓰는 HTTPS만 작동합니다. 사용자는 이후 다른 관련 없는 사이트나 서비스에 액세스 하기 위한 트랜젝션을 개시하면 다음 단계가 발생합니다.

1. 첫 번째 웹사이트가 사용자를 대신해 두 번째 웹사이트에 접속한다. 오쓰를 사용하고, 사용자의 확인된 ID를 제공한다.

2. 두 번째 사이트는 해당 트랜젝션 및 관여 당사자에 고유한 1회성 암호와 1회성 토큰을 생성한다.

3. 첫 번째 사이트는 이 토큰과 암호를 사용자의 클라이언트 소프트웨어에 제공한다.

4. 클라이언트 소프트웨어는 요청 토큰과 암호를 인증(인가) 공급업체에 제시한다(두 번째 사이트 또는 다른 사이트나 서비스).

5. 인증(인가) 공급업체에 인증이 되어 있지 않다면, 클라이언트가 인증을 요청할 것이다. 인증 후, 클라이언트는 두 번째 웹사이트에 인증 트랜젝션 승인을 요청한다.

6. 사용자 또는 소프트웨어는 첫 번째 웹사이트에서 특정 트랜젝션을 승인한다.

7. 그리고 사용자에게 승인된 액세스 토큰이 제공된다(더 이상은 요청 토큰이 아님).

8. 사용자는 첫 번째 웹사이트에 승인된 액세스 토큰을 제공한다.

9. 첫 번째 웹사이트는 사용자를 대신, 인증에 대한 증명인 액세스 토큰을 두 번째 웹사이트에 제공한다.

10. 두 번째 웹사이트는 사용자를 대신, 첫 번째 웹사이트가 사이트에 엑세스 할 수 있도록 허락한다.

11. 사용자는 트랜젝션이 성공적으로 완료된 것을 확인한다.

12. OAuth는 최종 사용자를 대신해 이런 방식으로 작동하는 첫 번째 인증/인가(승인) 시스템은 아니다. 유사하게 작동하는 인증 시스템이 많다. 오쓰의 차별점은 여러 웹에서 작동을 하고, 널리 도입되었다는 점이다. 과거 다른 시스템과 달리, (여러 이유 덕분에)도입률을 높이는 데 성공했다.

XML과 JSON에 대해서 알려주세요.

JSON과 XML 공통점
1. 데이터를 저장하고 전달하기 위해 고안되었습니다.
2. 기계뿐만 아니라 사람도 쉽게 읽을 수 있습니다.
3. 계층적인 데이터 구조를 가집니다.

JSON과 XML 차이점
1. JSON은 종료 태그를 사용하지 않습니다.
2. JSON 구문이 XML 구문보다 더 짧습니다.
3. JSON 데이터가 XML 데이터보다 더 빨리 읽고 쓸 수 있습니다.
4. XML은 배열을 사용할 수 없지만 JSON은 배열을 사용할 수 있습니다.

JSON은 HTML과 JavaScript가 연동된 빠른 응답이 필요한 웹 환경에서 많이 사용됩니다.
XML은 스키마를 사용하여 데이터의 무결성을 검증할 필요가 있을 때 많이 사용됩니다.

OSI 7 Layer에 대해서 설명해주세요.

1. Physical
2. Data Link
3. Network
4. Transport
5. Session
6. Presentation
7. Application

로 이루어져 있습니다.

1 계층인 물리 계층은 단순한 전기적 신호 전달 역할을 합니다. 단위는 비트를 쓰며 전선, 광케이블, 무선 전파 등이 여기에 해당합니다.

2 계층인 데이터 링크 계층은 1 계층의 물리적 링크인 MAC 주소를 참조해 장비 간 데이터 전송합니다. 

3 계층인 네트워크 계층은 IP 주소를 할당하는 논리 주소 기능, IP 주소 기반을 네트워크 구분하는 라우팅 기능, 최적 경로 설정 기능이 있으며 IP, ICMP 등의 프로토콜/기술이 포함됩니다.

4 계층인 전송 계층은 데이터 전송의 전반적 조율을 담당합니다. 
각각의 데이터 유닛을 포트 번호로 구분하여 응용 계층이 나눠 받도록 하는 분할 작업, 흐름 제어 작업, 수신 못한 세그먼트만을 재송신하는 오류제어 작업, 데이터 수신 유/무 확인하는 연결형 작업, 데이터 수신 유/무 확인 안하는 비연결형 작업 기능이 있습니다.
TCP/UDP등의 프로토콜/기술이 포함됩니다.

5 계층인 세션 계층은 데이터가 서로 만나는 환경 조성 단계이며 인증에 따른 권한 부여를 합니다. TLS/SSH 등의 프로토콜/기술이 포함됩니다.

6 계층인 표현 계층은 데이터를 빠르고 안전하게 전송하기 위해 데이터 압축, 암호화/복호화 단계입니다. SSL, JPEG, MPEG 등의 프로토콜/기술이 포함됩니다.

7 계층인 응용 계층은 도착 데이터를 브라우저나 메일, 메신저 같은 수단으로 최종 사용자가 확인하는 단계로 HTTP, HTTPS, SNMP와 같은 프로토콜이 포함됩니다.

TCP와 UDP 방식의 차이점을 설명해주세요.

1. (연결 방식) TCP는 연결형이고 UDP는 비연결형입니다.
2. (패킷 교환 방식) TCP는 가상 회선으로 교환, UDP는 데이터 그램
3. (전송 순서) TCP는 순서 보장, UDP는 순서 보장 X
4. (통신 방식) TCP는 1:1 UDP는 1:1, 1:N, N:N
5. (신뢰성) TCP 높다, UDP 낮다
6. (속도) TCP는 느리고, UDP는 빠르다

TCP/UDP 모두 네트워크 계층 중 전송계층에서 사용하는 프로토콜입니다.

TCP는 3-way handshaking 과정을 통해 연결을 설정하기 때문에 신뢰도를 확보해서 순서를 보장하는 대신 속도가 느리고, UDP는 순서를 보장하지 않고 신뢰도가 낮은 데이터 전송을 하는 대신, 단방향 데이터 전송으로 속도가 빠르다는 차이가 있습니다.

TCP는 신뢰가 필요한 HTTP 통신, 이메일 통신 등에 사용되고, UDP는 스트리밍 서비스에 사용됩니다.

(😒)TCP의 3 Way-HandShake와 4 Way-HandShake에 대해서 알고 있나요?

3-Way HandShake
응용 프로그램이 데이터를 전송하기 전 먼저 정확한 전송을 보장하기 위해 사전에 세션을 수립하는 과정입니다. 즉, 양쪽 모두 데이터 전송 준비가 되었다는 것을 보장하고, 실제로 데이터 전달하기 전 한쪽이 다른 쪽의 준비 상태를 알 수 있도록 합니다.

SYN -> SYN/ACK -> ACK 를 거쳐 연결한다
SYN : synchronize sequence numbers(순차 일련번호) ACK : Acknowledgement

4-Way HandShake
세션을 종료하기 위해 사용되는 것입니다.

Client가 서버에 연결 종료를 위해 FIN flag를 보내고 서버는 ACK를 보내고 자신의 통신이 끝날 때까지 TIME_WAIT 상태가 됩니다. 서버의 통신이 끝나면 FIN flag를 Client에게 보내고 Client는 ACK를 보냅니다.

(😒😒)TIME_WAIT 상태가 뭔가요?

TIME_WAIT 상태란 연결 종료 시 마지막 패킷 전송 실패를 대비하기 위한 상태입니다.

혹시 모를 패킷 전송 실패를 대비하기 위해 TIME_WAIT이 존재하는 것

DNS에 대해서 설명해주세요.

DNS은 Domain Name Server의 줄임말로 전화번호부와 같은 역할을 하는 서버 또는 시스템을 말합니다.
사람이 쉽게 기억하고 읽을 수 있는 주소를 컴퓨터가 이해할 수 있는 IP주소로 변환하여 사용자의 컴퓨터가 서버로 접근할 수 있도록 하는 서비스를 제공합니다.

(😒) DNS의 구조는 어떻게 이루어져 있죠?

DNS의 구조는 루트 도메인 -> 1단계 도메인 -> 2단계 도메인 -> 3단계 도메인 -> 4단계 도메인으로 이루어져 있습니다.

ex) www.google.co.kr
1단계 도메인 : 국가 최상위 도메인과 일반 도메인이 있다. kr/com 
2단계 도메인 : co
3단계 도메인 : google
4단계 도메인 : www

프록시 서버가 뭔가요?

주로 보안상의 이유로 직접 통신할 수 없는 두 점 사이에서 통신할 경우 중계기로 대리로 통신을 수행해주는 것을 프록시 라고 합니다.

(😒) 프록시 서버는 왜 필요하죠?

1. 다른 서버로의 자원 요청을 중계하여 데이터 전송 시간, 외부 트래픽 감소, 네트워크 병목현상을 방지할 수 있습니다.
2. 위험이 예상되는 웹 콘텐츠 및 악성 코드를 필터링할 수 있습니다.
3. 사용자는 웹 서핑 기록을 익명화하기 위해 사용하기도 합니다.

CORS 에 대해서 설명해주세요. 그리고 본인이 코드를 작성하여 CORS 문제에 직면한 적이 있었나요? 그렇다면 어떻게 해결하셨나요?

브라우저에서는 보안적인 이유로 cross-origin HTTP 요청을 제한합니다. cross-origin 요청을 하려면 서버의 동의가 필요합니다. 서버가 동의한다면 요청을 허락하고 동의하지 않는다면 브라우저에서 거절합니다.

서버 개발을 할 때 사용자쪽과 포트가 달라 CORS 이슈를 경험한 적이 있습니다. 서버 측에 Access-Control-Allow-Origin 설정을 통해 사용자쪽을 허용하여 문제를 해결하였습니다.

(😒) cross-origin이 뭔가요?

프로토콜이 다르거나(http, https)
도메인이 다르거나 (google, naver)
포트번호가 다르면(8000, 3000)

cross-origin이라고 합니다.

(😒) CORS는 왜 필요하죠?

모든 곳에서 오는 데이터를 요청할 수 있으면 다른 사이트에서 기존 사이트를 모방할 수 있습니다. 이러한 보안 문제를 해결하기 위해 허용된 브라우저에서만 접근할 수 있도록 하기 위해 필요합니다.

(😒)same-origin policy에 대해서 알고 계신가요?

불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 방식입니다.

(😒) Prefilght Request에 대해서는 들어본적 있으세요?

Preflight Request는 실제 Actual 요청 전에 인증 헤더를 전송하여 서버의 CORS 허용 여부를 미리 체크하는 테스트 요청입니다.

Frontend 지식

Web Browser

홈페이지가 사용자에게 보이는 순서에 대해서 설명해주세요.

1. 브라우저 주소 창에 특정 주소를 입력합니다('www.google.co.kr')
2. 해당 주소의 서버를 찾아가고 DNS가 실제 서버가 있는 곳으로 연결을 해줍니다.
3. 서버에 설정되어있는 HTML파일을 서버에서 클라이언트 쪽으로 보내줍니다.
4. HTML 파일을 받은 브라우저에서는 이 파일을 파싱하면서 DOM 트리를 만들어 나갑니다.
5. HTML을 읽다가 CSS 요청이 발생하면 요청과 응답과정을 통해 CSS을 파싱합니다.
6. CSS 파싱이 종료되면 잠시 중단 되었던 HTML을 다시 읽고 DOM tree를 완성시킵니다.
7. 완성된 DOM Tree와 CSSOM Tree를 합쳐서 Render Tree를 만들게 됩니다.
8. HTML 파서는 파싱을 하다가 Script Tag를 만나면 JS 코드를 실행하기 위해 파싱을 중단합니다.
9. 제어권한을 JS engine에게 넘기고 JS 코드 또는 파일을 로드해서 파싱하고 실행합니다.

(😒) DOM은 뭔가요?

DOM은 Document Object Model 즉 문서객체 모델로 웹 브라우저가 HTML 페이지를 인식하는 방식을 의미합니다.

(😒) CSSOM은 뭔가요?

브라우저는 HTML을 DOM으로 만들면서 개발자가 정의해놓은 CSS와 기본적으로 설정되어 있는 CSS를 병합하여 CSSOM을 만들게 됩니다.

(😒😒) 개발자가 정의한 CSS와 기본적으로 설정되었는 CSS는 Cascade rule을 이용하여 병합합니다. 이것에 대해서 들어본적 있나요?

CSS 적용 우선순위로 알고 있습니다. 캐스캐이딩에는 세가지 규칙이 있는데, 중요도, 명시도, 선언순서가 영향을 줍니다.
CSS가 어디 선언 되었는지에 따라 우선순위가 달라집니다.
	1. head 요소 내의 style 요소, 
	2. head 요소 내 style 요소 내의 import문
    3. Link로 연결된 CSS 파일 등...
대상을 명확하게 특정할수록 명시도가 높아지고 우선순위가 높아집니다.
나중에 선언된 스타일이 우선 적용됩니다.

(😒) 어떻게 하면 홈페이지 로딩을 빠르게 만들 수 있을까요?

다양한 방법이 있겠지만 Render Tree를 빠르게 만들면 홈페이지의 로딩을 빠르게 할 수 있을거라 생각합니다.
DOM Tree 와 CSSOM Tree 를 합친 Render Tree를 빠르게 만들기 위해서는 HTML의 경우 Div tag의 남용, 과하게 Wrapping하기 등 불필요한 태그 사용을 줄이고 CSS의 경우 top, left 등의 속성을 이용하기 보다 translate를 사용하면 더 빠르게 만들 수 있습니다.

(😒😒) Top, left 보다 translate를 이용하면 왜 더 빠른가요?

Render Tree가 만들어진 후에는 Layout과 Paint, 레이어 합성 과정을 거치게 되는데, 

top, left을 이용하면 Layout 부터 시작하여 Paint, 레이어 합성과정을 다시 거치지만
Translate를 사용하면 레이어 합성 과정만 다시 거치면 됩니다.

크로스 브라우징이 뭔가요?

크로스 브라우징은 웹 표준에 따라 서로 다른 OS 또는 플랫폼에 대응하는 것을 말합니다. 브라우저별 렌더링 엔진이 다른 경우에도 문제 없이 동작하게 하는 것을 목표로 합니다.
개발자는 한쪽 환경에 최적화를 하기 보다 전체적인 웹 표준을 지키는 데 노력해야 합니다.

(😒) 웹 표준이 뭔가요?

웹 표준이란 브라우저 종류 및 버전에 따른 기능 차이에 대해서 호환이 가능하도록 제시된 표준으로 한쪽에 최적화되고 치우치치 않도록 하는 기법입니다.

CSR과 SSR의 차이에 대해서 설명해주시겠어요?

서버 사이드 렌더링은 전통적인 웹 방식으로 페이지가 새로고침될 때 마다 서버로부터 전달받아 화면에 렌더링 하는 방식입니다. 하지만 React, Vue 등이 등장하면서 훨씬 좋은 성능의 SPA 방식의 개발 환경을 선호하게 되었습니다. CSR에서 서버는 단지 JSON 파일을 보내주는 역할만 할 뿐이고 HTML을 그리는 역할을 Client에서 수행합니다. 

CSR은 클라이언트에서 초기 구동 속도를 제외한 다른 곳으로 이동하는 식의 동작에서 속도가 빠릅니다.
CSR은 자바스크립트가 모든 동작을 수행한 후 화면에 내용이 나타나므로 초기 구동 속도가 SSR에 비해 느리다는 단점이 있습니다.

CSR은 대표적으로 React, Vue가 있습니다.
SSR은 Next.js가 있습니다.

(😒) 왜 기업들은 React를 사용하면서 Next.js를 통한 SSR을 이용하려고 할까요?

검색 엔진은 크롤러를 이용하여 웹 사이트들을 읽는데, CSR은 동적으로 컨텐츠가 생성되기 때문에 검색 엔진에 등장하기 힘듭니다. 따라서 SSR을 통해서 크롤러에 대응하기 위해 사용합니다.

(😒😒) 어떤 경우에 SSR과 CSR을 사용해야 할까요?

SSR 사용경우

1. 네트워크가 느릴 때 
2. SEO(검색 엔진 최적화)가 필요할 때
3. 최초 로딩이 빨라야 하는 사이트 개발 시
4. 메인 스크립트가 크고 로딩이 느릴 떄

CSR 사용 경우
1. 네트워크가 빠를 때
2. 서버의 성능이 좋지 않을 때
3. 사용자에게 보여줘야하는 데이터가 많을 때
4. 메인 스크립트가 가벼울 때

HTML

쿠키와 세션 스토리지, 로컬 스토리지 차이를 설명해주세요.(웹 스토리지에 대한 얘기를 해주세요)

웹에서 로그인 등과 같은 상태를 유지하기 위해서 쿠키를 통해 해결할 수 있습니다. 쿠키는 저장 공간이 4KB로 작은 편인데 이러한 단점을 보완하기 위해 만든 것이 웹 스토리지 입니다.

웹 스토리지는 서버에 클라이언트 데이터를 저장하지 않습니다. 웹 스토리지에는 로컬 스토리지와 세션 스토리지가 있는데,
로컬 스토리지는 브라우저 정보가 계속해서 남아있는 반면
세션 스토리지는 브라우저가 닫히면 데이터가 사라진다.
웹 스토리지는 데스크탑 기준 5~10MB를 가지고 있어서 쿠키에 비해 저장공간이 훨씬 크다는 장점이 있지만 웹 스토리지는 HTML5부터 지원하기 때문에 이전 브라우저에는 지원이 되지 않습니다,.

Progressive Rendering이 뭔가요?

프로그래시브 렌더링은 컨텐츠를 가능한 빠르게 표시하기 위해 성능을 향상시키는 기술입니다. 이미지를 한번에 로딩하지 않고 JS를 통해 사용자가 표시하려는 부분만 스크롤 시 이미지 로드하는 것입니다. 대표적으로 레이지 로딩이 있습니다. 

(😒) 레이지 로딩이요?

레이지 로딩은 페이지 내에 바로 필요하지 않은 이미지들의 로딩시점을 뒤로 미루어서 성능을 향상시키는 기법입니다.

SEO는 무엇인가요?

검색 엔진 최적화란 웹 페이지 검색엔진이 자료를 수집하고 순위는 매기는 방식에 맞기 웹페이지를 구성해서 검색 결과의 상위에 나올 수 있게 하는 작업을 말합니다. SPA를 개발하는 경우 SEO가 잘되지않는 단점이 있습니다. 따라서 React 나 Vue와 같은 프레임워크는 서버 렌더링을 선별적으로 사용하는 경우가 많습니다.

HTML5 태그에 대해서 설명해주세요.

모든 HTML5문서는 <!DOCTYPE>로 시작하고 <html> <head> <body> 등이 있습니다.

Semetic 태그에 대해서 설명해주세요.

시멘틱 태그는 HTML5에 도입되었고 개발자와 브라우저에게 의미있는 태그를 제공하는 것을 의미합니다. 시멘틱 태그는 태그명을 통해 대략적으로 들어갈 내용을 유추할 수 있다는 장점이 있습니다.
<header> <table> <section> 와 같은 태그를 의미하고 <div>는 시멘틱 태그가 아닙니다.

CSS

margin과 padding에 대해서 설명해주세요

각 요소와의 Border 간격을 margin, Border과 안의 요소와의 간격을 padding이라고 합니다.

Position을 어떻게 사용하는지 알려주세요

Position 속성은 요소들을 어떻게 배치할 지 정하는 속성입니다. 
relative, absolute, fixed등이 있고 relative는 부모 요소에 연결, absolute는 원하는 위치를 지정할 수 있는 방식, fixed는 지정한 좌표에 고정하여 위치하는 방식입니다.

Class와 ID의 차이점에 대해서 알려주세요.

id는 유일한 요소에 접근할 때 사용하고 Class는 복수적으로 접근할 수 있습니다.
쉽게 말하면 동일한 id 값을 다른 요소에 적용못합니다. 우선순위는 id가 class보다 높습니다.

float는 어떻게 동작하나요?

float 속성은 현재 위치의 왼쪽이나 오른쪽으로 Shift되어 배치되는 박스의 일종입니다. 이 때 컨텐츠는 float 속성이 적용된 요소의 주변에 위치하게 된다.

클리어링에는 어떤 것들이 있으며, 각각은 어떨 때 사용되나요?

float 속성의 영향에서 벗어나기 위해 사용되는 clear 속성은 float의 특성을 지워주는 역할을 합니다. both는 양쪽 left, right는 각각의 속성을 지워주고 none은 아무거도 지워주지 않는다.

표준 폰트가 아닌 폰트 디자인을 사용할 때 어떤 방식으로 처리하나요?

구글웹폰트 등을 import하여 사용합니다.

Sass를 사용해 보신적이 있으신가요, CSS 전처리기의 장점과 단점은 어떤게 있나요?

CSS 전처리기는 css가 가질 수 있는 불합리한 점을 해결하기 위해 탄생하였습니다. 
웹 페이지가 커지고 복잡해지면 정의하는 스타일도 많아지고 선택자를 불필요하게 많이 사용하게 되는 등 코드가 지저분해질 수 있습니다. 

저는 사용해본적이 없습니다. CSS-in-JS를 통해 대체할 수 있다고 생각했기 때문입니다.
SASS대신 Styled-component를 사용해본적이 있습니다.

(😒) CSS-in-JS에 대해서 설명해주세요.

CSS-in-JS는 CSS보다 더 강력한 추상화로 CSS파일을 별도로 두어 관리하지 않고 자바스크립트 코드 내에서 모두 해결하는 방식입니다. 

CSS-in-JS의 장점은 다음과 같습니다.
1. CSS 모델을 문서 레벨이 아닌 컴포넌트 레벨로 추상화하는 모듈성
2. 현재 사용중인 스타일만 DOM에 포함

단점은 다음과 같습니다.
1. 러닝 커브가 느립니다.
2. 속도가 느립니다.

JavaScript

var, let, const의 차이점에 대해서 설명해주세요.

ES6 이전 변수 선언문 var에는 치명적인 문제가 있는데, 바로 중복 변수 선언 문제입니다.

중복 변수 선언이란?

var a = 3
console.log(a) // 3
var a = 4
console.log(a) // 4

동일한 변수명을 재 선언할 수 있게 하는 것인데, 이 문제를 해결하기 위해서 ES6에는 let과 const가 도입되었습니다.

중복 변수 선언이 뭐가 문제죠?

위와 같은 예에서는 큰 문제가 아니지만, 프로젝트의 규모가 커지면 개발자가 실수로 동일한 변수 명을 사용할 수도 있습니다.


var a = 2
var result = 0

for(var a = 0; a< 3; a++){ // a를 재선언하여 위의 a가 소멸됨
	result += a
}

console.log(a)// 3



위와 같은 상황이면 a가 예상과 다른 결과 값이 나오게 됩니다. 이러한 개발자의 실수를 차단하기 위해 도입된 것이라 이해하면 될 것 같습니다.

그렇다면 let과 const의 차이점은 무엇인가요?

let은 변수 값 변경 가능, const는 변수 값 변경 불가합니다.


let i = 0
i = 3 // it's ok

const i = 0
i = 3 // ?

let과 const중 어느 것으로 변수를 선언하는 것이 적절할까요?

불필요한 변수 값이 변경되는 것을 막기 위해 기본적으로 변수를 const로 선언하고 변경이 필요한 변수는 let으로 선언하여 예상 밖의 변수 값의 변경을 차단하는 것이 가장 적절합니다.

Arrow Function이 뭔지 아시나요?

Arrow Function은 ES6에 도입된 문법으로 화살표를 이용하여 간편하게 함수를 선언할 수 있는 방식입니다.


//다양한 함수 선언 방식
// 1.
function Function(){
    return 1
}
// 2.
const generalFunction = function(){
    return 1
}
// 3. ArrowFunction
const arrowFunction = () => {
    return 1
}

Arrow Function 선언 방식과 기존 선언 방식에는 무슨 차이가 있을까요?

1. **Arrow Function을 사용하면 this값을 외부에 있는 this값을 그대로 가져옵니다.**
2. 매개변수가 하나라면 소괄호를 생략할 수 있습니다.
3. return문만 있다면 중괄호와 return을 생략할 수 있습니다.


const one = () => {
    console.log(this) // {}
}
const oneFunction = function () {
    console.log(this) // <ref *1> Object [global] { ... }
}
const Two = x => {return x*2}
const Three = (x) => x*2;

그렇다면 어떨 때 Arrow Function을 사용하는 것이 적절하겠습니까?

함수를 이용한 객체지향 프로그래밍을 할 때 상위 함수의 this를 사용해야 하는 경우 Arrow Function을 사용하는 것이 적절합니다.


function Person () {
    this.age = 0;

    setInterval(function growUp(){
        this.age++;
        console.log(this.age)
    }, 1000)
}

var p1 = new Person(); // NaN NaN NaN ...

function Person2 () {
    this.age = 0;

    setInterval(() => {
        this.age++;
        console.log(this.age)
    }, 1000)
}

var p2 = new Person2(); // 1 2 3 ...


혹은 매개변수가 하나이거나 간단하게 return만 하는 경우에 코드 간소화를 위해 사용하는 것이 적절해보입니다.(2, 3)

OO씨는 일반적인 함수 선언 방식과 Arrow 함수 선언 방식 중 어떤 것을 선호하시나요? 그리고 그 이유를 알려주세요.

저는 Arrow Function을 일관적으로 사용하는 것을 좋아합니다.
1. 다른 언어에서는 단 한번도 Arrow 함수 선언 방식으로 선언하는 것을 본 적이 없어 JavaScript만의 특별한 함수 선언 방식이라 선호하게 된 경향이 있습니다. 
2. 대부분의 Frontend 개발자 혹은 Javascript를 이용하는 개발자는 일반적인 함수 선언 방식 보다 Arrow Function 선언 방식을 선호한다고 생각하기 때문입니다.

많은 사람들이 사용하는 것과 OO씨가 사용하는 것과는 무슨 관계가 있죠?

많은 사람들이 선호하는 방식으로 선언하는 것이 코드의 가독성을 높인다고 생각합니다. 같은 일을 하는 팀원들이 선호하는 방식으로 통일하는 것이 서로의 코드를 이해하기 더 쉽다고 생각합니다.

Literal이 무엇인지 아시나요?

Literal이란 선언과 동시에 값을 적용해 생성하는 방식입니다.


let A; // 왜 const 대신 let을 썼을까요?
const B = 3; // Literal
const C = new Number(3) // Literal

그렇다면 Template Literal은 무엇인가요?

Template Literal은 ES6에서 적용된 문법으로 백틱과 ${}(딸러중괄호)을 통하여 간편하게 변수를 문자열 안에 삽입할 수 있는 방식입니다.


let a = 3;
let b = `a is ${a}`

console.log(b) // a is 3

Template Literal 방식 제외하고는 어떤식으로 문자열 안에 변수를 삽입할 수 있나요?

1. C언어의 방식과 마찬가지로 기본형식에 맞춰 표현할 수 있습니다.

let a = 3;

console.log("a is %d", a) // a is 3


2. Java의 방식과 마찬가지로 +연산자를 통하여 표현할 수 있습니다.


let a = 3;
let b = "a is "

console.log(b + a) // a is 3

그렇다면 Template Literal에서 줄바꿈은 어떻게 하죠?

let b = `a is 
3`

console.log(b)

Nesting Templates에 대해서 들어본 적이 있나요?

중첩으로 조건을 삽입하여 다른 변수를 저장하고 싶을 때 사용하는 것으로 알고있습니다. 기존에는 괄호를 넣어서 표현하였는데, 백틱과 ${}를 이용하여 중첩할 수 있는 기능입니다.


//ES5
var classes = 'header'
classes += (isLargeScreen() ? 
            '' : item.isCollapsed ? 
            ' icon-expander' : ' icon-collapser');
            
//ES6, Not use nesting templates
const classes = `header ${ isLargeScreen() ? '' :
                (item.isCollapesd ? 'icon-expander' : 'icon-collapser')}`;
                
//ES6, Used nesting templates
const classes = `header ${ isLargeScreen() ? '' :
                `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;

OO씨는 Nesting Templates를 사용해본 적이 있나요?

아니요. 기존 ES5방식이 제가 생각했을 때 더 가독성이 높다고 판단하여 사용하지 않습니다.

Tagged Templates에 대해서 들어본 적이 있나요?

네. Tagged Templates는 중간 적용 함수를 적용하여 입력받은 변수 값을 조건에 따라 다른 값으로 변환해 템플릿에 적용할 수 있도록 하는 기능입니다.


function myTag(strings, personExp, ageExp) {

  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }
  return str0 + personExp + str1 + ageStr;

}

var output = myTag`that ${ person } is a ${ age }`;

console.log(output);
// that Mike is a youngster

OO씨는 Tagged Templates를 사용해본 적이 있나요?

없습니다. 저는 조건에 따라 다른 값을 출력해야 할 때 ${}안에 조건문을 넣어서 표현하는 것이 더욱 가독성이 높다고 판단하여 Tagged Templates 대신 ${a?a:b}와 같은 방식으로 표현하는 것을 선호합니다.

문자열을 출력할 때 이스케이프 문자를 해석하지않고 출력하려면 어떻게 해야할까요?

Raw String을 이용하여 표현할 수 있습니다. String.raw\`\`를 통해 표현할 수 있습니다.

let s = String.raw`xy\n${1+1}z`;
console.log(s);     //xy\n2z

JavaScript는 기본 매개 변수를 선언할 수 있나요?

네. ES6에서 제공한 문법으로 기본 매개 변수를 선언할 수 있습니다.


const People = (name, age = 26) => {
	return `hi my name is ${name}, ${age} years old`
}

console.log(People('정민')
//hi my name is 정민, 26 years old

기본 매개 변수를 선언할 때 주의해야 할 점은 무엇이 있죠?

다른 언어에서는 디폴트 파라미터의 값을 오른쪽 파라미터부터 순서대로 채워야 하지만 JavaScript는 순서 상관없이 선언할 수 있습니다.

JavaScript에서 기본 매개 변수를 사용하는 경우는 오직 값이 undefined인 경우입니다.
따라서 false나 NaN, Null값 모두 기본 매개 변수가 사용되지 않습니다.


const Test =(num = 1) => {
    console.log(num)
}

Test() // 1
Test(undefined) // 1
Test('') // '' 
Test(null) //null
Test(NaN) // NaN

왜 C++와 같은 다른 언어에서는 기본 매개 변수를 선언할 때 오른쪽에서부터 선언하죠?

그 이유는 매개변수를 왼쪽에서 부터 오른쪽으로 넣기 때문입니다. 예를 들어 매개변수를 3개 넣는다고 가정해봅시다. (num1 = 1, num2 = 2, num3) 이런식으로 선언하는 것이 의미가 없다는 것을 금방 눈치 챌 수 있습니다. 매개변수는 왼쪽부터 채워지기때문에 위와 같은 기본 매개 변수는 사용될 일이 없습니다. num3을 무조건 채워야 하니까요.

그렇다면 JavaScript에서는 왜 순서와 상관없이 선언할 수 있나요?

JavaScript에서는 undefined라는 타입 값을 직접 넣어서 표현할 수 있기 때문에 허용하는 거라고 생각합니다.


const Test =(num1 = 1, num2 = 2, num3) => {
    console.log(num1, num2, num3)
}

Test(, ,3) // error!
Test(3) // 3, 2, undefined
Test(undefined, undefined, 3) // 1, 2, 3

배열 및 객체 비구조화에 대해서 알고 있나요?

값을 보다 편리하게 받아올 수 있게 하는 문법으로 let 이후에 중괄호 혹은 대괄호를 넣어 편리하게 값을 할당받을 수 있는 방식입니다.


//ES5
const contacts = {
	name : '임정민',
	age: 26
};

let name = contacts.name
let age = contacts.age

//ES6
const contacts = {
	name : '임정민',
	age: 26
};

let {name, age} = contacts;
//혹은
let { a : name, b : age} = contacts;

//배열도 마찬가지
const contacts = ['임정민', 26]

let [name, age] = contacts

Import와 Export를 사용하면 어떤 이점이 있죠?

1. 코드 관리가 쉽고 가독성이 좋아진다.
2. 필요 함수만 import할 수 있다.

Promise에 대해서 알고있나요?

프로미스는 자바스크립트 비동기 처리에 사용되는 객체입니다. 일반적으로 fetch 함수를 통해 데이터를 받아올 때 사용됩니다.

그렇다면 Promise는 왜 생긴것일까요? 그냥 받아오면 되는데

서버에 데이터를 요청하고 데이터를 받아오는 과정에서 데이터를 다 받아온 것처럼 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜹니다. 이를 해결하기 위해 나온 것이 Promise입니다.

비동기 처리가 뭔가요?

동기식(Synchronous) : 작업이 끝날 때 까지 다른 작업을 시작하지 않고 기다리는 방식
비동기식(Asynchronous) : 작업의 완료 여부와 상관없이 새로운 작업을 시작하는 방식

자바스크립트에서는 어떤 비동기 처리 방식이 있나요?

1. CallBack 함수 사용
2. Promise
3. async/await

어떤 경우에 비동기 처리를 해야할까요?

1. 사용자 이벤트 처리 시
2. 네트워크 응답 처리 시
3. 파일을 읽고 쓰는 등의 파일 시스템 작업 시
4. 의도적으로 시간 지연을 사용할 때

CallBack 함수는 뭔가요?

나중에 호출되는 함수를 말합니다. 개발자는 함수를 등록하기만 하고 어떤 이벤트가 발생하거나 특정 시점이 도달했을 때 시스템에서 호출하는 함수입니다. 대표적으로 EventHandler가 있습니다.

CallBack 함수가 있는 상태인데 Promise와 async/await는 왜 생겼을까요?

CallBack 함수가 중첩되어 있는 경우에 코드가 복잡해지고 가독성이 떨어지기 때문입니다.


// 가장 간단한 CallBack 함수 중첩
function first(callback) {
  let value;

  setTimeout(() => {
    value = { name: "임정민", age: 26 };
    callback(null, value);
  }, 4000);
}

first(function callbackOne(error, value) {
  if (error) {
    // ErrorHandling
  } else {
    second(value, function callbackTwo(error, value) {
      if (error) {
        // ErrorHandling
      } else {
        third(value, function callbackThree(error, value) {
          if (error) {
            // ErrorHandling
          } else {
            console.log(
              `Final value is ${value}. Here is end of Callback hell...`
            );
          }
        });
      }
    });
  }
});

Promise는 어떤식으로 그 문제를 해결하나요?

Promise는 생성되고 종료될 때까지 3가지 상태를 갖습니다. 

• Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태

• Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

• Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

Promise가 Pending 상태라면 콜백 함수 인자로 resolve(성공), reject(실패)를 사용할 수 있습니다. resolve를 호출하면 Fulfilled 상태가 되고, reject를 호출하면 Reject 상태가 됩니다.
Promise가 Fulfilled 상태가 되면 then()을 이용하여 처리 결과 값을 받을 수 있습니다.
Promise가 Rejected 상태가 되면 catch()를 통하여 실패 이유를 받을 수 있습니다.


function async(num) {
    return new Promise((resolve, reject) => {
      if (num > 20) resolve();
      else reject();
    });
}
  

setTimeout(() => {
    const promise1 = async(25);
    promise1
        .then(() => {
        console.log("1 then!");
        })
        .catch(() => {
        console.log("1 catch!");
        });
    const promise2 = async(15);
    promise2
        .then(() => {
        console.log("2 then!");
        })
        .catch(() => {
        console.log("2 catch!");
        });
}, 3000);

async/await 과 Promise는 무슨 연관이 있죠?

async/await를 사용하면 위에서 사용하던 new Promise()를 리턴하는 함수를 손쉽게 만들 수 있습니다. 그 말은 async 함수의 리턴값은 무조건 Promise가 된다는 뜻이기도 합니다.


async function async(num) {
    if(num> 20) return `Success`
    else throw new Error()
}
  

setTimeout(() => {
    const promise1 = async(25);
    promise1
        .then(() => {
        console.log("1 then!");
        })
        .catch(() => {
        console.log("1 catch!");
        });
    const promise2 = async(15);
    promise2
        .then(() => {
        console.log("2 then!");
        })
        .catch(() => {
        console.log("2 catch!");
        });
}, 3000); // 위의 함수와 동일하게 작동합니다.


await는 Promise가 끝날 때 까지 기다리는 함수입니다. async 함수 안에서만 사용할 수 있습니다.



async function async(num) {
    if(num> 20) return `Success`
    else throw new Error('ERROR!!!')
}
  
function setTimeoutPromise(ms) {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(), ms);
    });
  }
  

const startAsync = async () => {
    await setTimeoutPromise(1000);
    try{
        const promise1 = await async(25)
        console.log(promise1)
    }catch(e){
        console.log(e)
    }
    try{
        const promise2 = await async(15);
        console.log(promise2)
    }catch(e){
        console.log(e)
    }
}

startAsync()

다음과 같이 사용할 수 있습니다. await를 사용하면 resolve 값을 리턴합니다. reject가 발생하면 예외가 발생하기 때문에 try, catch문으로 예외처리를 해야합니다.

Promise와 async/await의 차이점이 뭔가요?

Promise를 활용할 때에는 .catch()를 통해 에러 핸들링이 가능하지만 async/await는 try-catch문을 이용해야 합니다.

async/await은 비동기 코드가 동기 코드처럼 읽히게 해주어 코드가 길어질수록 async/await를 이용한 코드가 가독성이 좋다.

여러 비동기 동작을 한꺼번에 기다리는 건 어떻게 해야할까요?

Promise.all을 통해서 여러 비동기 동작을 한꺼번에 해결할 수 있습니다.
예를들어 밑과 같은 예시로는 여러 비동기 동작을 한꺼번에 해결할 수 없습니다. for문을 통해서 한개씩 기다리기 때문입니다.


function setTimeoutPromise(ms) {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(), ms);
    });
  }
  
  async function fetchAge(id) {
    await setTimeoutPromise(1000);
    console.log(`${id} 사원 데이터 받아오기 완료!`);
    return parseInt(Math.random() * 20, 10) + 25;
  }
  
  async function startAsyncJobs() {
    let ages = [];
    for (let i = 0; i < 10; i++) {
      let age = await fetchAge(i);
      ages.push(age);
    }
  
    console.log(
      `평균 나이는? ==> ${
        ages.reduce((prev, current) => prev + current, 0) / ages.length
      }`
    );
  }
  
  startAsyncJobs();



위와 같은 코드는 어떨까요? 1초만에 모든 사원의 정보를 모두 가져올 수 있습니다.

async function startAsyncJobs() {
  let promises = [];
  for (let i = 0; i < 10; i++) {
    promises.push(fetchAge(i));
  }
  
  let ages = await Promise.all(promises);

  console.log(
    `평균 나이는? ==> ${
      ages.reduce((prev, current) => prev + current, 0) / ages.length
    }`
  );
}

startAsyncJobs();

Spread Operator가 뭔지 아시나요?

Spread 연산자는 연산자의 대상 배열을 개별 요소로 분리합니다.

console.log(...[1, 2, 3]) // 1 2 3
console.log(...'Hello') // H e l l o

Rest parameter가 뭔가요?

Spread 연산자를 사용하여 함수의 파라미터를 작성한 형태를 말합니다. Rest Parameter를 사용하면 함수의 파라미터로 오는 값들을 'Array'로 전달받을 수 있습니다


function foo(...rest) {
	console.log(rest) // [1, 2, 3, 4, 5]
    
}
foo(1, 2, 3, 4, 5)

Spread 연산자와 Rest parameter의 차이점은 무엇인가요?

Rest parameter과 Spread 연산자 모두 ...을 통해 표현한다는 공통점이 있지만 
Rest parameter은 함수 선언문의 파라미터에 선언하여 배열로 만들어서 사용하는 것이고 
Spread 연산자는 배열을 각각의 개별 요소로 분리하는 것입니다.

arguments 객체에 대해서 알고 계신가요?

ES5에서도 가변 인자 함수의 경우 arguments 객체를 통해 인자값을 확인할 수 있습니다.
이는 유사 배열 객체로 순회가능하고 length값을 알 수 있지만 배열은 아닙니다. 대신 rest parameter은 실제 배열을 반환하기 때문에 rest parameter을 사용하는 것이 더욱 바람직하다고 판단됩니다.


var foo = function () {
  console.log(arguments);
};
foo(1, 2); // { '0': 1, '1': 2 }

JavaScript의 동작원리에 대해서 알고 계신가요?

JavaScript의 대표적인 예인 Google V8 엔진으로 설명드리겠습니다.
엔진은 Memory Heap(메모리 할당이 일어나는 곳), Call Stack(호출 스택이 쌓이는 곳) 두 개로 이루어져 있습니다.

이 두개와 Event Loop, setTimeout과 같은 브라우저 내장 API를 사용하게 해주는 Web APIs들을 통해 동작하게 됩니다.

Call Stack에 대해서 자세하게 알려주세요.

JavaScript는 한 개의 호출 스택을 가지고 있습니다. (single thread) 따라서 한 번에 한 작업만 처리할 수 있습니다.


function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);


PrintSquare을 실행하면 어떻게 될까요?


printSquare(5) -> printSquare(5) - multiply(x, x) -> printSquare(5) - console.log(s) -> printSquare(5) -> empty!

위와같은 스택 프레임이 생기게 됩니다.

싱글 스레드와 멀티 스레드의 장단점에 대해서 말씀해주세요.

싱글 스레드의 장점 
1. Context Switching을 사용하지 않기 때문에 자원 소모가 적다
2. 자원 접근에 대한 동기화를 신경쓰지 않아도 된다.
3. 단순 CPU만 사용한다면 싱글스레드로 프로그래밍하는 것이 효율적이다.(Context Switching안하니까!!)

싱글 스레드의 단점
1. 여러 개의 CPU를 활용하지 못한다.
2. 연산량이 많은 작업을 하는 경우 그 작업이 완료되어야 다른 작업을 수행할 수 있다.

멀티 스레드의 장점
1. 응답성 : 프로그램의 일부분이 중단되거나 긴 작업을 수행하더라도 프로그램의 수행이 계속되어 응답을 유지할 수 있다. (새로운 스레드를 생성하여 극복이 가능하다) 하지미나 싱글 스레드는 프로그램이 중단된다.
2. 다중 CPU 구조에서는 각각의 스레드가 다른 프로세서에서 병렬로 수행될 수 있으므로 병렬성이 증가한다.

멀티 스레드의 단점
1. Context Switching, 동기화 등의 이유로 싱글 스레드보다 느리다.
2. 프로그래밍 난이도가 높다. 스레드 수만큼 사원을 많이 사용한다.

JavaScript는 싱글 스레드의 단점을 어떻게 극복하나요?

비동기처리를 통해서 단점을 극복합니다. Callback 함수, ES6 이후의 Promise, async/await가 있습니다.

V8 엔진에 대해서 자세하게 설명해주세요.

구글이 만든 오픈 소스 자바스크립트﹒웹어셈블리 엔진으로, 자바스크립트 코드를 실행 전에 최적화된 머신 코드로 컴파일하는 엔진이다. (즉, V8은 자바스크립트 코드를 받아 컴파일하고 실행하는 C++ 프로그램이다.) 크롬 브라우저와 노드 js에서 사용된다.

왜 머신 코드로 컴파일해야 하나요?

우리가 사용하는 컴퓨터 안에는 마이크로프로세서라는 작은 기계가 있는데, 이것은 CPU의 핵심 기능을 통합한 집적 회로(IC)입니다. 프로그래머가 어떤 코드를 짜서 컴퓨터에게 일을 시키려면 결국 이 마이크로프로세서가 해석할 수 있는 언어로 전달해야 합니다. 마이크로프로세서는 이것을 만든 회사나 버전에 따라 각자 다른 언어를 사용하는데, 가장 많이 쓰이는 것들은 IA-32, x86-64, MIPS, ARM 등입니다. 이 언어들은 하드웨어와 직접적으로 소통할 수 있는 코드들이고 그래서 기계어, 머신 코드라 불리는데, 결국 프로그래머들은 프로그래밍 효율을 위해 추상화 수준이 높은 high level 언어를 사용해서 코딩을 하지만 이는 결국 머신 코드로 컴파일되어야만 CPU가 이해하고 처리를 할 수 있습니다.

V8이 하는 일에 대해서 설명해주세요.

1. JavaScript 코드를 컴파일하고 실행합니다.
2. 콜 스택을 핸들링해서 JavaScript 함수를 특정 순서에 따라 실행합니다.
3. 메모리 힙에 객체들의 메모리 할당을 관리합니다.
4. 더 이상 쓰이지 않는 객체들을 가비지 콜렉팅합니다.
5. 모든 데이터 타입, 연산자, 객체, 함수를 제공합니다.
6. 이벤트 루프를 제공합니다.

V8은 어떻게 JavaScript 코드를 컴파일할까요?

V8에는 Ignition이라는 JS 인터프리터와 TurboFan 이라는 컴파일러를 이용합니다.
이전에는 Crankshaft와 Full-codegen을 통해서 컴파일하였습니다.

1. 코드 실행 전에 Full-codegen이 JS 코드를 빠르게 non-optimized 머신 코드로 컴파일
2. 한 번 컴파일된 코드를 런타임 동안 분석하여 Crankshaft가 optimized 머신 코드로 재 컴파일

이 과정을 

1. Ignition이 JS코드를 non-optimized 바이트코드를 생성
2. TurboFan이 optimized 머신 코드로 컴파일

로 변경하였습니다. 그 이유는 TurboFan이 ES6를 제공하고 TryCatch와 같은 것들을 Crankshaft가 최적화하지 못했고
Ignition이 바이트 코드로 컴파일하는 것이 머신 코드로 컴파일 하는 것보다 1/2~1/4 정도로 사이즈가 작았기 때문에 웹페이지 로드 시간을 줄였기 때문입니다.

호이스팅(Hoisting)에 대해서 설명해주세요.

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위 최상단에 선언하는 것을 말합니다.

var 변수 선언과 함수 선언문에만 일어나는 현상입니다.

var : Hoisting
let, const : Not Hoisting

function foo(){} : Hoisting
var foo2 = function () {} : Not Hoisting

Scope에 대해서 알고 계신가요?

스코프란 식별자 접근 규칙에 따른 유효 범위입니다.
범위는 중괄호 혹은 함수에 의해 나뉘어 집니다.

스코프의 규칙
1. 안쪽 스코프에서 바깥쪽 스코프로 접근할 수 있지만 반대는 불가능
2. 스코프는 중첩이 가능
3. 전역 스코프와 지역 스코프
4. 지역 변수는 전역 변수보다 우선순위가 더 높다.

스코프는 블록 스코프와 함수 스코프가 있는데 화살표 함수는 함수 스코프가 아닙니다.

var은 범위를 함수 스코프를 기준으로 하기 때문에 
for(var i = 0; i<9;i++){
}
console.log(i)가 가능!!
let은 불가능

클로저에 대해서 알고 계신가요?

JS는 함수안에 함수를 중첩으로 가질 수 있고 JS는 함수 또한 객체로 취급합니다.
클로저는 이러한 함수의 특징을 이용하는 방법 중 하나라고 볼 수 있습니다.

클로저란 특정한 함수에서 자신을 감싸고 있는 함수의 변수나 중첩 함수 등을 그대로 활용할 수 있게 해주는 함수입니다.

function add(){
	let counter = 0;
    counter += 1
}

이 함수에서 add 함수를 3번 호출한다고 하면 모두 1이 나옵니다.
하지만 함수안에 선언해 놓은 어떠한 변수를 함수가 끝난 후에도 계속해서 사용하고 싶으면 전역 변수로 만드는 방법도 있지만, 클로저를 이용할 수 있습니다.

var add = (function add(){
	var counter = 0;
    return function() {return counter += 1}
})();

이렇게 하면 3번 호출 하였을 때 1, 2, 3이 출력됩니다.

(😒) 클로저는 그러면 왜 사용하나요?

객체지향의 관점으로 캡슐화를 적용하기 위해
전역변수의 오용을 줄이기 위해
다양한 JS의 디자인 패턴 적용

이벤트 버블링, 이벤트 캡쳐링에 대해서 아시나요?

이벤트 버블링은 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미합니다.

이벤트 캡쳐링은 이벤트가 하위 화면 요소들로 전달되어 가는 특성을 의미합니다.

참고 출처
쿠키와 세션의 차이점 : https://interconnection.tistory.com/74
JWT 토큰 : https://tofusand-dev.tistory.com/89
OSI 7단계 : https://bit.ly/3gJBnFk
OAuth란? : https://www.ciokorea.com/column/35252?page=0,1
홈페이지 렌더링 : https://patrick-f.tistory.com/14?category=1033516
프론트엔드 필수 질문 : https://realmojo.tistory.com/300

1개의 댓글

comment-user-thumbnail
2023년 1월 2일

프론트로 취업하려면 이런 내용들을 다 알고 암기하고 있어야하나요...?/

답글 달기