Essential Developer
/
개발 일지
Search
Share
개발 일지
Golang Web Frameworks
•
Golang은 다른 언어에 비해 절대적인 입지를 가진 프레임워크가 없기 때문에 여러 프레임워크 중에서 선택해야한다.
Java - Spring Node.js - Express, NestJS Python - Django, FastAPI
•
다만 절대적인 입지를 가진 프레임워크가 없을 뿐이지 Golang에서 자주 쓰이는 대표적인 프레임워크는 총 5개정도 있다.
gin-gonic/gin
•
Golang의 가장 오래된 웹 프레임워크이자 압도적으로 많은 Github Star를 보유중인 프레임워크.
•
다만, 한국에선 다른 프레임워크들에 비해 무겁다는 이유로 잘 사용되지 않는 것 같다.
gofiber/fiber
•
해당 글에서 다룰 웹 프레임워크이다.
•
다른 웹 프레임워크보다 압도적인 성능을 보여준다.
•
위 그래프를 보면 다른 프레임워크에 비해 가장 늦게(2020년) 출시되었지만 압도적인 성장을 보여주고 있다.
beego/beego
Go Fiber를 이용한 MVC 기반 웹서버 만들기 (+boilerplate)
Backend
2024/02/18
Fiber의 Default Error Handler
•
Go fiber에서
기본적으로 제공해주는 error handler
는 여러 제약이 많았다.
•
그러기에 많은 개발자들이 Custom Error Handler를 만든다.
•
fiber 공식 문서
에 Custom Error Handler를 만드는 방법에 대해 아주 간략하게 나와있다.
•
다만, 해당 내용만으로 개발자가 원하는 Custom Error Handler를 만들기 힘들기에
내가 Custom Error Handler를 만든 경험을 공유하고자 글을 적는다.
Custom Error Handler
먼저 내가 만들고 싶은 Error Handler에 대해 정의했다.
Error 구조 정의
•
Code
: 사전에 정의된 Custom Error Code.
•
Err
: Golang 기본 error type.
Go Fiber Error Handler 커스텀하기
Backend
2024/01/23
테스트를 하기 전에 알아야할 것들
1.
테스트 코드의
func
의 이름의 가장 앞에는 항상
Test
라고 prefix가 있어야 Go가 인식합니다. 또한 파일 이름이
_test
로 끝나야합니다.
2.
단위 테스트는 테스트할
func
과 같은 패키지
에 있어야하고, 통합 테스트는 Project Root에 두는걸 권장합니다. (import cycle 방지)
3.
테스트 실행 방법 (
테스트 코드 옵션
)
단위 테스트
가장 빠르게 단위 테스트 하는 법
해당 방법은 꼭 JetBrain사의 IDEA를 사용해야합니다.
바쁘신 분들을 위해 가장 손쉽게 단위 테스트하는 방법입니다.
•
테스트하고 싶은
func
이름을 우클릭합니다.
•
Go To
->
Test
를 클릭해주세요.
•
Test할 범위를 고를 수 있습니다. 저희는 단위 테스트를 할 것이기에
Test for function
을 선택하겠습니다.
가장 빠르게 Go Test Code를 작성하는 방법
Backend
2023/07/18
Go Docker 경량화
•
기존 Dockerfile의 경우 우분투 이미지를 사용하고 있으며
go build
후 실행 파일을 우분투에 올려 실행합니다.
•
하지만 이렇게 할 경우 우분투의 기능을 사용하지 않음에도 무거운 우분투 이미지를 이용해 빌드하기에 비효율적이라고 생각되었습니다.
Image Options
•
Golang의 docker 이미지는 대표적으로 아래와 같이 5가지 정도입니다.
이미지 용량 비교
•
기본적으로
scratch
는 timezone과 CA certificates가 포함되어 있지 않기에 정확한 비교가 될 수 없습니다.
•
BusyBox
,
Scratch-advanced
및
Distroless
는 용량이 3.06MB와 4.17MB 사이에 위치하여 매우 비슷합니다. 특히 컨테이너에 연결하여 다른 도구를 설치하지 않을 경우(예: 디버깅 목적) 안전한 이미지들 입니다.
•
Debian
은 가장 큰 이미지이며 개발 목적과 테스트, 컨테이너 내부에 다른 도구를 배치하려는 경우에 좋을 수 있습니다.
•
Alpine
은 가장 작은 세 개의 이미지와
Debian
사이에 좋은 절충안을 제공합니다.
scratch
•
여러 이미지들 중에서 가장 경량화가 잘 되어 있는 scratch를 선택했습니다.
Go Docker 경량화
DevOps
2023/07/03
Decorator란?
데코레이터는 함수로서 호출됩니다. 데코레이터 함수는 꾸밀 대상인 클래스, 메서드, 프로퍼티를 인자로 받고, 그 대상을 변경한 결과를 반환합니다. 이 결과를 다시 대상에 할당함으로써, 대상을 꾸밀 수 있습니다.
자바스크립트의 데코레이터는 클래스, 메서드, 프로퍼티 등을 꾸밀 수 있는 기능입니다.
ES2016(ES7)에서는 이 기능이 표준으로 추가되었습니다.
•
데코레이터는 비즈니스와 상관 없는 로직들을 숨기면서 기능을 변경하거나 확장할 수 있게 한다.
•
또한 여러 클래스에서 반복되는 공통 관심사가 있을 때 데코레이터를 사용하면 중복 코드를 줄이고 코드를 모듈 단위로 관리하는 효과를 거둘 수 있다.
TypeScript에서의 Decorator
TypeScript 및 ES6에 클래스가 도입됨에 따라, 클래스 및 클래스 멤버에 어노테이션을 달거나 수정하기 위해 추가 기능이 필요한 특정 시나리오가 있습니다. 데코레이터는 클래스 선언과 멤버에 어노테이션과 메타-프로그래밍 구문을 추가할 수 있는 방법을 제공합니다. 데코레이터는 JavaScript에 대한
2단계 제안
이며 TypeScript의 실험적 기능으로 이용 가능합니다.
tsconfig.json
소개
•
TypeScript의 많은 라이브러리는 데코레이터를 기반으로 만들어졌다.
•
데코레이터의 종류 및 적용 가능 범위
NestJS Custom Decorator
Backend
2023/05/02
AWS Parameter Store 란?
AWS Systems Manager의 기능인 Parameter Store는 구성 데이터 관리 및 암호 관리를 위한 안전한 계층적 스토리지를 제공합니다.
특징
•
구성 데이터 관리 및
암호 관리를 위한 안전한 계층적 스토리지를 제공
한다.
•
파라미터를 생성할 때
고유 이름을 지정해서 다양한 곳에서 참조 가능
하다.
•
파라미터 값으로 저장할 수 있는 데이터.
•
저장 값 종류.
암호 교체 수명 주기를 구현하려면 AWS Secrets Manager를 사용합니다. Secrets Manager를 사용하면 수명 주기 동안 데이터베이스 자격 증명, API 키 및 기타 보안 암호를 손쉽게 교체, 관리 및 검색할 수 있습니다.
사용 비용
•
무료
Parameter Store 파라미터를 지원하는 AWS 서비스
•
Amazon EC2
•
Amazon Elastic Container Service
NestJS AWS Parameter Store 라이브러리 개발 일지
Backend
2023/04/22
MVC 패턴이란?
Express, NestJS 구현 차이점
Routing
•
위 코드처럼 Express는 라우팅을 할 때
app.use
처럼 등록을 해서 사용한다.
•
하지만, NestJS는 Module별로 나누어 라우팅을 한다.
Controller
•
코드만 봤을 땐 Express쪽이 편해보인다.
•
Express가 간결해 보이지만, 가독성,확장성 등을 고려했을 때 NestJS쪽이 구조가 더 명확하고 좋다고 생각한다.
Express를 NestJS처럼 사용하기 (feat. InversifyJS)
Backend
2023/01/12
Index를 이용한 통계 데이터 GET API 개선
•
저번 시간
에 검색 성능을 개선했지만 여전히 k6의
http_req_duration
이 약 3초 정도 걸린다.
•
이를 해결하기 위해 API 성능을 다 조사해본 결과 통계 데이터를 가져오는 API가 상당히 오래 걸리는 것을 확인했다.
기존 방식
•
사용자의 성별이 남성, 체중이 100kg 일 경우, 성별이 남자면서 체중이 93~105kg 인 모든 사용자의 3대 운동 총량을 가져옵니다. 그 후에, 3대 운동 총량을 기준으로 정렬합니다.
•
하지만 이럴 경우 체중이 93~105kg인 사용자들이 테이블에 여기저기 흩어져 있기 때문에 Full Table Scan을 통해 모든 사용자 정보를 가져옵니다.
개선 방법
아이디어
•
처음에는 체중을 정렬 시킨 상태로
between
으로 가져오는 것이 휠씬 빠를 것이라 생각했다.
Single Column Index (weight)
•
하지만 실험 결과 성별로 인해
Index Range Scan
을 과도하게 길게 한다는 것을 파악했다.
Index를 이용한 DB 성능 개선 일지
Database
2022/12/19
Cluster Mode
PM2의 cluster mode
The cluster mode allows networked Node.js applications (http(s)/tcp/udp server) to be scaled accross all CPUs available, without any code modifications. This greatly increases the performance and reliability of your applications, depending on the number of CPUs available.
•
코드 수정 없이 Node.js 애플리케이션을 CPU에 따라 확장할 수 있다.
•
안정성과 성능을 크게 향상할 수 있습니다.
•
Node.js의 cluster mode를 사용한다.
Node.js의 cluster mode
A single instance of Node.js runs in a single thread. To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load.
•
Node.js의 단일 인스턴스는 단일 스레드에서 실행되는데, 멀티 코어 시스템을 이용하기 위해서 Node.js 프로세스들을 클러스터로 사용할 수 있다.
•
이를 통해 모든 서버 포트를 공유하는 하위 프로세스를 생성한다.
The worker processes are spawned using the child_process.fork() method, so that they can communicate with the parent via IPC and pass server handles back and forth.
•
이 하위 프로세스들은
child_process.fork()
메서드를 사용해서 생성되는데, 부모 자식 간의 통신을 위한 IPC(Inter-process communication) 채널을 가지고 있으며, 생성된 각 프로세스는 자체 V8 인스턴스가 있다.
무중단 배포 맛보기
DevOps
2022/12/17
유저 검색 개선
기존 방식
•
검색 페이지에 들어올 때 마다 모든 유저의 [ id, name, introduce, profile_image ]를 가져와 클라이언트로 전송한다.
•
클라이언트측에서는 검색을 할 때 해당 검색어를 리스트의 name에서 찾아 일치하는 유저들을 보여준다.
문제점
•
검색 페이지에 들어올 때 모든 유저의 정보를 가져오는게 너무 오래 걸린다.
•
검색 페이지에 들어오면 로딩 시간이 필요한 상황이라 사용자 입장에서 사용했을 때 심각한 불편을 느꼈다.
•
개발자 도구에서 네트워크를 확인해보니 모든 유저 정보를 가져오는데 대략 120ms이 걸리는 것을 볼 수 있으며, 다른 API와 비교했을 때 대략 4~6배 느린것을 확인할 수 있다.
고민
•
먼저 사용자 입장에서 검색 기능의 이용 빈도를 생각 했을 때 과연 얼마나 사용할까를 생각해봤다.
•
인스타를 생각해봤을 때 다른 사람을 팔로잉할 때 주로 검색 기능을 사용한다.
•
그 때문에 다른 기능에 비해 상대적으로 낮은 이용 빈도가 예상된다.
•
그래서 굳이 모든 유저 정보를 가져올 필요 없이 사용자가 검색어(이름)를 입력할 경우 해당 검색어에 해당되는 유저 정보들만 가져와서 보여주면 되지 않을까라는 생각을 했다.
Full Text Search를 이용한 DB 성능 개선 일지
Database
2022/12/14
상황 설명
•
현재 우리 프로젝트는 클라이언트측에서 가지고 있는
user_id
와 쿠키의 payload에 있는
user_id
를 비교하여 같을 경우에만 API 호출이 가능하도록 하는 검증 단계(AuthGuard)가 있다.
•
하지만 로컬에서는 문제 없이 request header와 쿠키에서
user_id
를 갖고 오지만, 배포 환경에서는 request header에서
user_id
를 갖고오지 못해 계속 unauthorized 401 에러가 발생 했다.
•
(역시 한번에 성공적으로 배포하기가 쉽지 않다...)
클라이언트에서 custom header를 못보내주나?
•
처음에는 클라이언트에서 헤더를 못보내주는 줄 알았다.
•
그 때문에 개발자 도구의 네트워크 탭을 확인하자, request header에 정상적으로 user_id가 있는걸 확인했다.
CORS 문제인가?
•
클라이언트측에서 request header를 잘 보내주는걸 확인한 뒤로 의심해볼것은 만악의 근원 CORS 였다.
•
알아본 결과, 예비 요청(Preflight)에 대한 Response Header에 사용되며, 본 요청에서 사용할 수 있는 HTTP Header를 지정하는 Access-Control-Allow-Headers라는 설정이 있었다.
•
그래서 NestJS를 사용하는 우리 프로젝트에서 다음과 같이 적용해봤다.
•
allowedHeader 설정을 추가해도 역시나 header에서
user_id
를 받을 수 없었다.
underscores_in_headers
Request Header의 특정 헤더값이 확인이 안되는 경우
DevOps
TroubleShooting
2022/12/14
기존 방식의 문제점
•
클라이언트측에서
/api/oauth/google
을 호출 할 경우
AuthGuard
로 인해 자동으로 구글 로그인 페이지로 redirect됩니다.
•
그 후, 로그인을 완료할 경우 아래의 구글 측에서
/api/oauth/google/callback
으로
access token
과 함께 callback합니다.
•
이 경우, 클라이언트측에서는
/api/oauth/google/callback
API를 호출한적이 없으므로 로그인 여부를 알 수 없고, 유저 정보 또한 얻을 수 없습니다.
•
SSR을 사용할 경우 문제 없이 유저 정보를 전송할 수 있지만, CSR을 사용하고 있는 상황에서는 해당 문제가 발생한다.
개선된 방식
•
구글 공식 문서
를 확인해본 결과 사용자가 request token을 주면 구글에서 authorization code를 보낸다.
•
그 후, 사용자는 authorization code를 이용해 access token을 요청하고, access token을 이용해 구글 로그인을 수행한다.
•
실제 프로젝트에 대입해보면 아래와 같은 흐름도가 나온다.
Google OAuth 트러블 슈팅
Backend
TroubleShooting
2022/12/10
SSL Server Test A등급으로 올리기
•
ssllabs.com
를 통해
SSL Server Test
를 한 결과 B등급이 나왔다. 해당 결과에 만족스럽지 못한 나는 Protocal Support에 문제가 있다는 것을 발견했다.
•
cerbot
+
let’s encrypt
를 이용해 HTTPS 설정을 하게 될 경우 ssl 관련 설정들이
/etc/letsencrypt/options-ssl-nginx.conf
에 저장된다.
•
해당 파일을 살펴보면
ssl_protocols TLSv1 TLSv1.1 TLSv1.2
라고 적혀 있는걸 볼 수 있는데, 2020년부터 TLSv1.0 TLSv1.1에 대한 지원을 중단했다.
•
그 때문에
SSL Server Test
에서 B등급이 나왔다는 것을 알 수 있었다. 단순히
TLSv1
와
TLSv1.1
을 삭제하는 것만으로도 A등급이 나오며 문제를 해결 할 수 있었다.
•
하지만 최신 버전인 TLSv1.3도 적용할려고 할 경우
POODLE(Padding Oracle On Downgraded Legacy Encryption) 취약점
•
구식 암호화 기법을 악용할 수 있게 하는 프로토콜 다운그레이드 취약점.
BEAST(Browser Exploit Against SSL/TLS) 취약점
•
앤드 유저 브라우저에서 HTTPS 의 쿠키들을 해독하고 효과적인 타킷의 세션을 하이제킹할 수 있는 취약점.
•
주요 웹 브라우저 및 애플리케이션에 구현된 TLS 는 다운그레이드 협상 프로세스 (downgrade negotiation process)를 지원하기 때문에 서버가 최신 버전을 지원하더라도 공격자가 취약한 프로토콜을 이용할 수 있다.
TLSv1.3 적용하기
SSL Server Test A+ 받기
DevOps
2022/12/10