Jieunny의 블로그
[CS] CS 지식 본문
자바스크립트
1. this에 대해 설명해주세요.
this는 인스턴스 자신을 가리키는 참조변수 입니다.
1. 단독으로 쓴 this
// 1. 단독으로 쓴 this => global object
var x = this;
console.log(x); //window;
2. 함수 안에서 쓴 this
// 함수의 주인에게 바인딩 된다 => 함수의 주인은 window 객체!
// strict 모드에서는 this에 디폴트 바인딩이 없기 때문에 undefined가 된다.
function F() {
return this;
}
console.log(F()); //window
3. 메서드 안에서 쓴 this
// 해당 메서드를 호출한 객체로 바인딩 된다.
var person = {
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return this.firstName + ' ' + this.lastName;
},
};
person.fullName(); //"John Doe"
4. 이벤트 핸들러 안에서 쓴 this
// 이벤트를 받는 HTML 요소를 가리킨다
var btn = document.querySelector('#btn')
btn.addEventListner('click',function() {
console.log(this); //#btn
});
5. 생성자 안에서 쓴 this
// 생성자 함수가 생성하는 객채로 바인딩 된다.
function Person(name) {
this.name = name;
}
var kim = new Person('kim');
var lee = new Person('lee');
// new 키워드를 빼먹는 순간 일반 함수 호출과 같아지기 때문에 window에 바인딩 됩니다!!!
console.log(kim.name); //kim
console.log(lee.name); //lee
6. 명시적 바인딩을 한 this
// apply()에서 매개변수에 받은 첫번째 값은 함수 내부에서 사용되는 this에 바인딩되고 두번째 값인 배열은 자신을 호출한 함수의 인자로 사용한다.
// call()도 거의 똑같은데 인수 배열이 아닌 인수 목록을 받는다.
function whoisThis() {
console.log(this);
}
whoisThis(); //window
var obj = {
x: 123,
};
whoisThis.call(obj); //{x:123}
7. 화살표 함수로 쓴 this
화살표 함수에는 this라는 변수 자체가 존재하지 않기 때문에 상위 환경에서의 this를 참조하게 된다.
=> 객체의 메소드를 화살표 함수로 정의하면 안된다 => 그 메소드는 태생부터 this를 window를 가르키기 때문이다.
const object = {
name: 'je',
nickname: 'cinnamon',
getIntro: function() {
innerFunc = () => `${this.name}님의 닉네임은 ${this.nickname}입니다.`;
console.log(innerFunc());
}
};
object.getIntro();
// 'je님의 닉네임은 cinnamon입니다.'
2. 콜백 함수에 대해 설명해주세요.
+ 콜백 지옥을 해결하는 방법을 설명해주세요.
콜백함수는 다른 함수의 인자로 전달되어지는 함수 입니다. 어떤 함수가 실행되고 나서의 실행이 보장됩니다. 익명 함수, 화살표 함수를 쓰는 것을 권장합니다.
함수의 매개변수 넘겨지는 콜백함수가 너무 많아져 들여쓰기의 깊이가 깊어지게 되고, 감당할 수 없을 정도를 콜백 지옥이라고 합니다.
콜백지옥을 해결하는 방법은 Promise객체를 사용하는 방법이 있다.
3. Promise에 대해 설명해주세요.
자바스크립트 비동기 처리에 사용되는 객체입니다.
promise 생성자 함수는 reject, resolve함수를 인자로 받는 콜백함수를 인자로 받는다.
promise는 대기, 이행, 거부 상태를 가지는데 대기는 프로미스 객체를 생성했을 때, 이행은 resolve()가 호출되었을 때, 거부는 reject()가 호출되었을 때이다.
비동기 처리가 성공하면 resolve(), 실패하면 reject()를 호출한다.
성공했을 경우 then()으로 성공처리를, 실패할 경우 catch()로 실패처리를 할 수 있다.Promise는 콜백 함수를 사용했을 때 발생할 수 있는 콜백지옥을 해결할 수 있다.
4. Promise와 Callback을 비교 설명해주세요.
callback으로 코드를 작성할 경우 들여쓰기가 불필요하게 많이 작성되어 가독성이 떨어집니다.
5. Async, Await가 무엇인지, 사용 방법을 설명해주세요.
콜백지옥이나 프로미스가 여러개 의존하고 있는 경우, async와 await를 통해 더 간결하게 promise객체를 사용해서 비동기를 처리할 수 있습니다. 함수 앞에 async를 붙이면 그 함수는 promise를 반환하게 되고, await를 붙이면 그 부분은 해당 promise가 끝날때가지 기다렸다가 처리됩니다. await는 async가 붙은 함수 안에서만 사용 가능하며, promise가 resolve한 값을 내놓습니다. promise 객체를 사용하기 때문에 then, catch를 사용해서 예외 처리가 가능합니다.
function promiseFunc() {
return new Promise((resolve, reject) => {
resolve('Promise is awesome')
})
}
promiseFunc().then(console.log);
async function asyncFunc() {
return 'Async is awesome'
}
asyncFunc().then(console.log)
Q. 에러 핸들링?
try/catch로 감싸서 에러 핸들링을 할 수 있다.
6. Promise와 Async, Await의 차이를 설명해주세요.
7. var, let, const 차이를 설명해주세요.
var는 (함수 레벨 스코프) 함수 외부에서 선언했을 경우 전역 변수처럼 쓰인다. 함수 내에서 선언했을 때는 함수 내부에서만 쓸 수 있다. 재선언, 재할당이 가능하다.
let은 블록 범위 내에서만 사용 가능하다. 재할당은 될 수 있지만 재선언은 불가능하다.
const는 블록 범위 내에서만 사용 가능하다. 재할당도, 재선언도 불가능하다.
Q. var변수는 왜 지양하라고 할까?
1. 중복 선언이 가능하다.
개발자가 의도치않게 중복선언을 해서 문제가 발생할 수 있다.
2. 함수 레벨 스코프이다.
함수 외부에서 선언된 var 변수는 전역 변수가 되고, 전역 변수를 남발해서 사용하면 개발에 문제가 될 수 있다.
8. 이벤트 버블링과 캡처링, 이벤트 위임에 대해 설명해주세요.
1. 이벤트 버블링 : 자식 요소에서 발생한 이벤트가 부모 요소로 전파(기본값)
- addEventListener() 함수로 요소의 이벤트를 등록하면 기본적으로 버블링 전파 방식으로 이벤트가 흐르게 된다.
2. 이벤트 캡쳐링 : 자식 요소에서 발생한 이벤트가 부모 요소부터 시작해서 안쪽 자식 요소까지 도달
- addEventListner() 함수의 3번째 매개변수로 true 값을 주면 캡처링을 통해 이벤트를 전파할 수 있다.
3. 이벤트 위임 : 하위 요소마다 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식
<html>
<head></head>
<body>
<table>
<tbody>
<tr>
<td>Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr>
<td>Over the River, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
</body>
</html>
(1) <td> 를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파된다(캡처링 단계)
(2) 이벤트가 타깃 요소에 도착해 리스너를 실행한다(타깃 단계)
(3) 그리고 다시 상위로 이벤트를 전파한다 (버블링 단계)
- 이벤트 전파가 있는 이유
(1) 자식 요소가 부모 요소 안에 위치 하고 있기 때문
(2) 이러한 특징 때문에 이벤트 등록 코드를 줄일 수 있다는 장점이 있다 => 이벤트 위임
부모 요소인 <ul>에만 이벤트를 등록하면 몇번째 <li> 요소를 클릭하든 부모 요소인 <ul>에 이벤트가 전파되기 때문에 원하는 구현을 간단히 할 수 있다.
- 이벤트 위임의 이점
- 상위 엘리먼트에서만 이벤트 리스너를 관리하기 때문에 하위 엘리먼트는 자유롭게 추가 삭제할 수 있다.
- 이벤트 핸들러 관리가 쉽다.
- 동일한 이벤트에 대해 한 곳에서 관리하기 때문에 각각의 엘리먼트를 여러 곳에 등록하여 관리하는 것보다 관리가 수월하다.
- 메모리 사용량이 줄어든다.
- 방지 방법
(1) 이벤트 전파 방지 : e.stopPropagation()
(2) 형제 이벤트 실행 중지 : e.stopImmediatePropagation()
9. 호이스팅과 발생하는 이유에 대해 설명해주세요.
호이스팅이란 코드 실행 전 변수, 함수 선언이 최상단으로 끌어 올려진 것 같은 현상을 말합니다.
자바스크립트 엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언을 스코프에 등록합니다. 실행 컨텍스트는 코드가 실행되기 위해 필요한 환경을 의미합니다.
var 변수 같은 경우에는 선언 단계와 초기화 단계가 같이 이루어지기 때문에 undefined으로 이미 초기화되어있는 상태이다. 때문에 선언 전에도 참조가 가능하다.
하지만 let과 const는 선언 단계와 초기화 단계가 따로 이루어지기 때문에 참조가 되지 않아 호이스팅이 이루어지지 않는 것처럼 보이지만 호이스팅이 일어난다.
10. 클로져에 대해 설명해주세요.
클로저는 함수와 함수가 선언된 어휘적 환경의 조합입니다. 어휘적 환경이란 함수가 선언된 주변환경을 의미합니다. 내부 함수의 어휘적 환경에 외부 함수가 포함됩니다. 외부 함수가 리턴되어도 내부 함수를 사용해서 접근할 수 있습니다.
11. 동기와 비동기에 대해 설명해주세요.
동기는 요청이 끝날 때까지 기다렸다가 다음 요청을 처리하는 것이고, 비동기는 기다리지 않고 다음 요청을 처리하는 것입니다. 자바스크립트는 싱글 스레드 언어이기 때문에 동기적으로 작동하지만, 자바스크립트 런타임에서 비동기 처리를 돕기 때문에 비동기 처리가 가능하다.
12. null, Undefined, NaN, 선언하지 않은 변수에 대해 설명해주세요.
null은 원시 자료형 null로 구분되며, 자바스크립트는 대소문자를 구분하기 때문에 Null, NULL과는 다릅니다.
비어있는 값을 의미하며 변수에 값이 없다는 것을 의도적으로 명시하기위해 사용합니다.
typeof로 찍을 경우 object를 반환하는 이유는, null이 빈 참조를 나타내는 데 자주 사용되기 때문입니다.
undefined는 원시 자료형 undefined로 구분되며, 아무 값도 할당받지 않은 상태를 의미합니다. (선언 이후 값이 할당되지 않은 변수)
var 키워드로 선언한 변수는 undefined로 초기화됩니다.
변수 선언에 의해 확보된 메모리 공간을 처음 할당이 이루어질 때 까지 내버려두지 않고 자바스크립트 엔진이 undefined로 초기화합니다.
NaN은 Not a Number로 유효하지 않은 연산일 때 반환되는 값 입니다. 타입은 Number입니다.
선언되지 않은 변수는 메모리 공간을 차지 하지 않고, 존재하지 않는 변수입니다.
13. attribute와 property의 차이는 무엇인가요?
attribute는 HTML 태그의 속성을 의미하며 정적이라는 특성이 있습니다.
<div class="my-class"></div>에서 class가 attribute가 된다.
property는 DOM에서의 속성을 의미하며 동적이라는 특성이 있습니다.
<input value="텍스트를 입력하세요">에서 value는 attribute이지만, 사용자가 input 박스에 고양이 라는 단어를 입력한다면 property라고 할 수 있다.
.attr()은 html의 attribute를 다루고, .prop()은 js의 property를 다룹니다.
<a id="get_comment" href="#comments">코멘트</a>
var $comment = $('#get_comments');
alert($comment.attr('href')); // href 속성 값을 표시
alert($comment.prop('href')); // href 프로퍼티 값을 표시
.attr()은 '#comments'
.prop()은 'http://test.com/path/page#comments'
14. PHP 언어란 무엇인가요?
Personal Home Page Tools의 약자로, 웹사이트 제작에 특화된 백엔드 언어입니다.
동적인 웹페이지를 만들기 위해 설계 된 언어입니다.
정적인 언어인 HTML 코드 내부 안에 동적인 기능이 구현 가능한 PHP 코드를 넣어 웹페이지의 기능을 실행할 수 있습니다.
PHP는 사용자가 어떠한 동작을 요청하면 웹 서버(Server)에서 값을 받아 데이터베이스(DB)와 연동을 위해 PHP 파서(Parser)를 통해서 응답을 받아 그 결괏값을 사용자에게 전달합니다.
자바스크립트와 차이점은?
js는 클라이언트 측 스크립트이고, PHP는 서버 측 스크립트 입니다.
js와 달리 코드가 보여지지 않기 때문에 보안성이 뛰어납니다.
15. es5와 es6의 차이점은 무엇인가요?
1. let, const 키워드 추가(스코프 차이)
2. 화살표 함수 추가(가독성 및 유지 보수성 상승)
3. dafault 파라미터 추가(함수 내부에 따로 로직 작성 필요 없어짐)
4. 템플릿 리터럴 추가(백틱으로 작성하면 됨)
5. 클래스, 모듈 추가
7. 프로미스 추가
8. string 메서드 추가(includes, startsWith, endsWith)
Q. 과거 버전은 왜 알아야 하는가?
1. 레거시 코드(누군가 남기고 간 기존 코드)를 최신 문법으로 리팩토링 할 수 있어야 하기 때문
2. 구글링한 코드의 동작을 해석해서 유지 보수 할 수 있어야 하기 때문에
3. 모든 회사가 최신 문법을 사용하지 않으며, 최신 문법을 사용하더라도 시간이 지나면 레거시 코드가 되기 때문
16. 얕은 복사(Shallow Copy), 깊은 복사(Deep Copy)
1. 얕은 복사(참조에 의한 할당)
const obj1 = { a: 1, b: 2};
const obj2 = obj1;
console.log(obj1 === obj2); // true
obj2.a = 100;
console.log(obj1.a); // 100;
- 두 객체는 같은 주소를 가지고 있기 때문에 하나를 바꾸면 다른 하나도 바뀐다.
const obj1 = {a: 1, b: 2};
const obj2 = { ...obj1 };
obj2.a = 100;
console.log( obj1 === obj2 ) // false;
console.log(obj1.a) // 1
- spread 연산자를 통해 obj1의 속성을 복사해서 obj2에 할당했다.
- obj1과 obj2는 다른 주소를 가진 다른 객체이다. (딱 1 depth 까지만!)
const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
- Object.assign()을 통해 obj1을 obj2에 할당했다.
- obj1과 obj2는 다른 주소를 가진 다른 객체이다. (딱 1 depth 까지만!)
2. 깊은 복사(아예 새로운 객체를 만드는 것)
📌 2단 이상으로 이루어진 객체 깊은 복사하기
1. JSON.parse(), JSON.stringify()
const iu = {
name : '아이유',
age : 30,
album : {
Lilac : "타이틀곡",
Palette : 2017
}
}
const iu2 = JSON.parse(JSON.stringify(iu));
iu2.album.Lilac = 2021;
console.log(iu);
console.log(iu2);
2. 재귀함수 사용
const iu = {
name : '아이유',
age : 30,
album : {
Lilac : "타이틀곡",
Palette : 2017
}
}
const copy = (obj) => {
if(typeof obj !== "object" || obj === null){
return obj;
}
// object가 아닐때
const deepCopyObj = {};
// object 일때
for(let key in obj){
deepCopyObj[key] = copy(obj[key]);
}
return deepCopyObj;
}
const iu2 = copy(iu);
iu2.album.Lilac = 2021;
console.log(iu);
console.log(iu2);
리액트
1. 리액트 라이프 사이클과 라이프 사이클 메서드에 대해 설명해주세요.
리액트 컴포넌트에는 생명 주기가 있는데 이를 라이프 사이클이라고 표현합니다. 컴포넌트는 생성(Mounting) -> 업데이트(Updating) -> 제거(Unmounting) 의 생명 주기를 갖습니다. 리액트 클래스 컴포넌트는 라이프 사이클 메서드를 사용하고, 함수형 컴포넌트는 리액트 훅인 useEffect를 사용합니다.
클래스 컴포넌트의 라이프 사이클 메서드
1. 마운트 : 컴포넌트가 생성되는 시점을 의미하며, constructor -> getDerivedStateFromProps -> render -> componentDidMount 순서로 메서드가 호출된다.
constructor : 컴포넌트 생성자 메서드로 컴포넌트가 만들어지면 가장 먼저 실행되는 메서드
getDerivedStateFromProps : props로 받아온 것을 state로 넣어주고 싶을 때 사용한다. 컴포넌트가 처음 렌더링 되기 전에 호출되며 리렌더링 되기 전에도 항상 실행된다. Props나 State가 변경되었을 때도 호출된다.
render : 컴포넌트를 렌더링하는 메서드
componentDidMount : 컴포넌트의 첫번째 렌더링이 끝나고 나면 호출되는 메서드로, 이 메서드가 호출되는 시점에선 컴포넌트가 화면에 출력된 상태이다.
2. 업데이트 : 컴포넌트가 업데이트 되는 시점을 의미하며, getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate 순서로 메서드가 호출된다.
shouldComponentUpdate : 컴포넌트의 리렌더링 여부를 결정하는 메서드로 React.memo와 유사하다.
getSnapshotBeforeUpdate : render에서 만들어진 결과가 브라우저에 실제 반영되기 직전에 호출되는 메서드. 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면, 그 다음 발생하는 componentDidUpdate에서 받아와서 사용할 수 있다.
componentDidUpdate : 리렌더링 마치고, 화면에 우리가 원하는 변화가 모두 반영되고 난 뒤에 호출되는 메서드, 의존성 배열이 변할때만 useEffect가 실행되는 것과 같다.
3. 언마운트 : 컴포넌트가 화면에서 사라지는 시점을 의미하며, 컴포넌트가 화면에서 사라지기 직전에 componentWillUnmout 메서드가 호출된다.
componentWillUnmount : 주로 DOM에 직접 등록했던 이벤트를 제거한다.
함수형 컴포넌트의 useEffect
화면에 렌더링이 완료된 후에 수행되며 componentDidMount, componentDidUpdate, componentWillUnmout가 합쳐진 것
// 1. 컴포넌트가 리렌더링 될 때 마다 실행됨.
useEffect(() => {
})
// 2. componentDidMount()
// 렌더링이 완료된 후 호출됨 => 마운트 이후 1회만 실행
useEffect(() => {
}, [])
// 3. componentDidUpdate() & getDerivedStateFromProps()
// 컴포넌트 업데이트 작업이 완료된 후 실행됨 => 2번째 파라미터 배열에 적어준 변수가 변경될 때만 실행
useEffect(() => {
}, [props, state, ...]}
// 4. componentWillUnmount()
// 언마운트 관련 코드는 return 콜백에 작성
useEffect(() => {
return () => {
// unmount 코드
}
}, [props, state, ...])
2. 리액트 Hook에 대해 설명해주세요.
기존 클래스형 컴포넌트의 코드를 작성할 필요 없이 함수형 컴포넌트에서도 상태 값과 리액트의 여러 기능을 사용할 수 있도록 하는 기능입니다. 대표적으로는 useState와 useEffect가 있습니다.
Hook을 사용하기 위해서는 두가지 규칙을 지켜야 합니다.
최상위에서만 훅을 호출해야합니다. 리액트는 이 훅들을 호출되는 순서대로 저장해놓고 매 렌더링마다 순서대로 훅을 호출합니다. 조건문이나 반복문에서 훅을 사용할 경우 조건에 따라 훅이 실행되지 않을 수 있기 때문에 호출 순서가 꼬일 수 있습니다.
리액트 함수 컴포넌트 내에서만 훅을 호출해야 합니다. 훅은 리액트의 함수형 컴포넌트 내에서 사용되도록 만들어졌기 때문에 일반 JavaScript 함수 내에서는 정상적으로 작동하지 않습니다.
3. Props Drilling에 대해 설명해주세요.
props를 하위 컴포넌트로 전달하기 위해 여러 컴포넌트를 거쳐야 하는데, 그 데이터가 필요하지 않은 컴포넌트에까지 props를 전달하게 되는 현상입니다.
해결 방법으로는 Redux 같은 상태 관리 라이브러리를 사용해 전역으로 상태를 관리하는 방법이 있습니다. 상태를 전역으로 관리하게되면서 필요한 컴포넌트에서만 상태를 불러올 수 있습니다.
4. Key props를 사용하는 이유에 대해 설명해주세요.
Key는 리액트가 어떤 항목을 변경, 추가 또는 삭제할 지 식별하는 것을 돕는 역할을 합니다.
Key props를 주었을 때는 변경된 부분만 식별해서 필요한 부분만 렌더링하지만, 주지 않는다면 불필요한 렌더링이 추가로 발생하게 됩니다.
또한 엘리먼트에 안정적인 고유성을 부여하기 위해서 입니다.
Key는 그 값이 변하지 않는 유일한 식별자 역할을 합니다. 때문에 고유성 부여를 위해서 Key 값은 데이터의 id와 같이 바뀌지 않는 고유한 값을 주는 것이 좋습니다.
5. 리액트에서 메모이제이션을 어떤 방식으로 활용할 수 있나요?
메모이제이션은 연산의 결과값을 메모리에 저장해두고 이전 값과 결과가 동일할 때 재사용하는 기법입니다.
리액트에서는 React.memo(), useMemo()와 useCallback() 메서드를 통해 사용할 수 있습니다.
Q. useMemo와 useCallback에 대해 설명해주세요.
React.memo(컴포넌트) 컴포넌트 자체를 메모이제이션해서 들어온 props의 값이 바뀌면 해당 컴포넌트를 리렌더링 시킵니다. 때문에 props를 받는 자식 컴포넌트에서 사용하는 것이 권장됩니다.
useMemo(() => 함수의 리턴값, [])는 함수의 리턴 값을 메모이제이션해서 deps에 들어있는 의존성 값이 변경되지 않는다면 메모이제이션 된 값을 사용합니다.
useCallback(() => {함수}, [])는 함수 자체를 메모이제이션해서 deps에 들어있는 의존성 값이 변경되지 않는다면 이전에 생성한 함수의 참조 값을 반환해줍니다.
자바스크립트에서 함수는 객체로 취급되므로 리렌더링이 일어날 때마다 새로운 함수가 생성됩니다. useCallback()으로 감싸주게 되면 첫 렌더링 시에만 생성하고 그 이후에는 재생성하지 않습니다.
6. dependency 배열의 참조 타입 처리에 대해 설명해주세요.
자바스크립트에서 객체는 참조값(메모리 주소)을 비교하기 때문에 객체의 속성 값이 같더라도 다른 메모리 주소에 저장되어 있으면 다른 객체로 판단합니다. 참조 타입은 렌더링이 될 때마다 참조 메모리 주소가 달라지기 때문에 리액트는 다른 값으로 인지해서 렌더링을 발생시킵니다. 때문에 참조 타입을 의존성 배열에 넣을 때는 깊은 비교를 통해 값을 비교해야 합니다.
7. Redux에 대해 설명해주세요.
리덕스를 사용하는 이유와 장단점 포함.
리덕스는 리액트에서 사용되는 상태 관리 라이브러리 중 하나입니다. 프로젝트의 규모가 커질수록 많은 상태들을 사용하게 되고, 컴포넌트 간에 데이터를 주고받기 위해서는 props로 전달해야 합니다. 상위 컴포넌트가 너무 위에 있는 경우에는 props drilling의 문제가 발생할 수 있고, 상태를 관리하기가 복잡해집니다. 리덕스를 사용해 상태를 전역적으로 관리할 경우 이 문제를 해결할 수 있습니다.
스토어에 상태를 저장하고 관리하기 때문에 전역적으로 상태를 관리할 수 있습니다. action -> dispatch -> reducer -> store 의 순서로 단방향으로 데이터가 흐르게 되며 store에 저장한 상태들은 useSelector를 사용해서 가져다 쓸 수 있습니다.
상태를 쉽게 관리할 수 있고, 상태가 어디에서 어떻게 변했는지 예측 가능하다는 장점이 있지만 러닝 커브가 높고, 액션값과 리듀서, 디스패치 함수 등 초기에 많은 코드를 미리 작성해야 한다는 단점이 있습니다.
8. Redux와 Recoil을 비교해주세요.
리덕스와 리코일은 리액트에서 사용하는 상태 관리 라이브러리입니다. 리덕스는 이미 검증된 신뢰성 있는 라이브러리로, Redux Devtools과 같은 확장 프로그램을 통해 직관적으로 볼 수 있습니다. 리코일은 따로 안정적인 Devtool이 아직 없으며, 리덕스에 비해 직관적으로 보기 어렵습니다. 하지만 리덕스에 비해 간단한 구조를 가지고 있어서 적은 코드로 상태를 관리할 수 있습니다. 리덕스는 객체를 사용해서 상태를 구성하며 리코일은 Atom이라는 상태의 단위를 사용해 구성합니다.
리덕스는 redux-saga 등의 라이브러리를 사용해서 비동기 처리를 해야하는 반면, 리코일은 비동기 처리를 기반으로 작성되기 때문에 라이브러리에 의존할 필요가 없습니다.
9. state의 불변성을 지켜야하는 이유는?
- 불변성을 지킨다 => 메모리 영역에서 값을 변경할 수 없게 한다.
- 리액트의 state 변화 감지 기준은 콜 스택의 주소값! (얕은 비교)
- 원시 타입과 참조 타입의 저장 방식
1. 원시 타입 : 콜 스택에 값이 저장된다.
- 값을 변경할 경우, 콜 스택에 새로운 주소를 추가해 값을 저장하고 변수가 그 주소를 바라보게 한다 => 불변성 유지
- 더 이상 참조되지 않는 데이터는 가비지 컬렉터에 의해 적절한 시점에서 메모리가 해제된다.
2. 참조 타입 : 메모리 힙에 실제 값이 저장되고 콜 스택에 메모리 힙의 주소가 저장된다.
- push를 통해 값을 추가할 경우 콜 스택의 값(주소)이 변경되지 않고, 메모리 힙에 있는 데이터가 변경되어 불변성이 유지되지 않는다.
- 리액트에서 불변성을 지켜야 하는 이유
1. 원시 타입의 경우 값을 재할당할 경우 새로운 메모리가 할당되어 콜 스택의 주소값이 변경되 감지가 되지만,
2. 참조 타입의 경우 실제로 콜 스택의 주소값은 변경이 없어 state 감지가 되지 않아 리렌더링이 되지 않는다. 그래서 spread 연산자를 쓰는 등 새로운 배열과 오브젝트를 만들어 반환해야 한다!!
타입스크립트
1. 타입스크립트를 사용하는 이유에 대해 설명해주세요.
오류를 잡아내기 쉽기 때문입니다. 자바스크립트는 인터프리터 언어, 타입스크립트는 컴파일 언어입니다. 인터프리터 언어는 런타임 환경에서 코드를 읽어내려가며 해석하도록 만들어진 언어이고 컴파일 언어는 컴파일링 과정을 거쳐 실행되어지는 언어입니다. 타입스크립트는 컴파일링을 거쳐 자바스크립트로 변환되는데 실제 런타임 과정까지 거치지 않고 이 과정에서 오류를 잡아내기 때문에 우류를 잡아내기 쉽다는 장점이 있습니다.
2. Type과 Interface의 차이점에 대해 설명해주세요.
인터페이스 : 오직 객체 타입에만 가능하다. 확장이 가능하다.
타입: 모든 타입에 이름을 달아줄 수 있다. 확장이 불가능하다.
3. 제네릭에 대해 설명해주세요.
타입을 마치 함수의 파라미터처럼 사용하는 것
아직 정해지지않은 타입을 표기할 수 있다.
한 가지 타입보다 여러 타입에서 동작하는 컴포넌트를 생성하는 데 사용한다.
프론트엔드 전반
1. 브라우저 렌더링 과정을 설명해주세요.
브라우저는 렌더링 엔진을 사용해 요소들을 렌더링 합니다. HTML, CSS 파일을 각각 파싱 후 DOM(Document Object Model) TREE, CSSOM(CSS Object Model) TREE를 구축하고 두 TREE를 결합해 RENDER TREE를 구축합니다. RENDER TREE를 구축한 후, 레이아웃과 페인팅 단계를 거칩니다. 레이아웃 단계는 렌더트리의 각 노드의 크기와 위치를 계산해서 배치하는 과정이며, 페인팅은 이를 기반으로 노드를 픽셀 단위로 변환해 화면에 그려주는 과정입니다.
2. CSR과 SSR의 차이는 무엇인가요?
CSR은 브라우저 측에서 렌더링을 처리하는 방식이고, SSR은 서버에서 렌더링을 처리하는 방식입니다.
CSR의 경우 서버로부터 HTML, CSS, JS 파일을 처음에 다 가져오기 때문에 초기 로딩은 느리지만, 추가적인 정보가 필요할 때 비동기적으로 데이터를 가져오기 때문에 서버의 부하가 적습니다. 리액트가 CSR에 최적화 된 라이브러리 입니다.
SSR은 서버에서 렌더링 준비를 마친 상태로 브라우저에 전달하기 때문에 초기 로딩이 빠르고 SEO에 최적화 되어 있습니다. 하지만 매번 서버에 요청을 해야하기 때문에 서버 자원을 더 많이 사용합니다.
Q. 서버부하를 줄이는 법? (Next.js의 SSG방식)
Next.js란 Single Page Application에 SSR을 적용하기 위한 프레임워크이다.
SSG는 Sever-Side-Generation 또는 Static-Site-Generation 이라고 표현하는데 Next에서 사용하는 렌더링 방식이다. 브라우저에 렌더링할 때 기본적으로 pre-rendering으로 각 페이지들을 사전에 미리 HTML문서로 생성해서 가지고 있는 것이다. 그래서 서버로 요청이 들어올 때 알맞은 페이지를 반환해준다.
1. SSG : HTML을 빌드 타임에 각 페이지별로 생성하고 해당 페이지로 요청이 올 경우 이미 생성된 HTML 문서를 반환한다.
2. SSR : 요청이 올 때 마다 해당하는 HTML 문서를 그때 그때 생성해서 반환한다.
SSG로 렌더링을 하면 서버의 부하가 줄어들고, 응답 속도가 매우 빠르다.
3. CORS와 해결 경험을 말씀해주세요.
CORS는 Cross Origin Resource Shring으로 한 출처에서 실행 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 크게 프리플라이트 요청, 단순 요청, 인증정보 포함 요청 3가지가 있습니다.
프리플라이트 요청은 본 요청을 보내기 전에 OPTIONS 메서드를 통해 다른 출처의 리소스에 요청이 가능한지 확인 작업을 하고, 가능하다면 본 요청을 보내는 것입니다.
단순 요청은 요청이 특정 조건을 만족할 때 프리플라이트 요청을 보내지 않고 서버가 본 요청에 대한 응답 헤더에 CORS 관련된 헤더를 보내서 브라우저가 이를 검사하는 형태로 CORS 정책 위반 여부를 검사합니다.
인증정보 포함 요청은 헤더에 credentials 옵션을 사용해서 인증과 관련된 정보를 담아 보내는 요청입니다.
해결 경험은 서버에서 CORS를 허용해주는 것입니다. 서버에서 Access-Control-Allow-Origin 헤더를 세팅해주는 방법이 있습니다. 허용하고자 하는 도메인을 헤더에 작성해주면 됩니다.
프론트엔드 쪽 해결방법 : proxy 서버 설정(CORS 정책 우회 가능) - 프록시서버를 통해서 다른 네트워크 서비스에 간접적으로 접근이 가능하다.
4. Cookie, Session, Web Storage(local storage, session storage)의 차이에 대해 설명해주세요.
쿠키 : 클라이언트(브라우저)에 저장되는 키와 값 형태의 작은 파일
Session Cookie : 브라우저가 종료되면 삭제되는 쿠키
Permanent Cookie : 브라우저가 종료되어도 일정 기간 유지되는 쿠키
- Expires 또는 Max-Age 속성을 명시해주어야한다.
- 디스크에 저장되기 때문에 공공 PC의 경우 쿠키를 탈취할 수 있음.
세션 : 세션 ID를 식별자로 서버에 정보를 저장한다.
클라이언트는 HTTP Session ID를 쿠키로 가지고 있다(세션 쿠키)
브라우저가 종료 시 삭제된다.
로컬 스토리지 : 새창을 띄워도 도메인만 같으면 동일한 데이터를 공유하며 다른 도메인의 로컬 스토리지에는 접근이 불가능하다. 브라우저를 종료해도 삭제되지 않는다.
자동 로그인
세션 스토리지 : 새창, 새탭의 단위로 스토리지가 생성되며 데이터를 공유하지 않는다. 브라우저의 창이나 탭을 닫으면 저장된 객체가 사라진다.
일회성 로그인
5. 세션 기반 인증 & 토큰 기반 인증에 대해 설명해주세요.
1. 세션 기반 인증 : 인증 정보를 서버에 저장
사용자 로그인 -> 정보를 서버의 세션 저장소에 저장 -> 사용자에게 Session ID 발급(브라우저에 쿠키 형태로 저장되고 실제 인증 정보는 서버에 저장됨) -> 브라우저는 요청마다 HTTP Cookie 헤더에 Session ID를 함꼐 서버로 전송 -> 서버는 Session ID를 확인하고 존재한다면 사용자를 인증
2. 토큰 기반 인증 : 인증 정보를 클라이언트가 들고 있음
사용자 로그인 -> JWT 토큰 생성 -> 사용자에게 전달(브라우저의 로컬 스토리지 혹은 쿠키에 저장) -> 사용자가 요청 시 가지고 있는 토큰을 HTTP의 Authorization 헤더에 실어 보냄 -> 헤더를 수신한 서버는 토큰 위변조, 만료 기간 확인 후 인증
Q. JWT 토큰을 쿠키에 저장했을 때 취약점
쿠키는 자바스크립트로 읽을 수 있는 값이기 때문에 아무런 처리없이 쿠키에 저장하면 보안에 취약하다.
쿠키는 자동으로 http request 에 담아서 보내기 때문에 공격자가 request url을 알고 있다면 request를 위조하기 쉽다.
Q. JWT 토큰
Json Web Token : 모바일이나 웹의 사용자 인증을 위해 사용하는 암호화된 토큰
6. 크로스 브라우징에 대해 설명해주세요.
웹 페이지 제작 시에 모든 브라우저에서 깨지지 않고 의도한 대로 올바르게 나오게 하는 작업
브라우저마다 렌더링 엔진이 다르기 때문에 크로스 브라우징이 필요하다.
가장 높은 점유율을 가지고 있는 브라우저에 맞추고, CSS 초기화 작업을 통해 브라우저마다 차이가 나는 기본 스타일 값을 초기화 시킨다. Vender Prefix 를 사용해서 CSS 속성 앞에 브라우저 별 접두사를 붙인다.
.selector {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
7. REST API에 대해 설명해주세요.
API : 응용 프로그램(애플리케이션)에서 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스
REST API : 웹상에서 사용되는 여러 리소스를 HTTP URI로 표현하고, 해당 리소스에 대한 행위를 HTTP Method로 정의하는 방식 -> 리소스를 어떻게 하겠다! 라고 깔끔하게 표현하는 방법
리소스에 대한 행위는 HTTP Method를 통해 표현, 슬래시는 계층 관계를 나타낼 때 사용 등...
RESTful API : REST API 설계 가이드를 따라 API를 만드는 것
그 자체만으로도 API의 목적이 무엇인지 명확하게 알 수 있다!
Q. URI(Uniform resource identifier) ?
웹 서버의 리소스들은 각자 이름을 가지고 있어서 클라이언트가 원하는 리소스를 지목해서 요청할 수 있다. 서버 리소스 이름은 URI로 불리며 URI는 인터넷의 우편 주소 같은 것으로 리소스를 고유하게 식별하고 위치를 지정할 수 있다.
URI는 URL과 URN 두 종류로 나뉜다.
URL(Uniform resource locator) : 특정 서버의 어떤 리소스에 대한 구체적인 위치를 표기
URN(Unifrom resource name) : 어떤 리소스에 대해서 해당 리소스가 위치에 영향을 받지 않는 유일한 이름을 갖는 역할을 한다.(리소스가 이름을 바꾸지 않는 한 이곳저곳으로 옮기더라도 문제없이 작동함을 의미)
8. SEO에 대해 설명해주세요.
SEO는 검색 엔진 최적화 입니다. 웹 사이트가 검색 방식을 통해 검색 엔진에서 상위에 노출될 수 있도록 최적화하는 과정을 말합니다. 검색 엔진은 웹 페이지를 크롤링 하는 로봇인 웹 크롤러를 사용해서 해당 페이지가 어떤 콘텐츠를 갖고 있는지 판단합니다. 크롤링, 인덱싱, 검색 결과 제공의 단계를 거칩니다.
1. 크롤링 : 검색 엔진이 웹사이트를 방문해서 페이지 내용을 수집하는 과정
2. 인덱싱 : 검색 엔진이 웹페이지를 수집하고 분류하는 과정
3. 검색 결과 제공 : 사용자가 검색어를 입력하면 구글은 해당 검색어와 관련된 페이지를 데이터베이스에서 찾아서 결과 페이지에 노추출한다.
Q. 최적화 방법
문법에 맞는 HTML 작성하기(시맨틱 태그)
고유하고 정확한 페이지 제목 만들기(title 태그)
메타 태그 사용하기(설명에 콘텐츠 관련 정보 포함하기)
anchor 태그를 활용한 적절한 키워드 배치하기
이미지 최적화하기(img 태그를 사용하고 alt 속성 사용하기)
HTTPS 적용하기
9. 리플로우와 리페인트에 대해 설명해주세요.
1. 리플로우 : 요소의 너비, 높이, 위치 등이 변경되어 렌더트리를 재생성하는 작업
DOM 요소의 기하학적 속성이 변경될 때
브라우저의 사이즈가 변할 때
JS에서 DOM 관련 메소드를 실행하거나 DOM 속성에 접근할 때
2. 리페인트 : 변경된 요소를 화면에 그려주는 작업
리플로우가 발생했을 때
요소의 색상, 배경색 등 스타일이 변경되었을 때
visibility: hidden <-> visible 가 변화할 때(리페인트만 발생)
이 요소는 단순히 보이지 않을 뿐 크기나 위치가 변하는 게 아니기 때문에 리페인트만 발생한다.
display: none이 적용된 요소는 영역도 차지하지 않으면서 보이지 않기 때문에 렌더트리에서 제외된다. 때문에 주변요소의 위치, 크기에도 영향을 주므로 리플로우도 함께 발생한다.
Q. 리플로우 최적화?
리플로우는 비용을 발생시키는 절차이므로 가능한 안하는 것이 좋다.
1. 스타일을 변경할 경우 가장 하위 노드의 클래스를 변경한다.
2. 인라인 스타일을 사용하지 않는다.
3. 애니메이션이 있는 노드는 position을 fixed 또는 absolute로 지정한다.
4. table 레이아웃은 피한다.
5. 숨겨진 노드의 스타일을 변경한다.
6. DOM 사용을 최소화한다.
7. 캐시를 활용한다.
10. 어플리케이션의 성능은 어떤 식으로 측정하셨나요?
Lighthouse라는 자동화 도구로 측정합니다.
Lighthouse로 브라우저가 첫번째 DOM의 콘텐츠를 렌더링하는 데 걸리는 시간, 사용자가 제일 먼저 볼 수 있는 영역에 존재하는 콘텐츠를 렌더링 하는 시간 등을 측정할 수 있습니다.
크롬 브라우저 내의 개발자 도구에서 이용할 수 있습니다.
Performance : 화면에 콘텐츠가 얼마나 빨리 표시되고 사용자가 얼마나 빠르게 해당 콘텐츠를 인식하는 지
Accessibility : 웹 어플리케이션의 접근성을 검사(<img> 태그에 alt 속성이 있는지, <html> 태그에 lang 속성이 있는지 등)
Best Practices : 웹 페이지가 웹에 대한 표준 모범 사례를 따르고 있는지 확인(콘솔에 오류 출력되는지, 더는 사용하지 않는 API를 호출하고 있는지, HTTPS를 통해 해당 페이지에 접근할 수 있는지 등)
SEO : 웹 페이지가 검색 엔진에 대해 최적화된 순위 결과를 가지고 있는지 확인(일부 SEO 모범 사례를 확인)
Progressive Web App : Progressive Web App을 정의하는 일련의 기준에 따라 웹 페이지를 확인한다(점수를 부여하는 게 아니라 합격 또는 실패를 부여한다)
HTML + CSS
1. DOCTYPE 이란?
Document Type Declaration 으로, 문서의 유형을 정의하기 위해 사용하는 선언문입니다. HTML5, XHTML, HTML 세가지 유형이 존재하며, 웹 문서의 시작을 알려줍니다. 웹 브라우저 처리할 문서가 어떤 버전이며 해당 방식으로 해석하라는 의미를 갖습니다.
2. 메타 태그란?
페이지에 대한 중요한 정보를 검색 엔진에 재공하는 요소로 검색 엔진에 사용자에게 페이지를 표시하는 방법과 검색 결과에 표시되는 방법을 알려줍니다. 메타 타이틀, 메타 디스크립션, 헤더가 있습니다.
3. 시맨틱 태그란?
의미가 있는 태그로, 태그 이름만 보고 어떤 내용인지 알 수 있는 태그 입니다. header, nav, main, section, footer 등이 있습니다.
Q. 왜 시맨틱 태그를 써야합니까?
컴퓨터에게도, 보는 사람에게도 해석하기 쉬운 코드를 제공하기 위해서 입니다.
검색 엔진(SEO 최적화)
4. css position에 어떤 것들이 있나요?
position은 element를 배치하는 방법을 지정하는 속성 입니다.
static은 기본 값으로, 요소가 흘러가는 위치대로 위치합니다.
relative는 static 위치를 기준으로 top, bottom, left, right 만큼 위치합니다.
absolute는 가장 가까운 위치에 있는 static이 아닌 부모 요소를 기준으로(없으면 body) top, bottom, left, right 만큼 위치합니다.
fixed는 뷰포트를 기준으로 top, bottom, left, right 만큼 위치합니다. 스크롤 되어도 움직이지 않습니다. => 페이지 내 절대적인 위치(요소들이 겹쳐보일 수 있는 상황이 나올 수 있다)
sticky는 처음에는 static 속성처럼 동작하다가 스크롤이 특저 지점에 도달하면 요소를 fixed 속성처럼 동작하게 할 수 있습니다.
5. css display에 어떤 것들이 있나요?
display는 요소를 어떻게 보여줄 지 레이아웃을 결정하는 속성입니다.
none은 렌더링 하지 않도록 설정하는 것으로 영역도 차지하지 않습니다.
inline은 span, a 태그 등과 같이 줄 바꿈이 되지 않고 width, height, 여백을 지정할 수 없습니다.
block은 div, p 태그 등과 같이 가로 영역을 모두 차지하며 줄 바꿈이 됩니다. width와 height 속성을 지정할 수 있습니다.
inline-block은 요소 자체는 inline 처럼 동작하지만 줄바꿈이 되지 않고, 요소 내부에서는 블록 요소처럼 동작합니다. width와 height를 지정할 수 있습니다.
flex는 요소를 가로 방향 또는 세로 방향으로 배치할 수 있는 효율적인 방법입니다.
grid는 2차원으로 요소를 배치하는 방법으로 column과 row의 비율이나 크기를 지정합니다.
6. box model이란?
모든 HTML 요소는 BOX 모양으로 구성되며 이를 박스 모델이라고 부릅니다. margin, border, padding, content로 구성됩니다.
margin은 border 바깥 쪽, padding은 border 안쪽 여백 입니다.
Q. box-sizing 속성?
default 속성은 content-box : width만 200px, padding이랑 border는 따로(width는 순수한 content 크기)
border-box 로 정해주면 width 값이 안쪽 padding과 border값까지 포함한 값
7. 단위 차이점?
px은 고정값으로 다른 단위의 기준이 됩니다.
em은 부모 요소를 기준으로 자식 요소의 크기를 정하는 것을 말합니다.
rem은 최상단 태그 html에 정의된 사이즈를 기준으로 크기를 정하는 것을 말합니다.
vh, vw는 뷰포트를 기준으로 크기를 정하는 것을 말합니다.
8. Sass, Scss, Css in Js 장단점
1. Sass, Scss 차이
- SASS(Syntactically Awesome Style Sheets)
- 더 간결하고 작성하기 편리, 중괄호나 세미콜론 없이 깔끔한 코드
- SCSS(Sassy CSS)
- 한 줄로 인라인 코드 작성, CSS와 유사한 문법(CSS와 거의 같은 문법으로 Sass 기능을 지원한다)
2. css-in-js
- 장점 : 자바스크립트 내부에서 관리하기 때문에 편리하고, 동적으로 변경이 편리하다.
- 단점 : 자바스크립트 번들 파일의 용량이 커져 화면 로딩 시간이 지연된다
9. CSS 우선순위
1. !important (가장 높은 우선순위)
.title-box{color: red !important;}
.title-box{color: green !important;}
.title-box{color: blue;}
// 일반적으로 후정의사항이 우선순위가 높게 측정되지만
// !important 키워드를 썼기 때문에 파란색이 아니라 초록색인 것
2. inline
<h3 id="title" class="title-box" style="color:red;">타이틀</h3>
3. id 선택자
4. class명
5. HTML 태그명
6. DOM 구조에서 상위것 상속
<div id="app" class="sample-box">
<h3 id="title" class="title-box">타이틀</h3>
</div>
.sample-box{color:darkcyan;}
알고리즘 및 자료구조
1. 스택과 큐의 차이점에 대해 설명해주세요.
스택은 후입선출, 큐는 선입선출 입니다.
스택은 top으로 정해진 곳을 통해서만 접근할 수 있으며 가장 마지막에 삽입된 자료가 가장 먼저 삭제되는 구조를 가지고 있습니다. 삽입 연산을 push, 삭제 연산을 pop 이라고 합니다. 후입선출의 특징을 활용해서 역순 문자열 만들기, 실행 취소, 후위 표기법 계산 등에서 쓰입니다.
큐는 front에서 삭제 연산이, rear에서 삽입 연산이 이루어지며 가장 먼저 삽입된 자료가 가장 먼저 삭제되는 구조를 가지고 있습니다. 삽입 연산을 Enqueue, 삭제 연산을 Dequeue라고 부릅니다. 데이터가 입력된 시간 순서대로 처리해야 할 필요가 있는 상황에 이용합니다. BFS(간선을 적게 거치는 순서대로 큐에 숫자가 들어가고, 거리가 짧은 순서대로 큐에서 제거된다)에서 쓰입니다.
2. 알고리즘은 어떻게 공부하셨나요?
프로그래머스 문제를 풀며 공부했습니다. 각 문제를 풀 때 그 문제에 적용된 알고리즘을 학습하는 방식으로 공부했습니다.
프로그래머스 기준으로 140개 정도 풀었습니다.
3. DFS와 BFS에 대해 설명해주세요.
DFS와 BFS는 그래프를 탐색하는 방법으로, DFS는 깊이 우선 탐색이고 BFS는 너비 우선 탐색 입니다.
그래프는 node와 edge로 구성된 자료구조 입니다.
DFS는 그래프의 깊은 부분을 우선적으로 탐색하는 알고리즘으로, 특정한 경로로 쭉 타고 밑바닥까지 내려간 후 막다른 길에 도착하면 다시 돌아와 다른 경로를 탐색합니다. 모든 노드를 방문하고자 하는 경우에 이 방법을 선택한다.
1. 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다.
2. 스택의 최상단 노드에 방문하지 않은 인접 노드가 있다면 그 노드를 스택에 넣고 방문 처리를 한다.
인접 노드가 여러 개 있으면 번호가 낮은 순으로 처리한다.
방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다.
3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
// 주어진 배열의 정수들의 순서를 바꾸지 않고 적절히 더하거나 빼서 타겟 넘버 만들기
function solution(numbers, target) {
var answer = 0;
dfs(0, 0);
function dfs(index, sum) {
if(index === numbers.length) {
// numbers 배열을 다 돌았을 때
if(sum === target) answer++;
// 구하는 타겟 넘버를 구했을 때
return 0;
}
dfs(index + 1, sum + numbers[index]);
// 더하기 연산
dfs(index + 1, sum - numbers[index]);
// 빼기 연산
}
return answer;
}
BFS는 루트 노드에서 시작해서 인접한 노드를 먼저 탐색하는 방법으로, 시작 정점으로부터 가까운 정점들을 먼저 방문한다. 두 노드 사이의 최단 경로를 찾고 싶을 때 이 방법을 선택한다.
1. 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
2. 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
3. 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
// 게임 맵 최단거리 구하기
function solution(maps) {
var answer = 0;
const n = maps.length;
const m = maps[0].length;
const queue = [[0, 0, 1]];
const dx = [0, 0, -1, 1];
const dy = [1, -1, 0, 0];
if(maps[n-1][m-2] === 0 && maps[n-2][m-1] === 0) return -1;
while(queue.length) {
let [x, y, count] = queue.shift();
if(x === n-1 && y === m-1) return count;
for(let i=0; i<4; i++){
const moveX = x + dx[i];
const moveY = y + dy[i];
if(moveX >= 0 && moveX < n && moveY >= 0 && moveY < m) {
if(maps[moveX][moveY] === 1) {
maps[moveX][moveY] = 0;
queue.push([moveX, moveY, count + 1]);
}
}
}
}
return -1;
}
DFS(Depth-First Search) | BFS(Breadth-First Search) | |
동작 원리 | 스택 | 큐 |
구현 방법 | 재귀 | 큐 자료구조 이용 |
장점 | 그래프의 깊이가 깊을수록 빠름 메모리가 적음 |
찾는 노드가 인접할 때 유리 최단 경로임을 보장 |
단점 | 해가 없는 경로의 경우 끝날 때까지 탐색해야함 | 노드가 많을수록 메모리를 많이 소비 |
적용 | 미로 문제, 길 찾기, 경로의 특징을 저장해야하는 경우 | 빠른 경로 찾기, 주변 위치 찾기 |
4. 그래프와 트리의 차이에 대해 설명해주세요.
그래프는 node와 edge로 구성된 자료구조 입니다.
그래프는 순환 혹은 비순환 구조를 이루며 방향 그래프, 무방향 그래프가 있습니다.
부모-자식 관계가 없습니다.
트리는 그래프의 한 종류로, 방향성이 있는 비순환 그래프를 트리라고 합니다.
부모-자식 관계가 있으며 최상위에 루트 노드가 존재합니다.
이진트리(Binary tree)
모든 노드들이 둘 이하의 자식을 가진 트리입니다.
이진 탐색 트리(Binary Search Tree)
왼쪽 자식은 부모보다 작고 오른쪽 자식은 부모보다 큰 이진 트리 입니다.
완전 이진 트리(Complete Binary Tree)
마지막 레벨을 제외하고 모든 레벨이 완전히 채워져 있는 이진 트리
마지막 레벨은 꽉 차 있지 않아도 되지만, 노드가 왼쪽에서 오른쪽으로 채워져야 한다.
5. 정렬 알고리즘에 대해 알고 있는대로 설명해주세요.
1. 선택 정렬
데이터 중 가장 작은 값의 데이터를 선택해서 앞으로 보내는 정렬
O(N^2)
2. 삽입 정렬
데이터를 순서대로 뽑아서 적절한 위치를 찾아 삽입하는 정렬
O(N^2), 이미 정렬되어 있는 경우 O(N)
3. 버블 정렬
옆에 있는 데이터와 비교해서 더 작은 값을 앞으로 보내는 정렬
O(N^2)
4. 합병 정렬
데이터 배열을 2개 이상의 배열로 분할하고, 부분 배열에서 정렬해서 결합한 후 다시 정렬 진행
O(NlogN)
5. 퀵 정렬 : 데이터 중 임의의 기준값(Pivot)을 정해서 두 부분 집합으로 나누고, 왼쪽은 Pivot보다 작은 값, 오른쪽은 큰 값을 배치하고 더 이상 집합을 나눌 수 없을 때까지 재귀적으로 진행
O(NlogN), 이미 정렬되어 있는 최악의 경우 O(N^2)
운영체제
1. 프로세스와 스레드를 비교 설명해주세요.
프로세스 : 실행중인 프로그램, 운영체제로부터 자원을 할당받은 작업의 단위
스레드 : 할당 받은 자원을 이용하는 실행 흐름의 단위이고 프로세스 내에 여러개 생길 수 있다.
프로세스는 다른 프로세스의 변수나 자료에 접근할 수 없지만, 스레드는 스택 영역을 제외한 메모리 영역을 서로 공유한다.
Q. 멀티 태스킹 vs 멀티 스레드
멀티 태스킹 : 하나의 운영체제 안에서 여러개의 프로세스가 실행되는 것
장점
프로세스 하나가 죽어도 다른 프로세스에 영향이 미치지 않아 정상적으로 수행된다.
단점
멀티 스레드보다 많은 메모리 공간과 CPU 시간을 차지한다.
멀티 스레드 : 하나의 프로세스가 여러 작업을 여러 스레드를 사용해 동시에 처리하는 것
장점
Context-Swiching 할 때 공유하고 있는 메모리만큼 메모리 자원을 아낄 수 있다.
스레드는 stack 영역을 제외한 메모리를 공유하기 때문에 통신 부담이 적어서 응답 시간이 빠르다.
단점
스레드 하나가 망가지면 모든 프로세스가 종료될 수 있다.
데드락(교착상태)이 발생할 수 있다.
Q. Context Switch
CPU가 프로세스를 번갈아가면서 처리하는 것 - 프로세스 전환이 일어날 때, 현재 진행 중인 작업의 상태(Context)를 PCB(Process Control Block)에 저장하고 대기하고 있던 다음 순서의 작업 수행을 위해 해당 작업의 이전 상태 값
Q. 스레드에서 독립적인 Stack 메모리 영역이 필요한 이유
스택은 지역변수, 매개변수, 리턴 값 등을 저장하는 메모리 공간이다. 따라서 독립적인 함수 호출을 위해서는 독립적인 스택 메모리 공간이 필요하다. 스레드는 독립적인 실행 흐름이므로 독립된 스택을 할당해야 한다.
네트워크
1. HTTP에 대해 설명해주세요.
HyperText Transfer Protocol, 인터넷에서 데이터를 주고받을 수 있는 프로토콜
클라이언트가 브라우저를 통해서 어떠한 것을 요청(request)하면 서버는 요청에 맞는 결과를 사용자에게 응답(response)하는 형태로 동작한다.
Q. Method 종류와 언제 사용하는지?
GET - 데이터 조회
POST - 데이터 추가, 등록
PUT - 데이터 수정, 해당 데이터가 없으면 생성
DELETE - 데이터 삭제
PATCH - 리소스 부분 수정
Q. GET vs POST
GET은 데이터를 읽거나 검색할 때 사용하는 메소드로 필요한 데이터를 URL 주소 끝에 파라미터(쿼리 스트링)로 포함하여 요청한다.
데이터를 수정하지 않기 때문에 데이터 변형의 위험 없이 사용할 수 있다.
데이터 길이에 대한 제한이 있으며, 성공 시 200 HTTP 응답 코드와 함께 여러 데이터를 반환한다.
idempotent 하다.
POST는 새로운 데이터를 생성 할 때 사용하는 메소드로 서버로 전송할 데이터를 HTTP 메시지의 body에 포함해서 요청한다.
데이터 길이에 대한 제한이 없으며, 성공 시 201 HTTP 응답 코드를 반환한다.
idempotent 하지 않다.
idempotent : 여러 번 적용하더라도 결과가 달라지지 않는 성질
Q. HTTP의 Status Code
클라이언트가 서버에게 요청을 보낼 때 그 요청의 결과가 어떻게 되었는지를 알려주는 것
1XX(조건부 응답) : 서버가 요청을 받았으며 클라이언트는 계속 작업을 하라는 의미
2XX(성공) : 서버와의 요청이 성공했을 시
200(OK) : 요청이 성공적으로 수신되었음
3XX(리다이렉션 완료) : request를 마치기 전에 추가 동작을 해야 할 경우
301(Moved Permanently) : URL이 영구적으로 다른 위치로 이동했음
4XX(요청 오류) : 클라이언트의 request에 에러가 있음을 알려주는 코드
403(Forbidden) : 서버에서 설정해 둔 권한과 맞지 않는 접속 요청이 들어올 경우 접근 거부
404(Not Found) : 손상된 링크(요청된 리소스를 찾을 수 없음)
5XX(서버 오류) : 서버 오류로 인해 request를 수행할 수 없음을 알려주는 코드
503(Service Unavailable) : 서버를 현재 사용할 수 없음.
Q. HTTP vs HTTPS
HTTPS는 SSL(Secure Socket Layer) 인증서를 사용하는 HTTP입니다.
SSL인증서는 일반 HTTP 요청 및 응답을 암호화하기 때문에 HTTPS는 HTTP보다 안전한 보안용 프로토콜 이라고 할 수 있다.
HTTPS의 원리 : 공개키(Public Key Infrastructure) 방식
공개키는 두 개의 키를 갖게 되며 A키로 암호화하면 B키로 복화하가 가능하며, 반대로 B키로 암호화할 경우 A키로 복호화가 가능하다. 두 개의 키 중 하나는 공개키, 하나는 비공개키로 비공개키는 소유자가 가지고 있게 되며 공개키는 소유자와 타인에게 공개된다.
2. 주소창에 주소를 입력했을 때의 흐름을 설명해주세요.
1. 브라우저가 주소창에 주소를 입력한다.
2. 브라우저가 IP주소를 찾기 위해 캐시에서 DNS기록을 확인한다.
DNS(Domain Name System) : 웹 사이트의 IP 주소와 도메인 주소를 연결해주는 시스템
인터넷의 모든 URL에는 고유한 IP 주소가 할당되어 있다.
DNS 기록을 찾기 위해서 브라우저는 네 개의 캐시를 확인한다.
브라우저 캐시 : 브라우저는 내가 이전에 방문한 웹 사이트의 DNS기록을 일정 기간 동안 저장하고 있다.
-> OS캐시 : 브라우저가 내 컴퓨터 OS에 시스템 호출을 통해 DNS기록을 가져온다.
-> 라우터 캐시 : 컴퓨터에도 원하는 DNS 레코드가 없다면, 라우터에서 DNS기록을 저장한 캐시를 확인한다.
-> ISP 캐시 : ISP는 DNS 서버를 가지고 있는데, 해당 서버에서 DNS 기록 캐시를 검색할 수 있다.
ISP(Internet Service Provider) : 유선 또는 무선 연결을 통해 고객에게 인터넷 액세스를 제공하는 회사
3. 만약 요청한 URL이 캐시에 없다면, ISP의 DNS서버가 DNS쿼리로 URL을 호스팅하는 서버의 IP 주소를 찾는다.
DNS서버 : 할당된 도메인 영역에 대한 정보를 가지고 있는 서버로, 도메인을 IP주소로 변환하는 역할
DNS쿼리의 목적은 웹 사이트에 대한 올바른 IP주소를 찾을 때까지 인터넷에서 여러 DNS 서버를 검색하는 것(재귀적 질의)
여기서 ISP의 DNS 서버를 DNS 리커서 라고 부르는데, DNS 리커서는 인터넷의 다른 DNS 서버에 답변을 요청하여 의도된 도메인 이름의 적절한 IP주소를 찾는 일을 담당한다.
4. 브라우저가 해당 서버와 TCP 연결을 시작한다.
브라우저가 올바른 IP 주소를 수신하면 IP 주소와 일치하는 서버와 연결해 정보를 전송한다.
인터넷 프로토콜(IP)을 사용하여 이러한 연결을 구축한다. 일반적으로 HTTP 요청에서는 TCP(Transmission Control Protocol)라는 전송 제어 프로토콜을 사용한다.
IP(Internet Protocol) : 송신 호스트와 수신 호스트가 패킷 교환 네트워크에서 정보를 주고받는 데 사용하는 정보 위주의 규약
TCP 연결 방법 : TCP/IP 3-way handshake
클라이언트와 서버가 SYN(연결 요청) 및 ACK(응답) 메시지를 교환하여 연결을 설정하는 3단계 프로세스
5. 브라우저가 웹서버에 HTTP 요청을 보낸다.
TCP 연결이 설정되면 데이터 전송이 시작되고 브라우저는 URL 페이지를 요청하는 GET 요청을 보낸다.
6. 서버가 요청을 처리하고 응답을 보낸다.
서버에 있는 웹 서버가 브라우저로부터 요청을 수신하고, 해당 내용을 request handler에 전달하여 응답을 읽고 생성하는 역할을 한다. 그런 다음 응답을 특정 포맷(JSON, XML, HTML)으로 작성한다.
Request handler : 요쳥, 요청의 헤더 및 쿠키를 읽고 필요한 경우 서버의 정보를 업데이트하는 프로그램
7. 서버가 HTTP 응답을 보낸다.
서버 응답에는 요청한 웹 페이지와 함께 Status Code, Content-Encoding, Cache-Control, Cookie 등이 포함된다.
8. 브라우저가 HTML 컨텐츠를 보여준다.
브라우저는 응답받은 HTML을 화면에 표시한다.
3. OSI 7계층에 대해 설명해주세요.
OSI 7 계층은 네트워크 통신이 일어나는 과정을 7단계로 나눈 것입니다.
Physical, Data Link, Network, Transport, Session, Presentation, Application
ETC
1. 깃?
깃은 버전 관리 시스템으로 소스 코드 변경에 따른 버전을 효과적으로 관리하게 해줍니다. 깃허브는 깃을 이용한 웹 호스팅 서비스 입니다.
- 레포지토리 : 저장소, 로컬(개인pc), 리모트(원격저장소-깃허브)
- 브랜치 : 어떤 작업을 하기 위한 구분
- clone : 리모트 레포의 내용을 통째로 다운로드
- fork : 다른 사람의 리모트 레포의 내용을 내가 어떤 부분을 추가, 수정하고 싶을 때 해당 레포를 내 리모트 레포에 그대로 복제, 원본(다른 사람의 리모트 레포)와 연결되어 있어서 변화가 생기면 반영할 수 있음
- commit : 변경된 파일, 폴더를 저장(기록), 로컬 저장소에는 반영되었지만 리모트에는 아직 반영 안된 상태
- push : commit 내용을 리모트 저장소에 업로드
- fetch : 리모트 저장소에서 변경된 내용을 로컬에 내려받기, 내려받기만 하기 반영은 안하기 때문에 merge 해야함
- merge : 브랜치의 변경사항을 다른 브랜치에 반영함
- pull : 리모트 저장소의 변경된 내용을 내려받아서 반영함(fetch + merge)
- pull request : 브랜치에서 완료된 작업을 프로젝트를 같이하는 사람끼리 리뷰하고 합치도록 요청
📚 참고: https://velog.io/@arthur/%EC%A7%80%EA%B8%88%EA%B9%8C%EC%A7%80-%EB%B0%9B%EC%95%98%EB%8D%98-%EC%8B%A0%EC%9E%85-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%A9%B4%EC%A0%91-%EC%A7%88%EB%AC%B8%EB%93%A4
https://velog.io/@kim_unknown_/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EB%A9%B4%EC%A0%91-%EC%A7%88%EB%AC%B8-%EB%AA%A8%EC%9D%8C
'Study' 카테고리의 다른 글
[PF] 포트폴리오 완성 (0) | 2023.09.06 |
---|---|
[PF] 포트폴리오 만들기 (0) | 2023.08.29 |