7월, 2023의 게시물 표시

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

타입스크립트에서 이벤트 처리기 구현하기 이벤트 처리 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도 날아갔나 싶은 생각이 들었기 때문이다. 하지만 결론부터 말하자면, 다

WSL, Docker Desktop 관련 Distro의 크기 줄이기

WSL, Docker Desktop 관련 Distro의 크기 줄이기 1테라도 부족해 지금도 가난하지만 더 가난했던 어린 시절, 컴퓨터는 무조건 중고였던 때에는 40GB, 20GB, 심지어 4GB 하드 디스크를 사용했던 적도 있다. 특히 4GB짜리를 사용할 때엔 초등학교 4학년이었는데, 당시 재밌게 즐겼던 워록 이라는 FPS 게임을 설치하기 위해 크레이지 아케이드 , 서든어택 을 지우고 시스템 드라이브에서 필요 없다고 판단되는 폴더들을 최대한 지운 뒤 1 당시 시골 깡촌에서 ADSL 회선의 느려터진 초당 120KBps로 600MB 가까이 되는 워록 설치 파일을 받고, 또 그걸 설치하고 실행하고 하는 생 쇼를 했었다. 시간이 지나 현재 1테라 NVMe SSD 3개, 512GB SSD 한 개, 2테라 하드디스크 한 개를 합해 총 5.5TB를 굴리고 있는 입장에서 보면 말도 안 되는 짓거리이긴 하나, 4GB 하드를 사용한 기간은 길지 않았고 어차피 게임 한두개에 어도비 플래시 MX 또는 8, 포토샵, Visual Studio 2008을 설치하기만 했으면 됐기에 큰 문제는 아니었다. 그러나 이제는 문제가 된다. 5.5TB도 부족하기 때문이다. 심지어 어디 한 곳에 쏠려 있으면 분산이라도 시키겠는데, 용도별로 딱 딱 정리된 상태가 이렇다. 각 디스크에 많아야 200GB 여유가 있고, 평균 100GB정도 여유가 있다. 용량이 왜 이리 부족할까 근 10년간 쌓인 용량이기에 한 번은 도대체 뭐가 들어있어서 이렇게 용량이 부족할까 하여 TreeSize 툴로 분석을 해봤다. 당시 C드라이브는 일단 Visual Studio 2019 가 100기가바이트를 넘게 차지했고, Adobe, Cocos, Unity, Unreal, … 등과 NuGet package cache , ReSharper cache , WSL Ubuntu distro , Docker Distro , … 아무튼 많았다. 다른 드라이브는 주로 개발에 필요한 라이브러리들,

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

이미지
브라우저에서 사용할 간단한 로거 만들기 로깅 개발 단계에서든 프로덕션 단계에서든 로깅은 필수다. 각 단계마다 로그에 포함되는 정보의 차이는 있을지라도 로깅 기능이 없는 프로그램은 개인적으로 제대로 된 프로그램이 아니라고 생각한다. 디스코드의 로그 개발 단계에서는 더 상세한 로그를 작성하게 하여 번거롭게 브레이크포인트를 걸지 않고서 간단한 로직들이 제대로 돌아가는 중인지 확인할 수 있고, 프로덕션 단계에서는 문제가 발생할 경우 개발자가 사용자의 로그를 보고 어떤 문제가 어떻게 발생한 것인지 분석하는 데 사용할 수 있다. 로깅 라이브러리 이러한 로깅의 중요성 덕분에 언어를 막론하고 다양한 로깅 라이브러리가 꾸준히 업데이트되고 있다. 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를 프로젝트에서 빼서 해결했다고 했다. 하지만 난 도대체가 이해가 안 됐다. 두 라이브러리는 이미 유명해질대로 유명해진 라이브러리들이고, 나온지도 오래 되었는데 절대로 호환성이 없

개발 단계에서 리액트 컴포넌트가 두 번 렌더링 되는 이유

개발 단계에서 리액트 컴포넌트가 두 번 렌더링 되는 이유 분명 empty array([])를 전달했는데 왜 두 번 렌더링되나 리액트를 처음 접했을 땐 클래스형 컴포넌트를 작성해서 사용했었으나, 함수형 컴포넌트의 엄청난 편리함을 알아차린 뒤로는 쭉 함수형 컴포넌트를 사용해오고 있다. 클래스형 컴포넌트에서 componentDidMount 에 해당하는 역할을 하는 함수형 컴포넌트의 훅은 useEffect 의 두 번째 인자에 [] 를 넘겨주면 된다. useEffect ( ( ) => { // do something... console . log ( "Hello, world!" ) ; } , [ ] ) ; 문제는, Hello, world! 가 두 번 출력된다는 것이었다. React.StrictMode 컴포넌트 결론부터 말하면, 원인은 React.StrictMode 컴포넌트였다. 공식 문서 를 보면, 적용된 컴포넌트가 남는 시간에 재 렌더링 된다는 내용이 있다. 뿐만 아니라, 각종 이펙트 역시 다시 호출된다고 한다. 해당 컴포넌트의 조상 중 React.StrictMode 가 적용된 부분을 제거하니 정상적으로 Hello, world! 가 한 번만 출력되는 것을 확인할 수 있었다. 공식 문서는 항상 꼼꼼히 챙겨보자 난 시간이 촉박한 경우가 아니라면 코드를 완전히 똑같이 베끼게 되더라도 복사/붙여넣기 하지 않고 손으로 베껴 쓰는 편이다. 이번 경우도 마찬가지로, StrictMode 가 적용된 컴포넌트를 구현할 때 참조한 소스 코드를 베끼는 과정에서 도대체 이 StrictMode 가 뭘까? 하며 공식 문서를 본 기억이 있다. 언제나 하는 실수를 또 반복했던 나. 또 한 번 제대로 읽지 않아서 일을 두 번 하게 되었다. 심지어 저 공식 문서 링크의 내용이 아직도 기억에 남아있다. 다만, 제대로 읽지 않았기에 구글링해서 스택오버플로우의 답변을 볼 때까지 생각이 나지 않았을 뿐

서로 다른 크기의 모니터 사이를 마우스가 쉽게 이동하는 경우

이미지
서로 다른 크기의 모니터 사이를 마우스가 쉽게 이동하는 경우 윈도우 업데이트 이것도 언제부터 생긴 기능인지 모르겠지만 바로 이전의 Print Screen 키의 기능 변경 과 같이 조용히 바뀐 것으로 추정된다. 하여간 윈도우 업데이트에 중요한 변경 사항이 있으면 팝업으로 알려주든 했으면 좋겠다. 서로 다른 해상도의 모니터 사이를 마우스가 쉽게 이동하는 현상 글로 쓰자니 와닿지 않는 느낌이 있는데, 서로 다른 해상도의 2개 이상의 모니터를 쓰는 사람이라면 쉽게 이해할 수 있을 것이다. 내 모니터는 주 모니터가 2K, 보조 모니터가 FHD 해상도를 가지고 있으며 실물 크기도 27인치와 22인치인지 23인치인지 아무튼 한 쪽이 크고 한 쪽이 작다. 또한 주 모니터는 모니터 암을 사용해 목 디스크 예방 차원에서 높게 달아놨고, 보조 모니터는 그보다는 아래에 놓여있다. 따라서 다음과 같은 형태가 된다. 모니터 배치 주 모니터의 우측 상단은 허공이고, 보조 모니터의 좌측 하단 역시 허공이다. 오직 겹치는 부분만 자연스럽게 이어져서 보이게 된다. 문제는 이번에도 역시 언제부터인진 모르겠으나 마우스를 주 모니터의 우측 상단으로 이동하면 보조 모니터의 좌측 상단에서 나타나고, 역으로 보조 모니터의 좌측 하단으로 이동해도 주 모니터의 우측 중간에서 나오는 현상이 생겼다는 것이다. 더 짜증나는 점은 애초에 주 모니터의 우측 상단에서 작업하기 위해 마우스를 움직였기 때문에 보조 모니터로 넘어간 마우스를 확인하고 다시 주 모니터의 우측 상단으로 이동하려고 마우스를 주 모니터 쪽으로 움직이면 주 모니터의 중간 상단 지점에서 나온다는 것이다. 즉 다른 모니터로 넘어갈 때는 테두리를 무시하지만, 돌아올 때는 가능한 부분으로만 돌아온다는 것. 일관성이 없다. 해결 방법 일주일 정도는 그냥 무시하고 쓰다가, 오늘은 피곤해서 그런지 주 모니터의 우상단에서 보조 모니터의 좌상단으로, 다시 보조 모니터의 좌상단에서 주 모

윈도우 11 7월 11일 업데이트(KB5028185) 스크린샷 기능

이미지
윈도우 11 7월 11일 업데이트(KB5028185) 스크린샷 기능 KB5028185 업데이트 이후 몇 가지 새로운 기능이 추가됐다. 그 중 자주 쓰는 스크린샷 기능에 변화가 생겼다. 스크린샷 윈도우 8부터인지 10부터인지는 정확히 기억이 나지 않으나 Win + Shift + S 키를 누르면 캡쳐 도구가 열리는 기능이 추가되었었다. 이 캡쳐 도구는 기존에 여러 외부 프로그램을 이용해야만 했던 캡쳐 기능을 윈도우에 내장시킨 느낌이다. 캡쳐 도구 지금까지는 PowerToys 와 같은 기본 단축키 변경 프로그램을 사용하지 않으면 위 단축키를 눌러야만 캡쳐 도구를 사용할 수 있었는데, 이번 업데이트로 Prt Scr 키가 캡쳐 도구를 여는 기본값이 되었다. 복원 대다수의 유저는 이번 업데이트에 만족하며 사용할 것 같지만, 나는 아니다. 나는 애초에 예전부터 캡쳐 도구와 프린트 스크린 키를 별개로 사용해왔기 때문에 이번 업데이트가 불편하다. 다행히 이 기능은 설정 - 접근성 - 키보드 에서 끌 수 있다.

Next.js 13 App Router Client Component에서 Loading Convnetion 사용하기

Next.js 13 App Router Client Component에서 Loading Convnetion 사용하기 Loading convention Next.js 13 app router (또는 app dir )의 loading convention을 사용하려 했다. 그러나 MUI를 사용하기 위해서 page 는 클라이언트 컴포넌트가 되어야만 했다. 공식 문서 를 보니, 예제들은 전부 서버 컴포넌트를 기준으로 하는 것 같았다. 다행히 React Suspense 기반이라는 내용이 친절하게 잘 적혀있어서 이를 바탕으로 해결 방법을 모색해 보았다. React Suspense 리액트 서스펜스는 <Suspense> 컴포넌트를 사용하여 해당 컴포넌트의 children 들은 <Suspense> 컴포넌트의 부모 컴포넌트에 필요한 리소스가 로드되기 전까지 fallback 프롭에 지정된 ReactNode 를 렌더링하게 해준다. 따라서 서스펜스 컴포넌트를 사용한다면 useEffect 에서 이것 저것 리소스 로딩 로직을 잔뜩 짜고, 이를 useState 를 사용해 핸들링하고, 이걸 또 렌더링 부분에서 조건문(주로 삼항 연산자)을 사용해 렌더할 필요 없이 선언적으로 코딩할 수 있다. 도대체 어떻게 리소스가 로딩중이란 걸 알 수 있나 <Suspense> 컴포넌트(이하 서스펜스 컴포넌트)의 children에서 throw된 내용을 기반으로 로딩중인지, 완료되었는지, 아니면 에러가 발생했는지 구분한다고 한다. “pending” 상태인 Promise가 throw됐다면 로딩 중. fallback 프로퍼티의 ReactNode 렌더. Error가 throw됐다면 일반적인 에러 핸들링 로직대로 처리. 즉 throw. 둘 다 아니라면 로딩 완료로 간주, fallback 대신 children 을 렌더. Next.js 13 App Router의 Client Component에서 로딩 상태 구현 앞서

Chrome DevTools Network 탭의 엄청난 렉

이미지
Chrome DevTools Network 탭의 엄청난 렉 확장 프로그램 개발하랴 웹 사이트 개발하랴 API 테스트하랴 올해들어 크롬이 가장 바쁘게 일하고 있다. 당연히 DevTools도 재보지는 않았지만 한 시간에 수백번은 열고 닫는 것 같은데 사실 이렇게 많이 열고 닫을 일은 아니다. 한 번 열어놓고 앵간하면 닫을 일이 없으니까… 하다 못해 외부 사이트에서 열더라도 닫는 건 내가 닫을 일이 없다. 탭을 닫으면 닫히니까. 그럼 왜 이렇게 많이 닫게 됐나? Network 탭의 미친듯한 렉 그 이유는 바로 Network 탭의 미친듯한 렉에 있다. 어느 버전부터 이런 증상이 생긴 것인지는 모르겠지만, 요청이 100개 정도 쌓이면 도저히 사용할 수 없을 정도의 버벅임이 발생한다. 문제는 Network 탭에서만 발생 한다는 것이다. 콘솔에 수백만 줄이 올라가도, 수천 줄짜리 소스를 리포맷해도 이런 문제는 발생하지 않는다. 1 원인 파악 비슷한 사례가 없나 구글링을 해보니 넘쳐나고 있었다. 그 중 한 글에서는 chrome://flags 에서 Force color profile 을 sRGB 로 바꿔보라는 내용도 있었는데, 댓글을 보면 효과를 본 사람이 있는 것 같았지만 일단 나는 아니었다. 그 밑에는 확장 프로그램 관련 문제일 수 있으니 React Developer Tools, Firebug, Omnibug, ... 등을 비활성화 해보라고 하길래 아예 devtools 기능이 있는 모든 확장프로그램을 비활성화 했다가, 전부 다 비활성화 했다가, 별 지랄을 다 해봤으나 증상은 동일했다. 시간은 흘러가고, 일단 파이어폭스로 작업을 하다가 문득 생각이 들었다. 이게 정말 크롬 업데이트 이후로 생긴 문제일까? 결론부터 말하자면, 반은 맞고 반은 틀렸다. Overview 기능 왜 반만 맞고 반만 틀리냐면, 언젠가 업데이트 된 기능 때문이긴 하니까. 문제는 얼마나 오래전에 추가된 기능인지 알 수가 없다. 즉, 얼마 전에 업데이

Docker WSL2에서 gitlab 컨테이너 사용 중 dev shm 용량 문제 발생

Docker WSL2에서 gitlab 컨테이너 사용 중 dev shm 용량 문제 발생 Docker/WSL2, GitLab Container 내 OS는 Windows 11 22H2이다. 윈도우 10 시절부터 Docker for Windows를 사용해왔고, WSL2가 나왔을 때 굉장한 성능 향상에 반해 바로 Hyper-V 기반에서 WSL2 기반으로 갈아탄 뒤 지금까지 쭉 써오고 있다. GitLab 컨테이너는 GitLab 을 직접 호스트할 수 있게 해주는 컨테이너이다. 깃랩은 깃헙처럼 자체 웹 사이트도 존재하지만 필요한 사람은 Self-hosted 인스턴스를 구축해 사용할 수 있는데, 리눅스에 직접 설치할 수도 있고 도커에 설치할 수도 있다. 나는 WSL에 직접 설치하려 했었으나 여러 이유로 실패하고 1 , 잠깐 다녔던 회사의 방식처럼 NAS를 하나 구비해서 쓸까 하다가 돈 낭비라는 생각이 들어 최종적으로 도커 컨테이너 방식에 안착했다. 로그 스팸, 접속 불안정 그렇게 몇 년간 잘 쓰다가 며칠 전 부터 갑자기 때때로 내 깃랩 사이트에 접속할 수 없는 문제가 발생했다. 특이 사항으로는 처음 하룻동안은 아예 예고없이 Docker for Windows 자체가 크래시 됐었다. 2 위 문제를 해결하는 과정에서 깃랩 컨테이너 뿐 아니라 Docker for Windows 자체를 재시작했고, 이 때문인지 그 날은 문제 없이 잘 사용했다. 엄청나게 많은 WARN/DEBUG 로그 스팸 그러던 중 오늘 다시 비슷한 증상이 발생했다. 이번엔 Docker for Windows가 꺼지거나 하진 않았으나, 사이트에 여러 문제가 발생했다. 일단 어떤 페이지이든지 한 번에 들어가지는 법이 없었다. 응답이 느린 것은 아니지만, 500 에러나 422 에러 등 여러 에러 페이지가 반복해서 출력되었고, 혹시나 하는 마음에 Push/Pull을 해봤으나 역시나 5번 시도해야 한 번 성공할까 말까 하는 수준이었다. 뭔가 문제가 있다고 생각한 나는 컨테이너

SemaphoreSlim을 사용해 동시 병렬 처리 개수 제한

SemaphoreSlim을 사용해 동시 병렬 처리 개수 제한 병렬 처리 병렬 처리는 잘 쓰면 굉장한 성능 이점을 가져올 수 있지만, 잘못 쓰면 오히려 굉장한 성능 하락을 가져온다. 병목 현상이고 뭐고 멀리 갈 것도 없이 다음과 같은 경우에는 확실하게 성능이 저하된다. A 로직이 실행되는 데에 시스템 리소스의 10%가 필요함. 한 번에 20개의 A 로직 병렬 실행 이런 경우에는 한 번에 처리할 수 있는 병렬 처리 작업의 최대치를 정해야 한다. Parallel.ForEachAsync Parallel.ForEach 는 완료를 대기하지 않으므로 .NET 6 이상이라면 Parallel.ForEachAsync 를 사용해 다음과 같이 구성할 수 있다. var rnd = new Random ( ) ; var voList = Enumerable . Range ( 0 , 99 ) . ToList ( ) ; await Parallel . ForEachAsync ( voList , new ParallelOptions { MaxDegreeOfParallelism = 10 } , async ( i , token ) = > { await Task . Delay ( rnd . Next ( 200 , 1200 ) ) . ConfigureAwait ( false ) ; Console . WriteLine ( $ "{DateTime.Now:HH:mm:ss.fff}: Finished work: {i:#,##0}" ) ; } ) . Con

ASP.NET 7에서 두 개 이상의 Path 기준 라우트하기. Path 기반 라우팅의 주의점.

Welcome file Routing ASP.NET 7을 사용해 API 프로젝트를 개발 중인데, OAuth를 처리하기 위해 Path의 두 부분이 동적으로 변하는 URL에 대해 라우팅이 필요해졌다. 예를 들어 다음과 같다. /api/auth/signin/google /api/auth/signout/google /api/auth/signin/naver /api/auth/signout/naver ... 공식 문서에 따라 다음과 같이 라우트하려 했지만 404 에러가 발생했다. [ AllowAnonymous ] [ HttpPost ( "{action}/{provider}" ) ] pubilc IActionResult HandleAuthRequest ( string action , string provider ) { // ... } 하지만 다음과 같이 하니 작동하더라. [ AllowAnonymous ] [ HttpPost ] [ Route ( "signin/{provider}" ) ] [ Route ( "signout/{provider}" ) ] public IActionResult HandleAuthRequest ( string provider ) { var isSignIn = Request . Path . Value ? . Contains ( "signin" ) == true ; // ... } 문서는 항상 꼼꼼히 읽자 하지만 뭔가 이상했다. 구글링을 하는 동안 {param1}/{param2} 가 불가능하고 무조건 Path 라우트 패러미터는 한 개여야만 한다는 글을 본 적이 없다는 것이 걸렸다. 그리고 가만히 생각해보니, 이 문제를 해결하고자 찾아보던 여러 페이지 중 MSDN 공식 문서에 MapControllerRoute 관련 내용이 떠올랐다. 대충 다음과 같은 형식의 코드를

Next.js 터보팩 + HTTPS 개발 서버 사용하기

Welcome file 기본값은 HTTP Next.js의 개발 서버 기본값은 HTTP이다. Turbopack을 사용하든 사용하지 않든 마찬가지. 리액트도 역시 HTTP이다. 그렇다면 도대체 어떻게 HTTPS를 사용해야 할까? 보안도 물론 엄청나게 중요하지만, 개발 측면에서 볼 때 HTTP 프로토콜을 사용하면 클립보드, CORS, 인증, …등등 다양한 HTTPS를 요구하는 기능을 사용하지 못하게 된다. server.js? 구글링에서 가장 먼저 찾은 것은 server.js를 사용해 Custom Server 를 만들라는 내용이었다. 문제는, 이렇게 되면 터보팩을 사용하는 의미가 사라진다. 터보팩을 사용하지 않는 사람들은 써볼만 한 옵션일지도? 구글에 관련 자료를 검색 하면 다양한 방법이 나오니 참고하길 바란다. local-ssl-proxy 내 경우에는 터보팩을 사용해야만 의미가 있는 상황이기에 더 깊게 구글링 하던 도중 local-ssl-proxy 라는 키워드를 찾았다. 알아보니 local-ssl-proxy(이하 프록시)가 소스 포트에서 동작하면서 타겟 포트로 들어온 트래픽을 HTTPS로 변환해주는 동작을 하는 것 같았다. 전문 분야가 아니라 설명이 이상해도 양해 바란다. 아무튼, npm -i -g local-ssl-proxy 명령어를 입력해 전역으로 프록시를 설치하고, 인증서는 기존에 사용하던 pem 들을 쓰려고 했으나 왜인지 bad decrypt 예외가 계속 발생했다. Passphrase 이유는 패스프레이즈 때문이었다. 해당 PEM 인증서는 패스프레이즈가 걸려있었는데 이걸 그만 깜빡한 것이다. 때문에 win-acme 를 사용하여 새 PEM을 만들고 이를 다음과 같이 적용하니 정상적으로 로컬 뿐 아니라 외부에서 역시 HTTPS로 잘 접속이 되는 것을 확인하였다. "scripts" : { ... "ssl-proxy" : "local-s