Outsider's Dev Storyhttps://blog.outsider.ne.kr/Stay Hungry. Stay Foolish. Don't Be Satisfied.2024-03-15T09:41:57+09:00Textcube 1.10.7 : Tempo primo기술 뉴스 #241 : 24-03-01Outsiderhttps://blog.outsider.ne.kr/17102024-03-01T22:41:05+09:002024-03-01T22:41:05+09:00<h1>웹개발 관련</h1>
<ul>
<li><strong><a href="https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024">React Labs: What We've Been Working On – February 2024</a></strong> : React에서 연구 개발 중인 프로젝트의 진행상황을 정리한 글이다.(영어)<br />
<br />
<ul>
<li>상태 변경으로 종종 너무 많은 렌더링이 일어나는 문제를 그동안 <code>useMemo</code>, <code>useCallback</code>, <code>memo</code> 등 수동 메모이제이션을 사용해서 해결해 왔다. 합리적인 타협점이지만 이 문제를 해결하기 위해 React를 위한 최적화 컴파일러를 구축하는 것이 React Compiler다. 그동안 리서치 프로젝트였지만 이미 instagram.com에서 사용 중이고 Meta에 더 적용한 후 첫 릴리스를 오픈소스로 공개하기 위해 준비 중이다.</li>
<li>Server Actions는 클라이언트에서 서버로 데이터를 보내는 방법으로 개발 중 이 API를 클라이언트에서만도 사용할 수 있도록 API를 확장해서 이러한 기능을 Actions라고 부르게 되었다.</li>
<li>이전에는 Meta 내부에서 개발하고 안정 버전만 공개되었는데 React Canary의 도입으로 개발 중인 새로운 기능도 커뮤니티에서 미리 확인할 수 있게 되었다. Directives, Document Metadata, Asset Loading, Actions 같은 기능도 모두 react.dev 문서에 추가되었다.</li>
<li>오랜 작업으로 릴리스할 준비가 되었고 Document Metadata, Asset Loading은 일부 앱에는 큰 변화가 되므로 다음 버전은 React 19가 될 예정이다.</li>
<li>화면에서 보이지 않는 부분에 적용되기 때문에 Offscreen라는 이름으로 개발 중이던 기능을 개발하면서 화면에 보이면서도 비활성 상태일 수 있다는 것을 알게 되어 이름을 Activity로 변경했다.</li>
</ul></li>
<li><strong><a href="https://tech.inflab.com/20240219-dynamic-og-image/">인프런 콘텐츠에 동적으로 생성되는 Open Graph(OG) 이미지 적용하기</a></strong> : 인프런에서 콘텐츠를 외부에 공유할 때 OG 이미지를 콘텐츠에 맞게 동적으로 생성해 주기 위해 작업한 결과를 정리한 글이다. Vercel이 만든 <code>og</code>를 사용하고 CDN을 연결해서 기능을 구현했지만, 서버 쪽 성능은 좋지 않았기에 <code>og</code> 라이브러리 대신 그 내부에서 사용하는 <code>satori</code>를 직접 사용하면서 병목이 되는 부분을 개선하고 <code>satori</code>에 성능 개선 제안도 하면서 최초 이미지 생성 성능을 35배나 개선했다.(한국어)</li>
<li><strong><a href="https://netflixtechblog.com/introducing-safetest-a-novel-approach-to-front-end-testing-37f9f88c152d">Introducing SafeTest: A Novel Approach to Front End Testing</a></strong> : Netflix에서 내부에 적용해서 사용하는 프론트엔드 테스트 프레임워크 <a href="https://github.com/kolodny/safetest">SafeTest</a>를 공개했다. 기존의 UI 테스트 프레임워크 중 react-testing 라이브러리 같은 단위테스트 도구는 렌더링 대상이나 임포트 등을 제어할 수 있지만 실제 페이지와 상호작용할 수 없게 되고 Cypress나 Playwright같은 통합테스트 도구는 페이지는 제어할 수 있지만 내부를 제어할 수가 없게 된다. 이러한 문제를 해결하기 위해 SafeTest를 만들게 되었고 지연 로딩을 활용해서 페이지에 테스트를 실행하는 코드를 동적으로 로딩하는 것이 주용 아이디어다. 이렇게 설정한 뒤에 Playwright를 사용해서 실행하므로 페이지를 테스트할 수 있으면서도 특정 함수나 컴포넌트를 오버라이딩해서 더 쉽게 테스트할 수 있다.(영어)</li>
<li><strong><a href="https://socket.dev/blog/jsr-new-javascript-package-registry">JSR: What We Know So Far About Deno’s New JavaScript Package Registry</a></strong> : <a href="https://jsr.io/">JSR</a>은 Deno 팀에서 만든 패키지 레지스트리로 Deno 팀에서는 npm을 고려했지만 Deno 환경과는 맞지 않는 부분이 있어서 ESModules가 도입된 상황에서 npm 레지스트리말고 새로운 개발자 경험을 줄 새로운 중앙 패키지 레지스트리를 구축할 필요가 있었다고 한다. 개발자들은 TypeScript를 제대로 지원을 하는 점에서 매력적이라는 의견도 있지만 반드시 모듈을 발행하려면 Deno를 써야하는 문제도 있고 생태계가 분열되는 것에 대한 걱정도 있다.(영어)</li>
<li><strong><a href="https://x.com/triblondon/status/1761852117579427975?s=20">If your website uses http://polyfill.io, remove it IMMEDIATELY</a></strong> : 브라우저 간 동작 차이를 채워주는 polyfill.js를 쉽게 사용할 수 있도록 <a href="http://hacks.mozilla.or.kr/2014/12/an-easier-way-of-using-polyfills/">pollyfill.io에서 서비스로 제공</a>하고 있었는데 이 polyfill.io를 운영하던 사람이 <a href="https://x.com/JakeDChampion/status/1761315228447277184?s=20">polyfill.io를 Funnull이라는 회사에 넘기기로 했다</a>. 이에 polyfill.io 서비스를 만들었던 사람이 공급망 공격을 걱정하며 이제는 polyfill 자체도 그리 필요 없으니 즉시 제거하라고 경고했다. 이에 <a href="https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk">Cloudflare는 자사의 CDN에서 이를 제공</a>한다고 빠르게 공지했다.(영어)<br />
<br></li>
</ul>
<h1>그 밖의 개발 관련</h1>
<ul>
<li><strong><a href="https://velog.io/@hakokim/React-Native-%EC%95%B1-%EC%A0%91%EA%B7%BC%EC%84%B1-%EC%A7%80%EC%9B%90-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0">React Native 앱 접근성 지원 시작하기</a></strong> : 뉴스레터 서비스인 <a href="https://www.newneek.co/">뉴닉</a>의 React Native 앱에서 접근성을 개선한 내용을 정리한 글이다. 다크모드를 지원하고 기능을 말로 설명해 주는 보이스오버나 톡백 기능을 구현하고 가로 모드 지원과 폰트 크기를 다양하게 지원할 수 있도록 개선했다. 스타트업에서 제품의 성장과 접근성 지원 간의 우선순위에 대해 고민이 많았지만, 접근성이 중요하다고 공감하는 사람이 많아서 할 수 있었다고 한다. 이렇게 접근성 개선을 노력하는 서비스를 응원한다.(한국어)</li>
<li><strong><a href="https://jvns.ca/blog/2024/02/16/popular-git-config-options/">Popular git config options</a></strong> : Git에서 설정하면 좋을 설정을 정리한 글이다. pull 할 때 어떻게 동작할지나 컨플릭트시 보여주는 방식, autosquash 설정이나 push할 브랜치 설정등 많은 사람들이 기본적으로 설정해서 사용하는 옵션들이 어떤 기능을 제공하는지를 정리해 두었다.(영어)</li>
<li><strong><a href="https://ductile.systems/zdiff3/">Better Git Conflicts with zdiff3</a></strong> : Git에서 컨플릭트가 발생했을 때 두 브랜치의 차이점이 파일에 표시되는데 설정에서 <code>diff3</code>를 사용하면 원래 어떻게 되었는지 3개의 차이를 모두 보여주어서 수정하기가 훨씬 쉬워진다. Git 2.35에서 추가된 <code>zdiff3</code>를 사용하면 공통 조상에서 충돌된 부분을 더 정확하게 잡아준다.(영어)<br />
<br></li>
</ul>
<h1>인프라 관련</h1>
<ul>
<li><strong><a href="https://tech.devsisters.com/posts/finding-and-fixing-cert-manager-bug/">세계 최초로 cert-manager 버그를 발견하고 해결하기</a></strong> : Let's Encrypt 인증서를 사용하던 중 연결에 문제가 생긴걸 발견하고 원인을 추적해서 해결한 과정이다. Let's Encrypt에는 지금은 만료된 <code>DST Root CA X3</code> 루트 인증서와 새로운 <code>ISRG Root X1</code> 루트 인증서가 있는데 설정에서 <code>ISRG Root X1</code>를 사용하게 했음에도 <code>DST Root CA X3</code>가 내려오는 상황이었다. Let's Encrypt가 Trust CA가 되기 전에 <code>DST Root CA X3</code>를 사용한 과거가 있고 이를 deprecte 한 뒤 <a href="https://github.com/cert-manager/cert-manager">cert-manager</a>에서 버그가 발생하는 조건이 충족되어 문제가 발생했다.(한국어)</li>
<li><strong><a href="https://tech.inflab.com/20240221-dora-metric-with-devlake/">개발-운영 생산성 모니터링하기 (with Devlake, Grafana)</a></strong> : 인프런에서 DORA의 생산성 매트릭인 배포 빈도, 변경 사항이 적용되는 시간, 변경 실패율, 서비스 복원 시간을 측정해서 가시화하기 위해 작업한 내용이다. 여러 도구를 검토 후 오픈소스인 Devlake를 이용해서 GitHub, Jenkins, Jira를 연동해서 데이터를 수집한 뒤에 MySQL에 저장하고 이 데이터를 Grafana에 데이터소스로 연결해서 대시보드를 통해서 빌드, PR, 커밋, 이슈 등의 통계를 한 번에 볼 수 있게 했다. 한눈에 현황을 파악할 수 있어서 상당히 좋아 보인다.(한국어)</li>
<li><strong><a href="https://sre.google/resources/practices-and-processes/product-focused-reliability-for-sre/">Product-Focused Reliability for SRE</a></strong> : 사이트 안정성 엔지니어(SRE)는 보통 서비스의 안정성을 책임지지만 이는 제품의 최종 사용자 경험에는 어느 정도 한계가 있다. 이를 개선하기 위해 Google의 SRE가 인프라와 서비스에 집중하는 대신 제품과 최종 사용자의 요구사항 지원에 집중해서 어떻게 해결했는지를 설명한 글이다. 이를 위해 엔지니어뿐 아니라 관리자와 디자이너 등 이해관계자의 참여를 유도하고 제품의 목적을 정의해서 우선순위를 정하고, 제품의 SLO를 측정하기 위해 클라이언트 SLO나 e2e SLO를 도입해서 제품의 SLO를 만들어서 이 신뢰성을 관리한다. 이 접근 방법은 SRE팀이 사용자와 비즈니스에서 가장 중요한 곳에 자원을 집중하게 만들어준다.(영어)</li>
<li><strong><a href="https://tech.inflab.com/20240227-finops-for-startup/">스타트업 엔지니어의 AWS 비용 최적화 경험기</a></strong> : 인프런이 AWS 비용을 최적화 하기 위해서 해온 활동을 정리한 글이다. 각 팀이 비용에 관심을 가지도록 분위기를 만들고 높은 비용부터 분석해서 개선해 나갔는데 스팟 인스턴스, CDN 등을 활용하고 같은 AZ내의 통신을 하도록 개선하고 일부 SaaS는 내부 설치형 도구로 바꾸면서 월간 3천만원 이상을 아낄 수 있었다고 한다.(한국어)</li>
<li><strong><a href="https://blog.cloudflare.com/pingora-open-source">Open sourcing Pingora: our Rust framework for building programmable network services</a></strong> : Cloudflare가 <a href="https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/">2022년 Nginx를 대체하기 위해</a> Rust로 작성한 HTTP 프록시 서버 Pingora를 오픈소스로 공개했다. Pingora는 HTTP/1, HPTT/2, gRPC, WebSocket 프록시를 지원하고 Pingora 기반으로 서비스를 구축할 수 있는 라이브러리와 API도 제공하고 있다.(영어)</li>
<li><strong><a href="https://thenewstack.io/freenginx-a-fork-of-nginx/">Freenginx: A Fork of Nginx</a></strong> : 웹서버인 Nginx의 핵심 개발자 중 한 명인 Maxim Dounin이 Nginx를 포크해서 <a href="https://freenginx.org/">freenginx</a>를 만든다고 <a href="https://mailman.nginx.org/pipermail/nginx-devel/2024-February/K5IC6VYO2PB7N4HRP2FUQIBIBCGP4WAU.html">발표</a>했다. Maxim Dounin는 원래 Nginx를 소유한 F5에서 일하다가 2022년 F5가 모스크바 사무실을 없앤 뒤로는 F5에서 일하진 않지만, 자원봉사자로 계속 일하기로 합의했다. 하지만 F5의 nginx에 너무 많이 관여하고 있고 F5내에서 이뤄지는 작업도 알 수 없기 때문에 nginx 개발에 더 이상 참여하지 않고 포크해서 freenginx에서 작업한다고 한다.(영어)</li>
<li><strong><a href="https://netflixtechblog.com/announcing-bpftop-streamlining-ebpf-performance-optimization-6a727c1ae2e5">Announcing bpftop: Streamlining eBPF performance optimization</a></strong> : Netflix가 eBPF 프로그램의 성능 최적화와 모니터링을 쉽게 할 수 있게 하는 <a href="https://github.com/Netflix/bpftop">bpftop</a> CLI를 오픈소스로 공개했다. bpftop으로 실행중인 eBPF 프로그램의 성능 통계를 실시간으로 볼 수 있고 bpftop을 사용 중일 때만 활성화되므로 오버헤드도 최소화하고 있다.(영어)</li>
<li><strong><a href="https://dagger.io/blog/introducing-dagger-functions">Introducing Dagger Functions</a></strong> : Dagger Functions 기능이 도입되어 원하는 언어로 기능을 구현하고 이를 다른 언어에서도 불러와서 사용할 수 있는 기능이 추가되었다. Dagger는 CI/CD를 위한 블록을 만들 수 있는 프로젝트라고 할 수 있는데 CUE에서 프로그래밍 언어로 바뀌면서 재사용면에서는 프로그래밍 언어의 제약이 생겼다고 생각했는데 Dagger Function을 이용해서 언어가 달라도 사용할 수 있게 되었다. 현재는 Go, Python, TypeScript의 가이드를 제공하는데 다른 언어의 가이드도 추가될 예정이다.(영어)<br />
<br></li>
</ul>
<h1>볼만한 링크</h1>
<ul>
<li><strong><a href="https://zed.dev/blog/we-have-to-start-over">We Have to Start Over: From Atom to Zed</a></strong> : Zed 에디터는 GitHub에서 Atom을 만들던 Nathan Sobo, Antonio Scandurra, Max Brunsfeld이 나와서 창업한 회사인데 이 세 명의 창업자와 인터뷰한 내용이 정리된 글이다. Zed의 비전은 Atom에서 가졌던 비전과 거의 비슷한데 Atom때는 당시 기술적 성숙도가 미치지 못했고 IDE처럼 강력하면서 확장성 있으면서도 가벼운 에디터를 만드는 것이 목표라고 한다. Atom을 만들기 위해 Electron을 만들고 VS Code가 훌륭하게 해냈지만, 이들은 더 많은 것을 원했고 Rust와 GUI 가속을 선택했고 UI 프레임워크인 GPUI 2를 만들어서 Zed를 만들기 위한 기술 스택을 모두 소유할 수 있게 되었다.(영어)<br />
<br></li>
</ul>
<h1>IT 업계 뉴스</h1>
<ul>
<li><strong><a href="https://www.theverge.com/2024/2/22/24079876/google-gemini-ai-photos-people-pause">Google pauses Gemini’s ability to generate AI images of people after diversity errors</a></strong> : Google이 Gemini의 이미지 생성 기능을 공개했는데 여기서 인물 이미지가 제대로 생성되지 않아서 해당 기능을 일시 중지했다. <a href="https://blog.google/products/gemini/gemini-image-generation-issue/">구글의 공지</a>에 따르면 이미지 생성 시 특정 인종에만 한정되지 않도록 하고 싶었지만 반대로 문화적, 역사적 배경이나 특정 인종을 요청하는 경우는 정확하게 생성되어야 하지만 제대로 동작하지 않았다고 한다. 그래서 1800년대 미국 상원의원 등의 이미지 요청에서 흑인과 원주민 여성의 이미지가 생성되어 실제 역사적 사실과 성차별의 역사를 오히려 지우는 문제가 발생했다.(영어)</li>
<li><strong><a href="https://blog.google/technology/developers/gemma-open-models/">Gemma: Introducing new state-of-the-art open models</a></strong> : Google이 Gemini 모델을 만든 것과 같은 기술과 연구로 만든 경량 오픈형 모델인 <a href="https://ai.google.dev/gemma">Gemma</a>를 공개했다. Gemma는 2B, 7B 2가지 크기를 제공하고 개발자 노트북 등에서 직접 실행할 수 있다.(영어)</li>
<li><strong><a href="https://stability.ai/news/stable-diffusion-3">Stable Diffusion 3</a></strong> : 텍스트-이미지 변환 모델인 Stable Diffusion 3의 프리뷰 버전이 발표되었다. 8억 ~ 80억개의 파라미터를 지원하고 대기자로 등록해야 사용해 볼 수 있다.(영어)<br />
<br></li>
</ul>
<h1>프로젝트</h1>
<ul>
<li><strong><a href="https://cursor.sh/">Cursor</a></strong> : 코드 자동완성이나 채팅 등 AI 기능에 초점을 맞춘 코드 에디터.</li>
<li><strong><a href="https://tempo.formkit.com/">Tempo</a></strong> : JavaScript 날짜/시간 라이브러리</li>
<li><strong><a href="https://github.com/loft-sh/devpod">DevPod</a></strong> : <code>devcontainer.json</code>를 이용해서 개발자 환경을 만들 수 있는 클라이언트 도구로 Codespaces의 오픈소스 버전이라고 생각할 수 있다.</li>
<li><strong><a href="https://github.com/mcollina/borp">Borp</a></strong> : Node.js 테스트 라이브러리인 <code>node:test</code>릐 위한 TypeScript 러너</li>
<li><strong><a href="https://github.com/zellij-org/zellij">Zellij</a></strong> : <a href="https://github.com/tmux/tmux">Tmux</a>와 같은 터미널 멀티플렉서로 <a href="https://github.com/zellij-org/zellij/discussions/1701">플로팅 윈도우 등 현대적인 기능</a>을 지원한다.</li>
<li><strong><a href="https://github.com/readysettech/readyset">readyset</a></strong> : Postgres와 MySQL을 위한 데이터베이스 캐시.</li>
<li><strong><a href="https://testcontainers.com/">Testcontainers</a></strong> : 테스트 목적으로 데이터베이스, 레디스 등을 컨테이너로 환경을 구성해 주는 프레임워크<br />
<br></li>
</ul>
<h1>버전 업데이트</h1>
<ul>
<li><strong><a href="https://redwoodjs.com/">RedwoodJS</a> v7.0.0</strong> : 풀스택 웹프레임워크, <a href="https://community.redwoodjs.com/t/redwood-v7-0-0-is-now-available/5777">릴리스 공지</a></li>
<li><strong><a href="http://git-scm.com/">Git</a> v2.44.0</strong> : 분산 형상관리 도구, <a href="https://github.blog/2024-02-23-highlights-from-git-2-44/">변경사항</a></li>
<li><strong><a href="https://grafana.com/oss/tempo/">Grafana Tempo</a> v2.4.0</strong> : 분산 트레이싱 백엔드, <a href="https://grafana.com/blog/2024/02/29/grafana-tempo-2.4-release-traceql-metrics-tiered-caching-and-tco-improvements/">릴리스 공지</a><br />
<br />
<ul>
<li>TraceQL에 실험적인 <a href="https://grafana.com/docs/tempo/latest/operations/traceql-metrics/">metrics</a> 기능 추가로 trace 쿼리 결과에 함수를 적용해서 trace 쿼리를 확장할 수 있게 됨.</li>
<li>vParquet3이 기본이 됨.</li>
</ul></li>
<li><strong><a href="https://vitest.dev/">Vitest</a> v1.3.0</strong> : Vite 유닛 테스트 프레임워크, <a href="https://github.com/vitest-dev/vitest/releases/tag/v1.3.0">릴리스 공지</a></li>
<li><strong><a href="https://panda-css.com/">panda</a> v0.33.0</strong> : CSS-in-JS, <a href="https://github.com/chakra-ui/panda/discussions/2274">릴리스 공지</a></li>
<li><strong><a href="https://kafka.apache.org/">Kafka</a> v3.7.0</strong> : 분산 이벤트 스트리밍 플랫폼, <a href="https://archive.apache.org/dist/kafka/3.7.0/RELEASE_NOTES.html">릴리스 공지</a></li>
<li><strong><a href="https://remix.run/">Remix</a> v2.8.0</strong> : 풀스택 웹 프레임워크, <a href="https://remix.run/docs/en/main/start/changelog#v280">릴리스 공지</a></li>
<li><strong><a href="https://jotai.org/">Jotai</a> v2.7.0</strong> : React 상태 관리 라이브러리, <a href="https://github.com/pmndrs/jotai/releases/tag/v2.7.0">릴리스 공지</a></li>
<li><strong><a href="https://babeljs.io/">Babel</a> v7.24.0</strong> : JavaScript 컴파일러, <a href="https://babeljs.io/blog/2024/02/28/7.24.0">릴리스 공지</a></li>
<li><strong><a href="http://electron.atom.io/">Electron</a> v29.0.0</strong> : 크로스 플랫폼 데스크톱 애플리케이션 플랫폼, <a href="https://www.electronjs.org/blog/electron-29-0">릴리스 공지</a></li>
<li><strong><a href="https://www.scala-lang.org/">Scala</a> 3.4.0</strong> : 프로그래밍 언어, <a href="https://www.scala-lang.org/blog/2024/02/29/scala-3.4.0-and-3.3.3-released.html">릴리스 공지</a></li>
<li><strong><a href="https://deno.land/">Deno</a> v1.41.0</strong> : TypeScript 런타임, <a href="https://deno.com/blog/v1.41">릴리스 공지</a></li>
<li><strong><a href="http://eslint.org/">ESLint</a> v8.57.0</strong> : JavaScript 코드 분석 도구, <a href="https://eslint.org/blog/2024/02/eslint-v8.57.0-released/">릴리스 공지</a></li>
<li><strong><a href="https://kargo.akuity.io/">Kargo</a> v0.4.0</strong> : Kubernetes용 배포 도구, <a href="https://akuity.io/blog/whats-new-kargo-0.4.0/">릴리스 공지</a></li>
<li><strong><a href="https://zed.dev/">Zed</a> v0.124.8</strong> : 코드 에디터, <a href="https://zed.dev/releases/stable#zed-0.124.8">릴리스 공지</a></li>
<li><strong><a href="https://parceljs.org/">Parcel</a> v2.12.0</strong> : 웹 애플리케이션 번들러, <a href="https://parceljs.org/blog/v2-12-0/">릴리스 공지</a></li>
<li><strong><a href="https://www.docker.com/products/docker-desktop">Docker Desktop</a> v4.28</strong> : 데스크톱용 Docker 애플리케이션, <a href="https://www.docker.com/blog/docker-desktop-4-28/">릴리스 공지</a></li>
<li><strong><a href="https://bevyengine.org/">Bevy</a> v0.13</strong> : Rust로 작성된 데이터 드리븐 게임 엔진, <a href="https://bevyengine.org/news/bevy-0-13/">릴리스 공지</a></li>
<li><strong><a href="https://www.selenium.dev/">Selenium</a> v4.18.0</strong> : 브라우저 자동화 프레임워크, <a href="https://www.selenium.dev/blog/2024/selenium-4-18-released/">릴리스 공지</a></li>
<li><strong><a href="https://www.prisma.io/">Prisma</a> v5.10.0</strong> : TypeScript/Node.js 데이터베이스 툴킷, <a href="https://github.com/prisma/prisma/releases/tag/5.10.0">릴리스 공지</a></li>
</ul>
<p><strong><a href="https://blog.outsider.ne.kr/1710?commentInput=true#entry1710WriteComment">댓글 쓰기</a></strong></p>44BITS 팟캐스트가 어느새 200회나 되었다.Outsiderhttps://blog.outsider.ne.kr/17092024-02-27T21:39:42+09:002024-02-27T21:39:42+09:00<p><a href="https://www.youtube.com/@44BITSTV">44BITS 팟캐스트</a>(<a href="https://podcast.44bits.io/">홈페이지</a>)는 첫 화부터 모든 에피소드를 들었을 정도로 나에게 꽤 애착이 있는 팟캐스트임에도 사이트가 따로 있고 거기서 에피소드가 발행되다 보니 문득 회고 등에서나 언급할 뿐 블로그에서 제대로 얘기한 적이 없다는 생각이 들었다.</p>
<p>지난주 방송으로 어느새 <a href="https://www.youtube.com/watch?v=n3jgpHUw8AY">200회</a>를 녹음했다. 200회면 매주 녹음한다고 해도 거의 4년이 걸리는 시간이라 새삼 '44BITS가 참 오래되었구나!' 하는 생각이 들었다.<br />
<br></p>
<h2>stdout.fm 팟캐스트</h2>
<p><a href="https://www.youtube.com/watch?v=n3jgpHUw8AY">200회</a> 방송에서도 얘기 나왔지만 44BITS 팟캐스트는 2018년에 10월에 <a href="https://twitter.com/stdoutfm">stdout.fm 팟캐스트</a>라는 이름으로 <a href="https://podcast.44bits.io/episodes/1">1화</a>를 시작했다. 이 팟캐스트는 <a href="https://twitter.com/seapy">seapy님</a> 주도로 <a href="https://twitter.com/nacyo_t">nacyot님</a>, <a href="https://twitter.com/raccoonyy">너굴님</a> 세 분이 시작했다.</p>
<p style="text-align: center;"><img src="//blog.outsider.ne.kr/attach/1/1589989830.jpg" width="282" height="282" alt="사용자 삽입 이미지" title="" /></p>
<p>Twitter나 커뮤니티 활동을 오래 하다 보니 꽤 친해진 사람도 언제 어디서 친해지게 되었는지 잊어먹은 경우가 꽤 많다. nacyot님과 너굴님은 stdout.fm이 시작되기 전에 같은 회사에 다니긴 했지만, 같이 일하기 전에도 이미 알고 있는 사이였다. 회사 같이 다니기 전에는 아마 오프라인에서는 한두 번 인사한 정도면서 트위터에서 많이 떠들던 사이지 않았나 싶다.(정확히 기억이 나지 않는다) Seapy님도 그전에 트위터에서 얘기 나눈 기록은 많이 있는데 어디서 알게 되었는지는 잘 기억나지 않는다. 창업한다고 퇴사하는 글을 본 기억이 있어서 친분은 꽤 있었던 거 같다.</p>
<p>그래서 자연스레 stdout.fm 팟캐스트가 시작할 때부터 알고 있었고 1화부터 듣기 시작했다. 당시에도 다들 YouTube를 사용하고 있었는데 Seapy님이 팟캐스트의 유행이 다시 올 거라고 했던 기억이 난다. 물론 실제로 팟캐스트 유행은 돌아왔다. 전 세계에서는 유행이 되었지만, 한국에서는 그렇지 않았을 뿐이다.</p>
<p>국내에서는 2011년 "나는 꼼수다"가 등장하면서 팟캐스트가 인기를 끌었지만 나는 2009년 정도부터 팟캐스트를 들었는데 그때부터 지금까지 팟캐스트란 매체를 좋아하는 편이다. 그래서 stdout.fm이라는 한국어로 하는 기술 팟캐스트가 생겼다는 게 꽤 반가웠고 그래서 1화부터 열심히 들었다. 팟캐스트 앱은 내 아이폰에서 중요한 앱 중 하나였기에 구독만 하나 추가하면 쉽게 들을 수 있었다.</p>
<p>시작하는 사람들이 다 알고 있던 사람이었다 보니 아주 초반인 <a href="https://podcast.44bits.io/episodes/3">3화부터 게스트로 출연</a>해서 해외 콘퍼런스에 갔다 왔던 경험을 얘기하기도 했다. 큰 준비 없이 수다 떨듯이 나와서 꽤 재미있었던 걸로 기억한다. 진행자들하고 친분이 있고 나도 뉴스레터를 계속 발행하고 있다 보니 이슈가 있을 때마다 게스트로 참석해서 같이 떠들었다. 시간이 지나면서 <a href="https://twitter.com/subicura">subicura</a>님과 <a href="https://twitter.com/ecleya">ecleya</a>님도 멤버로 참여했는데 다 아는 사람들이었기 때문에 지인들과 그냥 수다 떠는 기분으로 참여했다.</p>
<p><a href="https://twitter.com/sduck4">SDuck님</a>이 만들어주신 2020년 <a href="https://sduck4.github.io/stdout.fm-100th/">100회 기념 페이지</a>를 보면 100회 중에 총 8번 참여했다. 엄청 많은 건 아니지만 게스트 중에는 가장 많이 참여했다.<br />
<br></p>
<h2>44BITS 팟캐스트</h2>
<p>팟캐스트는 stdout.fm이고 <a href="https://www.44bits.io/ko">블로그는 44BITS로 운영</a>하다가 <a href="https://podcast.44bits.io/episodes/101">101회</a>부터 팟캐스트도 44BITS로 이름을 변경해서 운영하기 시작했다.</p>
<p style="text-align: center;"><img src="//blog.outsider.ne.kr/attach/1/8096114853.jpg" width="357" height="168" alt="사용자 삽입 이미지" title="" /></p>
<p>그리고 난 2020년 12월에 <a href="https://blog.outsider.ne.kr/1518">당근마켓으로 이직</a>했다. 이직 글에도 썼지만, 당시 난 꽤 소진된 상태로 번아웃이 왔다 갔다 하는 상태였고 당시 이직을 생각하고 있진 않았지만, 소고기를 구워주면서 당근마켓에 와서 같이 일하면서 팟캐스트 하자고 했을 때 재밌겠다는 생각에 맘이 꽤 동한 게 사실이다. 하지만 막상 이직했을 때는 코로나가 한창이었기 때문에 모이기가 어려워서 녹음은 별로 못하고 한참 동안은 그냥 일만 했다. 뭐 원래도 난 주기적으로 녹음하던 사람은 아니라서 크게 영향은 없었고 당연히 업무에 적응하느라 정신없기도 했다.</p>
<p>재택을 주로 하다 보니 가끔 모이거나 Zoom으로 녹음했지만 쉽지 않았고 녹음 간격도 꽤 띄엄띄엄하기 시작했다. 그러다 작년 초였나 오랜만에 번개로 다 같이 모여서 다시 팟캐스트를 잘하기 위해 2주마다 날짜를 정해서 하기로 했다. 전에는 지속해서 할 수 있도록 점심시간에 녹음했는데 요즘은 다들 바빠져서 점심시간에도 시간을 내기 어려워서 저녁으로 녹음 시간을 옮겼다. 다행히도 이게 효과가 꽤 있어서 이후로는 거의 2주마다 계속 녹음을 할 수 있게 되었다.</p>
<p style="text-align: center;"><img src="//blog.outsider.ne.kr/attach/1/4661979713.jpg" width="750" height="407" alt="사용자 삽입 이미지" title="" /></p>
<p>게스트로 나올 때보다 자주 나오니까 더 재밌게 녹음을 한 거 같다. 초기에 Seapy님 얘기대로 녹음하는 데 너무 큰 노력이 필요하면 오래 할 수 없기 때문에 보통 주제 정도만 모아놓고 대본도 없이 그냥 생각나는 대로 하는 편이다. 나는 <a href="https://blog.outsider.ne.kr/category/Newsletter">한 달에 2번씩 뉴스레터를 발행하기 때문에</a> 그중에서 팟캐스트에서 얘기해 볼 만한 이슈나 트위터에서 본 주제를 가져와서 같이 얘기한다. 물론 우리는 앞뒤 정도만 자르고 편집도 따로 하지 않는다. 그래서 200회까지 올 수 있었다는 생각도 들고 그냥 잡담을 하다 보니까 어느새 200회네? 하는 기분도 든다.</p>
<p>200회 방송하면서도 느꼈지만 잡담하듯이 하다 보니까 설명도 좀 부족하고 기술 이름이나 옛날얘기를 그냥 꺼내면서 얘기해서 듣는 사람에게 친절한 편은 아닌 거 같다. 그래서 그런지 듣는 사람도 항상 비슷비슷한 느낌인데 그 대단하지 않은 잡담이 꽤 즐겁긴 하다. 여기서 잡담을 많이 하다 보니 대본까지 힘들게 준비한 <a href="https://blog.outsider.ne.kr/1681">RetroTech 팟캐스트</a>를 기획하게 된 것이기도 하다.</p>
<p>멤버들이 다양한 관심과 재능이 있어서 시간만 많으면 재밌는 일을 더 많이 할 수 있을 것 같은데 다들 바빠서 좀처럼 쉽지 않다. 이번 200회때도 공개방송 얘기가 나왔지만 공개 방송이란게 장소 구하는거부터 녹음까지 할일이 한두개가 아니다 보니까 실제로 진행할 엄두가 나지 않았다.(물론 사람들이 오기는 할까? 하는 걱정도 있었다) 그래도 올해부터는 스튜디오가 생겨서 아지트처럼 쓸 수 있고 더 세팅되면 모이기만 하면 바로 방송도 할 수 있게 되어서 전보다 더 다양한 일을 할 수 있지 않을까 생각한다. 물론 스튜디오가 아주 가깝진 않아서(아주 멀지도 않지만) 자주 가진 못하지만 그래도 올해는 뭔가 또 재미난 일이 있지 않을까 기대한다. 지금처럼 계속 잡담하는 것도 좋고 ㅎㅎ</p>
<p><strong><a href="https://blog.outsider.ne.kr/1709?commentInput=true#entry1709WriteComment">댓글 쓰기</a></strong></p>기술 뉴스 #240 : 24-02-16Outsiderhttps://blog.outsider.ne.kr/17082024-02-16T10:18:28+09:002024-02-16T10:18:28+09:00<h1>웹개발 관련</h1>
<ul>
<li><strong><a href="https://webkit.org/blog/14955/the-web-just-gets-better-with-interop/">The web just gets better with Interop 2024</a></strong> : 브라우저 간 호환성을 유지하기 위해 여러 브라우저가 벤더와 회사들이 공동으로 테스트를 만들어서 상호 운용성을 개선하기 위한 Interop 2024가 발표되었다. <a href="https://wpt.fyi/interop-2023">Interop 2023</a> 컨테이너 쿼리, <code>:has()</code>, Flexbox, Grid 등의 영역의 상호 운용성을 크게 개선했다. 올해는 Microsoft Edge를 크롬과 별도로 구분해서 보여주기 시작했으며 접근성, 웹소켓용 HTTPS URL, CSS Nesting, CSS 커스텀 프로퍼티(<code>@property</code>), 선언적 쉐도우 DOM, 레이아웃, 스크롤바 스타일 등이다.(영어)</li>
<li><strong><a href="https://www.joshwcomeau.com/css/center-a-div/">How To Center a Div</a></strong> : DIV를 부모 요소의 중앙에 배치하는 것은 의외로 까다로운 작업인데 중앙에 배치한 다양한 방법을 설명하는 글이다. 마진을 <code>auto</code>로 설정해서 가운데 배치하거나 <code>flexbox</code>를 이용하는 방법 그리고 <code>position: fixed</code>를 이용해서 뷰포트의 중앙에 배치하거나 CSS Grid로 중앙에 배치하는 방법을 설명한다. 실행해 볼 수 있는 예제를 같이 보여주면서 특징을 설명하고 있어서 이해하기 좋다.(영어)</li>
<li><strong><a href="https://observablehq.com/blog/observable-2-0">Observable 2.0</a></strong> : d3.js를 만든 Mike Bostock이 만든 Observable에서 2.0을 출기하면서 Observable 프레임워크를 오픈소스로 공개했다. 그동안 데이터를 효과적으로 보여주기 위한 노트북을 제공했는데 이는 임시적인 데이터 탐색에는 적합하지만 세련된 대시보드와 앱에는 적합하지 않았기 때문에 프레임워크를 만들게 되었고 이를 이용해서 데이터앱을 구축할 수 있다. 모든 백엔드 언어와 연결이 가능하고 빌드시에 데이터로더가 실행되기 때문에 페이즈 로딩이 아주 빠르다.(영어)<br />
<br></li>
</ul>
<h1>그 밖의 개발 관련</h1>
<ul>
<li><strong><a href="https://fly.io/ruby-dispatch/the-plan-for-rails-8/">The Plan for Rails 8</a></strong> : Rails 8 웹프레임워크에 대한 계획이 공개었다. 최신 웹 앱의 복잡성을 압축해서 웹 앱을 더 쉽게 구축한다는 Rails의 모토를 여전히 유지하고 있다. NVMe SSD로 데이터베이스가 훨씬 빨라짐에 따라 Solid Cache와 Solid Queue를 통해 기존 Redis에 의존하던 캐싱이나 백그라운드 작업을 대체하고 데이터베이스를 사용하게 되었다. Postgres와 MySQL이 지원하는 WebSocket을 통해 브라우저에 메시지를 브로드캐스트할 수 있도록 지원하고 오랫동안 Rails의 에셋 파이프라인이었던 Sprockets을 <a href="https://github.com/rails/propshaft">propshaft</a>이 대체할 예정이다. 그외에도 Kamal 배포도구, HTTP 기본 인증 생성기, 벤치마크 도구, Rails 8의 Language Server 등의 도구가 포함될 예정이다.(영어)</li>
<li><strong><a href="https://blog.gitbutler.com/opening-up-gitbutler/">Opening Up GitButler</a></strong> : 전에 GitHub에서도 일하고 <a href="https://m.yes24.com/Goods/Detail/24841824">Pro Git</a>을 쓴 <a href="https://scottchacon.com/">Scott Chacon</a>이 창업한 Git 브랜치 관리 시스템인 GitButler가 정식 오픈했다. GitButler는 Virtual Branch라는 개념을 도입해서 워킹 디렉토리에서 작업을 하던 중 버그 수정을 위해 새로운 브랜치로 전환하지 않고 UI에서 필요한 수정사항만 끌어다가 새로운 브랜치를 만들어서 커밋하고 푸시할 수 있게 제공한다. 곧 클라이언트도 제공할 예정인데 GitButler는 기존 Git 워크플로우는 그대로 유지하면서 브랜치를 사용하는 완전히 새로운 방법이라고 소개하고 있다.(영어)</li>
<li><strong><a href="https://lucumr.pocoo.org/2024/2/4/rye-a-vision/">Rye: A Vision Continued</a></strong> : Python 프로젝트와 패키지를 관리하는 도구인 <a href="https://rye-up.com/">Rye</a>를 만든 Python의 유명 개발자 Armin Ronacher가 Rye의 중요성을 설명하는 글이다. Rye가 있으면 Python이 설치도 안 되어 있는 환경에서도 1분 이내에 모든 환경이 갖춰진 파이썬 프로젝트를 시작할 수 있는데 이는 Rust에서 Cargo의 원활한 통합을 보면서 이를 Python 커뮤니티에서도 비슷한 경험을 하고 싶어서 만들었다고 한다. Cargo가 그렇듯이 모든 도구를 다 만드는 것이 아니라 생태계의 다른 도구를 연결해 주는 역할을 하]고 이는 Rye도 비슷하게 하고 있지만 아직 1인 프로젝트이며 이러한 표준화 아이디어가 Python 생태계에 더 필요하다고 얘기한다.(영어)</li>
<li><strong><a href="https://astral.sh/blog/uv">uv: Python packaging in Rust</a></strong> : <code>pip</code>와 <code>pip-tools</code>를 대체하려고 Rust로 작성된 <a href="https://github.com/astral-sh/uv">uv</a>는 엄청나게 빠른 Python 패키지 인스톨러이면서 리졸버이다. Python을 위한 Cargo를 지향하고 있으며 이번 릴리스와 함께 Rye의 관리도 같이 맡아서 공동의 비전을 실현하기 위해 노력할 것이라고 한다.(영어)<br />
<br></li>
</ul>
<h1>인프라 관련</h1>
<ul>
<li><strong><a href="https://www.hashicorp.com/cloud-operating-model">Enabling a Cloud Operating Model</a></strong> : HashiCorp에서 클라우드 인프라를 운영하는 모델을 정리한 백서를 공개했다. 물론 회사에서 공개한 내용이니 상당 부분은 이러한 운영 모델을 HashiCorp의 제품으로 어떻게 구축하는지에 대한 내용이지만 운영 모델에 대한 내용과 HashiCrop의 접근도 참고할 만하다. 클라우드에서는 정적 인프라가 아니라 동적 인프라이고 IP 대신 ID 기반으로 보안과 네트워킹 정책을 세워야 하고 수동 티켓 시스템으로 운영하는 대신 자동화된 셀프서비스 플랫폼이 필요하다. 조직 내에 클라우드를 도입하고 이 운영 모델이 점점 성숙해질 수 있도록 플랫폼 엔지니어링 관행을 도입해서 운영을 소프트웨어 문제로 취급하도록 하고 베스트 프렉티스를 모아서 셀프서비스 기능으로 제공하고 동적 환경을 지원하는 워크플로우를 만들 수 있도록 변화가 필요하다고 얘기하고 있다. 23페이지로 된 PDF로 된 백서라서 개인 정보를 입력해야 다운로드 받을 수 있다.(영어)</li>
<li><strong><a href="https://grafana.com/blog/2024/02/06/combining-tracing-and-profiling-for-enhanced-observability-introducing-span-profiles/">Combining tracing and profiling for enhanced observability: Introducing Span Profiles</a></strong> : Grafana 10.3에 Span Profile 기능이 추가되었다. 기존 continuous profiling에서는 고정된 간격으로 시스템 전체에 대한 보기를 제공했지만 Span Profile에서는 개별 요청을 포함해서 애플리케이션의 특정 실행 범위에 대한 분석을 제공한다.(영어)</li>
<li><strong><a href="https://medium.com/nordnet-tech/unlocking-kubernetes-performance-with-no-cpu-resource-limits-56d5dc33037b">Unlocking Kubernetes Performance with no CPU Resource Limits</a></strong> : Kubernetes에서 리소스를 설정할 때 CPU의 <code>requests</code>와 <code>limits</code>가 어떻게 동작하는지 설명하고 왜 <code>limits</code>를 설정하지 않는 것이 좋은지를 설명한 글이다. <code>requests</code>가 있으면 사용할 CPU를 보장받을 수 있으면서 필요할 때는 그 이상의 CPU를 사용할 수 있지만 <code>limits</code>이 있으면 스로틀링 때문에 보장받은 CPU도 제대로 사용할 수 없기 때문인데 그림과 함께 이해하기 좋게 설명하고 있다. Kubernetes에서 나도 CPU <code>limits</code>를 해제하는 게 맞다고 생각하기에 동의하는 글이다.(영어)</li>
<li><strong><a href="https://rtfm.co.ua/en/aws-eks-pod-identities-a-replacement-for-irsa-simplifying-iam-access-management/">AWS: EKS Pod Identities – a replacement for IRSA? Simplifying IAM access management</a></strong> : AWS EKS에서는 Pod에 AWS 권한을 부여하기 위해 IRSA(IAM Roles for Service Accounts)를 사용하는데 새로 나온 EKS Pod Identities로 IRSA를 대체하는 방법을 사용한다. EKS Pod Identities는 OIDC를 사용하지 않기 때문에 IAM 역할을 만들고 클러스터 수준에서 서비스 어카운트를 연결해서 관리할 수 있다.(영어)</li>
<li><strong><a href="https://aws.amazon.com/ko/blogs/devops/announcing-cdk-migrate-a-single-command-to-migrate-to-the-aws-cdk/">Announcing CDK Migrate: A single command to migrate to the AWS CDK</a></strong> : 기존 AWS CloudFormation 스택이나 CDK 외부에서 생성한 리소스를 CDK로 마이그레이션 할 수 있는 <a href="https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/README.md#cdk-migrate">CDK Migrate</a>가 나왔다.(영어)<br />
<br></li>
</ul>
<h1>볼만한 링크</h1>
<ul>
<li><strong><a href="https://socket.dev/blog/express-js-spam-prs-commoditization-of-open-source">Express.js Spam PRs Incident Highlights the Commoditization of Open Source Contributions</a></strong> : 486만 명의 구독자를 보유한 인기 YouTube 영상에서 Pull Request를 제출하는 방법을 설명하면서 예시도 Express.js를 사용하는 바람에 <a href="https://github.com/expressjs/express/pulls?q=is%3Apr+is%3Aclosed">Express.js 저장소에 Readme를 업데이트하는 스팸 PR이 대량으로 등록</a>되는 사태가 발생했다. 영상에서 실제 Express.js 저장소를 사용했기 때문에 사람들이 따라 하면서 express 저장소에 PR을 등록하게 된 거고 메인테이너는 이 스팸에 대응하느라 고생하고 있다. 사람들은 오픈소스에 기여하는 것을 취업의 방법이 되었고 그로 인해서 오픈소스 생태계가 무너지고 있다며 대부분의 사람은 오픈소스에 기여하지 말라는 말까지 나오고 있다.(영어)</li>
<li><strong><a href="https://slate.com/technology/2024/02/quora-what-happened-ai-decline.html">How Quora Died</a></strong> : 전문가에게 답변을 받을 수 있는 커뮤니티인 <a href="https://www.quora.com/">Quora</a>가 쇠퇴해 가는 과정을 설명한 글이다. Quora는 좋은 질문과 좋은 답변을 얻을 수 있는 커뮤니티를 잘 구축했지만 트래픽을 모으려고 노력하면서 SEO를 위해 질문 길이를 제한하고 피드 최적화로 피드에 콘텐츠 기사를 넣기 시작했가 이어서 수익 공유 프로그램을 만들었는데 이는 기존 커뮤니티보다 봇을 만드는 게 더 돈이 된다는 것을 보여주었고 이후 답변에 AI를 도입하면서 답변은 전문가의 답변보다는 평이한 답변이 차지하게 되고 AI 학습을 위해 모든 질문 답변이 AI 학습에 사용된다는 이용약관의 변경으로 인해 사용자는 계속 이용할지 갈등하게 만들었다는 내용이다.(영어)</li>
<li><strong><a href="https://www.ssh.com/academy/ssh/port#the-story-of-getting-ssh-port-22">How SSH port became 22</a></strong> : 1995년 SSH를 만든 <a href="https://ylonen.org/">Tatu Ylonen</a>이 SSH의 포트 번호인 22번을 어떻게 할당받았는지를 적은 글이다. 당시 23번 포트의 Telnet과 21번 포트의 FTP를 대체할 수 있도록 SSH를 설계 후 무료인 22번 포트를 사용하면 좋겠다고 생각했습니다. 당시에는 인터넷의 규모가 작고 초기 단계였기에 IANA에서 포트 번호를 관리했기에 IANA에 SSH의 RFC를 첨부하면서 포트 번호를 받고 싶다고, 특히 22번을 받고 싶다고 이메일 보냈고 IANA에서 22번을 할당해 주고 Tatu Ylonen을 담당자로 지정해 주어 바로 SSH의 베타테스터들에게 공개했다.(영어)<br />
<br></li>
</ul>
<h1>IT 업계 뉴스</h1>
<ul>
<li><strong><a href="https://www.linkedin.com/posts/richardsonalexis_hi-everyone-i-am-very-sad-to-announce-activity-7160295096825860096-ZS67/">Weaveworks will be closing its doors and shutting down commercial operations</a></strong> : GitOps 솔루션을 만들던 <a href="https://www.weave.works/">Weaveworks</a>가 문을 닫기로 했다고 2014년에 Weavework를 창업한 Alexis Richardson이 글을 올렸다. 2023년에도 1,000만 달러 이상의 매출을 기록했고 도입되는 회사도 늘어났지만, 매출 성장이 고르지 못했고 현금 사정이 불안했기 때문에 파트너와 투자자가 필요한 상황이었다. 대기업과 합병을 논의하고 있었지만 11시간 만에 결렬되고 결국 문을 닫기로 했고 <a href="https://www.weave.works/">weave.works</a> 홈페이지도 이미 닫혔다. Weaveworks는 <a href="https://cortexmetrics.io/">Cortex</a>, <a href="https://eksctl.io/">eksctl</a>, <a href="https://flagger.app/">Flagger</a>, <a href="https://fluxcd.io/">Flux CD</a>등 다양한 오픈소스를 만들었고 이 오픈소스는 CNCF에 기부되거나 eksctl은 Amazon의 공식 CLI가 될 정도로 생태계에는 큰 영향을 주었다. 이런 회사가 문을 닫는다는 것은 안타까운 일이다.(영어)<br />
<br />
<ul>
<li>그동안 AWS와 파트너십으로 EKS의 공식 CLI가 된 <a href="https://github.com/aws/containers-roadmap/issues/2280">eksctl는 AWS에서 관리하기로 했다</a>.</li>
</ul></li>
<li><strong><a href="https://www.theverge.com/2024/1/25/24050478/apple-ios-17-4-browser-engines-eu">Apple is finally allowing full versions of Chrome and Firefox to run on the iPhone</a></strong> : Apple이 EU의 새 규정을 준수하기 위해 iOS 17.4부터 유럽 사용자는 Webkit 외 다른 브라우저 엔진을 선택할 수 있게 된다. EU에 거주하는 사람들만을 대상으로 하며 처음 Safari을 열때 브라우저 엔진을 선택할 화면을 볼 수 있게 되어 WebKit 외에 Blink나 Gecko를 선택할 수 있게 된다.(영어)</li>
<li><strong><a href="https://techcrunch.com/2024/02/01/the-epic-apple-antitrust-saga-isnt-over-yet/">The Epic-Apple antitrust saga isn’t over yet</a></strong> : Epic 게임즈와 Apple의 반독점 소성의 결과로 애플 인앱결제 외에 다른 결제 방법도 안내할 수 있다고 판결이 나왔지만 여기서도 27%의 수수료를 받겠다고 해서 Epic 게임즈가 비난하며 다시 제소할 계획이라고 밝혔다. Apple의 안내에 따르면 앱에 포함할 링크를 포함할 수 있는 권한을 신청하고 월말 기준으로 거래 보고서를 통해 매출을 입증해야 하며 사용자가 링크를 탭하고 발생한 거래에 대해 27%의 수수료를 받겠다고 한다.(영어)</li>
<li><strong><a href="https://blog.google/technology/ai/google-gemini-update-sundar-pichai-2024/">The next chapter of our Gemini era</a></strong> : Google이 자사의 생성형 AI인 Bard를 Gemini로 리브랜딩하고 Gemini Ultra를 출시했다. Gemini Android 앱을 출시하고 iOS 용도 곧 출시할 예정이라고 한다.(영어)</li>
<li><strong><a href="https://blog.google/intl/ko-kr/products/explore-get-answers/google-gemini-next-generation-model-february-2024-kr/">구글의 차세대 모델: 제미나이 1.5</a></strong> : Google에서 최근 Gemini 1.0 Ultra에 이어 Gemini 1.5를 발표했다. 1.5는 Mixture-of-Experts(MoE) 아키텍처를 사용해서 효율적으로 훈련해서 Gemini 1.0 Ultra와 비슷한 수준의 중형 멀티모달 모델로 기존 3만 2천 토큰을 넘어 최대 100만 토큰까지 처리할 수 있게 되었다.(한국어)</li>
<li><strong><a href="https://openai.com/sora">Creating video from text</a></strong> : OpenAI에서 텍스트를 입력하면 비디오를 만들어주는 AI 모델 Sora를 공개했다.(영어)</li>
<li><strong><a href="https://arstechnica.com/gadgets/2024/02/google-search-kills-off-cached-webpages/">Google will no longer back up the Internet: Cached webpages are dead</a></strong> : Google에서 크롤링한 웹사이트를 캐시에 저장하고 있어서 검색 결과의 사이트에서 드롭다운 메뉴를 누르면 캐시된 페이지를 볼 수 있었는데 이 기능을 더는 제공하지 않기로 했다.(영어)</li>
<li><strong><a href="https://www.cnbc.com/2024/02/07/disney-to-take-1point5-billion-stake-in-epic-games-maker-of-fortnite.html">Disney to take $1.5 billion stake in Epic Games, work with Fortnite maker on new content</a></strong> : Disney가 Epic Games에 15억 달러(약 2조 원)를 투자해서 지분을 인수하면서 파트너십을 강화했다.(영어)<br />
<br></li>
</ul>
<h1>프로젝트</h1>
<ul>
<li><strong><a href="https://jsr.io/">jsr</a></strong> : Deno에서 npm을 대체할 새로운 자바스크립트 레지스트리를 만들고 있다. 아직 자세한 내용은 공개되지 않았지만, Deno의 denoland를 대체할 것으로 예상된다.</li>
<li><strong><a href="https://github.com/awslabs/llrt">LLRT(Low Latency Runtime)</a></strong> : AWS에서 실험적으로 QuickJS 엔진을 사용하고 Rust로 만든 JavaScript 런타임을 공개했다. 이는 서버리스 애플리케이션의 빠르고 효율적인 요구사항을 해결하기 위한 런타임으로 AWS Lambda에서 10배 빠른 시작 시간과 2배 저렴한 비용을 보여주었다.</li>
<li><strong><a href="https://pkl-lang.org/">Pkl</a></strong> : Apple이 프로그래밍할 수 있고 확장성 있으면서 안전한 구성 언어(Configuration Language)를 공개했다. Pickle로 발음한다.</li>
<li><strong><a href="https://github.com/keephq/keep">Keep</a></strong> : 오픈소스 얼럿 관리 및 자동화 플랫폼</li>
<li><strong><a href="https://github.com/hyperdxio/hyperdx">HyperDX</a></strong> : Datadog이나 New Relic의 오픈소스 대체제로 로그, 메트릭, 트레이스, 예외, RUM 등을 한곳에 모아서 서비스 문제를 쉽게 찾을 수 있게 해준다.<br />
<br></li>
</ul>
<h1>버전 업데이트</h1>
<ul>
<li><strong><a href="https://turbo.hotwired.dev/">Turbo</a> v8.0.0</strong> : 싱글 페이지 애플리페이지의 변경을 관리하는 라이브러리, <a href="https://github.com/hotwired/turbo/releases/tag/v8.0.0">릴리스 공지</a></li>
<li><strong><a href="https://hono.dev/">Hono</a> v4.0.0</strong> : 엣지용 웹 프레임워크, <a href="https://github.com/honojs/hono/releases/tag/v4.0.0">릴리스 공지</a></li>
<li><strong><a href="https://mobyproject.org/">Moby Project</a> v25.0.0</strong> : Docker, <a href="https://github.com/moby/moby/releases/tag/v25.0.0">릴리스 공지</a></li>
<li><strong><a href="https://probot.github.io/">Probot</a> v13.0.0</strong> : GitHub 앱을 만들 수 있는 프레임워크, <a href="https://github.com/probot/probot/releases/tag/v13.0.0">릴리스 공지</a></li>
<li><strong><a href="https://adonisjs.com/">AdonisJS</a> v6.0.0</strong> : TypeScript 웹 프레임워크, <a href="https://adonisjs.com/blog/adonisjs-v6-announcement">릴리스 공지</a></li>
<li><strong><a href="https://cilium.io/">Cilium</a> v1.15.0</strong> : eBPF 기반 CNI, <a href="https://github.com/cilium/cilium/releases/tag/v1.15.0">릴리스 공지</a></li>
<li><strong><a href="https://orbstack.dev/">OrbStack</a> v1.4.0</strong> : mac용 Docker 애플리케이션, <a href="https://docs.orbstack.dev/release-notes#v1-4-0">릴리스 공지</a></li>
<li><strong><a href="https://remix.run/">Remix</a> v2.6.0</strong> : 풀스택 웹 프레임워크, <a href="https://github.com/remix-run/remix/blob/main/CHANGELOG.md#v260">릴리스 공지</a></li>
<li><strong><a href="https://gradle.org/">Gradle</a> v8.6</strong> : Java 빌드 도구, <a href="https://docs.gradle.org/8.6/release-notes.html">릴리스 공지</a></li>
<li><strong><a href="http://www.babylonjs.com/">Babylon.js</a> v6.41.0</strong> : WebGL 자바스크립트 프레임워크, <a href="https://github.com/BabylonJS/Babylon.js/releases/tag/6.41.0">릴리스 공지</a></li>
<li><strong><a href="https://github.com/pinojs/pino">pino</a> v8.18.0</strong> : Node.js 로거, <a href="https://github.com/pinojs/pino/releases/tag/v8.18.0">변경사항</a></li>
<li><strong><a href="https://flow.org/">flow</a> v0.228.0</strong> : JavaScript 정적 타입 체커, <a href="https://github.com/facebook/flow/releases/tag/v0.228.0">릴리스 공지</a></li>
<li><strong><a href="https://mermaid.js.org/">Mermaid</a> v10.8.0</strong>: JavaScript 기반 다이어그램/차트 도구, <a href="https://github.com/mermaid-js/mermaid/releases/tag/v10.8.0">릴리스 공지</a></li>
<li><strong><a href="https://github.com/TryGhost/Ghost">Ghost</a> v5.79.0</strong> : 오픈소스 블로그 플랫폼, <a href="https://github.com/TryGhost/Ghost/releases/tag/v5.79.0">릴리스 공지</a></li>
<li><strong><a href="https://www.boundaryproject.io/">Boundary</a> v0.15</strong> : 인프라 접근 관리, <a href="https://www.hashicorp.com/blog/boundary-0-15-adds-new-storage-policies-and-desktop-cli-features">릴리스 공지</a></li>
<li><strong><a href="https://vitejs.dev/">Vite</a> v5.1.0</strong> : 프론트엔드 빌드 도구, <a href="https://vitejs.dev/blog/announcing-vite5-1.html">릴리스 공지</a></li>
<li><strong><a href="http://www.rust-lang.org/">Rust</a> 1.76.0</strong> : 프로그래밍 언어, <a href="https://blog.rust-lang.org/2024/02/08/Rust-1.76.0.html">릴리스 공지</a></li>
<li><strong><a href="https://argoproj.github.io/argo-cd/">Argo CD</a> v2.10.0</strong> : Kubernetes 배포 도구, <a href="https://blog.argoproj.io/argo-cd-v2-10-release-candidate-f69ba7bf9e06">릴리스 공지</a><br />
<br />
<ul>
<li>ApplicationSet 템플릿 지원</li>
<li>관리자 권한 없이도 앱 사용자가 알림 설정 가능</li>
</ul></li>
<li><strong><a href="https://k6.io/">k6</a> v0.49.0</strong> : 부하 테스트 도구, <a href="https://grafana.com/blog/2024/02/07/new-in-grafana-k6-the-latest-oss-features-in-v0.49.0-and-static-ips-in-grafana-cloud-k6/">릴리스 공지</a></li>
<li><strong><a href="https://github.com/web-infra-dev/rsbuild">Rsbuild</a> v0.4.0</strong> : Rspack 기반의 빌드 도구, <a href="https://rsbuild.dev/community/releases/v0-4">릴리스 공지</a></li>
<li><strong><a href="https://golang.org/">Go</a> v1.22</strong> : 프로그래밍 언어, <a href="https://tip.golang.org/doc/go1.22">릴리스 공지</a></li>
<li><strong><a href="http://jquery.com/">jQuery</a> v4.0.0 Beta</strong> : JavaScript 라이브러리, <a href="https://blog.jquery.com/2024/02/06/jquery-4-0-0-beta/">릴리스 공지</a><br />
<br />
<ul>
<li>IE 10 이하 지원 중단</li>
</ul></li>
<li><strong><a href="https://www.docker.com/products/docker-desktop">Docker Desktop</a> v4.27</strong> : 데스크톱용 Docker 애플리케이션, <a href="https://www.docker.com/blog/docker-desktop-4-27/">릴리스 공지</a></li>
<li><strong><a href="https://typescript-eslint.io/">typescript-eslint</a> v7.0.0</strong> : TypeScript의 ESLint, <a href="https://typescript-eslint.io/blog/announcing-typescript-eslint-v7">릴리스 공지</a></li>
<li><strong><a href="https://github.com/tmux/tmux">tmux</a> v3.4.0</strong> : 터미널 멀티플렉서, <a href="https://raw.githubusercontent.com/tmux/tmux/3.4/CHANGES">변경사항</a></li>
<li><strong><a href="https://panda-css.com/">panda</a> v0.31.0</strong> : CSS-in-JS, <a href="https://github.com/chakra-ui/panda/discussions/2202">릴리스 공지</a></li>
<li><strong><a href="https://angular.io/">Angular</a> v17.2.0</strong> : JavaScript 프레임워크, <a href="https://blog.angular.io/angular-v17-2-is-now-available-596cbe96242d">릴리스 공지</a></li>
<li><strong><a href="https://about.gitlab.com/">GitLab</a> v16.9</strong> : 오픈소스 설치형 Git 플랫폼, <a href="https://about.gitlab.com/releases/2024/02/15/gitlab-16-9-released/">릴리스 공지</a></li>
<li><strong><a href="https://www.dartlang.org/">Dart</a> v3.3.0</strong> : 프로그래밍 언어, <a href="https://medium.com/dartlang/dart-3-3-325bf2bf6c13">릴리스 공지</a></li>
<li><strong><a href="https://flutter.io/">Flutter</a> v3.19</strong> : iOS, Android 네이티브 앱을 만드는 프레임워크, <a href="https://medium.com/flutter/whats-new-in-flutter-3-19-58b1aae242d2">릴리스 공지</a></li>
<li><strong><a href="https://astro.build/">astro</a> v4.4</strong> : JavaScript 웹 프레임워크, <a href="https://astro.build/blog/astro-440/">릴리스 공지</a></li>
</ul>
<p><strong><a href="https://blog.outsider.ne.kr/1708?commentInput=true#entry1708WriteComment">댓글 쓰기</a></strong></p>Git의 새로운 기본 Merge 전략 ortOutsiderhttps://blog.outsider.ne.kr/17072024-02-11T21:24:45+09:002024-02-11T21:24:45+09:00<p>현재 Git이 Merge 할 때 사용하는 전략이 <code>ort</code>로 바뀌었다. Git에 <code>ort</code> 머지 전략이 들어온 것은 <a href="https://github.blog/2021-08-16-highlights-from-git-2-33/#merge-ort-a-new-merge-strategy">Git 2.33</a>부터였고 <a href="https://github.blog/2021-11-15-highlights-from-git-2-34/#a-new-default-merge-strategy">Git 2.34</a>에서 별도의 설정 없이도 Merge할 때 사용되는 기본 전략으로 바뀌었다.</p>
<p>이 Merge 전략은 <code>git merge</code>와 <code>git pull</code>을 할 때 주로 사용되지만 <code>rebase</code>, <code>cherry-pick</code>, <code>revert</code>, <code>stash</code>, <code>checkout</code>에서도 사용된다. 2.34가 2021년 11월에 나왔으니 바뀐 지는 꽤 되었지만 뭐가 바뀌는지는 정확히 모르고 있어서 정리를 해봤다. 이 글 쓰는 시점의 Git 최신 버전은 <a href="https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.43.0.txt">2.43.0</a><br />
<br></p>
<h2><code>resolve</code> 전략</h2>
<p>Git이 2개의 브랜치를 머지할 때 변경 사항을 합치기 위해 여러 가지 전략 중 하나를 선택한다. 원래의 전략은 <a href="https://en.wikipedia.org/wiki/Merge_(version_control)#Three-way_merge">3-way merge</a> 알고리즘을 사용하는 <code>resolve</code> 전략을 사용했다.</p>
<p>3-way merge는 A 파일과 B 파일의 차이점을 분석한 후 두 파일의 공통 조상인 C 까지 고려해서 합칠 변경 사항을 구성하고 A, B, C 셋 다 다른 경우는 충돌(Conflict)로 표시해서 사용자가 해결하도록 한다.<br />
<br></p>
<h2><code>recursive</code> 전략</h2>
<p>Git이 만들어진 초기인 2005년에 <code>resolve</code> 전략은 <code>recursive</code>라는 전략으로 <a href="https://github.com/git/git/commit/fbf8ac212caa74fc506434da83f8e9630b09ed12">교체</a>된다. 이렇게 <code>recursive</code>로 바꾼 주요 이유는 머지할 두 브랜치가 공통된 조상이 없는 경우에도 각 브랜치에서 그 이름대로 재귀적으로 머지할 수 있어서 <code>resolve</code> 전략에서 충돌하는 경우에도 머지할 수 있고 한 브랜치에서는 파일이 수정되고 다른 브랜치에서는 파일명이 변경된 경우에도 이를 감지할 수 있기 때문이다.</p>
<p>이렇게 적용된 <code>recursive</code>는 오랫동안 Git의 기존 전략으로 사용되었다. 2005년에 적용되고 2021년에 나온 Git 2.33에서 바뀌었으니 16년 동안 사용된 셈이다.<br />
<br></p>
<h2><code>ort</code> 전략</h2>
<p><code>ort</code>는 재귀(recursion)와 파일이름 변경 탐지를 하는 <code>recursive</code>와 같은 컨셉을 가지고 처음부터 새로 작성된 전략이다. 그래서 ort라는 이름도 Ostensibly Recursive’s Twin의 약자로 표면적으로는 Recursive의 쌍둥이라는 의미이고 이전에 비해 <a href="https://lore.kernel.org/git/4a0f088f3669a95c7f75e885d06c0a3bdaf31f42.1628055482.git.gitgitgadget@gmail.com/">훨씬 빨라졌다</a>.</p>
<p><a href="https://git-scm.com/docs/merge-strategies#Documentation/merge-strategies.txt-ort">Git 공식 문서</a>를 보면 <code>ort</code> 전략을 다음과 같이 설명하고 있다.</p>
<blockquote>
<p>하나의 브랜치를 가져오거나(pull) 머지할 때 사용하는 기본 머지 전략이다. 이 전략은 3-way 머지 알고리즘을 사용해서 두 개의 헤드(head)만 처리할 수 있다. 3-way 머지에 사용할 수 있는 공통 조상이 2개 이상 있다면 공통 조상의 머지된 트리를 만들어서 이를 3-way 머지의 참조 트리로 사용한다. Linux 2.6 커널 개발 기록에서 가져온 실제 머지 커밋을 대상으로 테스트한 결과 ort가 잘못된 머지도 없고 머지 충돌이 더 적게 발생했다. 또한, 이 전략은 이름 변경과 관련된 머지를 탐지하고 처리할 수 있으며 감지된 사본(detected copies)을 사용하지 않는다.</p>
</blockquote>
<p>그러면 오랫동안 사용하던 <code>recursive</code> 전략을 왜 바꿀 필요가 있는지를 알아야 하는데 새로운 전략이긴 하지만 방법 자체를 바꾸었다기보다는 많은 최적화 작업을 합쳐서 <code>ort</code>라는 새로운 전략이 탄생했다고 볼 수 있고 그렇기에 이름도 <code>recursive</code>의 쌍둥이라는 이름을 가지게 된 것이다.</p>
<p>Git에서 <code>recursive</code> 머지의 코드 베이스는 문제를 해결하기 위해 조금만 고치다 보니 결국 고칠 수 없는 상황까지 왔습니다. 그래서 버그도 많이 발생하고 해결하기 어려운 엣지 케이스도 발생하고 있었고 개발자들도 이 부분의 코드 수정은 피하고 있었다. Git의 핵심 개발자 중 한 명인 <a href="https://github.com/newren">Elijah Newren</a>가 큰 변경을 하려고 하자 초기부터 Git을 리드하고 있는 <a href="https://github.com/gitster">Junio Hamano</a> 그냥 다시 작성하자는 제안하고 이에 따라 아주 대규모의 최적화 작업이 시작된다.</p>
<p>이 최적화 과정을 이해하려면 Git의 3-way 머지를 좀 이해해야 한다.</p>
<pre class="line-numbers"><code class="language-bash"> A---B---C topic
/
D---E---F---G main
</code></pre>
<p>즉, 위처럼 2개의 브랜치를 머지한다고 했을 때 각 브랜치의 최신 커밋인 <code>C</code>와 <code>G</code>, 두 브랜치의 공통 조상이 되는 커밋인 <code>E</code>까지 고려해서 머지하는 것이다. 특정 라인이 C 커밋에는 없고 G 커밋에는 있다고 했을 때 이 둘만 가지고는 이 라인이 추가된것인지 제거된 것인지 알 수 없다. 공통 조상이 E 커밋을 봤을 때 해당 라인이 있다면 C 커밋에서 제거한 것이고 E 커밋에 해당 라인이 없다면 G 커밋에서 추가된 것이다.(참고로 git에서 <a href="https://blog.outsider.ne.kr/805">diff3 설정</a>을 하면 충돌이 발생했을 때 공통 조상의 내용도 같이 보여서 수정할 때 편하다.)</p>
<p>여기서 파일 이름 변경까지 되면 훨씬 복잡해진다. 각 브랜치에서 파일 내용을 수정할 수 있지만 파일명을 바꾸거나 파일명은 그대로이지만 디렉터리 위치가 바뀔 수 있다. Git은 파일명을 따로 추적하고 있지 않기 때문에 머지할 때 이 이름 변경을 감지해서 이름이 변경된 파일을 찾아내야 하는 것이다. 위에서 말한 대로 머지를 할 때 3개의 커밋이 필요한데 각 커밋에서 고유의 파일명 목록을 만들고 서로 일일이 비교하면서 내용의 유사성을 비교해서 파일 변경인지를 표시하게 되므로 상당히 느린 부분이다.</p>
<p>코딩에서 추상화는 중요한 개념이지만 때로는 경계를 만들어서 경계에 걸쳐서 어떤 작업을 하려고 할 때 어렵게 만들기도 한다. Git도 이러한 추상화로 인해서 최적화가 어려웠던 경우인데 Git에도 파일 이름 변경을 탐지하는 컴포넌트가 분리되어 있었다. 이 컴포넌트는 3개의 커밋에 대한 정보가 아니라 2개 커밋에 대한 정보만 받고 있었는데 파일 이름 변경을 추적하려면 3개 커밋의 정보가 모두 필요했기 때문에 이 추상화 경계를 넘어서 추가 정보를 제공해야 했다.</p>
<p>또한, rebase나 cherry-pick을 할 때도 각 커밋 단계마다 이름 변경 탐지를 하게 되는데 이게 반복적으로 진행되므로 인메모리에 캐싱해서 개선하게 된다. 당연히 왜 이전에는 안 했는지 궁금할 수 있지만 캐싱해도 동작의 차이가 없는지를 확인하는 것이 아주 복잡했기 때문에 못 했던 것인데 이번에는 몇 가지 제약사항을 가진 채 이 캐싱 최적화를 추가했다.</p>
<p>Git에서 Index라는 것은 보통 우리가 Stage 영역이라고 부르는 것으로 다음 커밋에 포함될 파일에 대한 정보를 가지고 있는 데이터 구조인데 <code>recursive</code> 전략에서는 이 Index 데이터 구조가 핵심이었다(working tree 포함). <code>ort</code> 전략에서는 이 Index를 사용하지 않고 <code>recursive</code>에서 성능에 영향을 많이 주던 <code>unpack_trees()</code>라는 저수준 함수의 사용을 안 하도록 바뀌었다. 그래서 이 두 가지에 의존함으로써 생긴 제약을 대부분 해결할 수 있게 되었다.</p>
<p>다시 정리하면 <code>ort</code>는 index와 working tree를 건드리지 않고 머지 결과를 트리로 만들어서 이 머지 결과가 나왔을 때만 <code>ort</code>가 체크아웃 로직을 이용해서 머지 결과로 이동하게 된다. index에 항목을 추가 제거하는 동작과 머지하면서 수행되는 값비싼 트리 탐색을 피할 수 있게 되어 속도가 훨씬 빨라지게 된다.</p>
<p>최대한 간단히 정리했지만, 이 내용은 이 수많은 최적화 작업을 주도한 <a href="https://github.com/newren">Elijah Newren</a>이 작성한 6편의 글 Optimizing Git’s Merge Machinery, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-1-127ceb0ef2a1">#1</a>, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-2-d81391b97878">#2</a>, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-3-2dc7c7436978">#3</a>, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-part-iv-5bbc4703d050">#4</a>, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-part-v-46ff3710633e">#5</a>, <a href="https://blog.palantir.com/optimizing-gits-merge-machinery-6-7bf887a131d8">#6</a>에 잘 나와 있다. 아주 긴 글이지만 한번 읽어볼 만한 좋은 글이다.</p>
<p><a href="https://github.blog/2021-08-16-highlights-from-git-2-33/#merge-ort-a-new-merge-strategy">Git 2.33 공지</a>에 따르면 ort가 이전보다 훨씬 빨라져서 파일명 변경이 많고 복잡한 머지의 경우 500배가 빨라졌고 rebase 과정에서 비슷한 머지를 반복해서 하게 되면 <code>ort</code>가 일부 계산을 캐싱하기 때문에 9,000배 이상 빨라진다고 한다. 이건 특수한 경우고 일반적으로도 <code>ort</code>가 <code>recursive</code>보다 약간 빠른 것으로 나타났지만 <code>recursive</code>는 상황에 따라 속도 편차가 크지만 <code>ort</code>는 일관된 속도를 보여주었다.</p>
<p>일반적인 상황에서 보통 머지 속도가 문제 되진 않지만 아마 머지와 리베이스를 가장 많이 실행하는 <a href="https://github.blog/2023-07-27-scaling-merge-ort-across-github/">GitHub이 <code>ort</code>를 적용</a>한 결과를 보면 머지 속도가 p50에서는 10배 p99에서는 5배 빨라졌고 리베이스에서도 이전에 512시간 걸리던 리베이스가 <code>ort</code>에서는 33시간으로 줄어들었다는 것을 보면 속도가 얼마나 개선되었는지 알 수 있다.</p>
<p>추가로 Git으로 머지할 때 다음과 같이 어떤 전략이 사용되었는지 나온다.</p>
<pre class="line-numbers"><code class="language-bash">Auto-merging a.txt
Merge made by the 'ort' strategy.
</code></pre>
<p><code>git merge --strategy recursive BRANCH-NAME</code>처럼 머지할 때 <code>-s</code>나 <code>--strategy</code> 옵션으로 머지 전략을 지정하면 다른 머지 전략을 사용할 수 있다. 여기서처럼 <code>ort</code> 대신 <code>recursive</code>를 지정하면 메시지에서도 <code>Merge made by the 'recursive' strategy.</code>라고 나와서 머지 전략이 바뀌었음을 확인할 수 있다.</p>
<p><strong><a href="https://blog.outsider.ne.kr/1707?commentInput=true#entry1707WriteComment">댓글 쓰기</a></strong></p>기술 뉴스 #239 : 24-02-01Outsiderhttps://blog.outsider.ne.kr/17062024-02-01T08:48:28+09:002024-02-01T08:42:55+09:00<h1>웹개발 관련</h1>
<ul>
<li><strong><a href="https://vercel.com/blog/how-core-web-vitals-affect-seo">How Core Web Vitals affect SEO</a></strong> : Google은 Core Web Vitals로 사이트의 성능을 평가해서 SEO에 반영하는데 이 데이터를 실제 사용자에게 수집하므로 필드 데이터라고 부른다. Google은 크롬 브라우저의 실제 사용자의 75 퍼센타일로 전 세계에서 필드 데이터를 수집하기 때문에 사용자는 데스크톱이나 Android에서 Chrome을 사용해야 한다.(다른 말로 하면 iPhone 사용자는 집계되지 않는다) 지역별로 다르게 다루지 않고 전 세계에서 수집하므로 전 세계 모든 사용자에게 뛰어난 성능을 제공할 수 있어야 하고 점수는 지난 28일간의 평균 점수이므로 성능을 개선한 후 영향을 파악하려면 한 달 정도가 걸린다. Lighthouse 등으로 Core Web Vitals를 측정한 것은 실험실 데이터라고 부르는데 이러한 결과는 검색 결과에는 반영되지 않고 실제 사용자와는 다르기 때문에 성능 문제를 찾는 참고용으로 사용해야 한다.(영어)</li>
<li><strong><a href="https://medium.com/rate-labs/quic-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EA%B5%AC%EA%B8%80-%EB%98%90-%EB%84%88%EC%95%BC-932befde91a1">QUIC 프로토콜 | 구글 또 너야?</a></strong> : QUIC 논문을 보고 내용을 정리한 글이다. 불필요한 RTT(Round Trip Time)을 줄이면 페이지 로드 시간에 큰 영향을 주기 때문에 QUIC은 TCP가 아니라 UDP 위에 구현되었는데 QUIC을 설계한 이유는 프로토콜을 변경하기 어렵고 핸드 쉐이크를 줄일 필요가 있었고 HOL 블러킹 문제를 해결하기 위해서였다. 이를 구현한 과정과 적용한 과정까지 정리되어 있다.(한국어)</li>
<li><strong><a href="https://web.dev/blog/interop-2023-wrapup?hl=en">Celebrate a more interoperable web with Interop 2023</a></strong> : 브라우저간 호환성을 유지하기 위해 여러 브라우저가 벤더가 공동으로 테스트를 만들어서 상호 운용성을 개선하기 위한 Interop 2023이 마무리 되었다. <a href="https://web.dev/blog/interop-2023">작년 초와 비교</a>했는때 대부분 90점대 후반으로 큰 개선이 이루어 졌고 <code>:has()</code>, 컨테이너 쿼리, 서비그리드, 색공간 등 주요한 기능이 추가되었다. 곧 Interop 2024가 발표될 예정이다.(영어)</li>
<li><strong><a href="https://www.flightcontrol.dev/blog/nextjs-app-router-migration-the-good-bad-and-ugly">NEXT.JS APP ROUTER MIGRATION: THE GOOD, BAD, AND UGLY</a></strong> : Flightcontrol이라는 서비스가 Next.js의 페이지 라우터로 구축되어 있던 대시보드를 앱 라우터로 다시 구축하면서 경험한 내용을 정리했다. 중첩된 레이아웃을 구축할 수 있게 되었고 로딩 상태를 유연하게 표시할 수 있지만 실시간 업데이트를 위해 클라이언트에서 데이터 불러오는 코드를 중복으로 작성해야 했고 서버 측 오류가 쉽게 삼켜져서 추적하기에 어려웠다고 한다. 지금은 해결되었지만 개발하면서 버그가 너무 많아서 고생했고 개발 서버의 성능이 너무 안 좋아서 성숙도에 비해 너무 빨리 마케팅이 되었다고 한다.(영어)<br />
<br></li>
</ul>
<h1>그 밖의 개발 관련</h1>
<ul>
<li><strong><a href="https://techblog.lycorp.co.jp/ko/about-atlassian-jira-ranking-algorithm-lexorank">Jira의 이슈 정렬 방식이 Integer 방식이 아니라고?!</a></strong> : 드래그 앤 드롭으로 리스트의 정렬을 조정하는 구현을 할 때 각 아이템의 정렬을 관리하는 방식에는 Integer, GreenHopper, Linked List 방식이 있습니다. Integer 방식은 위치를 변경하면 다른 모든 아이템의 값도 변경해야 하고 GreenHopper은 각 아이템 사이에 충분한 간격을 두어 쉽게 업데이트할 수 있지만 공간이 고갈되면 문제가 생긴다. Linked List는 앞뒤 아이템만 업데이트해 주면 되지만 조회할 때 풀 스캔을 해야 한다. Atlassian이 이러한 문제를 해결하기 위해 LexoRank를 만들었고 사전적 정렬을 위해 <code>Bucket|FixedKey:VariableKey</code>를 사용해서 정렬해서 O(1)로 정렬할 수 있으며 공간 고갈 시에는 무중단으로 재조정 할 수 있다.(한국어)</li>
<li><strong><a href="https://techblog.lycorp.co.jp/ko/docusaurus-as-a-technical-document-website">기술 문서 사이트로 Docusaurus 활용하기</a></strong> : Line내에서고 기술 문서의 규모가 커지면서 그때그때 다른 SSG(Static Site Generator)를 쓰게 되면서 공용 SSG를 선정하게 되었다. SSG를 선정하면서 웹 문서에 필요한 기본 기능이 충실하고 새로운 기능을 자유롭게 추가할 수 있어야 한다는 기준을 정하고 2세대 SSG 도구 중에 React 기반이면서 MDX도 지원하는 Docusaurus를 선정했다. 기술 문서에 필요한 기능을 추가하기 위해 줄 바꿈 테이블, 용어집, API 레퍼런스 기능을 만든 과정을 설명한다.(한국어)</li>
<li><strong><a href="https://techblog.lycorp.co.jp/ko/developing-android-ui-with-jetpack-compose">Jetpack Compose로 LINE 앱 Yahoo!검색 모듈 개발하기</a></strong> : Line에서 선언적 UI 툴킷인 Jetpack Compose를 도입한 과정을 설명한 글이다. 기존 앱을 운영하면서 도입해야 했기에 새로운 뷰에 도입하기로 하고 Composable에 도입하기로 조건을 걸고 선언적 UI를 위해 상태관리를 일원화하고 Composable을 stateless로 만들고 만든 Composable은 미리보기로 만들고 미리보기는 Pull Request에 포함하기로 하면서 Jatpack Compose 도입을 했다고 한다.(한국어)</li>
<li><strong><a href="https://zed.dev/blog/zed-is-now-open-source">Zed is now open source</a></strong> : GitHub의 Atom을 만들던 개발자가 나와서 만든 Zed 에디터가 오픈소스가 되었다. 오픈소스로 해야 최고의 제품이 될 수 있고 훨씬 더 재밌을 거로 생각해서 오픈소스로 공개했다고 한다.(영어)<br />
<br></li>
</ul>
<h1>인프라 관련</h1>
<ul>
<li><strong><a href="https://istio.io/latest/blog/2024/inpod-traffic-redirection-ambient/">Maturing Istio Ambient: Compatibility Across Various Kubernetes Providers and CNIs</a></strong> : Istio의 사이드카 없는 버전인 Ambient Mesh를 구현하고 작년 알파를 출시해서 Ambient 모드의 가치를 입증하는 데 중점 했으나 초기 메커니즘이 다른 CNI와 충돌하는 것을 알게 되었고 사용자들은 어디서나 모든 CNI 구현에서 Ambient 모드를 원한다는 것을 알게 되고 베타버전으로 가기 전에 가장 중요한 요구사항이 되었다. <code>istio-cni</code>는 기본 CNI 구현이 아니고 클러스터의 기본 CNI를 확장하는 노드 에이전트인데 이 초기 구현이 기본 CNI 구현의 네트워킹 구성과 충돌이 발생하고 적용한 네트워크 정책도 상황에 따라 Istio CNI 확장에서 적용되지 않을 수 있어서 이 요구사항을 충족할 수 없다는 게 확실해졌다. 새로운 솔루션을 찾기 시작했고 사이드카를 모방하여 파드의 네트워크 네임스페이스에서 리다이렉션을 구성하는 아이디어가 나왔고 Linux 소켓의 기본 기능을 이용해서 다른 네임스페이스 내의 수신 소켓을 생성하고 소유할 수 있다는 걸 알게 되고 이를 구현하기로 했고 그 결과 모든 트래픽 캡처와 리다이렉션이 파트의 네임스페이스 내부에서 발생하고 마치 사이드카 프록시가 있는 것처럼 보이게 되었다.(영어)</li>
<li><strong><a href="https://github.blog/2024-01-17-github-hosted-runners-double-the-power-for-open-source/">GitHub-hosted runners: Double the power for open source</a></strong> : GitHub이 공개 저장소에서 사용하는 GitHub Actions은 무료로 제공하고 있었고 기존에는 2 vCPU 머신을 사용하고 있었는데 2023년 1월부터 Linux와 Windows의 러너를 새로운 4 vCPU, 16 GiB 메모리, 150 Gib 스토리지로 2배 업그레이드를 진행했다. 그 결과 기존보다 25% 속도가 빨라졌다고 한다.(영어)</li>
<li><strong><a href="https://www.bitsand.cloud/posts/slashing-data-transfer-costs/">Slashing Data Transfer Costs in AWS by 99%</a></strong> : AWS에서 가용영역(AZ)간에 데이터를 전송하면 비용이 발생한다. S3는 1a, 1b 같은 AZ 단위가 아니라 리전 단위로 버킷을 저장하므로 같은 리전에 모든 AZ에서 똑같이 사용할 수 있으며 (공용 인터넷이 아니라면) 다운로드와 업로드가 무료이며 스토리지 비용은 시간단위로 부과된다. 이 두가지 특징을 이용해서 1a에 있는 인스턴스에서 1b에 있는 인스턴스로 데이터를 보낼 때 직접 보내는 대신 S3를 거쳐서 보내도록 해서 비용을 절감하겠다는 아이디어이다.(전송후에는 S3에서 지워서 스토리지 비용을 아낀다) 직접 테스트로 1TB를 전송했을 때 직접 보내면 20.48달러가 청구되었지만, S3를 통해서 보낼 때는 8센트만 청구되었다.(영어)</li>
<li><strong><a href="https://www.docker.com/blog/introducing-docker-build-cloud/">Introducing Docker Build Cloud: A New Solution to Speed Up Build Times and Improve Developer Productivity</a></strong> : Docker에서 <a href="https://www.docker.com/products/build-cloud/">build cloud</a>를 공개했다. 시간이 지나면서 빌드 시간은 점점 길어지는 데 빌드 클라우드를 이용하면 빌드 시간도 39배 빨라지고 멀티아키텍처 빌드도 할 수 있다고 소개한다.(영어)</li>
<li><strong><a href="https://blog.cloudflare.com/ddos-threat-report-2023-q4-ko-kr">2023년 4분기 DDoS 위협 보고서</a></strong> : Cloudflare에서 2023년 4분기 DDoS 위협 보고서를 공개했다. 여기서 나오는 DDoS 공격은 처리량보다 더 많은 요청을 보내는 HTTP 요청 집중형 DDoS, 라우터/방화벽/서버에서 처리할 수 있는 패킷보다 더 많은 패킷을 보내는 IP 패킷 집중형 DDoS, 인터넷을 포화 상태로 만드는 비트 집중형 DDoS 세가지 유형이 있다. 이전에 비해 HTTP DDoS 공격을 줄어들고 Network 계층의 DDoS 공격 증가하고 있다. 분야별 지역별 DDoS 위협을 살펴볼 수 있다.(한국어)<br />
<br></li>
</ul>
<h1>볼만한 링크</h1>
<ul>
<li><strong><a href="https://grafana.com/story-of-grafana/">The Story of Grafana | The Grafana documentary: The first 10 years</a></strong> : Grafana가 10주년을 기념해서 다큐멘터리를 만들고 있다. 1편 Democratize Metrics, 2편 Community, 3편 Open (Source) for Business까지 나왔고 4편은 곧 나올 예정이다.(영어)</li>
<li><strong><a href="https://01010011.blog/2024/01/28/%eb%a6%ac%eb%b7%b0-q60max-%ed%98%84%ec%a1%b4-%ec%b5%9c%ea%b3%a0%ec%9d%98-hhkb-%eb%b0%b0%ec%97%b4-%ea%b8%b0%ea%b3%84%ec%8b%9d-%ed%82%a4%eb%b3%b4%eb%93%9c/">[리뷰] Q60MAX – 현존 최고의 HHKB 배열 기계식 키보드</a></strong> : 키크론 Q60 MAX에 대한 리뷰입니다. HHKB 키보드 배열의 장점과 정적 용량 무접점의 특징까지 설명한 뒤 키크론 Q60 MAX가 기계식임에도 좋은 키감을 커스텀 키보드이면서 완성품으로 제공하기 때문에 편의성을 주면서 커스텀도 가능해진다. 글을 읽고 나서 사고 싶어졌다.(한국어)</li>
<li><strong><a href="https://note.com/pocketpair/n/n54f674cccc40">3일 후 운명이 결정되는 팔월드라는 우연한 이야기</a></strong> : 요즘 스팀에서 인기라는 팔월드라는 게임이 만들어진 과정에 대한 이야기이다. 작은 게임 회사 입장에서 퍼블리싱이 어렵다는걸 깨닫고 스팀으로 발향을 돌리면서 여러 게임을 만들다가 팔월드라는 인기 게임이 나오기까지 편의점 알바생을 고용하고 게임엔진을 교체하고 모션 디자이너를 고용하고 탈락 시켰던 사람을 채용했는데 그 사람이 너무 잘하는 등 수많은 기적 속에 팔월드라는 인기게임을 만들게 되었다는게 그걸 기적으로 설명하는 부분이 현실감있고 재미있다. 일본어인데 번역해서 보면 읽을만 하다.(일본어)</li>
<li><strong><a href="https://github.blog/2024-01-23-good-devex-increases-productivity/">Yes, good DevEx increases productivity. Here is the data.</a></strong> : 개발자 경험(DevEx)을 개선하는 것은 중요한 일이지만 그에 대한 데이터는 많지 않았는데 GitHub이 <a href="https://getdx.com/">DX</a>와 협업해서 생산성에 어떤 영향을 미치는지 연구했다. Slack 메시지 등 모든 방해 요소를 최소화해서 심층 작업(Deep Work)에 충분한 시간을 사용하는 개발자는 생산성이 50% 향상되고 코드에 대한 이해도가 높은 개발자가 아닌 개발자보다 생산성이 42% 높았고 피드백 루프가 중요하기 때문에 코드 리뷰가 빠른 등 처리시간이 빠르면 20% 더 혁신적이라고 느꼈다.(영어)<br />
<br></li>
</ul>
<h1>IT 업계 뉴스</h1>
<ul>
<li><strong><a href="https://elists.isoc.org/pipermail/internet-history/2024-January/009265.html">Dave Mills has passed away</a></strong> : NTP(Network Time Protocol)을 발명하고 인터넷 아키텍처 테스크 포스의 초대 의장을 하는 등 인터넷 개발에 여러 가지 기여를 했던 <a href="https://en.wikipedia.org/wiki/David_L._Mills">Dave Mills</a>가 지난 17일 85세의 나이로 세상을 떠났다고 인터넷의 아버지로 알려진 Vinton Cerf가 메일링 리스트의 부고를 전했다. 삼가 고인의 명복을 빕니다.(영어)</li>
<li><strong><a href="https://www.theverge.com/2024/1/16/24039983/supreme-court-epic-apple-antitrust-case-rejected">Supreme Court rejects Epic v. Apple antitrust case</a></strong> : Epic Games가 2020년 포트나이트에서 자체 결제시스템을 도입하자 Apple이 포트나이트를 앱 스토어에서 차단하면서 시작된 소송인데 대법원에서 두회사가 각기 제기한 청원을 기각함으로써 재판이 끝났다. 이 기각으로 애플은 앱 스토어에서 다른 결제 수단을 금지하는 것이 반경쟁적 행위라고 판단했으므로 애플은 다른 결제시스템을 허용해야 하게 되었고 Epic Games가 주장했던 다른 스토어를 통해서 iOS에 앱을 배포하도록 허용하도록 하는데까지는 실패했다.(영어)</li>
<li><strong><a href="https://www.bnnbloomberg.ca/adobe-gives-up-on-web-design-product-to-rival-figma-after-deal-collapse-1.2028498">Adobe Gives Up on Web-Design Product to Rival Figma After Deal Collapse</a></strong> : Figma 인수를 포기한 Aodbe가 Figma의 경쟁 제품인 Adobe XD를 유지 보수 모드로 전환하고 새 기능 추가도 안 하고 따로 판매도 안 할 생각이라고 발표했다. 2022년 XD의 연간 매출은 1,700만 달러였고 개발자는 19명뿐이었다고 한다.(영어)</li>
<li><strong><a href="https://opensource.org/license/blue-oak-model-license/">Blue Oak Model License</a></strong> : Open Source initiative가 권한을 최대한 부여하고 기여자를 보호하는 Blue Oak Model 라이센스를 오픈소스 라이센스로 승인했다.(영어)<br />
<br></li>
</ul>
<h1>프로젝트</h1>
<ul>
<li><strong><a href="https://notion-avatar.vercel.app/ko">Notion Avatar Maker</a></strong> : Notion 스타일로 아바타를 만들어주는 서비스<br />
<br></li>
</ul>
<h1>버전 업데이트</h1>
<ul>
<li><strong><a href="https://astro.build/">astro</a> v4.2</strong> : JavaScript 웹 프레임워크, <a href="https://astro.build/blog/astro-420/">릴리스 공지</a></li>
<li><strong><a href="https://expo.dev/">Expo</a> 50</strong> : React로 네이티브 앱을 만드는 플랫폼 SDK, <a href="https://expo.dev/changelog/2024/01-18-sdk-50">릴리스 공지</a></li>
<li><strong><a href="https://angular.io/">Angular</a> v17.1.0</strong> : JavaScript 프레임워크, <a href="https://github.com/angular/angular/releases/tag/17.1.0">변경사항</a></li>
<li><strong><a href="https://about.gitlab.com/">GitLab</a> v16.8</strong> : 오픈소스 설치형 Git 플랫폼, <a href="https://about.gitlab.com/releases/2024/01/18/gitlab-16-8-released/">릴리스 공지</a></li>
<li><strong><a href="https://keda.sh/">KEDA</a> v2.13.0</strong> : Kubernetes 오토스케일러, <a href="https://github.com/kedacore/keda/releases/tag/v2.13.0">릴리스 공지</a></li>
<li><strong><a href="https://ionicframework.com/">Ionic</a> v7.6</strong> : 하이브리드 모바일 앱 프레임워크, <a href="https://ionic.io/blog/announcing-ionic-7-6">릴리스 공지</a></li>
<li><strong><a href="https://www.elastic.co/kr/products">Elastic Stack</a> v8.12.0</strong> : 엘라스틱 스택, <a href="https://www.elastic.co/kr/blog/whats-new-elasticsearch-platform-8-12-0">릴리스 공지</a></li>
<li><strong><a href="https://www.terraform.io/">Terraform</a> v1.7</strong> : Infrastructure as Code 도구, <a href="https://www.hashicorp.com/blog/terraform-1-7-adds-test-mocking-and-config-driven-remove">릴리스 공지</a><br />
<br />
<ul>
<li>1.6에서 추가된 테스트 프레임워크에 <code>mock_provider</code>가 추가되었다.</li>
</ul></li>
<li><strong><a href="https://querydsl.com/">QueryDSL</a> v5.1.0</strong> : Java용 쿼리 프레임워크, <a href="https://github.com/querydsl/querydsl/releases/tag/QUERYDSL_5_1_0">릴리스 공지</a></li>
<li><strong><a href="https://airbnb.design/lottie/">Lottie for Android</a> v6.3.0</strong> : After Effects 애니메이션 랜더링 라이브러리, <a href="https://github.com/airbnb/lottie-android/releases/tag/v6.3.0">릴리스 공지</a></li>
<li><strong><a href="https://grafana.com/oss/beyla-ebpf/">Grafana Beyla</a> 1.2.0</strong> : eBPF를 이용한 자동 계측, <a href="https://grafana.com/blog/2024/01/24/grafana-beyla-1.2-release-ebpf-auto-instrumentation-with-full-kubernetes-support/">릴리스 공지</a></li>
<li><strong><a href="https://deno.land/">Deno</a> v1.40.0</strong> : TypeScript 런타임, <a href="https://deno.com/blog/v1.40">릴리스 공지</a></li>
<li><strong><a href="https://undici.nodejs.org/">undici</a> v6.5.0</strong> : Node.js HTTP 클라이언트, <a href="https://github.com/nodejs/undici/releases/tag/v6.5.0">릴리스 공지</a></li>
<li><strong><a href="https://podman.io/">podman</a> v4.9.0</strong> : 컨테이너 엔진, <a href="https://github.com/containers/podman/releases/tag/v4.9.0">릴리스 공지</a></li>
<li><strong><a href="http://grafana.org/">Grafana</a> v10.3</strong> : 매트릭 대쉬보드, <a href="https://grafana.com/blog/2024/01/23/grafana-10.3-release-canvas-panel-updates-multi-stack-data-sources-and-more/">릴리스 공지</a></li>
<li><strong><a href="https://facebook.github.io/relay/">Relay</a> v16.2.0</strong> : 데이터주도 Recat 애플리케이션용 프레임워크, <a href="https://github.com/facebook/relay/releases/tag/v16.2.0">릴리스 공지</a></li>
<li><strong><a href="https://line.github.io/armeria/">Armeria</a> v1.27.0</strong> : Java용 비동기 RPC/REST 라이브러리, <a href="https://armeria.dev/release-notes/1.27.0/">릴리스 공지</a></li>
<li><strong><a href="https://www.pgbouncer.org/">PgBouncer</a> v1.22.0</strong> : PostgreSQL 커넥션 풀, <a href="https://www.postgresql.org/about/news/pgbouncer-1220-released-2802/">릴리스 공지</a></li>
<li><strong><a href="https://turborepo.org/">Turborepo</a> v1.12.0</strong> : JavaScript/TypeScript 빌드 시스템, <a href="https://turbo.build/blog/turbo-1-12-0">릴리스 공지</a></li>
<li><strong><a href="http://pytorch.org/">PyTorch</a> v2.2.0</strong> : Python 딥러닝 프레임워크, <a href="https://pytorch.org/blog/pytorch2-2/">릴리스 공지</a></li>
<li><strong><a href="https://nuxt.com/">Nuxt</a> v3.10.0</strong> : 서버렌더링 Vue.js 애플리케이션 프레임워크, <a href="https://nuxt.com/blog/v3-10">릴리스 공지</a></li>
<li><strong><a href="https://ui.nuxt.com/">Nuxt UI</a> v2.13.0</strong> : UI 라이브러리, <a href="https://github.com/nuxt/ui/releases/tag/v2.13.0">릴리스 공지</a></li>
<li><strong><a href="https://www.prisma.io/">Prisma</a> v5.9.0</strong> : TypeScript/Node.js 데이터베이스 툴킷, <a href="https://github.com/prisma/prisma/releases/tag/5.9.0">릴리스 공지</a></li>
</ul>
<p><strong><a href="https://blog.outsider.ne.kr/1706?commentInput=true#entry1706WriteComment">댓글 쓰기</a></strong></p>