본문 바로가기

Hanghae99

10/9 TIL

3주차 주특기 심화 주차가 마무리되면서 몇 가지 개념에 대해 고민해볼 시간이 주어졌다.

피상적으로만 알고 있던 개념들을 조금 더 깊게 이해할 수 있었고 해당 내용을 기록해두고자 한다.


Q. Cookie를 쓰신 분도 계시고, localStorage를 쓰신 분도 계신 것 같습니다. 각자 왜 cookie 또는 localStorage를 선택하셨나요?

A. 많은 보안 웹사이트들은 로그인을 한 후 Cookies를 사용해 유저의 신원을 확인하여 모든 페이지에서 재인증을 거치지않아도 되게 됩니다. Cookie는 HTTP요청에 자동으로 데이터를 넘겨주고, LocalStorage와 다르게 header를 안 써도 되기 때문에 cookie를 사용했습니다.

LocalStorage는 Cookies와 달리 모든 HTTP 요청에서 데이터를 주고 받을 필요가 없어서 클라이언트와 서버간의 전체 트래픽과 낭비되는 대역폭의 양을 줄일 수 있습니다. 또한, LocalStorage를 사용하면 문자열 뿐만 아니라 javascript의 primitives와 object도 저장할 수 있고, LocalStorage는 최대 5MB의 정보를 저장할 수 있습니다. (cookies는 4KB이다).

 

Q. 웹/앱 어플리케이션을 사용하는 유저들을 보호하기 위한 간단한 정책들은 무엇이 있을까요?

A. 사용자가 유도하지 않은 요청을 실행하게 하는 XSS공격을 막기 위해 데이터를 입력할 때와 출력할 때, 모두 필터링하고, 클라이언트에도 막을 수 있을만한 수단을 구성해놓는 것이 좋습니다. 예를 들자면 간단한 XSS필터를 만들고 모든 파라미터가 해당 필터를 통과하게 하는 방법이 있습니다.

또한 사용자의 비밀번호와 같이 매우 중요한 정보는 반드시 암호화를 통해 원래 암호가 들어나지 않도록 변환해야합니다.

 

Q. HTTP/HTTPS 프로토콜이 아닌 gRPC 프로토콜로 통신하는 서버 프로그램은 API 서버라고 부를 수 있을까요? (배포된 환경, 구현된 기능은 동일)

A. gRPC는 구글에서 만든 RPC 플랫폼이며 protocol buffer와 RPC를 사용합니다.

SSL/TLS를 사용하여 서버를 인증하고 클라이언트와 서버간에 교환되는 모든 데이터를 암호화하기 때문에 요청의 무결성을 보장할수 있고. HTTP 2.0을 사용하여 성능과 확장성이 뛰어난API를 지원합니다.

또한 클라이언트 응용 프로그램을 서버에서 함수를 바로 호출 할 수 있어 분산 MSA(Micro Service Architecture)를 쉽게 구현 할 수 있습니다. 서버 측에서는 서버 인터페이스를 구현하고, 클라이언트 호출을 처리하기 때문에(proto Request, proto Response) API서버라 부를수 있습니다.

 

Q. Sequelize같은 ORM과 MySQL같은 데이터베이스의 차이가 무엇인가요?

- ORM(Object Relational Mapping)은 application과 database 사이를 맵핑 시켜주는 도구입니다.

- nodejs 기준 Sequelize를 가장 많이 사용합니다.

- ORM을 활용해 객체모델을 활용하여 추상화 레벨을 높일 수 있습니다.

- 객체 모델과 관계형 모델간의 불일치가 존재 하는데, SQL를 자동 생성하여 불일치를 해결할 수 있습니다.

- Sequelize는 Promise(비동기작업 제어방식)를 기본으로 동작하고, MySQL, PostgreSQL, MariaDB, SQLite, MSSQL을 지원합니다.

- 즉, ORM은 application과 database 사이를 맵핑해주는 도구로, 실제 데이터 구조가 구현되는 데이터베이스와는 다릅니다.

 

Q. express.js의 라우터는 미들웨어입니다. 어떤 원리로 동작하기 때문에 미들웨어로 라우터를 구현할 수 있나요?

A. 선언한 미들웨어를 호출하면 미들웨어는 순서대로 실행되며 모든 요청에서 실행됩니다. 그러나 첫 번째 인수로 주소를 입력하면 해당 주소에서만 실행되며 메서드를 post, get과 같은 메서드로 대체하여 호출하면 해당 메서드 요청에서만 미들웨어가 실행됩니다. 이 처럼 특정 요청과 주소를 특정하여 실행할 수 있는 미들웨어의 동작원리를 활용해 라우팅을 구현할 수 있습니다.

 

//express 내부 router 없이 미들웨어로 구현한다면 아래와 같다. 미들웨어로 라우터 구현하는 것은 당연하다.
app.use((req, res) => {
	if (req.method !== 'GET' || req.path !== '/users/me') {
		res.status(404).end();
	}

	// logic...
	const result = getUserByToken(token);

	res.send(result).end();
});

//--------
//함수 앞에 첫 번째 인자로 경로를 주거나, get메소드 등으로 변경하여 적용할 수도 있다.
app.get('/',function(req,res,next){

}

 

Q. Node.js에서 리팩토링시 사용하며, npm을 통해 다운로드 했던 모듈을 불러오는 require 함수는 어떻게 동작하나요? IIFE와 연결지어 찾아보고 정리해보세요.

A. IIFE 란 Immediately Invoked Function Expression (즉시 실행되는 함수 표현식) 의 약자로 정의와 동시에 즉시 실행되는 함수를 의미합니다.

IIFE는 가장 바깥에 변수를 선언하더라도 함수로 감싸져 있기 때문에 전역에 변수를 선언하지 않고 캡슐화하는 특성을 가지고 있어 전역 스코프를 오염시키지 않기 위해 사용하는 경우가 많습니다.

전역 변수는 몇가지 문제점을 내재하고 있는데

  1. 내 의도와는 다르게 어디서든지 전역변수를 참조 및 변경이 가능합니다.
  2. 생명주기가 프로그램의 종료시점과 거의 일치하므로, 이는 상태 변경기회를 늘리게 되며 메모리에도 게속 상주하게 되는 것이므로 리소스도 오랜 기간 소비합니다.
  3. 스코프 체인 상에서 종점에 존재하므로 전역변수의 검색 속도가 가장 느립니다.

이러한 이유로 자바스크립트는 모듈화를 하려는 시도를 다양하게 하였고 require를 사용하게 되었습니다.

require의 동작은 먼저 파라미터로 받은 경로값에 위치한 파일을 불러오고, module이라는 예약어가 해당 모듈 파일에 module이라는 빈 객체를 만들게 됩니다. 이 빈 객체에서 js파일을 즉시 실행 함수로 둘러친 뒤, 이를 바로 실행시키고 module.exports를 리턴합니다.

이렇게 IIFE의 캡슐화 원리가 require메서드에서도 그대로 쓰이는데 보호하고자 하는 api들을 즉시실행함수로 둘러싸 외부의 접근을 막고, 접근 가능한 object들을 리턴하여 사용할 수 있게 합니다.

 

Q. 불필요한 테스트코드는 무엇이며, 100개의 테스트 케이스보다 1개의 테스트 케이스가 더 효과적일 수 있는 이유는 무엇인가요?

A. 테스트 케이스는 특정 테스트 목표 / 목표를 검증하기위한 '방법'에 대한 일련의 지침으로, 시스템의 예상 동작이 충족되는지 여부를 알려줍니다.

 

- 대다수의 결함들은 소수의 특정 모듈에 집중되어 발생하는 경향이 존재합니다. 따라서 복합적인 상호작용이 존재하지 않거나 복잡한 구조가 아니거나 크기가 작은 모듈들에 집중적인 테스트코드를 작성하는것은 불필요한 경우가 될 수 있습니다.

- 동일한 테스트 케이스로 동일한 테스트를 사용한다면 나중에는 새로운 결함을 찾아내는데 도움을 줄 수 없습니다. 따라서 정기적으로 리뷰와 개선을 통해 테스트 케이스를 리뷰하고 개선해야합니다.

- 완벽하게 테스트코드 검증이 끝나고 테스트 시에도 아무런 결함이 존재하지 않는다 하여도 요구사항에 부합하지 않으면 품질이 높은 코드라 볼 수 없기 때문에 이점을 유의하고 코드를 작성해야합니다.

- 무엇보다 I/O 가 의도치 않게 달라진 경우 검증할 수 없다면 불필요한 테스트코드라고 볼 수 있습니다.