[code-camp(back-end)] 회고록

진성·2022년 8월 21일
0

코드캠프에서 프론트엔드 커리큘럼을 마치고 2개월동안 잠깐의 휴식을 취했다.
프론트엔드에서 배웠던 수업영상을 다시 보면서 복습을 하고 만들었던 프로젝트를 리팩토링하는 시간을 가지고 나서 다시 백엔드 커리큘럼을 들어가게 되었다.
현재 7주차를 진행중에 있고 지금까지에 간략한 수업내용과 회고를 기록하려고 한다.

1주차

1주차에는 node.js를 이용한 REST-API를 만드는 것을 중점적으로 배웠다.

확실히 완전 노베이스로 배우시는 분들도 계시기에 아주 기본적인 함수의 사용법과 같은 것들도 배웠는데 인자가 무엇인지, 매개변수가 무엇인지, return은 언제 사용하는 것인지, 함수는 어떻게 실행시키는 것인지와 같은 함수의 아주 기본적인 사용방법 들을 배웠다.
이러한 함수의 기본적인 내용들은 프론트엔드에서 모두 배웠던 내용들이여서 복습하는 마음으로 들었고 크게 어려운 부분으 없었다.

node.js는 자바스크립트 실행기이기에 자바스크립트를 사용하는데, 프론트엔드에서 들었던 내용이 있어서 그런지 크게 어려운 부분은 없는줄 알았지만 swagger와 graphql로 REST API를 만드는 부분에서 약간의 어려움이 있었다.
특히 swagger는 들여쓰기, 공백, 오타 하나라도 있으면 작동이 안되었는데 에러메시지도 없고, vscode에서 잡아주는 것도 없었기에 문제를 해결해나가는데 쉽지 않았다.
하지만 확실히 프론트엔드를 수강해서 그런지 Docs를 읽는데 큰 거부감이 없었기에 문제를 해결해 나갈 수 있었다.

REST API를 만드는데 express라는 프레임워크를 사용했다.
express는 node.js를 사용할 때 서버를 만드는 프레임워크인데 프레임워크라고 부르기에는 조금 애매한 프레임워크이다.
express를 이용해서 서버를 띄어서 API를 만드는 것은 크게 어렵지 않았는데, 서버를 통신하기 위한 HTTP 통신에 대한 이론적인 내용이 프론트에서 들었던 내용보다 조금 더 자세하게 설명해주셔서 몰랐던 부분도 알게 되었고, 흥미가 생겨 혼자 조금 더 찾아봤었다.

graphql API를 만드는 부분도 많이 생소해서 조금 해맸다.
배웠던 내용을 기억해보면 resolvers에 내가 만든 API들을 넣어준다.
이때 주의할점이 API를 만들면 그에 맞는 type도 정해주어야 하는데 type은 typeDefs에 넣어준다.
type을 넣어주는 이유는 swagger와 같이 API Docs를 만들기 위한 것이라 생각하면 된다.
설명을 조금 듣다보니 금방 이해가 되고 내용을 깊게 들어가지 않아서 어려운 부분 없이 정리했다.

1주차를 정리해보면 확실히 프론트엔드를 수강하고 와서 그런지 대부분 어렴풋이는 알고 있는 내용이었고, 크게 어렵지 않게 마무리 했었던 것 같다.

2주차

2주차에는 스크래핑과 크롤링, 몽고DB, 몽고DB를 사용하기 위한 도커를 중점적으로 배웠고 Coolsms와 Nodemailer를 이용한 이메일과 SMS 보내기를 배웠다.

2주차에서는 들어는 봤지만 실제로 사용하지 않았던 내용들이 나왔다.
도커를 사용하는 것은 프론트에서 배웠지만 도커를 이용해 데이터베이스를 띄우는 것이나 스크래핑, 크롤링이 어떤것인지는 알았지만 실제로 로직으로 구현하는 것과 같은 것들이 있었다.
Collsms나 Nodemailer는 들어보지도 못했던것들이었기에 되게 재미있게? 했던 것 같다.

Collsms나 Nodemailer는 크게 어려움 없이 했다.
물론 원두 멘토님과 함께했기에 어렵지 않았던 것이지 아마 혼자 했다면 시간이 오래 걸렸을 것 같긴하다.
그럼에도 사이트에 들어가면 설명이 나와 있고, 사전설정만 해놓는다면 사용하는 방법은 간단하다.
이때 하나 배웠던것이 환경변수이다.
환경변수는 말로만 들어봤지 실제로 사용해본적은 없었다.
Collsms나 Nodemailer와 같은 것들은 고유의 키와 시크릿이 존재하는데 이러한 것들을 깃에 올리게 되면 모르는 사람들이 내 키와 시크릿을 악용할 수 있기에 올리지 않는 것이 좋다.
이럴때 사용하는 것이 환경변수인데 환경변수에 내 키와 시크릿을 만들고 그 파일을 .env파일에 따로 관리를 하는 것이다.
그리고 사용할 때는 변수명만 불러와서 사용하고 깃에 올릴때는 .env파일을 올리지 않으면 된다.
Collsms, Nodemailer를 사용해 실제 핸드폰이나 이메일로 문자가 오고 메일로 오니 뭔가 신기하고 재미있었던것 같다.

데이터베이스에는 SQL과 No-SQL이 존재하는데 SQL은 관계형 데이터베이스라고 하고, No-SQL은 비관계형 데이터베이스라고 한다.
몽고DB는 No-SQL 데이터베이스며 No-SQL에 구조는 Document와 Collection이 존재한다.
쉽게 말하면 Document는 문서(A4용지)라고 생각하면 되고 그것을 담고있는 것이 Collection인데 문서들을 담는 서류 봉투라고 생각하면 된다.
데이터베이스를 다루기 위해서는 쿼리문이라는 데이터베이스 명령어를 알고 있어야 데이터 베이스를 다룰 수 있었지만 그것을 편하게 해주는 라이브러리들이 등장했다.
ORM과 ODM이다.
ORM은 Object Relational Mapper의 약자로 관계형 데이터베이스와 매핑을 해주어서 쿼리문을 작성하지 않고 더 간단한 명령어로 알아서 쿼리문을 작성해주는 것이다.
ODM은 Objedct Document Mapper의 약자로 비관계형 데이터베이스를 매핑해주는 것이다.
이러한 데이터베이스에 대한 내용도 프론트에서 간략하게 배웠지만 확실히 백엔드에서 배우니 더 깊게 배우기 때문에 많은 내용을 알았고 간단하게나마 알고 있었기에 금방 이해가 되었다.

프론트에서 도커는 커리큘럼 거의 마지막 주에 배운것 같았는데 백엔드에서는 2주차부터 배우게 되었다.
백엔드에서는 도커가 중요하다고 들었는데 그럼에도 매우 빨리 배운다는 생각이 들었다.
그럼 도커를 왜 사용하는가?
도커는 가상의 컴퓨터를 만드는 것이 가능하다.
근데 거기서 컴퓨터만을 만드는 것이 아닌 개발 환경의 요소들이 설치된 모습을 이미지로 저장을 해서 그 저장한 이미지를 클라우드에 올려 놓는다.
그리고 그 이미지를 다른 컴퓨터에서도 다운받아 설치해서 사용하는 것이 가능하다.
도커를 사용하면 같이 프로젝트를 하는 모두가 같은 환경에서 개발을 진행할 수가 있고 백엔드의 경우에는 데이터베이스나 레디스, 엘라스틱서치와 같은 프로그램들을 하나의 컴퓨터의 띄어서 사용할 수 없기에 가상 컴퓨터인 도커의 다운 받아 사용하는 것이다.
도커를 사용할 때 같이 사용되는 것이 있다.
바로 Docker-compose이다.
Dokcer-comopse는 복수의 컨테이너를 실행시키는 도커 애플리케이션이 정의를 하기 위한 툴이다.
즉, 여러개의 컴퓨터를 한번에 관리를 할 수 있게 해주는 것이라고 생각하면 된다.
위와 같은 이유로 도커를 사용하고 컴포즈를 사용한다.

몽고DB를 배우면서 들어만 봤던 데이터베이스를 직접 사용할 수 있게 되었다.
몽고DB는 No-SQL 데이터베이스 중 하나로 문서지향 저장소이다.
몽고DB는 스키마 제약이 없어 자유롭고 객체형태로 각 문서가 저장되고 관계를 연결하는 JOIN이 필요 없이 한 문서에 좀 더 이해하기 쉬운 형태 그래도 정보를 저장할 수 있다.
개체지향 프로그래밍과 잘 맞고 JOSN을 사용할 때 아주 유용하다.
그래서 자바스크립트를 기반으로 하는 node.js와 호환이 좋기 때문에, node.js에서 가장 많이 사용되는 데이터베이스이다.
데이터베이스를 확인하기 위해서는 쿼리문을 이용하여 터미널에 확인을 하는데 이것을 보기 좋게 해주는 GUI가 존재한다.
몽고DB Compass라는 GUI가 존재하는데 컴패스를 사용하면 데이터베이스를 보기 좋게 확인할 수 있다.

스크래핑과 크롤링 또한 물론 프론트에서 배웠던 내용 중 하나이다.
프론트에서는 메타 태그에 프로퍼티로 og:뒤에 이름을 붙여 서버사이드 렌더링을 돌려줬던 기억이 난다.
하지만 이는 내 사이트를 스크래핑할 수 있게 만든것에 불과했고 스크래핑을 했던 적은 없다.
스크래핑을 하기 위해서는 axios를 이용하여 자기가 원하는 웹사이트에 주소를 넣게 되면 웹사이트에 html코드를 가지고 올 수 있다.
그 html코드에서 내가 원하는 것들만 가져오기 위해서는 cheerio라는 라이브러리를 사용한다.
cheerio를 사용하면 원하는 태그에 원하는 값을 가지고 있는 것들을 뽑아서 가지고 올 수 있다.
위와 같이 한번만 데이터를 가져오는 것을 스크래핑이라고 한다.
크롤링은 스크래핑을 정해진 시간마다 매번 반복하는 것을 의미한다.
크롤링 또한 Puppeteer라는 라이브러리를 사용한다.
퍼페티어를 사용하면 내가 원하는 사이트에서 원하는 요소들만 가지고 올 수 있다.
예를들면 스타벅스에 커피 목록들만 가지고 올 수 있는것이다.
그리고 크롤링을 해온 데이터를 데이터베이스에 저장을 하고 저장한 데이터를 사용할 수 있게 된다.
하지만 무분별한 크롤링은 좋지 않다. 아래 링크를 참조하자.
👉여기어때 크롤링 위법 사례👈

2주차를 정리해보면 전체적인 데이터의 흐름이나 데이터베이스의 종류와 같은 내용도 배우고 보고 듣기만 했던 데이터베이스를 직접 관리하거나 스크래핑, 크롤링 API를 만들고, 도커를 제대로 까지는 아니더라도 조금은 다룰수 있게 된 것같다.

3주차

3주차에서는 NestJS와 관계형 데이터베이스를 중점적으로 배웠고, NestJS를 위한 클래스형 컴포넌트에 대한 이해와 의존석 주입에 대한 이해를 위해 mvc패턴과 같은 것들을 배웠다.

NestJS는 타입스크립트를 지원하는 효율적이고 확장 가능한 Node.js의 서버 애플리케이션 프레임워크이다.

타입스크립트란 자바스크립트에 타입을 부여한 언어이다.
자바스크립트의 확장된 언어라고 볼 수 있는데 타입스크립트는 자바스크립트와 달리 브라우저에서 실행하려면 파일을 한번 변환해주어야 한다.
이 변환 과정을 컴파일이라고 부른다.
타입스크립트를 사용하는 이유는 에러를 사전의 방지할 수 있고 코드 가이드와 자동 완성을 할 수 있어 개발할 때 매우 편리해진다.
에러를 방지할 수 있는 이유는 타입을 정해놓으면 다시 선언해서 사용할때 그에 맞는 타입이 아니면 에러가 나오기 때문에 사전에 에러를 방지 할 수 있는 것이다.
코드 가이드와 자동 완성은 타입스크립트에서 타입을 지정해주면 나중에 다시 사용할때 어떠한 타입이 지정되어 있는지, 어떠한 것을 리턴하거나 객체이면 어떠한 것을 가지고 있는지 알 수 있게되어 개발할 때 매우 편리해진다.
위와 같은 이유로 타입스크립트를 사용한다.
프론트에서도 타입스크립트를 사용하였지만 프론트에서는 타입을 지정하지 않아도
개발할 때 문제가 없었지만 백엔드에서 타입을 지정해주지 않거나 타입이 다르면 아예 실행자체가 되지 않았다.
또한 타입이 너무 달랐기에 처음에는 매우 혼란스러웠고 어려움이 있었다.

NestJS를 알기전에 Class에 대한 이해와 객체 지향 프로그래밍이 무엇인지 알아야 한다.
Class는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로 객체를 정의하기 위한 상태와 메서드로 구성된다.
즉 쉽게 말하면 클래스란 물건을 만드는 설명서 정도라고 생각하면 된다.
클래스 객체안에 기능을 넣어두고 새로운 클래스 객체를 선언해서 필요한 곳에서 꺼내서 사용한다.
그리고 이러한 기능들을 메서드라고 부르는것이다.
대표적인 예로 자바스크립트 내장객체인 Date객체가 존재하고 이 객체안에서 여러가지 시간에 관련된 메서드들을 뽑아서 사용하는 것이다.
이러한 클래스 객체를 가지고 프로그래밍을 하는것을 객체 지향 프로그래밍이라고 한다.

또 NestJS를 알기전에 MVC패턴이라는 것을 먼저 알아보아야 다른 구조를 이해하기 쉽다.
MVC패턴이란 일종에 프로그래밍 디자인 패턴중 하나인데, 폴더구조를 의미한다.
MVC는 Model, Veiw, Controller 이 세가지로 나누어진다.
Model은 데이터베이스와 연동하여 내부 로직을 처리하기 위한 역할을 하는 파일들을 모아놓는다.
쉽게 예를 들면 데이터베이스 스키마와 같은 파일들을 모아놓는다.
View는 프론트엔드에 해당하는 부분이다.
최근 개발 트렌드는 프론트와 백엔드로 나뉘어 개발을 진행을 하지만, 이전에는 프론트와 백에 대한 개념이 없고 한 개발자가 모두 개발을 진행하였기에 이러한 패턴이 나왔다.
Controller는 Model과 View를 이어주는 로직이고 백엔드 기능을 담당하고 있어 서비스 로직들을 모두 모아놓는 곳이다.
그리고 MVC 패턴을 사용하게 되면 의존성 주입이라는 것이 필요하다.

의존성 주입이란 클래스안에 다른 클래스를 불러와 사용할 때 필요한 것을로 의존하고 있는 클래스를 바깥에서 주입을 해주는 것이다.
되게 복잡해 보이지만, 사실 그렇게 어렵지 않다.
예를들면 서비스 클래스 컴포넌트가있고 컨트롤러에서 서비스 클래스를 불러와 사용하기 위해서는 바깥에서 컨틀로러 클래스를 생성할 때 서비스 클래스를 주입을 해주어야 사용이 가능해진다.

NestJS는 이러한 의존성 주입을 대신 해주는데, 이것을 제어의 역전이라고 한다.
제어의 역전은 일반적이 디자인 패턴 중 하나인데, 제어권이 개발자에서 프레임워크로 넘어가게 되었으며 이를 제어권의 흐름이 변경되었다고 하여 제어의 역전이라고 하게 되었다.
그래서 NestJS에서는 app파일에 모듈이라는 것이 존재하는데 그 곳에 프로파이더로 클래스 컴포넌트를 넣어주게 되면 어디서든 불러와서 사용할 수 있게 되는 것이다.

백엔드 개발자는 데이터를 다루는 일이 매우 중요하다.
프로젝트를 하나 만드는데 들어가는 데이터 양도 많고, 종류도 매우 많다.
그렇기에 처음부터 설계를 잘해서 데이터를 정리해야 하는데 이를 데이터 정규화라고 중보 데이터를 분리하는 것을 의미한다.
데이터 정규화에는 여러가지 정규형이 존재하는데, 백엔드 개발자가 실제 실무에서 사용하는 부분은 세가지 정도가 존재하고 그 외에는 데이터베이스를 전문적으로 다루는 개발자가 아닌 이상 깊게 파지는 않아도 된다.
가장 먼저 비정규화는 모든 데이터가 하나의 테이블 다 담겨있는 것을 의미하고 정규화가 되지 않은 상태를 의미한다.
제1정규화는 한 줄에 여러 데이터가 존재할 때 이러한 것을 다가 속성이라고 하는데 이러한 다가 속성을 가진 데이터가 없게 하나의 컬럼의 하나의 값만 들어가도록 만드는 것을 의미한다.
제2정규화는 복합키로 구성되어 있을 때 나머지 컬럼은 두가지 모두에 종속되어야 한다.
이러한 복합키로 두가지 모두에 종속되어 있는 것을 일부에만 종속적이게 하는 것을 의미한다.
제3정규화는 A -> B -> C 의 관계를 가지고 있을때, A와 B,B와 C를 묶어 다른 테이블로 분리하는 것을 의미한다.

위와 같이 데이터베이스에 테이블간의 관계를 가지고 있는 것을 관계형 데이터베이스라고 하며 대표적으로 MySQL이 존재한다.
그리고 관계형 데이터베이스는 처음에 설계를 해야하는데 이를 그림으로 나타낸것이 ERD라고 한다.

관계형 데이터베이스에 관계는 1대1, 1대다, 다대다가 존재한다.
1대1은 하나의 상품이 하나의 거래위치를 가지고 있고 하나의 거래위치가 하나의 상품을 가지고 있기에 1대1이다.
1대다는 유저 한명은 여러개의 상품을 올리수 있고, 하나의 상품는 하나의 유저만 가질 수 밖에 없기에 1대다이다.
다대다는 하나의 상품은 여러개의 카테고리를 가질 수 있고 또 하나의 카테고리는 여러개의 상품을 가질 수 있다.
데이터베이스에는 PK와 FK가 존재한다.
PK는 기본키로 그 로우의 유니크한 키값이다.
FK는 외래키로 다른 테이블에서 값을 참조할 때 참조해오는 테이블의 PK를 말한다.

3주차를 정리해보면 NestJS에 전체적인 구조와 그에 필요한 개념을 배웠고, 관계형 데이터베이스에 대한 내용을 배웠다.
이때는 확실히 어려운것이 많이 있었다.
처음보고 듣는 내용들이 너무 많았기에 1,2주차에 비해 한번에 이해하기는 어려웠었던 것 같다.
특히 ERD를 설계할 때 테이블간의 관계를 매치하는 것이 어려웠는데 그때는 PF랑 주말까지 얘기하면서 어떻게든 해결해 나갔던 기억이 있다.

4주차

4주차에서는 TypeORM과 GraphQl을 이용한 데이터베이스와 API를 만드는 것과, 인증과 인가를 위한 로그인을 중점적으로 배웠다.

이전에는 데이터베이스를 조작하기 위해서는 데이터베이스 명령어인 쿼리문을 작성할 줄 알야했다.
하지만 최근에는 ORM과 ODM이라는 라이브러리들이 나오면서 쿼리문을 직접 장석하지 않더라고 간단한 명령어만 적어도 쿼리문으로 자동으로 변환해서 데이터베이스를 조작할 수 있게 되었다.
ORM과 ODM은 2주차에서도 배웠지만 간단히 다시 복습해보자면 ORM은 관계혀 데이터베이스를 매핑해주는 것이고, ODM은 비관계형 데이터베이스를 매핑해주는 라이브러리들이다.
이러하게 매핑해주는 라이브러리들 중에도 대표적인게 몇개인가 하지만 내가 수업에서 배운것은 타입스크립트에서 사용하는 TypeORM이다.
TypeORM을 사용하면 데이터베이스에 데이터를 조회, 저장, 삭제, 수정 뿐만 아니라 테이블을 생성하는 것도 편하게 가능하다.
데이터베이스에서 데이터를 삭제할 때 데이터를 완전히 삭제하면 안된다.
그 이유는 나중에 유저가 그 데이터를 원할수도 있기 때문에 완전히 지우지 않고, 삭제시간 컬럼을 만들어서 실제 데이터는 남겨두고 삭제시간 컬럼만 업데이트를 해주는 것이다.
이러한 것을 Sofr-Delete라고 한다.

GraphQL은 페이스북에서 만든 쿼리언어이다.
GraphQL은 REST-API와 다르게 사용하지만 사실은 REST-API이다.
POST메서드를 사용해 graphql엔드포인트로 요청을 하는 것이다.
요청을 할때는 body에 graphql쿼리 요청을 하면 되는것이다.
GraphQL의 장점을 원하는 데이터만 골라서 받을 수 있고, 요청을 할 때 한번에 여러개의 API 요청을 할 수 있기 때문에 REST-API에 오버패칭 문제와 언더패칭문제를 한번에 해결하는 장점이 있다.
NestJS에서 GraphQL을 사용하는데, 이때 스키마를 자동으로 생성해주는 코드우선 개념이 있다.
GraphQL은 REST-API와 다르게 따로 스웨거를 작성할 필요없이 자동으로 스키마가 만들어지며 사이트가 나오기 때문에 이러한 장점 때문에 최근에 많이 사용되거나 바뀌어가는 추게가 되어가고 있다.
아직 국내에서는 REST-API를 많이 사용하지만 외국에 큰 기업이나, 국내에 스타트업은 많이 사용하는 추세이다.

웹사이트에서 가장 중요한 부분 중 하나가 로그인이다.
로그인 프로세스 완벽히 이해하기 위해 암호화와 인증, 인가를 정확히 알아야 한다.

데이터베이스에 비밀번호를 그대로 저장하게 되면 해커한테 데이터베이스가 해킹당한다면 그대로 노출되는 위험이 있고, 또한 개발자들 모두 그 비밀번호를 알 수 있기에 이는 너무 위험하다.
그래서 비밀번호 같은 중요한 데이터는 암호화를 진행하고 데이터베이스에 저장을 하게 된다.
이렇게 되면 사용자 말고는 그 비밀번호를 모르게 된다.
암호화에는 양방향 암호화와 단방향 암호화가 존재한다.
양방향은 말 그대로 암호화하고 복호화 할 수 있다는 의미이다.
양방향 암호화 같은 경우는 JWT 토큰과 같은 인증토큰을 만드는데 사용한다.
JWT 토큰은 인증과 인가를 할 때 필요한데 이 토큰은 복호화 할 수 있기에 여에는 중요한 데이터를 담지 않고 간략한 토큰 만료시간과, 간단한 유저정보만 담아둔다.
비밀번호를 양방향으로 만드는 경우는 너무 위험하기에 비밀번호는 단방향으로 만든다.
단방향도 말 그대로 한 쪽 방향 즉, 암호화를 하면 다시 복호화 할 수 없는 것이다.
이를 해싱이라고 하고, 아무리 해싱을 했다고 해도 해커가 작정하고 무한 반복문을 돌리면 뚫릴 수 있는 가능성이 있다.
거기서 나오는 것이 솔트이다.
솔트는 해싱을 할때 임의의 문자를 넣어주기에 해커가 해킹하기에는 조금 무리가 있다.

JWT란 JSON Web Token의 약자로 JSON 형태의 토큰이라고 보면 된다.
JWT는 header, payload, signature의 세개를 .로 구분하여 만들어져 있다.
hearder는 토큰의 타입과 해싱 알고리즘 두가지 정보를 담고있다.
payload는 토큰에 담을 정보가 들어간다. 대표적으로 토큰 발급자, 토큰 제목, 토큰 만료시간, 토큰 발급시간 등이 들어가는데, 여기에는 중요한 정보를 담으면 안된다.
signature는 서명이라는 의미이며 JWT에 비밀키이다.
이 서명은 JWT가 조작이 되었느지 판별하는 부분이기에 해커가 토큰을 탈취하더라도 조작을 하여 악용하는 것을 불가하기에 토큰을 사용할 때 안전하게 사용할 수 있다.

그래서 위와 같은 토큰이 나온 이유는 이전에 로그인 할때는 모든 유저의 정보를 데이터베이스 담아서 사용을 하거나 또는 백엔드의 어느 공간에 저장을 해놓고 사용하여야 했다.
하지만 이렇게 데이터를 저장해 놓으면 스케일 아웃을 하였을때 즉 백엔드 또는 데이터베이스를 물리적인 확장을 하였을때 모든 컴퓨터들이 유저정보를 가지고 있어야 했다.
이러한 것을 상태가 있다고 하고, state 하다고 한다.
그래서 유저정보를 저장하지 않고, 간단한 유저정보만 토큰화 한 후에 그 토큰을 이용하여 인증을 하고 인가를 하게 된 것이다.
이러한 토큰은 헤더를 통해 주고 받는다.

인가란 토큰이 유효한지 확인하는 절차이다.
예를 들어 로그인 한 유저만 물건을 등록할 수 있다면, 이것을 확인하는 것이 인가이다.
인가를 하기 위해서는 내 API 가드를 붙여 먼저 토큰을 확인 한후에 유효한 토큰이면 API를 요청하고, 유효하지 않다면 에러를 반환해 API를 사용하지 못하게 한다.
이러한 것을 도와주는 라이브러리가 존재하고, Passport라는 자격증명 라이브러리르 사용하면 인증상태를 관리하고 사용자에 대한 정보를 첨부해서 사용할 수 있다.

3주차를 정리해보면 실제로 데이터베이스와 연동되는 API를 만들었고, 이 때 TypeORM과 GraphQL을 사용했다.
프론트에서 GrapsQL을 많이 사용하였지만, 실제로 만들어보니 아 이렇게 만들어졌던거였구나 하면 먼가 깨달음?이 쪼금 있었고, 데이터베이스를 직접관리하며 관계에 대한 테이블을 정리하다보니 뇌의 과부하가 조금씩 왔었다.
인증과 인가부분은 정말 어려웠다.
스트레티지를 만드는것도 첨에 너무 이해가 안됬다.
또한 인가 절차가 생각보다 많이 간단해서 의의였다.
프론트에서는 그냥 토큰만 제대로 보내주면 알아서 통과가 되었기에 어떻게 동작하는지 전혀 몰랐지만 직접 만들어보니 새로웠고 구조를 파악하는데 시간이 오래걸리는 않았다.

5주차

5주차에는 로그인 프로세스에 대한 이해와 결제 API를 만드는 부분을 중점적으로 배웠다.

로그인 프로세스 같은 경우는 거의 프론트와 해주었던 설명과 똑같았다.
지금까지에 로그인 프로세스와 지금의 프로세스를 하나씩 알려주면 설명해주셨고, 그 이유까지 거의 비슷했던 것 같다.

먼저 로그인 프로세스에 들어가기 전에 알아야 하는 것이 브라우저 저장소이다.
브라우저에도 데이터를 저장할 수 있는 저장소가 세가지가 존재하고, LocalStorage, SessionStorage, Cookie 이렇게 세가지 있다.
개발자도구에 들어가 애플리케이션을 누르면 이 세가지가 모두 보인다.
Local의 데이터를 저장하면 지우지 않는 이상 지속적으로 남아있다.
Session은 저장을 하고 나갔다가 오면 사라진다.
여기서 중요한 것은 쿠키이다.
쿠키에 있는 데이터는 백엔드에 같이 딸려가고 쿠키에 있는 데이터는 옵션을 주면 HTTPS 통신만 가능하게 하거나 클라이언트에서 조작하지 못하게 할 수 있다.
이러한 특성때문에 쿠키는 보안이 좋기 때문에 여기에 리프레쉬 토큰을 담아 사용을 한다.

리프레쉬 토큰이란 토큰의 유효기간 지나게 되면 이 리프레쉬 토큰을 이용하여 토큰을 재발급을 받을 수 있다.
이러한 이유는 토큰은 탈취당하고 싶고 탈취를 당하게 되면 토큰의 유효시간 까지 탈취한 해커가 마음대로 사용할 수 있기에 이러한 문제점을 해결하기 위해 실제 토큰은 유효시간을 짧게하고 쿠키에 있는 리프레쉬 토큰을 길게 함으로써 보안을 조금 더 안전하게 만드는 것이다.

간략하게 로그인 프로세스에 대해 설명하자면, 먼저 회원가입을 해서 유저정보를 저장한다.
로그인을 하면 이메일과 비밀번호를 확인하고 인증이 되면 액세스 토큰과 리프레쉬 토큰을 같이 준다.
프론트에서는 받은 토큰을 변수에 저장을 하여 사용을 하고, 그 토큰을 이용하여 상품등록과 같은 인가가 필요한 API를 요청하면 토큰을 검증하고 나서 API를 응답해준다.
만약 액세스 토큰이 만료가 되어 다시 인가가 필요한 API를 요청하면 백엔드에서는 토큰 만료 에러를 보내주고 프론트에서는 토큰 만료 에러를 응답 받으면 바로 그 에러를 캐치해 토큰을 재발급 받는 API를 요청한다.
그러면 다시 백엔드에서 리프레쉬 토큰을 검증을 하고 리프레쉬 토큰이 유효하다면 액세스 토큰을 재발급 해주고, 프론트에서는 받은 액세스 토큰을 이용해 방금 토큰 만료로 인해 요청하지 못한 API를 다시 요청하게 되는 것이다.
이 과정이 굉장히 복잡해보이고 할 것이 많아 보이지만, 사용자 입장에서는 정말 한순간이여서 토큰 만료가 되었는지 모르고, 서비스를 이용할 수 있다.

결제 또한 웹사이트에서 가장 중요한 부분 중 하나이다.
결제가 안된다면 수익을 낼 수 없기에 중요한 부분 중 하나라고 볼 수 있다.
이전에 결제는 매우 복잡하였다.
구매자가 결제요청을 하게 되면 판매자는 PG사와 연동을 하고, PG사는 다시 카드사에 요청을 한다.
이때 연동과정에서 매우 복잡한 절차와 로직이 필요하기에 개발자가 결제를 완벽하게 구현하는 것이 결코 쉽지 않았다.
하지만 이러한 결제 연동을 아주 쉽게 해주는 대행사가 나왔다.
대표적으로 아임포트라는 결제 API이다.
아임포트에서 API를 제공해주고 우리는 그 API를 사용하긴만 하면 PG사와 거의 자동으로 결제가 연동이 된다.
복잡한 결제환경을 직접적으로 구현할 필요가 없어진 것이다.
그럼에도 결제는 복잡한것은 맞지만, 이전보다는 훨씬 수월해진 것이다.

결제를 할때는 경우의 수가 매우 많다.
카드 결제인지, 계좌 이체인지, 무통장 입급인지, 정기 결제 등등 결제 종류 매우 많기에, 각각의 상황마다 분기를 나누어 그에 맞는 기능을 따로따로 구현해 줘야한다.
API를 만들어 연결하는데 많은 시간이 소요되며 기능 개발이 완료되면 실제 정산을 받기 위해서 PG사와 카드사와의 검수 과정 또한 필요하다.
그래서 이 모든 과정을 처리하는데 적어도 2~3달 정도의 시간이 필요하기에 계획결제 솔루션, 대행사를 사용한다고 해도 쉬운일이 아니다.
이를 고려해 계획을 세워 프로젝트를 진행해야 한다.

5주차를 정리해보면 실제 배운 내용이 많지 않은것 같지만, 웹사이트에서 가장 굵직한 로직들 중 하나이기에 조금 더 깊게 알아햐 하는 부분이 많았다.
로그인과 결제는 프론트에서도 해보았지만, 실제 백엔드에서 API를 구현하고, 내가 만든 로직을 사용하는 것이 아닌 외부에서 빌려서 사용하는 것들이 있었기에 바로바로 내꺼처럼 만들어서 사용하기 쉽지 않았다.
결제와 같은 것은 나중에 조금 더 혼자서 공부를 해야 될 것 같은 부분이 있다.
특히 결제 또는 소셜로그인을 진행할 때 외부 API를 사용하는 것이기 때문에 에러가 무슨 에러인지 확인 하는 것이 가장 어려웠고 결제를 할 때 검증 과정이 자세하면 자세할수록 좋기에 이를 생각하는 것이 어려웠다.

6주차

6주차에는 Transaction과 이미지 업로드에 대해 중점적으로 배웠고 레디스라는 메모리디스크 기반 데이터베이스에 대해 배웠다.

슬슬 캠프생활에 막바지가 오니 슬슬 내용이 더 어려워졌고, 진짜 처음보는 개념들이 많이 나오기 시작했다.

트랜젝션(Transaction)이란 처리되는 작업의 단위로, 데이터베이스에서 이 트랜젝션 처리는 비즈니스 로직 상 굉장히 중요한 기능이다.
서로 다른 트랜잭션을 처리하는 도중에 하나의 단위 트랜잭션이 에러가 발생한다면 이전에 성공했던 트랜잭션들을 다시 롤백 시켜 데이터의 일관성이 깨지지 않도록 해주는 것이다.
모두 성공했을때는 커밋을 통해 확정시켜 데이터베이스 적용을 한다.
만약 트랜잭션 처리를 하지 않으면 결제를 한다고 가정했을때 유저의 포인트가 먼저 차감이 되고 그 후에 구매가 되는데, 유저의 포인트가 차감이 되고 구매를 하는 중에 에러가 발생해 결제가 제대로 진행이 되지 않는다면 유저의 포인트만 사라지게 되고 구매는 되지 않는 상황이 발생할 수도 있다.
그렇기에 트랜잭션 처리는 매우 중요하다.
트랜잭션의 특징으로는 ACID라는 속성이 존재한다.
Atomicty는 원자성이라는 뜻을로 안정성 보장을 위해 가져야 할 성질 중의 하나로 트랜잭션과 관련된 작업들이 부분적으로 실해되다가 중단되지 않는 것을 보장하는 속성이다.
Consistency는 일관성이라는 뜻으로 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성이 있는 데이터베이스 상태로 유지하는 것을 의미한다.
Isolation은 격리성이라는 뜻으로 트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 속성이다.
Durability는 지속성이라는 뜻으로 성공적으로 수행된 트랜잭션에 대한 로그가 남아야하는 성질로 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 한다는 의미다.

이미지 업로드에 대한 개념적인 프로세스에 대한 설명은 프론트와 다를게 거의 없었다.
그런데 막상 로직을 짜는데 직접 구글 스토리지를 조작해야 했기에 이 부분이 많이 어려웠다.
스토리지를 클라이언트에서 로직으로 짜는것이 매우 어려웠기 때문이다.

일단 전체적인 이미지 업로드 과정은 먼저 프론트에서 업로드 파일이라는 API가 있다면 요청을 한다.
백엔드에서는 이 받은 파일을 구글 스토리지에 직접 올리고 스토리지에 올라간 이미지 주소를 받아 데이터베에스 이미지 주소를 저장하고, 다시 프론트로 보내주는 것이다.
데이터베에스에 이미지 파일을 직접 저장하지 않는 이유는 데이터베이스에 파일 객체를 저장을 하게 되면 너무 큰 용량을 차지하기 때문에 파일을 데이터베이스에 저장하는 것을 비효율적이다.
그래서 스토리지 서비스를 이용하여 스토리지에 저장을 하는 것이다.
이러한 스토리지 서비스를 제공하는 대표적인 업체로는 AWS, GCP, Azure가 존재하고 이러한 곳들을 Cloud Provider라고 한다.
비용만 지불한다면 용량이 큰 파일들을 무제한으로 저장할 수 있는 클라우드 스토리지 서비스를 이용할 수 있다.

이 이미지를 업로드 하는데 있어 실제 스토리지에 저장하기 까지 약간의 시간이 걸린다.
그래서 제대로 저장을 하기 위해서는 async/await와 같은 기다려주는 로직을 짜야 하는데, 만약 이미지 파일이 여러개 온다면 이 때 반복문을 사용하는 것은 매우 비효율적이다.
이때 사용하는 것이 Promis.all이다.
프로미스 올은 여러개의 비동기 처리를 병렬로 처리해주는데, 만약 시간이 3초, 5초, 2초 정도 걸리는 각각의 비동기 로직이 있다면 프로미스 올을 사용하게 되면 가장 긴 시간이 5초만 기다리고도 모든 비동기처리가 완벽하게 요청이 되고 결과를 받아 올 수 있다.

구글 클라우드 플랫폼에는 트리거라는 것이 존재한다.
트리거는 어떠한 이벤트가 있었을때 자동으로 동작하는 것을 의미한다.
트리거는 데이터베이스에서도 사용할 수 있고, 구글 클라우드 플랫폼에서 지원한다.
이미지 썸네일 트리거를 구현하는데 정말 힘들었다.
혼자 어떻게든 로직을 짜보려고 이 방법, 저 방법 다 쓰면서 어떻게든 해결을 했었는데, 독스를 정말 제대로 읽었던 적을 이때 말고 없었던 것 같다.
또 프로시저라는 것이 존재하는데 프로시저는 데이터베이스에서 사용하는 함수이다.
데이터베이스를 전문적으로 사용하는 개발자가 아니면 잘 사용하지 않지만 지금도 간간히 사용되고 있다고 한다.

레디스는 메모리기반 데이터베이스이다.
레디스에 속도는 디스크기반에 비해 매우 빠르다.
이것을 알기전에 인덱스라는 개념을 알아야 한다.
인덱스는 책갈피라는 의미이며 테이블을 빨리 조회하기 위해 테이블 데이터에 포인터, PK와 같은 유니크키를 주어 검색하는 방법이다.
이는 책의 목차와도 같아서 특정 컬럼에 인덱스를 지정해주면 테이블 조회 시 인덱스를 이용해 빠르게 조회할 수 있다.

레디스는 Memcached와 비슷한 캐시 시스템으로 동일한 기능을 제공하면서도, 영속성, 다양한 데이터 구조와 같은 부가적인 기능을 지원하고 있다.
레디스는 모든 데이터를 메모리에 저장하고 조회한다.
이것이 의미하는 것은 레디스는 인메모리 데이터베이스이다.
그래서 검색을 구현할때 Cache-Aside패턴을 이용하여 레디스에 데이터를 먼저 조회해보고 있으면 바로 보내주고 없으면 원조 데이터베이스에서 가져오는 것이다.
레디스에 데이커가 있다는 것을 Cache-Hit라고 하고, 없으면 Cache-miss라고 한다.
레디스는 단순히 빠르기만 해서 좋은것이 아닌, 다양한 자료구조를 가지고 있어 더욱 좋은것으로 평가 받는다.

6주차를 정리해보면 확실히 점점 갈수록 내용이 어려워지고 깊어지기 시작했다.
알아야하는 내용이 너무 많아지고 수업시간에 바로 이해되는 내용은 거의 없는 수준이였다.
특히 6주차에는 트랜잭션 부분이 매우 어려웠고, 나만의 썸네일 트리거를 만드는 부분에서는 거의 벽까지 느껴졌다.
썸네일 트리거를 만들때 처음에 만들때는 정말 벽이 느껴지고 힘들었지만 막상 만들고 보니 너무 간단하게 만들었던 기억이 있어 좋은 감정보다 안 좋은 감정이 더 많았던 기억이 있다.

7주차

7주차에는 엘라스틱서치와 마이크로 서비스, TDD, GCP 배포를 하는 것을 배웠다,

아직 레디스도 잘 못 다루고 있는데 엘라스틱서치가 나와서 당황스러웠다.
확실히 후반부로 오니 점점 어려워지고 있는 것 같다.
세팅해야하는 부분도 더 생기고, 사용하는 라이브러리도 더 늘어나니 점점 머릿속이 뒤죽박죽이 되는 것 같다.

엘라스틱서치를 알아보기 전에 역인덱스를 알아야 한다.
보통 관계형 데이터베이스에서는 테이블을 작성할때 데이터를 저장을 한다.
하지만 이렇게 하면 생기는 문제점이 어떠한 키워드를 찾아 그 특정 키워드를 가지고 있는 데이터를 찾고 싶을때 테이블의 모든 로우를 다 찾아서 데이터를 가지고 와야한다.
이러한 것을 테이블 풀스캔이라고 한다.
이러한 문제를 해결하기 위한 방법으로 나온것이 역색인(역인데슥)이 있다.
역색인은 특정 키워드를 키값으로 가지고 그 특정 키워드가 있는 데이터들을 번호로 바꾸어 저장을 해놓는 것이다.
이렇게 하면 특정 키워드만 찾는다면 그 특정 키워드를 가지고 있는 데이터들을 한번에 뽑아서 가지고 울 수가 있다.
이러한 역색인 구조를 가지고 있는것이 엘라스틱서치라는 데이터베이스이다.

엘라스틱서치는 검색을 최적화에서 빠르게 결과값을 가져오기 위해서느 만들어졌다.
엘라스틱서치는 엘라스틱 스택(Elasic Stack)이라는 핵심 구성 요소중 하나이다.
엘라스틱 스택에는 Elasicesearch, Logstash, Kinana 이 세가지가 존재한다.
먼저 엘라스틱서치는 위에서 말한것과 같이 역 색인 구조로 만들어진 데이터베이스이다.
로그스태시는 내가 지정한 데이터베이스에 테이블과 동기화를 할 수 있어 내 원본 데이터베이스에 있는 데이터들을 일정 시간동안 최신화해서 가져올 수 있게 된다.
키바나는 이런 엘라스틱서치에 데이터베이스를 시각화하는 도구로서 웹사이트 처럼 생긴 GUI라고 생각하면 된다.

엘라스틱서치는 검색어를 저장하기 위해 Text Analysis라는 과정을 거치고, 이러한 과정을 처리하는 Analyzer라고 한다.
이 아날라이저는 Character Filter, Tokenizer, Token Filter로 이루어진다.
이 아날라이저를 잘 조합해 커스텀을 할 수 있고, 이 것을 이용해 검색어를 만들어 줄 수 있다.
이러한 아날라이저를 커스텀해서 사용할 수 있게 하기 위해 엘라스틱서치에는 세팅과 매핑이 존재한다.
세팅은 쉽게 말해 Index 정보 설정을 확인할 수 있는 단위이며 대부분의 설정들은 생성시 한번 지정되면 변경되지 않는다.
매핑은 세팅에서 인데스가 사용할 수 있도록 정의한 아날라이저와 같은 것을 내 데이터와 매핑하여 실제 사용할 수 있게 해주는 부분이다.
세팅과 매핑은 포스트맨으로도 할 수 있고 템플릿으로 만들어서 지속적으로 사용할 수 있게 만들 수도 있다.

마이크로서비스 아키텍처는 기존에 사용하던 모놀리식 아키텍처의 단점을 보안환 프로그래밍 설계구조 이다.
모놀리식 아키텍처는 지금 내가 하고 있는 매인프로젝트와 같이 모든 기능들을 한 파일 모두 모아놓고 그것을 빌드하여 실행시키는 것이다.
하지만 이렇게 하면 문제가 하나 있는데 하나의 API만 에러가 생겨도 모든 기능들이 모두 멈추어버리는 것이다.
마이크로서비스 아키텍처는 이러한 것을 방지하기 위해 나오 구조이다.
마이크로서비스 아키텍처는 하나의 파일에는 하나의 기능만을 넣은 폴더로 만들거나 관련된 것 들끼리만 묶어서 만든 후에 하나의 게이트웨이(프록시서버)를 모든 기능들의 접근할 수 있게 만드는 것이다.
이렇게 되면 기능별로 폴더가 나누어져 있기에 하나의 기능만 문제가 되면 그 폴더만 다시 수정하고 빌드하면 되기에 유지보수 또한 간단하고, 서비스 중에 하나의 기능 때문에 모든 서비스가 멈출 걱정은 안해도 된다.
그렇다고 해서 모든 프로젝트에서 마이크로서비스 아키텍처를 사용하는 것은 아니다.
왜냐하면 마이크로서비스 아키텍처를 하게되면 구조가 너무 복잡해지기에 팀 규모가 크지 않다면은 작업하는데 효율이 별로 좋지 않을 수 있다.
이러한 것을 오버엔지니어링라고 하는데 말그대로 과하게 기술을 사용하는 것을 의미한다.
프로젝트 규모와 팀 규모에 맞게 아키텍처를 짜는 것이 좋다.

TDD란 Test Driven Development의 약자로 테스트 주도 개발이라는 의미이다.
반복 테스트를 이용한 소프트웨어 방법론으로 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현하다.
이 테스트케이스가 디테일하면 디테일할수록 좋다.
테스트의 종류로는 단위 테스트, E2E 테스트, 통합 테스트가 있다.
유닛 테스트는 가장 작은 단위의 테스트를 의미한다.
E2E 테스트는 엔드투엔드라는 의미로 여러 시나리오를 만들어 시뮬레이션 하는것이다.
통합 테스트는 가장 작은 단위의 유닛 테스트들을 모아서 함께 테스트하는 것이다.

배포는 말 그대로 내 서비스를 세상의 공개를 하는 것이다.
서비스를 공개를 하면 내 컴퓨터는 항상 커져있어야하고 또 여러 유저의 트래픽을 감당하기 위해서는 좋은 컴퓨터가 있어야 한다.
이러한 문제점을 대신 해결해주는 것이 스토리지 서비스를 사용했던 GCP, AWS, Azure 같은 곳이다.
GCP에는 VM인스턴스라는 것을 빌릴 수 있다.
이 인스턴스는 구글에서 하나의 컴퓨터를 빌리는 것이다.
그리고 그 빌린 컴퓨터에서 배포를 진행하게 된다.
빌린 컴퓨터에서 도커를 띄어 백엔드 서버와 데이터베이스 서버를 키게 되면 서버가 실행이 되고, 인스턴스에는 각각의 고유한 IP가 있기 때문에 그 IP를 통해 접속을 할 수가 있다.
그리고 인스턴스에는 방화벽이 존재하는데, 이 방화벽은 내가 설정한 IP와 포트번호를 제외하고는 접속하지 못하게 막는 것이다.
이것을 풀어줘야 접속을 할 수 있게 된다.

7주차를 정리해보면 엘라스틱서치를 다루는 것이 가장 어려웠다.
세팅과 매핑을 하는 것이 너무 복잡했고 템플릿 만드는 것은 처음에 감도 못 잡았다.
그래도 다른 부분들은 크게 어려웠던 것 같지는 않다.
특히 배포를 하는 부분은 프론트에서도 해봤던 경험이 있어 크게 어렵지 않았고, 다른 부분도 많이 없었다.
아직 DNS라던가 쿠버네티스와 관련된 내용은 배우지 않아서 딱 잘라 쉽다고 할 수는 없지만 아직은 괜찮은 것 같다.
또한 테스트 케이스를 작성하는 부분은 프론트와 너무 달랐다.
프론트에서는 테스트 케이스를 대략적으로 작성하는 방법만 설명해주셨고 그냥 넘어갔던 부분이라 이 부분은 재밌게 했었다.
그리고 지금까지 알고리즘 테스트를 한번도 틀리지 않았는데 이번에 하나 틀렸다...
RunJS에 리턴값이 이상한지도 모르고 한문제를 시험끝날때까지 붙잡고 있었는데, 종료 5분전에 서브밋을 했더니 통과가 되는 것이다.
그래서 vscode에서 콘솔을 확인해봤는데 잘 리턴이 되고 있었다 하...
너무 아쉬었던 부분이었다. 그 한문제를 거의 1시간 넘게 잡고 있었는데, 이미 풀었던 내용인데 혼자 쉐도우 복싱하고 있엇던 것이다......
RunJS 믿을 놈이 못된다.

총 정리

벌써 7주차가 끝나게 되었다.
처음 3주차까지는 정말 어려웠던 부분이 많이 없어서 그런지 프론트보다 의욕이 많이 떨어져있었던 것 같다.
그래서 아침에 의지가 안 생겨서 그랬던건지 잘 일어나지 못했다.
그럼에도 4주차 시작하면서부터 모르는 부분이 많이 생기고, 뒤쳐지지 않기 위해서 이때부터 의지가 다시 생기기 시작했다.
그래서 늦게까지 블로깅도 하면서 공부했던 내용 복습하고 잘 되지 않는 부분 있으면 끝까지 해결하고 가려고 열심히 했었는데 살짝 무리도 했던것 같다.
앞으로 1주 남았는데 열심히 노력하되 너무 무리하지 않고 팀프로젝트를 위해서 많은 준비를 하려고 한다.

profile
풀스택 진행중...

0개의 댓글