라벨이 개발 팁인 게시물 표시

Nest.js 빌드 후 진입점이 이상한 위치에 생기는 이유는?

Nest.js 빌드 후 진입점이 이상한 위치에 생기는 이유는? 레거시 Nest.js 백엔드를 재작성하는 솔루션을 진행하던 중, 특이한 일이 발생했다. 재사용성과 유지보수성을 위해 공용 라이브러리 및 DB 스키마 등을 별도의 GitHub Private Packages로 분리해두고 있었는데, 그러던 중 갑자기 Nest.js 백엔드 빌드가 안 되는 문제가 발생한 것이다. 처음에는 Error: Cannot find module '[CENSORED]/dist/admin' 같은 에러가 떴다. 문제는 소비측 프로젝트와 라이브러리 패키지 프로젝트 둘 다에서 package.json, tsconfig.json, nest-cli.json 등 빌드에 관련된 파일을 하나도 건드리지 않았다는 것이다. 첫 번째 시도: nest start 진입점 변경 시간에 쫓기는 상황이라, 급하게 dist/ 디렉터리 구조를 파악한 뒤 소스 루트를 통째로 옮겨보려고 했다. 그런데 여기서 또 특이한 점이 있었는데, 디렉터리 구조가 평탄화된 상태가 아니라 재귀적인 구조로 바뀌어 있었다. 예를 들어, 이전에는 빌드하면 다음과 같은 디렉터리 구조가 나타났다. proj - dist - main.ts - .. . 그런데 지금은 아래와 같이 변경되어 있었다. proj - dist - lib - [ 라이브러리 프로젝트명 ] - src - .. . - [ 프로젝트명 ] - src - main.ts - .. . 뭔가 괴상하다는 느낌은 있었지만, 시간이 없어서 npm 스크립트에서 nest start 부분의 진입점을 변경해 시작해보려 했다. 당연히 문제가 발생했다. 문제 발생: This is likely not portable... 문제는 바로 아래와 같은 에러였다. src / decorators / public . decorator . ts :...

JetBrains WebStorm에서 Reference된 tsconfig 프로젝트를 인식하지 못하는 문제

이미지
JetBrains WebStorm에서 Reference된 tsconfig 프로젝트를 인식하지 못하는 문제 WebStorm이 tsconfig.*.json을 인식하지 못함 제목을 한 줄로 정리하려니 참 머리가 아프다. 제목만 보고 무슨 문제인지 잘 감이 안 잡힐 수도 있겠다 싶어서 방금 내가 겪은 일을 간단히 요약하고 들어가겠다. electron-vite 프로젝트 구성 : npx create electron-vite 명령어로 electron-vite 프로젝트를 구성했다. JetBrains WebStorm에서 프로젝트 열기 : 구성된 프로젝트를 JetBrains WebStorm으로 열었다. tsconfig.web.json의 compilerOptions.paths 에 alias 추가 : @renderer/*, @lib/* 등 path aliases를 추가했다. 코드 자동완성으로 import 시도 : @lib/abc 를 import하려 하였으나 ../../lib/abc 가 임포트됨 🤬 시도해 본 방법들 WebStorm이 업데이트된지 얼마 되지 않았기에 혹시 업데이트 관련해서 문제가 생긴 것인지 확인하기 위해 tsconfig.json 자체에서 paths를 추가해봤더니 정상 작동했다. 그 상태에서 tsconfig.web.json 의 paths를 제거해봤다. 기존 절대 경로 임포트들에서 에러가 발생했다. (IDE 자체 에러) tsconfig.paths.json 을 만들고 tsconfig.json 및 tsconfig.web.json 에서 reference를 해봤다. IDE에서는 잘 작동하는 것처럼 보이지만 프로젝트 전체 구성에 문제가 발생해 개발 및 프로덕션에서 사용할 수 없었다. 올바른 해결 방법 우선 문제를 확실히 하기 위해 완전히 새로운 electron-vite 프로젝트를 만들고 내 tsconfig.web.json 과 비교해 봤더니 기본적으로 @renderer/* 경로가 paths에 추가되어 ...

JetBrains WebStorm에서 electron-vite 디버그하기 (렌더러 메인 모두)

이미지
JetBrains WebStorm에서 electron-vite 디버그하기 (렌더러 메인 모두) electron-vite electron-vite 는 Electron 을 ViteJS 위에서 돌리기 위한 프리셋을 제공해주는 도구이다. vite Vite는 Webpack 에 비해 어마무시할 정도로 빠른 퍼포먼스를 자랑하기 때문에 내가 최근 들어 애용하기 시작했는데 아무래도 웹팩에 비해 후발 주자라서 갖는 단점 1 이 있긴 하지만, 그것을 압도하는 빠른 성능 때문에 안 쓸래야 안 쓸 수가 없게 되었다. electron 일렉트론은 웹앱을 데스크탑 응용 프로그램으로 제작하는 용도로 쓰인다. 다시 말해, 웹 사이트를 구축하듯이 디자인 및 프로그래밍을 하되 OS에서 제공하는 API들 역시 이용할 수 있게 해준다는 의미로 받아들이면 얼추 맞다. JetBrains WebStorm에서 electron-vite 디버그 그렇다면 electron-vite 디버그는 어떻게 해야 할까? 결론부터 말하자면 그냥 electron을 디버그하는 것과 크게 다르지 않다. npm dev 수정 일단 npm run dev 를 실행하는 기본 구성 파일을 수정한다. 2 Arguments 에 --sourcemap 을 추가해주고 Environment 에 REMOTE_DEBUGGING_PORT={디버그 포트} 를 추가한다. 난 공식 사이트 를 따라 9222 로 지정하였다. 위 프로젝트 설정은 해당 Run/Debug 설정으로 Run/Debug할 때 소스맵을 제공하면서 디버그 포트를 적용시켜 후술할 Attach 기능이 작동할 수 있도록 한다. Attach to Node.js/Chrome 설정 생성 이제 디버그 포트가 열린 채로 켜진 일렉트론 렌더러를 디버그하기 위해 렌더러 프로세스에 부착할 디버거 설정을 진행할 차례이다. Electron은 크로미움 기반 브라우저 위에서 돌아가기 때문에, CEF 프로그램 또는 크로미움 기반 브라우...

Visual Studio Code의 탐색기 항목 indent 조정하기

이미지
Visual Studio Code의 탐색기 항목 indent 조정하기 VSCode 탐색기 들여쓰기 조정하기 탐색기 들여쓰기 다른 IDE를 쓰다가 VSCode를 사용하면 불편한 점이 몇 가지 있지만 가장 눈에 띄는 불편함은 바로 탐색기 트리의 들여쓰기 너비이다. 8픽셀짜리 좁아터진 indent 내 시력이 나쁜 편이 아닌 데도 불구하고 VSCode의 탐색기 화면만 보면 눈이 아파온다. 특히 피곤할 때는 더. Explorer Indent 너비 조정 VSCode의 불편한 점은 대개 두 가지 방법으로 해결할 수 있는데, 한 개는 확장 프로그램 설치, 다른 한 개는 설정 조정이다. 이번 문제는 설정 변경 으로 해결할 수 있었다. Workspace 설정 변경 VSCode의 설정은 여러 방법으로 변경할 수 있는데, 주로 IDE 내에서 텍스트 또는 UI로 변경하게 된다. 당연히 이 설정 역시 두 가지 방법을 사용해 변경할 수 있으므로 하나씩 알려주도록 하겠다. UI로 변경 Ctrl + Shift + P 또는 <F1> 키를 눌러 Preferences: Open Settings (UI) 항목을 연다. 1 Workbench - Appearance 항목으로 이동해 Tree: Indent 섹션의 값을 적절히 변경한다. JSON으로 변경 Ctrl + Shift + P 또는 <F1> 키를 눌러 Preferences: Open User Settings (JSON) 항목을 연다. "workbench.tree.indent": 숫자 를 입력해 너비를 조정한다. 저장하면 바로 반영된다. 결과 기본 단축키: Ctrl + , . Workspace 가 아닌 User 탭에서 진행해야 모든 워크스페이스에 설정이 적용된다. ↩︎

자바스크립트에서 아예 선언되지 않은 변수 체크하기

자바스크립트에서 아예 선언되지 않은 변수 체크하기 선언되지 않은 변수? 값이 정의되지 않은 변수 와 선언되지 않은 변수 를 구분해야 한다. 가장 흔히 보이는 값이 정의되지 않은 변수 는 다음과 같다. var a ; let b ; ***const***는 초기값이 없는 상태로 초기화할 경우 SyntaxError 를 발생시키므로 제외하였다. 굳이 하자면 const a = undefined 가 될 수 있긴 하다. 위와 같은 코드는 남이 짜놓은 자바스크립트 코드를 보다 보면 흔하게 볼 수 있다. 혹은 그 사람은 그렇게 작성하지 않았더라도 minifier 등으로 처리된 코드에서는 저런 부분이 많이 보이곤 했다. 값이 정의되지 않은 변수 의 a 와 b 는 값이 할당되지 않아 보이지만 실제 스택에는 undefined 가 값으로 할당된 상태이다. 즉 다음과 같다. var a = undefined ; var b = undefined ; 때문에 값이 정의되지 않은 변수 === 값이 undefined로 정의된 변수 라고 보아도 무방하다. 이를 let 으로 선언했을 경우 스코프의 영향을 받고, 스코프 밖에서 사용하려 하면 ReferenceError 를 발생시킨다. 선언되지 않은 변수 선언되지 않은 변수 는 위 내용에 이어서 생각하면 편하다. 아예 선언조차 되지 않은 변수, 즉 현재 스코프(글로벌 포함)에 아예 해당 변수 이름이 정의되지 않은, 콜 스택에 변수 참조가 없는 상태를 발한다. 즉 이는 변수조차 아니다. 그렇다면 어떤 경우에 이런 상황을 마주하게 될까? 사실, 일반적인 개발 상황에서 마주하기 쉬운 상태는 아니다. 그러나 나는 브라우저 확장 프로그램을 개발하려다가 이와 같은 상황을 마주치게 되었다. content-script, background-script 어느 한 싱글톤 클래스의 메서드가 호출되었을 때, 호출한 당사자가 콘텐츠 스크립트인지 백그라운드 스크립트인지를 판별하려는 상황에서 이러한 문제가...

타입스크립트에서 이벤트 처리기 구현하기

타입스크립트에서 이벤트 처리기 구현하기 이벤트 처리 C#을 할 땐 이벤트 처리가 굉장히 간편했다. 언어 자체에서 event-driven 방식을 지원하기 때문이다. 자바스크립트(및 타입스크립트)를 처음 접했을 땐 당연히 자바스크립트에서도 이런 방식으로 손쉽게 이벤트 처리를 할 수 있을 줄 알았다. 그도 그럴 것이 NodeJS가 출시되지도 않았던 시절에 자바스크립트 하면 프론트엔드 개발에서 접할 수밖에 없었고, element.addEventListener 와 같은 메서드가 기본적으로 제공되었기 때문이다. 그러나 이런 추측은 반은 맞고 반은 틀렸다. NodeJS 이끌어가는 현 시대 자바스크립트 생태계에서 EventEmitter 클래스를 상속하여 손쉽게 이벤트 기반 클래스를 작성할 수 있기는 하다. 마찬가지로, 브라우저 단에서도 DOM 기반 클래스를 상속하면 대게 이벤트 처리가 가능하다. 여기까지 반이 맞고. 사용자 정의 프론트엔드 클래스에서 이벤트 핸들링 웹팩 이나 Vite 등을 사용해 번들링된 프론트엔드 코드가 있다고 치자. 물론, 바닐라 코드여도 마찬가지다. 아무튼 프론트엔드에서 특정 용도로 제작한 어떠한 클래스가 이벤트 기반으로 동작하게 하려면 어떻게 해야 할까? 여기가 반이 틀린 부분이다. 이런 경우에는 직접 EventEmitter 클래스를 제작하여 사용해야 한다. addEventListener , on , off , emit 등을 사용할 수 있게 만들기 위해 다음과 같은 코드를 짜서 상속해야 한다. export type IDisposable = { dispose ( ) : void ; } ; export type IListener < TEvent > = ( event : TEvent ) => void ; export type IEventEmitter < TEvent > = { emit : < TKey extends...

PostgreSQL에서 databse does not exists 메세지

PostgreSQL에서 databse <user> does not exists 메세지 failed: FATAL: database “<user>” does not exist 오늘 뜬금없이 잘 되던 개발 서버가 에러를 뿜길래 디버그해보니 유저가 존재하지 않는다는 메세지가 출력되고 있었다. 문제는 DB를 건드린 적이 없다는 것이다. 따라서 ASP.NET의 로그 메세지를 보기보다는 직접 DB에 접속해보고자 DataGrip으로 연결을 시도했으나, 여기서도 마찬가지로 에러 메세지가 발생했다. 마지막으로 도커 컨테이너 터미널에서 psql -Uuser -W 로 접속을 시도했으나, 비밀번호 입력 창까지는 뜨고 입력을 완료하면 다음과 같은 에러 메세지가 출력됐다. psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "user" does not exist 음. 갑자기 식은땀이 흐르기 시작했다. 왜 갑자기 멀쩡한 DB가 날아갔는가 일단 원인 파악부터 해봤다. 가장 최근에 DB에 영향을 미칠 만한 짓을 했었던가… 아! DB에 영향을 끼칠 만한 짓은 안 했지만, DB 컨테이너에 영향을 끼칠 만한 짓은 했었다. 용량을 확보하겠다고 Docker Desktop 의 Disk Usage 확장 기능에서 미사용중인 데이터를 날렸는데, 여기서 사용되지 않는 볼륨도 날렸었다. 아니 근데, 분명 어디에서도 사용되지 않는 볼륨을 날린다고 써져있던 것 같은데 도대체 왜? 설마 하니 DISKPART COMPACT VDISK때문은 아닐 것이고… 가장 가능성 높은 것은 역시 사용되지 않는 볼륨을 날린 것이다. 여기까지 생각이 들고 나니 흐르던 식은땀이 오한으로 바뀌어가는 기분이었다. 설마 DB도 날아갔나 싶은 생각이 들었기 때문이다. 하지만 결론부터 말하자면, 다...

브라우저에서 사용할 간단한 로거 만들기

이미지
브라우저에서 사용할 간단한 로거 만들기 로깅 개발 단계에서든 프로덕션 단계에서든 로깅은 필수다. 각 단계마다 로그에 포함되는 정보의 차이는 있을지라도 로깅 기능이 없는 프로그램은 개인적으로 제대로 된 프로그램이 아니라고 생각한다. 디스코드의 로그 개발 단계에서는 더 상세한 로그를 작성하게 하여 번거롭게 브레이크포인트를 걸지 않고서 간단한 로직들이 제대로 돌아가는 중인지 확인할 수 있고, 프로덕션 단계에서는 문제가 발생할 경우 개발자가 사용자의 로그를 보고 어떤 문제가 어떻게 발생한 것인지 분석하는 데 사용할 수 있다. 로깅 라이브러리 이러한 로깅의 중요성 덕분에 언어를 막론하고 다양한 로깅 라이브러리가 꾸준히 업데이트되고 있다. C#에서는 NLog를, Java에서는 log4j를 사용했었는데, 이제는 NodeJS용 라이브러리를 찾아야만 했다. 검색하니 나오는 것들이 몇 개 있었는데, 그 중 Winston 라이브러리가 좋아 보여서 사용하려 했다. 그러나 실행해보니 process is undefined 관련 예외를 쓰로우하면서 정상적으로 작동하지 않았다. 설마 하는 마음에 이슈를 뒤져보니 윈스턴은 공식적으로 브라우저 로깅을 지원하지 않는다고 한다. 굳이 라이브러리를 써야 하나? 그러던 중 문득 의문이 들었다. 어차피 지금 하려는 작업은 로그를 DB에 전송하는 등의 복잡한 단계가 필요 없는 작업이다. 그냥 브라우저 콘솔에 디스코드마냥 로그를 출력해주면 되는 일이다. 단, 확장 프로그램에서 사용하는 로깅이기 때문에 콘텐츠 스크립트에서 로그를 작성할 경우 사이트 자체의 로그와 겹치지 않게 적절한 레이블을 출력해주면 된다. 이런 간단한 로거를 사용하자고 라이브러리를 추가해 사용하는 것은 낭비라는 생각이 뒤늦게 들었다. 직접 구현 그리고 나서 생각해 보니 구현에 시간이 그렇게 많이 들 것 같지 않았다. 예전이었다면 패키지를 찾기 전에 구현할 생각부터 했을 텐데 시간에 쫓기다 보니 패키지를 먼...

react-toastify 사용 시 토스트가 끝날 때에 맞춰 코드를 실행하는 방법

이미지
react-toastify 사용 시 토스트가 끝날 때에 맞춰 코드를 실행하는 방법 토스트 알림 웹 페이지에서 전통적인 메세지 표시 방법은 역시 alert , confirm , prompt 이다. 2000년대 초반, 중반, 심지어 2010년대에 들어서도 가끔씩 prompt 를 사용해 입력 값을 받아오는 사이트를 볼 수 있었다. 1 허나 alert , confirm 은 2000년대 말 들어서 서서히 사라지다가, 어느 순간 메이저 사이트는 물론 어지간한 일반 사이트들에서도 사라졌다. 물론 아직도 일부 사이트, 특히 보안 프로그램을 가장한 스파이웨어를 심어대는 국내 사이트들에서는 보이기도 하지만 아무튼 예전에 비해서는 압도적으로 많이 사라진 상태이다. 토스트? 처음 이 용어를 들었을 때 떠오른 것은 당연하게도 음식 토스트였다. 토스터기를 아주 어렸을 때 빼고는 사용한 적이 없던 나는 곧바로 용어의 어원을 유추하기가 힘들었다. 위 문단에서 알 수 있듯, 토스트 메세지의 토스트는 말 그대로 토스트를 의미한다. 정확히는 토스터기에서 튀어 올라오는 토스트 이다. 나는 이런 형식의 알림을 웹이 아닌 안드로이드 스마트폰에서 처음 접했다. 화면 아래에서 페이드 인/슬라이드 되며 튀어올라오는 메세지. 이게 바로 토스트 메세지였던 것이다. 물론 꼭 아래에서 튀어올라오라는 법은 없다. 지금 와서는 스크린 가장자리 또는 외부에서 나타나는 알림 메세지를 전부 토스트 메세지라고 퉁치는 것 같다. react-toastify 이러한 토스트 메세지를 리액트에서 손쉽게 구현할 수 있도록 해주는 라이브러리가 바로 react-toastify 이다. <ToastContainer {...} /> 를 토스트를 출력해야 하는 컴포넌트 2 에 선언하고 원할 때마다 toast(), toast.info(), toast.promise, toast.error, ... 메서드를 호출하여 컨테이너의 설정에 따라 토스트 메세지를 화면에 출력할 수 있다. ...

MUI와 Tailwind CSS를 같이 사용할 때 TextField의 아웃라인 문제

MUI와 Tailwind CSS를 같이 사용할 때 TextField의 아웃라인 문제 MUI, Tailwind CSS MUI 도 Tailwind CSS 도 UI 스타일을 간편하게 작성할 수 있도록 도와주는 좋은 라이브러리들이다. MUI는 구글의 Material Design 을 리액트 기반 프론트엔드에서 손쉽게 적용할 수 있도록 도와주고, Tailwind CSS는 flex , p-auto 등 미리 정의된 1 클래스들을 가지고 순식간에 여러 컴포넌트들을 유연하게 작성할 수 있게 도와준다. 하나씩 쓰면 문제가 없는데 각각 모두 굉장히 유용한 라이브러리이다. 쓰는 것과 쓰지 않는 것의 개발 속도 차이가 어마어마하게 날 정도로 말이다. 문제는, 이것도 유용하고 저것도 유용해서 둘 다 한번에 쓰려고 할 때 생겼다. MUI의 TextField 컴포넌트 우선 말하자면, 방금 전까지 이게 두 라이브러리를 동시에 사용해서 생긴 문제라는 사실 자체를 인지하지 못했다. 그 문제는 다음과 같다. 일단, 어느 순간부터 MUI의 TextField 컴포넌트의 outlined variant가 :focus 되었을 때 크롬의 기본 유저 에이전트 스타일인 파란색 아웃라인이 보이기 시작했다. 처음 이 증상이 생겼을 때는 UI가 문제가 아니라 일단 전체적인 로직 흐름이 더 중요해서 무시했는데 이제는 앱의 윤곽이 잡혀과는 단계라 눈에 밟히게 되었다. 다행히도, 지금까지 이것 저것 리액트 기반 라이브러리들을 사용해오면서 스치듯 지나친 여러 문서들 중에 MUI와 Tailwind CSS를 동시에 쓰면 문제가 생긴다 는 글을 본 기억이 얼핏 나게 되었다. 해당 글 들 은 한국 문서였고, 어떤 사람은 MUI를 프로젝트에서 빼서 해결했다 하고, 어떤 사람은 Tailwind CSS를 프로젝트에서 빼서 해결했다고 했다. 하지만 난 도대체가 이해가 안 됐다. 두 라이브러리는 이미 유명해질대로 유명해진 라이브러리들이고, 나온지도 오래 되었는데 절대로 호환성이 없...