진행중인 사이드 프로젝트 백엔드 api에서 특정 url을 fetch시 fetch failed 에러가 발생하여 500 Internel Server Error로 error response가 발생하는 이슈가 있었다. 에러 로그를 확인해보면 TypeError: fetch failed와 함께 발생 원인으로 'unsafe legacy renogotiaion disabled' 가 적혀있었다. 해당 에러는 요청 들어온 url을 fetch할 때 해당 url의 보안 관련 SSL이 안전하지않은 레거시 버전을 사용하고 있어 fetch에 실패시 발생하는 것이었다. 기존에 사용하던 node 버전 16에서는 이 이슈가 한번도 발생한 적이 없었는데 이번에 프로젝트 node 버전을 16.x에서 18 LTS로 메이저 버전 업데이트를..
NestJs와 TypeORM을 같이 사용할 때, 대부분 TypeORM에서 기본 제공하는 Repository 구현체에 제네릭으로 해당 레포지토리를 통해 접근하려는 엔티티 클래스를 주입해서 Service 클래스의 생성자에 추가하여 사용하였었다. TypeORM에서 제공하는 해당 방식을 사용하면 Repository를 따로 구성하지 않고, 엔티티, 서비스 클래스 만으로 간결하게 구현할 수 있다는 장점이 있었지만, 추후 TypeORM에서 다른 라이브러리로의 전환시, 리팩토링 비용이 많이 들어갈 가능성을 배제할 수 없다. ORM 마다 제공하는 API가 다르기 때문에 interface에 필요한 스펙을 명시해두고, 구현체를 따로 구현하는 방식을 도입했다. 1. 인터페이스 기반 Custom Repository 구현 인터페..
기존에 작업하던 사이드 프로젝트 POC 발표 기간이 별로 남지 않았고, AWS 비용 지원도 나와서 CloudType, Neon 조합으로 무료 플랜을 활용해서 배포해두었던 백엔드 인프라를 AWS 기반으로 마이그레이션하고, 프론트 신규 배포를 진행하였다. 배포하면서 여러 이슈 상황이 있었는데 해당 히스토리를 정리해두었다. AWS 서비스의 경우, 기존에 static 파일 저장 스토리지 용도로 사용하던 S3를 유지한 채, EC2를 추가적으로 사용하였다. EC2 인스턴스 유형의 경우, 유효한 트래픽이 없는 상태에서 RDS 서비스를 사용하기에는 비용적으로 팀원들에게 부담이 되므로 DB를 인스턴스 내부에 docker 컨테이너로 띄울 계획으로 vCPU가 2개에 메모리가 2Gib인 t3.small를 사용하였다. DNS의..
블로그를 정리하던 중 과거의 아카이브된 글에서 해당 글을 발견하였다. 그래서 이번에 구현 방식까지 한번에 정리해두려고 한다. [NestJS & React] 유저 동접 방지 구현 유저 동시 접속 방지 기능을 개발이 완료된 서비스에 추가하는 방식으로 구현해야될 일이 생겼다. 해당 서비스의 경우, 로그인, 유저 관리를 세션/쿠키 방식이 아닌 JWT 방식으로 관리하고 있었 eight20.tistory.com 왜 세션/쿠키 방식으로 구현을 하지 않았는지에 대해 의문을 가질 수도 있다. 기존에 이미 JWT로 사용자 인증이 구현되어있는 상황에서 인증 방식의 수정없이 유저의 동시 접속을 막는 것이 요구사항이라 JWT 인증 기반 위에 웹소켓으로 동시 접속 방지를 구현하게되었다. 동시 접속 방지 로직 플로우은 아래와 같다..
가상계좌 관련 결제 시스템의 결제 관련 필요 정보들을 저장하는 현재 로직 플로우로는 해결이 불가능한 품절/적립금 적립 관련 이슈가 있었는데 프론트엔드 전역변수로의 처리에 대해 이야기하다 Redis를 사용하면 가능할 거 같다라는 생각에 NestJS에 Redis 캐싱을 적용시키게 되었다. Redis의 경우, AWS ElasticCache를 사용할 수 있지만, 기본적으로 메모리 용량 = 돈이기 때문에 docker 공식 redis 이미지를 기존 ec2 인스턴스 내에 docker 컨테이너로 standalone 모드로 띄워두는 방식을 사용하였다. Redis 관련 의존성 추가 Redis 캐시를 사용하기 위한 의존성을 추가해준다. yarn add cache-manager@4.1.0 cache-manager-redis-..
View 테이블을 사용하여 현재 특정 데이터들에 대한 순위를 계산해야하는 경우가 있었다. MySQL의 경우에는 RANK() 함수가 5.7버전부터 추가되어 특정 칼럼에 대해 값의 순위를 계산할 때 사용할 수 있다. RANK() 함수 사용 예시 사용시 문법은 다음과 같다. RANK() OVER (PARTITION BY [구분하려는 칼럼명] ORDER BY [정렬하려는 칼럼명] DESC/ASC) 해당 함수 사용시 PARTITION BY와 DESC/ASC는 생략이 가능하다. PARTION BY PARTITION BY는 특정 동일한 제약이 걸린 데이터 끼리의 순위를 얻고 싶을 때 사용가능하다. 예를 들어 근무 시간 테이블에서 지점명 A에 소속된 직원들의 근무 시간에 대해서만 순위를 얻고 싶다면 PARTITION ..
NestJs + Prisma 조합으로 신규 프로젝트를 진행하던 중 매일 새벽 1시마다 해당 날짜의 유가/최저가 주유소 관련 정보를 각각 Opinet의 API로 조회해서 저장하는 독립된 배치 2개를 구현하였었다. 유가 정보 조회/저장 배치가 스테이지 환경에서 정상적으로 동작하는 것을 확인하고, 최저가 주유소 관련 배치를 스테이지 환경에 배포해둔 상황이었다. DB 최저가 주유소 관련 테이블에 row들이 정상적으로 저장된 것을 확인하고, 해당 배치 기능은 완료된 것으로 생각하고 있었다. 유가 정보를 저장하고 있는 테이블과 최저가 주유소 정보를 저장하고 있는 테이블이 서로 연관이 없고, 독립된 배치에서 실행되고 있는 상황이라 insert 관련 락이나 PK 관련 이슈가 없을 거라고 생각하면서 DB와 서버 로그를 ..
기존의 NestJs + TypeORM 조합에서 NestJs + Prisma 도입을 위해 MVP 프로젝트에 적용하는 과정에서 위처럼 원격 환경에 배포시 빌드 과정에서 TS 컴파일 관련 에러가 발생하면서 node_modules 내부에 위치한 prisma client에 Schema Property가 없다는 에러가 발생하였다. 해당 에러가 로컬 환경의 빌드에서는 발생되지 않고, 해당 원격 환경에서 빌드시 발생하고 있었는데 해당 에러와 관련된 스택 오버플로우, 깃헙 이슈를 찾아보면 하나같이 "IDE를 재시작해라"와 같은 로컬 환경에서의 이슈에 대한 답변만 존재하였다. 현재 사용하고 있던 배포 플로우는 다음과 같았다. 원격 저장소의 지정된 브랜치에서 git pull yarn install rimraf로 기존 dis..
프로젝트를 하다보면 로컬에 설치된 NodeJS의 버전이 달라 상대적으로 낮은 버전을 사용하는 사람의 로컬에서 해당 메소드의 부재로 인해 에러가 발생하는 경우가 종종 있다. 로컬의 NodeJS 버전을 변경하는 방법에는 nvm(Node Version Manager)가 있다. nvm을 사용하여 서로 로컬의 NodeJS 버전 sync를 맞출 수 있지만, 해당 방법을 사용하면 새로운 팀원이나 주 개발 환경이 아닌 곳에서 작업할 시, 매번 nvm을 사용해서 다시 버전 sync를 직접 맞춰야된다는 단점이 있다. Volta를 사용하여 node 버전을 맞추게되면 volta만 설치후 바로 프로젝트 패키지 설치 및 실행에 별다른 허들 없이 진행가능하다. Volta는 javascript 커맨드 관리 툴로 node 버전 syn..
7-1. 상속 관계 매핑 관계형 DB에는 객체지향 언어의 "상속" 이라는 개념 X 슈퍼타입/서브타입 관계가 객체 상속 개념과 유사 각각의 테이블로 변환 각각을 모두 테이블로 만들고, 조회시 JOIN 사용 JPA에서 조인 전략이라 부름 통합 테이블로 변환 테이블을 하나만 사용하여 통합 JPA에서 단일 테이블 전략이라 부름 서브타입 테이블로 변환 서브 타입마다 하나의 테이블을 만듬 JPA에서 구현 클래스마다 테이블 전략이라 부름 조인 전략 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본키를 받아서 기본키 + 외래키로 사용하는 전략 조회시 JOIN을 자주 사용 객체는 타입으로 구분 가능 / 테이블은 타입의 개념이 X → 타입을 구분하는 칼럼 추가 필요 테이블 정규화 / 저장공간 효율성의 ..
개발 2024. 6. 8. 08:20
진행중인 사이드 프로젝트 백엔드 api에서 특정 url을 fetch시 fetch failed 에러가 발생하여 500 Internel Server Error로 error response가 발생하는 이슈가 있었다. 에러 로그를 확인해보면 TypeError: fetch failed와 함께 발생 원인으로 'unsafe legacy renogotiaion disabled' 가 적혀있었다. 해당 에러는 요청 들어온 url을 fetch할 때 해당 url의 보안 관련 SSL이 안전하지않은 레거시 버전을 사용하고 있어 fetch에 실패시 발생하는 것이었다. 기존에 사용하던 node 버전 16에서는 이 이슈가 한번도 발생한 적이 없었는데 이번에 프로젝트 node 버전을 16.x에서 18 LTS로 메이저 버전 업데이트를..
개발/NestJS 2023. 11. 22. 08:20
NestJs와 TypeORM을 같이 사용할 때, 대부분 TypeORM에서 기본 제공하는 Repository 구현체에 제네릭으로 해당 레포지토리를 통해 접근하려는 엔티티 클래스를 주입해서 Service 클래스의 생성자에 추가하여 사용하였었다. TypeORM에서 제공하는 해당 방식을 사용하면 Repository를 따로 구성하지 않고, 엔티티, 서비스 클래스 만으로 간결하게 구현할 수 있다는 장점이 있었지만, 추후 TypeORM에서 다른 라이브러리로의 전환시, 리팩토링 비용이 많이 들어갈 가능성을 배제할 수 없다. ORM 마다 제공하는 API가 다르기 때문에 interface에 필요한 스펙을 명시해두고, 구현체를 따로 구현하는 방식을 도입했다. 1. 인터페이스 기반 Custom Repository 구현 인터페..
프로젝트 회고 2023. 11. 9. 08:20
기존에 작업하던 사이드 프로젝트 POC 발표 기간이 별로 남지 않았고, AWS 비용 지원도 나와서 CloudType, Neon 조합으로 무료 플랜을 활용해서 배포해두었던 백엔드 인프라를 AWS 기반으로 마이그레이션하고, 프론트 신규 배포를 진행하였다. 배포하면서 여러 이슈 상황이 있었는데 해당 히스토리를 정리해두었다. AWS 서비스의 경우, 기존에 static 파일 저장 스토리지 용도로 사용하던 S3를 유지한 채, EC2를 추가적으로 사용하였다. EC2 인스턴스 유형의 경우, 유효한 트래픽이 없는 상태에서 RDS 서비스를 사용하기에는 비용적으로 팀원들에게 부담이 되므로 DB를 인스턴스 내부에 docker 컨테이너로 띄울 계획으로 vCPU가 2개에 메모리가 2Gib인 t3.small를 사용하였다. DNS의..
개발/NestJS 2023. 8. 12. 08:20
블로그를 정리하던 중 과거의 아카이브된 글에서 해당 글을 발견하였다. 그래서 이번에 구현 방식까지 한번에 정리해두려고 한다. [NestJS & React] 유저 동접 방지 구현 유저 동시 접속 방지 기능을 개발이 완료된 서비스에 추가하는 방식으로 구현해야될 일이 생겼다. 해당 서비스의 경우, 로그인, 유저 관리를 세션/쿠키 방식이 아닌 JWT 방식으로 관리하고 있었 eight20.tistory.com 왜 세션/쿠키 방식으로 구현을 하지 않았는지에 대해 의문을 가질 수도 있다. 기존에 이미 JWT로 사용자 인증이 구현되어있는 상황에서 인증 방식의 수정없이 유저의 동시 접속을 막는 것이 요구사항이라 JWT 인증 기반 위에 웹소켓으로 동시 접속 방지를 구현하게되었다. 동시 접속 방지 로직 플로우은 아래와 같다..
개발/NestJS 2023. 7. 10. 08:20
가상계좌 관련 결제 시스템의 결제 관련 필요 정보들을 저장하는 현재 로직 플로우로는 해결이 불가능한 품절/적립금 적립 관련 이슈가 있었는데 프론트엔드 전역변수로의 처리에 대해 이야기하다 Redis를 사용하면 가능할 거 같다라는 생각에 NestJS에 Redis 캐싱을 적용시키게 되었다. Redis의 경우, AWS ElasticCache를 사용할 수 있지만, 기본적으로 메모리 용량 = 돈이기 때문에 docker 공식 redis 이미지를 기존 ec2 인스턴스 내에 docker 컨테이너로 standalone 모드로 띄워두는 방식을 사용하였다. Redis 관련 의존성 추가 Redis 캐시를 사용하기 위한 의존성을 추가해준다. yarn add cache-manager@4.1.0 cache-manager-redis-..
개발/MySQL 2023. 6. 27. 00:26
View 테이블을 사용하여 현재 특정 데이터들에 대한 순위를 계산해야하는 경우가 있었다. MySQL의 경우에는 RANK() 함수가 5.7버전부터 추가되어 특정 칼럼에 대해 값의 순위를 계산할 때 사용할 수 있다. RANK() 함수 사용 예시 사용시 문법은 다음과 같다. RANK() OVER (PARTITION BY [구분하려는 칼럼명] ORDER BY [정렬하려는 칼럼명] DESC/ASC) 해당 함수 사용시 PARTITION BY와 DESC/ASC는 생략이 가능하다. PARTION BY PARTITION BY는 특정 동일한 제약이 걸린 데이터 끼리의 순위를 얻고 싶을 때 사용가능하다. 예를 들어 근무 시간 테이블에서 지점명 A에 소속된 직원들의 근무 시간에 대해서만 순위를 얻고 싶다면 PARTITION ..
개발/NestJS 2023. 6. 12. 08:20
NestJs + Prisma 조합으로 신규 프로젝트를 진행하던 중 매일 새벽 1시마다 해당 날짜의 유가/최저가 주유소 관련 정보를 각각 Opinet의 API로 조회해서 저장하는 독립된 배치 2개를 구현하였었다. 유가 정보 조회/저장 배치가 스테이지 환경에서 정상적으로 동작하는 것을 확인하고, 최저가 주유소 관련 배치를 스테이지 환경에 배포해둔 상황이었다. DB 최저가 주유소 관련 테이블에 row들이 정상적으로 저장된 것을 확인하고, 해당 배치 기능은 완료된 것으로 생각하고 있었다. 유가 정보를 저장하고 있는 테이블과 최저가 주유소 정보를 저장하고 있는 테이블이 서로 연관이 없고, 독립된 배치에서 실행되고 있는 상황이라 insert 관련 락이나 PK 관련 이슈가 없을 거라고 생각하면서 DB와 서버 로그를 ..
개발/NestJS 2023. 5. 29. 23:59
기존의 NestJs + TypeORM 조합에서 NestJs + Prisma 도입을 위해 MVP 프로젝트에 적용하는 과정에서 위처럼 원격 환경에 배포시 빌드 과정에서 TS 컴파일 관련 에러가 발생하면서 node_modules 내부에 위치한 prisma client에 Schema Property가 없다는 에러가 발생하였다. 해당 에러가 로컬 환경의 빌드에서는 발생되지 않고, 해당 원격 환경에서 빌드시 발생하고 있었는데 해당 에러와 관련된 스택 오버플로우, 깃헙 이슈를 찾아보면 하나같이 "IDE를 재시작해라"와 같은 로컬 환경에서의 이슈에 대한 답변만 존재하였다. 현재 사용하고 있던 배포 플로우는 다음과 같았다. 원격 저장소의 지정된 브랜치에서 git pull yarn install rimraf로 기존 dis..
개발 2023. 5. 16. 00:06
프로젝트를 하다보면 로컬에 설치된 NodeJS의 버전이 달라 상대적으로 낮은 버전을 사용하는 사람의 로컬에서 해당 메소드의 부재로 인해 에러가 발생하는 경우가 종종 있다. 로컬의 NodeJS 버전을 변경하는 방법에는 nvm(Node Version Manager)가 있다. nvm을 사용하여 서로 로컬의 NodeJS 버전 sync를 맞출 수 있지만, 해당 방법을 사용하면 새로운 팀원이나 주 개발 환경이 아닌 곳에서 작업할 시, 매번 nvm을 사용해서 다시 버전 sync를 직접 맞춰야된다는 단점이 있다. Volta를 사용하여 node 버전을 맞추게되면 volta만 설치후 바로 프로젝트 패키지 설치 및 실행에 별다른 허들 없이 진행가능하다. Volta는 javascript 커맨드 관리 툴로 node 버전 syn..
책 스터디 정리/JPA ORM 스터디 2023. 5. 9. 08:20
7-1. 상속 관계 매핑 관계형 DB에는 객체지향 언어의 "상속" 이라는 개념 X 슈퍼타입/서브타입 관계가 객체 상속 개념과 유사 각각의 테이블로 변환 각각을 모두 테이블로 만들고, 조회시 JOIN 사용 JPA에서 조인 전략이라 부름 통합 테이블로 변환 테이블을 하나만 사용하여 통합 JPA에서 단일 테이블 전략이라 부름 서브타입 테이블로 변환 서브 타입마다 하나의 테이블을 만듬 JPA에서 구현 클래스마다 테이블 전략이라 부름 조인 전략 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본키를 받아서 기본키 + 외래키로 사용하는 전략 조회시 JOIN을 자주 사용 객체는 타입으로 구분 가능 / 테이블은 타입의 개념이 X → 타입을 구분하는 칼럼 추가 필요 테이블 정규화 / 저장공간 효율성의 ..