Next.js 기술 블로그 최신 글
Next.js(넥스트.js) 렌더링, 라우팅, 캐시와 웹 서비스 운영 사례를 다룬 회사 기술 블로그 글입니다.
Next.js 관련 최신 기술 블로그 글
앱 리뷰 자동화 일주일만에 만들기
3년 동안 쌓이기만 하던 원티드 앱 리뷰에 다시 답글을 달기 시작했다. 원티드 Android, iOS 앱 리뷰는 거의 3년째 방치되어 있었습니다. 조직 개편이 진행되는 동안 누가 담당자인지 모호해졌습니다. 다들 언젠가 해야 한다고는 생각했지만 막상 누구 일도 아닌 상태로 시간이 흘렀 버렸습니다. 그러던 중 iOS개발자였던 찬주님이 슬랙에 위와 같은 아이디어를 올렸고, Android도 동일한 상황이라 이번에 앱 개발자 두 명(Android, iOS)이 직접 이 일을 정리해 보기로 했습니다. 일주일 동안 만든 건 이런 사이트 입니다. 하는 일은 단순합니다. 1시간마다 App Store와 Google Play에서 새 리뷰를 가져온다. 새 리뷰를 Slack 채널에 올리고, AI가 쓴 답글 초안을 스레드에 단다. 사람이 초안을 읽고 승인 이모지를 누르면 스토어에 답글이 올라간다. 버그 제보나 기능 제안이면 이모지 하나로 Jira 이슈를 만든다. Web에서는 리뷰를 걸러 보고, 답글을 고쳐서 게시하고, 통계를 본다. AI가 답글을 쓰긴 하지만 사람이 확인하지 않은 답글은 절대 올라가지 않습니다. 스토어 답글은 한 번 게시하면 사용자에게 바로 전달되기 때문에 이것만큼은 처음부터 정해 두고 시작했습니다. 스펙은 화면을 보면서 정했다 이 프로젝트에는 기획자도 디자이너도 없었습니다. 일단 스펙 문서부터 작성했지만 문서만으로는 자연스럽게 소통하기 힘들었습니다. 그래서 스펙을 Claude에게 보여 주고 이렇게 부탁했습니다. [문서]의 기능을 만들 건데, Claude Design에게 시킬 프롬프트를 작성해 줘. 프롬프트를 Claude Design에 넣자 리뷰 목록, 상세, 게시 확인, 통계, 배치 상태 화면까지 초안이 한 번에 나왔습니다. 여기서부터는 화면을 같이 보면서 바로바로 피드백을 주고받을 수 있었습니다. “통계에 Jira 이슈 수도 넣자”, “목록에서는 답글 게시 전 초안을 숨기자”, “게시 버튼 앞에 내용을 끝까지 확인했다는 체크를 두자” 같은 이야기가 화면 위에서 나왔고, 그렇게 정한 내용을 스펙으로 옮겼습니다. 글로만 논의할 땐 나오지 않던 피드백들이 자연스럽게 쏟아져 나왔습니다. Montage 디자인 시스템도 큰 역할을 했습니다. Claude Design에 원티드 디자인 시스템인 Montage를 연결해 두었더니 첫 초안부터 기존 원티드 서비스와 같은 버튼, 색, 글꼴로 나왔습니다. 웹 화면도 사내 표준 스택(Next.js + Montage)을 따랐기 때문에 목업을 코드로 옮길 때 같은 컴포넌트를 그대로 가져다 쓸 수 있었습니다. 디자이너 없이 만든 화면인데 어색하지 않은 건 Montage 덕분입니다. 사내 도구를 이어 붙여서 만들었다 Backyard: 웹 프론트, API 서버, DB Backyard는 원티드랩 사내 구성원들을 위한 샌드박스 실행 환경입니다. Kubernetes(이하 k8s) 위에서 돌아가고, 프로젝트를 하나 만들면 그 프로젝트만 쓰는 공간이 생깁니다. 그 안에서 웹 프론트엔드, 백엔드 API 서버, MySQL DB를 켜고 끌 수 있고, 필요하면 Redis와 S3 저장소도 붙일 수 있습니다. 각 구성 요소는 컨테이너로 뜨고, k8s 배포 설정, 서비스, 도메인 연결은 Backyard가 대신 만듭니다. Backyard가 MCP를 제공해주기 때문에 개발자는 k8s 설정 파일을 쓸 필요 없이 자연어로 “이 프로젝트에 프론트, 백엔드, DB를 켜줘.” 라고만 말해도 알아서 세팅해 줍니다. 배포는 도커 이미지를 올리는 것으로 끝납니다. 프로젝트 전용 레지스트리에 latest 태그로 이미지를 push하면, Backyard가 이를 감지해 실행 중인 컨테이너를 새 이미지로 차례로 교체합니다. 이 또한 자연어로 “Backyard로 배포해줘"라고만 말하면 됩니다. 덕분에 서버 신청이나 DB 발급을 기다릴 필요가 없었고, 킥오프 당일에 백엔드와 DB가 이미 떠 있었습니다. Ennoia: AI 에이전트 Ennoia는 원티드에서 운영하는 AI 에이전트 플랫폼으로, 에이전트를 자연어로 쉽게 만들 수 있습니다. 여기에 에이전트를 만들
원티드랩 기술 블로그 - Medium2026년 10월 21일AWS Lambda Web Functions 정식 출시
오늘 AWS는 코드를 이벤트 핸들러로 다시 작성하지 않고도 Lambda에서 표준 HTTP 웹 애플리케이션을 실행할 수 있는 새로운 폼 팩터인 AWS Lambda Web Functions를 발표합니다. Express, Hono, Fastify, Next.js 등의 Node.js 프레임워크로 구축한 표준 포트 리스닝 서버를 단일 명령으로 배포할 수 있으며, Lambda가 자동으로 확장, 다중 리전 배포 및 활성 CPU 사용량 기반 청구를 처리합니다. 어댑터도, […]
Amazon Web Services 한국 블로그2026년 10월 13일FE News 26년 10월 소식을 전해드립니다.
주요소식 The Story of VS Code Visual Studio Code 공식 채널이 공개한 약 1시간 38분 분량의 다큐멘터리로, Erich Gamma가 이끈 취리히 팀이 브라우저용 편집기 컴포넌트 Monaco Editor를 만들던 시기부터 데스크톱 VS Code 발표와 오픈 소스 전환까지의 과정을 30여 명의 관계자 인터뷰로 보여 준다. 확장을 별도 프로세스에서 실행하고 한번 공개한 API는 바꾸지 않는 원칙, TypeScript 서버에서 출발한 LSP, UI와 확장 호스트를 분리한 구조가 원격 개발과 vscode.dev로 이어진 배경을 설명한다. 후반부에서는 GitHub Copilot의 출발과 Ask, Edits, Agent Mode로 이어진 AI 기능, Cursor 같은 포크를 바라보는 VS Code 팀의 시각도 소개한다. Native is now the future of mobile at Shopify 2020년 React Native 전면 도입을 선언했던 Shopify가 모바일 앱을 다시 Swift와 Kotlin 네이티브로 옮긴다고 발표했다. 코딩 에이전트 덕분에 두 플랫폼에 각각 구현하는 비용이 줄면서 공유 구현보다 네이티브의 이점이 커졌다는 판단으로, Shop 앱은 12주 만에 재구축했고 화면을 작은 체크포인트로 나눠 테스트, 시각 비교, 적대적 코드 리뷰, 사람의 승인을 거치게 하는 Helix 시스템을 만들었다. React Native Skia, FlashList, Restyle 등 Shopify가 관리해 온 오픈소스의 향후 계획도 공개해, 이 라이브러리를 쓰는 프로젝트라면 전환 일정을 확인해 둬야 한다. 토스 FE 개발자들의 검증법 토스 웨비나에서 Front AI 팀이 AI로 만든 결과물을 검증하는 방법을 소개한 세션이다. 코드에서 시나리오를 추론해 E2E 테스트를 자동 생성하려던 시도가 실패한 뒤, 얼굴 인식 결제처럼 실수 비용이 큰 영역에서 테스트를 직접 작성하며 디바이스 팜 조작 도구, 액션 로그 조회 스킬처럼 테스트를 막던 요소를 해결하는 도구를 만들어 온 과정을 설명한다. 사람이 CI 실패 원인을 파악하도록 만든 replay 도구를 에이전트에 그대로 넘기자 버튼 문구 변경 같은 실패를 스스로 고쳤다는 경험은 AI 검증 체계를 고민하는 FE 팀이 참고할 만하다. penpot 브라우저에서 쓰거나 직접 설치해 운영할 수 있는 오픈소스 디자인, 프로토타이핑 플랫폼이다. 디자인을 SVG, CSS, HTML 같은 개방형 표준으로 표현하고 CSS Grid와 Flex 레이아웃, 디자인 토큰, 컴포넌트를 기본 기능으로 제공하며, MCP 서버를 통해 Cursor나 Claude Code 같은 AI 에이전트가 컴포넌트, 토큰, 레이어 구조를 읽고 수정할 수 있다. 셀프 호스팅이 가능해 디자인 데이터를 사내에 두어야 하는 조직이 검토해 볼 만한 MPL-2.0 라이선스 프로젝트다. Full Course: Spec-Driven Development with Coding Agents DeepLearning.AI와 JetBrains가 만든 명세 주도 개발(Spec-Driven Development) 강좌의 전체 영상으로, 마크다운 명세를 먼저 쓰고 코딩 에이전트가 이를 구현하게 하는 흐름을 WebStorm과 Claude Code로 Next.js 예제 앱을 만들며 보여 준다. mission.md, techstack.md, roadmap.md로 프로젝트 헌장을 만든 뒤 기능마다 명세를 작성하고 컨텍스트를 비운 상태에서 구현을 맡기는 반복 과정을 설명한다. 기존 코드베이스에서 헌장을 역으로 만드는 방법과 Spec Kit, OpenSpec 같은 공개 SDD 도구도 소개해, 코딩 에이전트 결과물의 일관성을 고민하는 개발자에게 도움이 된다. >> FE News 26년 10월 소식 보러가기 ◎ FE News란? 네이버 FE 엔지니어들이 엄선한 양질의 FE 및 주요한 기술 소식들을 큐레이션해 공유하는 것을 목표로 하며, 이를 통해 국내 개발자들에게 지식 공유에 대한 가치 인식과 성장에 도움
NAVER D22026년 10월 7일FE News 26년 9월 소식을 전해드립니다.
26년 9월 소식에서는 다음과 같은 유용한 정보들을 만나보실 수 있습니다. 주요소식 The AI Engineering Skills Map Andrew Ng이 DeepLearning.AI 팀과 함께 1만 건이 넘는 채용 공고 분석과 전문가 인터뷰, 설문을 종합해 정리한 AI 엔지니어링 역량 지도다. AI 애플리케이션 구축·배포, 소프트웨어 엔지니어링 기본기, 코딩 에이전트 활용, 그리고 무엇을 만들지 정하는 일(shaping the build) 네 가지를 지금 익힐 가치가 큰 역량으로 꼽는다. 저자는 이 역량들이 "AI 엔지니어"라는 직함에 한정되지 않고 풀스택, 데이터, DevOps를 포함한 모든 개발자에게 필요해진다고 보며, 앞으로 무엇을 학습 우선순위에 둘지 고민하는 개발자에게 참고할 만한 정리다. How We Migrated lovable.dev Away from Next.js 월 4,200만 방문 규모의 lovable.dev를 Next.js에서 Cloudflare workerd 런타임 위의 TanStack Start로 옮긴 기록이다. 전면 재작성 대신 6개월간 두 프레임워크를 동시에 운영하면서 프록시 워커가 라우트 단위로 분기하도록 하고, 사용자 여정에 따라 묶은 라우트 그룹을 순차 전환했으며 실제 코드 이전은 대부분 AI 에이전트가 처리했다. 빌드 시간은 6~9분으로 줄고 중위 TTFB는 49% 빨라졌으며 개발 환경 메모리 사용량은 8GB에서 1.5GB로 내려간 수치도 함께 공개해, 대규모 프로덕션 앱의 프레임워크 전환을 무중단으로 진행하는 방법론으로 참고할 만하다. How AI text watermarking works: a visual guide AI가 생성한 텍스트에 눈에 보이지 않는 표식이 어떻게 새겨지는지를 다섯 단계로 나눠 시각적으로 설명하는 가이드다. 워터마크는 글자가 아니라 단어와 단어 사이의 선택에 숨는데, 비밀 키로 후보 단어를 초록과 빨강으로 나누고 초록 쪽으로 확률을 살짝 기울인 뒤 검출 시 같은 방식으로 다시 색을 칠해 초록 비율을 세는 방식이다. 가벼운 편집은 표식을 희석하는 정도지만 표현이 겹치지 않게 다시 쓰면 사실상 지워지고, 키를 가진 쪽만 검증할 수 있어 공개된 "AI 탐지기" 사이트로는 확인할 수 없다는 실무적인 한계도 함께 짚는다. Bun 1.4 Bun 1.4의 헤드라인은 코어를 Zig에서 Rust로 재작성한 것이다. 시작 시간은 Linux에서 2배, Windows에서 2.5배 빨라졌고 HTTP 서버의 메모리 사용량은 13~48% 줄었다. 내장 헤드리스 브라우저 자동화(Bun.WebView), Bun.Image, Bun.markdown, Terminal과 cron API가 추가되었고 Node.js 26.3.0 호환으로 1,517개 테스트가 새로 통과한다. React 사용자에게 눈에 띄는 것은 React Compiler 지원으로, Babel이나 SWC를 거치지 않고 Bun 자체 파서 안에서 컴파일러가 돌기 때문에 약 860개 컴포넌트 규모의 코드베이스에서 빌드 시간이 71ms 늘어나는 데 그쳐 Babel 플러그인 대비 약 20배 빠르다. Next.js 16.3 Next.js 16.0 이후 가장 큰 업데이트로, 코드 변경 없이 얻는 개선과 옵트인 기능이 함께 담겼다. dev 서버는 Turbopack의 디스크 캐싱과 메모리 축출이 기본 활성화되어 메모리 사용량이 최대 90% 줄었고, next build에도 디스크 캐싱이 적용되어 CI 반복 빌드가 최대 5.5배 빨라졌다. 옵트인 기능인 Instant Navigations는 cacheComponents와 partialPrefetching 플래그를 켜면 Suspense 인라인 로딩 상태나 'use cache'로 표시한 UI를 추출해 내비게이션 전에 클라이언트로 실어 보내, 서버 주도 모델을 유지하면서 SPA 수준의 반응성을 확보한다. 이 외에 retry()로 서버 컴포넌트를 다시 가져올 수 있는 catchError 에러 바운더리, Vite 호환 import.meta.glob, root params가 추가되었
NAVER D22026년 9월 3일끝나지 않는 루프 에이전트를 멈추기까지
WORXPHERE 끝나지 않는 AI 에이전트 루프를 멈추기까지 React On Rails → Next.js 마이그레이션으로 시작한 루프 엔지니어링 안녕하세요. 웍스피어에서 잡플래닛 서비스를 담당하고 있는 프론트엔드 개발자 강태완입니다. 잡플래닛은 10년 넘게 운영된 서비스입니다. 오랜 시간 서비스를 운영하면서 Rails 위에 React가 붙고, 거기에 Next.js까지 들어왔습니다. 지금의 프론트엔드를 아주 단순하게 표현하면 대략 이런 구조입니다. 오래된 화면은 Rails가 렌더링하고, 그 안에서 React 컴포넌트가 동작합니다. 페이지를 이동하면 React가 들고 있던 상태도 함께 사라집니다. 한 페이지 안에서는 React를 사용하고 있지만, 페이지를 넘어 상태를 이어가기는 어렵습니다. 이전 단계의 값을 다시 전달하거나 복원하는 별도의 처리가 필요해서 페이지가 이어질수록 처리도 복잡해졌습니다. SEO도 비슷했습니다. 못 하는 건 아니지만, Rails와 React에 렌더링이 나뉘어 있다 보니 페이지마다 따로 챙겨야 할 부분이 있었습니다. 이런 불편함 때문에 지금은 오래된 Rails 페이지를 하나씩 Next.js로 옮기고 있습니다. 그런데 마이그레이션 기간이 길어질수록 또 다른 문제가 생겼습니다. 아직 안 옮긴 페이지는 Rails에 있고, 옮긴 페이지는 Next.js에 있습니다. 예를 들어 Rails와 Next.js 양쪽에서 공통으로 노출되는 상단 GNB를 수정하려면 두 프로젝트를 모두 수정해야 합니다. 한쪽만 고치면요? 당장은 아무 일도 일어나지 않습니다. 그리고 한참 뒤에 누군가 발견합니다. “어? 여기랑 저기 UI가 다른데요?” 그때 알게 됩니다. 아, 한쪽만 고쳤구나. 그래서 가능한 한 빨리 마이그레이션을 끝내는 것 자체가 이중 관리 비용을 줄이는 방법이었습니다. 문제는 옮겨야 할 페이지가 한두 개가 아니었다는 겁니다. 페이지마다 원본을 확인하고, Next.js로 구현하고, 다시 원본과 비교하는 비슷한 작업이 계속 반복됐습니다. 이 반복을 좀 줄여보고 싶어서 AI 에이전트를 사용하기 시작했습니다. 에이전트를 썼는데, 제가 더 바빠졌습니다 처음에는 단순하게 생각했습니다. “이 Rails 페이지를 Next.js로 옮겨줘.” 에이전트가 구현하면 결과를 확인하고, 다른 부분이 보이면 다시 요청했습니다. 수정이 끝나면 또 확인했습니다. 페이지 하나를 옮기는 데도 이 과정을 몇 번씩 반복해야 했습니다. 페이지가 많아지니 제가 확인해야 할 결과도 같이 늘어났고요. 에이전트를 쓰면 제가 편해져야 하는데, 제가 계속 에이전트를 감시하고 있었습니다. AI가 코드를 쓰는 속도보다 사람이 결과를 확인하는 속도가 느렸습니다. 병목은 에이전트가 아니라 사람 쪽에 있었습니다. 그러다 루프 엔지니어링에 대한 이야기를 접했고, 아이디어는 단순했습니다. 에이전트에게 사람이 매번 프롬프트하지 말고, 에이전트에게 프롬프트하는 프로그램을 만들자. 생각해보니 마이그레이션은 이 방식과 꽤 잘 맞아 보였습니다. 이미 원본 Rails 페이지가 있습니다. Next.js로 구현하고, 원본과 비교하고, 다르면 다시 고치면 됩니다. 그래서 사람이 반복하던 요청과 확인을 루프로 옮기기 시작했습니다. Workflow({ scriptPath: '.claude/workflows/rails-migration-loop.js', args: { page: 'welfare-review-write', phase: 'verify', }, }) 구현과 검증을 반복하다 보면 자연스럽게 원본에 가까워지고, 어느 순간 끝날 거라고 생각했습니다. 처음 돌려본 결과는 꽤 인상적이었습니다. 루프가 안 멈췄습니다. “더 고칠 게 있어?”라고 물으면 영원히 끝나지 않는다 첫 시도는 사실상 무한 루프였습니다. 루프에게 준 목표는 단순했습니다. “이 페이지를 Next.js로 옮겨줘.” 문제는 그다음이었습니다. 루프는 매 라운드마다 에이전트에게 “더 고칠 게 있어?”라고 물었습니다. 그러면 에이전트는 항상 고칠 것을 찾아냈습니다. “여백이 2px 정도 어색합니다.” 그걸 고치면 다음에는 타입을 조금
worxphere-tech - Medium2026년 8월 14일FE News 26년 7월 소식을 전해드립니다.
주요소식 26년 6월 소식에서는 다음과 같은 유용한 정보들을 만나보실 수 있습니다. TypeScript 7.0 RC Go로 재작성된 네이티브 컴파일러를 탑재한 TypeScript 7.0의 릴리스 후보(RC)가 공개되었다. 기존 타입 체크 로직과 구조를 그대로 유지한 채 포팅해 6.0보다 약 10배 빠르며, Bloomberg, Figma, Google, Slack, Vercel 등 여러 기업의 팀과 프리릴리스 빌드를 테스트해 왔다. 향후 한 달 내 정식 릴리스될 예정으로, 대규모 코드베이스에서 타입 체크와 빌드 속도로 고생해 온 팀이라면 미리 검증해 볼 가치가 있다. Ship the policy, not the code 프런트엔드와 백엔드처럼 별도로 배포되는 두 시스템에 동일한 비즈니스 규칙을 구현할 때 발생하는 코드 중복과 불일치 문제를 다룬다. 백엔드가 "allowedActions": ["CANCEL"] 같은 결정값을 내려보내거나, CASL이나 JSON Schema 같은 표준 형식으로 정책 자체를 데이터로 직렬화해 전송하는 방안을 제시한다. 마이크로서비스나 BFF 구조에서 규칙 일관성을 고민하는 개발자에게 실용적인 관점을 제공한다. Getting started with loops Claude Code 팀이 코딩 에이전트에게 프롬프트를 반복 입력하는 대신 "루프를 설계"하는 접근을 정리한 글이다. 트리거 방식과 종료 기준에 따라 턴 기반, 목표 기반, 시간 기반, 프로액티브 4가지 유형으로 분류하고, 검증 절차를 스킬(SKILL.md)로 인코딩해 자가 검증 능력을 높이는 방법을 소개한다. 명확한 종료 기준 설정과 대규모 실행 전 파일럿 테스트 등 토큰 사용량 관리 팁도 함께 제안한다. React Doctor AI 에이전트가 작성한 React 코드의 품질 문제를 자동으로 잡아내는 도구다. 상태 관리, 이펙트, 성능, 아키텍처, 보안, 접근성 전반을 검사하며 Next.js, Vite, TanStack, React Native, Expo 등 대부분의 React 환경을 지원한다. Claude Code, Cursor, Codex 같은 AI 에이전트와 연동되고, GitHub Actions를 통한 PR 자동 리뷰도 가능하다. vercel/eve Vercel이 공개한 파일시스템 기반의 지속형(persistent) AI 에이전트 프레임워크다. 시스템 프롬프트는 instructions.md, 도구는 tools/, 온디맨드 절차는 skills/ 디렉터리에 두는 식으로 에이전트의 구성 요소를 코드가 아닌 디렉터리 구조로 관리해 검사와 확장이 쉽다. 마크다운과 타입 정의된 함수만으로 에이전트를 구성하는 접근은 코드 중심 프레임워크 대비 낮은 진입 장벽을 제공한다. >> FE News 26년 7월 소식 보러가기 ◎ FE News란? 네이버 FE 엔지니어들이 엄선한 양질의 FE 및 주요한 기술 소식들을 큐레이션해 공유하는 것을 목표로 하며, 이를 통해 국내 개발자들에게 지식 공유에 대한 가치 인식과 성장에 도움을 주고자 하는 기술소식 공유 프로젝트 입니다. 매월 첫째 주 수요일, 월 1회 발행 되고 있으니 많은 관심 부탁드립니다. ▷ 구독하기
NAVER D22026년 7월 8일Playwright E2E 테스트로 자가개선 루프 구축하기
안녕하세요. 네이버페이 금융FE 팀의 정회원입니다. 사내 ENGINEERING DAY 2026에서 발표한 “AI 에이전트를 위한 Playwright E2E 테스트 하네스 구축하기” 내용을 글로 옮기고 일부 설명을 덧붙였습니다. 발표 영상은 NAVER D2나 YouTube에서 보실 수 있습니다. 검증이 병목이다 2026년, AI가 코드를 짜는 시대가 되며 코딩은 확실히 빨라졌습니다. 제가 주로 작업하는 코드베이스에서 개발자 한 명이 머지한 PR을 세어봤더니, AI 도구를 본격 도입하기 전 9개월은 227건, 도입 후 9개월은 348건으로 1.5배가 됐습니다. 그럼 PR이 늘어난 만큼, 검증도 1.5배 더 잘 되고 있을까요? 한번은 에이전트에게 Next.js 버전 업그레이드를 맡겼더니 얼마 뒤 ‘문제없이 완료했습니다.’ 라고 보고하고 PR도 작성했습니다. 그런데 막상 돌려보니 특정 페이지에서 뒤로가기를 눌렀을 때 기존 동작이 깨져 있었습니다. 프레임워크 내부 구현이 바뀌면서 기존 기능이 영향을 받은 것인데, 에이전트는 이걸 확인하지 않은 채 ‘끝났다’고 보고한 것입니다. 여러분도 누군가가 바이브 코딩하고 검토 없이 올린 PR을 보고 당황하신 적이 있으실 겁니다. PR마다 로컬에 받아 직접 돌려보고, 문제 없는지 확인할 수 있을까요? 쏟아지는 변경을 사람이 일일이 살펴보는 건 현실적으로 불가능합니다. 즉, 코딩은 빨라졌지만 검증이 병목이 된 것입니다. 간단한 스크립트나 사내 도구라면 일단 배포하고, 문제가 생기면 그때 손봐도 됩니다. 하지만 수십만 명이 쓰는 서비스라면, 걸러지지 않은 결함이 심각한 사업적 타격으로 이어질 수 있습니다. 그렇다고 전부 QA 팀에 떠넘길 수도 없는 노릇입니다. AI가 쓴 코드, 어떻게 검증해야 할까요? AI에게 검증할 수단을 주자 https://medium.com/media/c5f0d8d7e564b7e2b450435729f83521/href Claude Code를 만든 Boris Cherny는 얼마 전 X(트위터)에 ‘Claude에게 자기 작업을 검증할 수단을 줘라. 이건 늘 결과를 2~3배 끌어내는 방법이었다.’ 라고 남겼습니다. 모델에게 검증 수단을 제공하는 것이, 모델이 똑똑해질수록 오히려 더 중요해졌다는 이야기였습니다. 개발자가 자신이 쓴 코드의 결함을 잘 못 찾듯, 모델도 자기가 짠 코드에 대해서는 관대합니다. ‘이 정도면 잘했네’ 하고 작업을 끝내버립니다. 모델에게 검증할 수단을 주기 위해 가장 먼저 떠올린 방법은 에이전트가 직접 브라우저를 조작하게 하는 것이었습니다. Vercel의 Agent Browser, Claude의 Chrome 익스텐션, Playwright MCP 같은 도구들이 이미 나와 있었습니다. 이런 도구를 쥐어주면, AI 에이전트도 사람처럼 화면을 확인하고 브라우저를 직접 조작할 수 있습니다. 덕분에 사람이 매번 직접 확인하던 부담은 확실히 줄었습니다. 문제는 코드를 고칠 때마다 에이전트에게 그 시나리오를 처음부터 다시 시켜야 한다는 점이었습니다. 시나리오를 마크다운에 적어두고 반복하게 할 수는 있었지만, 매번 실행이 오래 걸리고, 토큰도 많이 소모됩니다. 무엇보다 결과가 비결정론적입니다. 필요한 건 에이전트가 언제 돌려도 똑같이 동작하는 결정론적인 테스트 코드였습니다. 🥵 에이전트에게 매번 건네는 테스트 시나리오 1. 대출 비교 페이지(/loan)를 연다 2. 한도조회 버튼을 누른다 3. 한도조회 결과가 보이는지 확인한다 매번 처음부터 다시 실행 → 느리고 토큰을 많이 소모 에이전트가 매번 새로 해석해 조작 → 비결정론적 ✅ 한 번 짜두는 테스트 코드 test('한도조회 버튼을 누르면 결과가 보인다', async ({ page }) => { await page.goto('/loan') await page.getByRole('button', { name: '한도조회' }).click() await expect(page.getByRole('heading', { name: '한도조회 결과' })).toBeVisible() }) LLM 없이 즉시 실행 → 빠르고 토큰
NAVER Pay Dev Blog - Medium2026년 7월 3일웹 서버가 터졌다: Next.js SSR에서 TanStack Query gcTime이 만든 OOM
0. 들어가며 안녕하세요. 중고나라 웹개발팀입니다. 현재 중고나라 웹개발팀은 웹 서비스를 리뉴얼하는 과정에서, 기술 스택을 변경하는 큰 규모의 마이그레이션을 진행했습니다. (Next.js Page Router → App Router, React 18 → 19) 리뉴얼을 마치고 출시 전 부하 테스트를 돌렸는데 문제가 터졌습니다. 웹 서버에서 OOM이 발생하는 것입니다. 그래프를 보면 단순한 Memory Peak가 아니었습니다. 메모리가 GC 되지 않고 계속 쌓이는 패턴이었습니다. Memory Leak이 발생해 Pod OOM Killed 확인 (Datadog) 원인을 추적한 결과, Server Component에서 TanStack Query(React Query)의 QueryClient를 클로저가 오랫동안 참조하고 있어 GC되지 못하는 것이 문제였습니다. 이 글에서는 이 메모리 이슈의 원인과 트러블슈팅을 공유하고, 문제의 원인이었던 TanStack Query의 gcTime이 왜 문제가 되었는지 분석한 내용을 설명하고자 합니다. 1. 사전 배경: App Router + TanStack Query SSR 구조 본격적인 트러블슈팅에 앞서, 문제가 발생한 코드를 먼저 짚고 넘어가겠습니다. Next.js App Router에서는 layout과 page가 동일한 요청 스코프 내에서 렌더링됩니다. 이 구조에서 React.cache()로 감싼 QueryClient를 요청 단위로 공유하고, 서버 컴포넌트에서 데이터를 prefetch한 뒤 dehydrate를 통해 클라이언트에 전달하는 패턴을 사용하고 있었습니다. const getQueryClient = React.cache(() => new QueryClient()); React.cache()로 감싼 함수는 동일 요청 내에서 같은 값을 반환하므로, 하나의 요청에서는 하나의 QueryClient가 공유됩니다. 요청이 끝나면 이 QueryClient는 자연스럽게 GC 대상이 되는데, 이 글의 핵심은 바로 이 전제가 깨지는 상황입니다. 전역 layout에서 렌더링되는 GNB 헤더에서, 이 QueryClient를 통해 GNB API를 prefetch하는 구조였습니다. import { dehydrate, HydrationBoundary } from '@tanstack/react-query'; // 서버 컴포넌트 GnbHeader에서 gnb API 응답 캐시 export default async function GnbHeader() { const queryClient = getQueryClient(); await queryClient.prefetchQuery({ queryKey: ["gnb"], staleTime: 1000 * 60 * 30, // 30분 gcTime: 1000 * 60 * 60, // 1시간 queryFn: () => fetchGnb(), }); return ( <HydrationBoundary state={dehydrate(queryClient)}> <HeaderView /> </HydrationBoundary> ); } (fyi. 신규 웹은 TanStack Query v5를 이용하고 있습니다.) GNB는 자주 변하지 않으니 캐시를 오래 유지하겠다는 의도였습니다. 페이지 레벨에서도 동일한 QueryClient를 통해 검색·상품 상세 등의 API를 prefetch했습니다. 즉, 하나의 HTTP 요청 안에서 GNB prefetch, 검색 결과, 상품 상세 등 모든 query 데이터가 하나의 QueryClient 인스턴스에 누적되는 구조였습니다. 정리하면 아래와 같습니다. QueryClient는 React.cache()로 감싸 request scope 내에서 재사용된다. GNB query에 긴 gcTime(1시간)이 설정되어 있다. app/layout.tsx └── Header.tsx (QueryClient 생성 + GNB 캐시 gcTime 1시간) └── page.tsx (동일 QueryClient 재사용, 검색/상품 API 캐시 추가) 기능적으로는 아무 문제가 없었기에, 별다른
중고나라 기술 블로그2026년 3월 4일[디자인 시스템 어떻게 만들었어요?(3)] Tree Shaking과 구형 브라우저 대응
지난번 YDS(Yogiyo Design System) v2 컴포넌트 라이브러리 구축기에 이어, 이번 글에서는 YDS v2 컴포넌트 라이브러리와 같은 외부 라이브러리가 서비스 애플리케이션 번들 결과물에 미치는 영향을 살펴봅니다. 또한, 구형 브라우저에 대한 하위 호환성 확보를 위해 요기요 FE 팀이 거친 기술적인 고민과 그 해결 과정들을 공유하고자 합니다. 들어가며 현재 요기요 FE팀은 주요 FE 프로젝트의 기반 프레임워크로 Next.js를 채택하여 사용하고 있습니다. Next.js는 React 기반의 프레임워크로서 웹 개발에 필요한 도구들을 기본적으로 제공합니다. 이러한 편의성 덕분에 개발자는 인프라 설정보다 비즈니스 로직 구현에 더 집중할 수 있는 환경을 갖추게 됩니다. 반면, 라이브러리를 개발하는 과정에서는 다음과 같은 오해에 빠지기 쉽습니다. 오해 1. Next.js가 알아서 Tree-shaking 해줄 것이다. Next.js automatically optimizes bundles by code splitting, tree-shaking, and other techniques. However, there are some cases where you may need to optimize your bundles manually. Next.js는 Code Splitting과 Tree Shaking을 통해 번들 사이즈를 최적화합니다. 이런 특징 때문에 라이브러리 개발자는 사용하지 않는 코드가 빌드 과정에서 알아서 제거될 것이라고 기대하곤 합니다. 하지만 라이브러리가 Tree shaking이 가능한 요건들을 충족하지 못했다면, 프레임워크의 최적화 기능은 무용지물이 됩니다. 라이브러리가 어떤 모듈 시스템(ESM or CJS)으로 배포되는지, Side-Effect를 어떻게 관리하는지, 하나의 파일로 번들링되어 있는지 혹은 모듈 트리구조를 유지하고 있는지에 따라 Next.js는 불필요한 코드를 제거하지 못하고, 결국 사용되지 않는 코드까지 번들에 포함하는 상황이 발생할 수 있습니다. 오해 2. Next.js를 쓰면 구형 브라우저 호환성 문제에서 자유롭다. Next.js 공식문서에 따르면 fetch, URL, Object.assign() 등 자주 사용되는 폴리필이 기본으로 제공됩니다. next-polyfill-nomodule을 통해 다양한 polyfill을 주입하지만, 이는 <script nomodule> 특성상 Chrome 64 미만의 구형 브라우저에서만 로드됩니다. 또한, ESM을 지원하는 브라우저용인 next-polyfill-module은 제한적인 기능만 지원하고 있습니다. 이 때문에 Promise.allSettled()처럼 Chrome 76부터 지원되는 메서드를 사용할 경우, 64~76 버전 사이의 Chrome 브라우저에서는 polyfill을 지원 받지 못하는 사각지대가 발생합니다. 따라서 프로젝트에서 Next.js 기본 제공 범위를 초과하는 API를 사용하고 있다면, 호환성 보장을 위해 개발자가 직접 누락된 폴리필을 확인하고 대응해야 합니다. 요기요 FE에서는 이러한 문제를 해결하기 위해 라이브러리 번들링 전략 개선과 Custom Polyfill 서비스를 구축하였습니다. 자세한 내용은 아래에서 이어서 설명하겠습니다. Tree Shaking을 위한 여정 ESM Tree shaking은 빌드 과정에서 사용되지 않는 코드를 제거하여 최종 번들 크기를 최적화하는 기법입니다. 정적인 import와 export 구문을 분석해 모듈 간의 참조 관계를 파악하고, 실제 실행에 필요 없는 코드를 선별해 삭제합니다. 결국, 코드의 정적 분석이 가능한 ESM을 채택해야만 완전한 Tree Shaking을 구현할 수 있습니다. 따라서 서비스 애플리케이션의 번들 크기를 최적화해 주기 위해서는 라이브러리 차원에서의 ESM 지원이 필수적입니다. Side-Effect 라이브러리를 ESM으로 배포했다고 해서, Tree Shaking이 자동으로 완벽하게 작동하는 것은 아닙니다. Webpack이나 Rollup 같은 번들러는 애플리케이션의 안전한 동작을
YOGIYO Tech Blog - 요기요 기술블로그 - Medium2026년 2월 26일Next.js에서 QueryClient를 전역변수로 사용해도 될까요?
들어가며 안녕하세요. 펫프렌즈 프리오더팀 프론트엔드 개발자 박재훈입니다. 저희 프론트엔드 챕터에서는 오랜 시간 해결하지 못한 과제가 있었습니다. 바로 Next.js 서버의 메모리 누수 현상인데요. 펫프렌즈 서비스는 상품 상세 페이지를 시작으로 점진적으로 Vue.js에서 Next.js로 전환해왔으며, 현재는 대부분의 화면이 Next.js 기반으로 동작하고 있습니다. 트래픽이 증가하면서 메모리 사용량이 늘어나는 것은 자연스러운 현상입니다. 하지만 저희가 마주한 상황은 달랐습니다. 메모리 사용량이 시간이 지날수록 계속 증가했고, GC가 제대로 동작하지 않았으며, 결국 서버가 OOM(Out of Memory) 직전까지 메모리를 사용하여 서버를 재실행하는 일이 반복되었습니다. 제목을 보시면 어떤 문제였는지 짐작하셨을 겁니다. 먼저 밝히자면 저희는 Next.js 서버 환경에서 export된 전역 변수로 QueryClient를 생성하였습니다. 이는 명백히 잘못된 패턴이었고, 메모리 누수의 직접적인 원인이었습니다. 이 글에서는 저희가 겪은 메모리 누수 현상의 발견부터 원인 분석, 그리고 해결 과정을 공유하고자 합니다. 이 글은 특정 라이브러리나 프레임워크 자체의 결함을 다루지 않습니다. Next.js와 TanStack Query는 모두 훌륭한 도구이며, 문제의 원인은 공식 문서에서 권장하는 사용 패턴을 따르지 않은 저희의 구현 방식에 있습니다. 이 글을 통해 같은 실수를 반복하지 않길 바라며, 올바른 사용 패턴의 중요성을 함께 나누고자 합니다. 메모리 누수 현상 브라우저 환경에서는 탭을 닫으면 메모리가 해제되고, 사용자가 페이지를 새로고침하면 모든 것이 초기화됩니다. 설령 메모리 누수가 있더라도 사용자 개개인의 브라우저에서 일시적으로 발생하는 문제에 그치는 경우가 많습니다.그러나 SSR(Server-Side Rendering) 환경은 완전히 다릅니다. Next.js 서버는 24시간 365일 동작하며, 수많은 사용자의 요청을 처리합니다. 브라우저처럼 ‘닫으면 끝’이 아닙니다. 한 번 발생한 메모리 누수는 서버가 재시작되기 전까지 계속 누적되며, 이는 모든 사용자에게 영향을 미치는 치명적인 문제로 이어집니다. 펫프렌즈 서비스 Next.js 서버 메모리 사용량 위 그래프를 보시면 문제가 명확하게 파악되실겁니다. 메모리 사용량이 계단식으로 올라가다가 서버를 재시작하는 패턴이 반복되고 있는데요, 정상적인 서버라면 메모리 사용량이 일정 수준에서 유지되거나, GC가 동작하면서 톱니바퀴 모양을 그려야 하는데 저희 서버는 그렇지 않았습니다. 증상은 다음과 같았습니다: 1. 지속적인 메모리 증가 서버 시작 후 시간이 지날수록 메모리 사용량이 선형적으로 증가 Garbage Collection이 실행되어도 메모리가 해제되지 않음 2. 서버 성능 저하 메모리 사용률이 높아질수록 응답 시간 증가 CPU 사용률 증가 (GC가 메모리를 회수하려고 과도하게 시도) 간헐적인 서버 응답 지연 발생 3. 주기적인 서버 재시작 필요 메모리 사용률이 임계치(약 60%)에 도달하면 수동으로 서버 재시작 재시작하지 않으면 OOM으로 인한 서버 크래시 위험 모니터링 부담 가중 무엇보다 사용자가 많아질수록 문제가 더 빨리, 더 심각하게 발생한다는 점이 가장 큰 문제였습니다. 저희는 이 문제를 더 이상 미룰 수 없었고, 근본 원인을 찾아 해결하기로 결심했습니다. Node.js 메모리 구조 메모리 누수 현상에는 다양한 원인이 있을 수 있습니다. 디버깅을 하기 위해서는 어디서부터 시작해야 할까요? 먼저 Node.js의 메모리 구조를 간단히 살펴볼 필요가 있습니다. Node.js 프로세스의 메모리는 크게 다음과 같이 구성됩니다: 대부분의 JavaScript 객체와 데이터는 Heap Memory에 저장됩니다. 왜 Heap Memory부터 확인하는가? 세 가지 이유가 있습니다: 애플리케이션 코드가 직접 관리하는 영역 Stack Memory는 함수가 종료되면 자동으로 해제되고, Native Memory는 Node.js 내부나 네이티브 모듈이 관리합니다. 하지만 Heap은 다릅니다. 저희
펫프렌즈 기술블로그2026년 1월 27일SEO 주도 개발 실천기: 구글이 인정한 ‘좋은 URL’ 99% 달성 여정
원티드 엔지니어분들은 원티드 플랫폼을 개발하고 운영하며, 더 나은 사용자 경험을 제공하기 위해 끊임없이 노력하고 있습니다. 그 노력의 일환으로, 저희는 ‘SEO 주도 개발’을 실천하고 있습니다. ‘SEO 주도 개발’이란, Google Search Console (이하 GSC)과 도구를 통해 SEO 관련 지표를 주기적으로 관찰하고, 이를 개선하는 것을 개발의 주요 목표 중 하나로 삼는 방식을 의미합니다. 모든 URL이 ‘좋은 URL’이 되기까지 10월 30일부로 원티드의 99% URL은 좋은 URL로 전환. 10월 30일, 저희는 Google Search Console의 코어 웹 바이탈(Core Web Vitals) 지표에서 모든 URL이 ‘좋은 URL(빠른 URL)’로 전환되는 값진 성과를 달성했습니다. 제가 처음 입사했을 때만 해도, GSC 지표는 ‘느린 URL’과 ‘개선이 필요한 URL’이 대부분이었습니다. 이 지표들을 모두 ‘좋은 URL’로 바꾸겠다는 목표를 세웠고, 그 개선 여정을 시작하게 되었습니다. 이 글은 그 목표를 달성하기까지의 과정을 공유합니다. 이 성과는 원티드의 모든 프론트엔드. 서버, Devops 엔지니어분들의 협업이 있었기에 가능했습니다. 1부: 기본기 다지기, 서버 사이드 로직 최적화 아무리 프론트엔드에서 렌더링 최적화를 진행해도, Next.js 서버에서 HTML 응답 자체를 늦게 내려준다면 사용자가 느끼는 속도는 느릴 수밖에 없습니다. 저희는 병목의 원인을 서버 사이드에서부터 찾아 해결하기로 했습니다. 1–1. 병목의 핵심, 번역키 데이터 제거 가장 큰 병목은 URL 첫 요청 시 받아오는 HTML의 용량이었습니다. 문제: 당시 원티드는 글로벌 서비스를 지향하며 방대한 양의 번역키 데이터를 HTML에 포함하고 있었습니다. 이 데이터가 전체 HTML 용량의 90%를 차지했습니다. 이는 경쟁사 대비 월등히 큰 용량이었고, 이 데이터를 가져오는 레이턴시까지 더해져 심각한 성능 저하를 유발했습니다. 과정: 하지만 이 번역키는 조직의 일하는 방식과 깊이 결합되어 있어 단순히 제거하기 어려웠습니다. 저는 현재 상황을 최대한 수치화(경쟁사 비교, 로딩 속도 영향)하여 자료를 만들었고, 조직장, 경영진, 그리고 동료 개발자분들께 공유하며 설득하는 과정을 거쳤습니다. 결과: 최종적으로 번역키 데이터를 제거해도 좋다는 공감대를 형성했고, 해당 로직을 과감히 삭제할 수 있었습니다. HTML 용량 66% 감소 (경쟁사보다 가벼운 페이지 달성) 프론트엔드 서버 Latency 16% 개선 FCP (First Contentful Paint) 10% 개선 LCP (Largest Contentful Paint) 21% 개선 번역키 데이터 제거 배포 후, 서버 Latency 지표 1–2. 로그인 사용자 TTFB 개선 (DB 인덱스 추가) 원티드 서비스는 유독 로그인한 사용자가 접속할 때 첫 요청이 느린 현상이 있었습니다. 원인분석과 해결은 프론트엔드 챕터 조윤환님과 서버 챕터 이지수님이 작업을 진행 하셨습니다. 문제: Datadog으로 메트릭을 분석한 결과, 로그인한 사용자의 세션 정보를 가져오는 DB 테이블에 인덱스(Index)가 누락된 것을 확인했습니다. 과정: 해당 테이블에 즉시 인덱스를 추가했습니다. 결과: TTFB (Time to First Byte) 지표 70% 개선 🚀🚀🚀🚀 1–3. 서버 사이드 API 호출 병렬 처리 Next.js 서버 사이드(SSR)에서 페이지 렌더링에 필요한 API들을 기본적으로 호출하고 있었습니다. 원인 분석과 해결은 프론트엔드 챕터 조윤환님이 진행하셨습니다. 문제: 이 API들이 순차적으로 호출되어 불필요한 대기 시간이 발생하고 있었습니다. 과정: API 간의 의존 관계를 분석하여, 서로 상관관계가 없는 API들은 Promise.all 등을 활용해 병렬로 처리하도록 로직을 수정했습니다. 결과: TTFB 20% 개선 1–4. Internal API 호출로 레이턴시 단축 서버 사이드에서 API를 호출할 때, 외부로 나갔다가 다시 들어오는 Public API를 사용하고 있었습니다.
원티드랩 기술 블로그 - Medium2025년 11월 4일Next.js App Router에서 prefetchQuery와 Suspense로 뚜루루뚜루 데이터 스트리밍하기
안녕하세요. 더핑크퐁컴퍼니에서 Software Engineering Intern으로 근무하고 있는 앤디입니다.😆 이번 포스트에서는 인턴으로서 처음 맡았던 업무 중 하나였던 사내 카페 서비스 프로젝트의 마이그레이션 과정에서 React Query를 활용하며 겪었던 경험을 공유드리려고 합니다. 목차 들어가며 기존 방식의 한계와 마이그레이션 여정 React Query v5.40.0 변화 세 가지 접근 방식 실험 v5 streaming 적용 및 성능 비교 결과 배운 점과 결론 1. 들어가며 🎯 프로젝트 배경 인턴십을 시작하고 처음 맡았던 프로젝트는 사내 카페 서비스의 Next.js App Router + React 19 기반 마이그레이션이었습니다. 기존에는 Pages Router를 사용하고 있었는데, 다음과 같은 이유로 마이그레이션을 결정했습니다: Server Components 활용: 서버에서 데이터 페칭을 더 효율적으로 처리 React 18의 Concurrent Features 활용 개발 경험 개선: 더 직관적인 라우팅과 레이아웃 시스템 🤔 마주한 문제 단순한 화면 전환 이상의 문제를 다루게 되었는데, 바로 SSR과 클라이언트 데이터 로딩이 맞물리면서 발생하는 UX 문제였습니다. // 기존 Home 페이지 - SSR로 사용자 정보 prefetch export async function generateMetadata() { const queryClient = new QueryClient(); await queryClient.prefetchQuery( useGetMeQuery.getKey(), useGetMeQuery.fetcher(graphqlRequestClient, undefined, { authorization: Bearer ${getToken() }, }) ); // ... 메타데이터 생성 } // HomeBoard 컴포넌트 - 클라이언트에서 데이터 로딩 function HomeBoard() { return ( <Suspense fallback={<BoardSkeleton />}> <BoardContent /> </Suspense> ); } function BoardContent() { const { data } = useGetHomeBoardQuery(); // 일반 쿼리 사용 return <div>{/* 게시판 내용 렌더링 */}</div>; } 이 구조에서는 Home 페이지 내에서 prefetchQuery + SSR로 빠른 초기 렌더링이 가능합니다. 또한 HomeBoard 클라이언트에서는 Suspense로 자연스러운 로딩을 체감할 수 있습니다. 하지만 두 방식이 일관되지 않고, 복잡한 페이지에서는 어떤 전략을 써야 할지 혼란이 오는 경우가 있었습니다. 2. 기존 방식의 한계와 마이그레이션 여정 📊 Pages Router 시절: 부분적 SSR 전략 기존 사내 카페 서비스에서는 선택적 prefetch 전략을 사용하고 있었습니다. 모든 데이터를 서버에서 미리 가져오는 것이 아니라, 꼭 필요한 인증 정보만 SSR로 처리하고 나머지는 클라이언트에서 로딩하는 방식이었죠. // Pages Router - 인증만 SSR로 prefetch export async function getServerSideProps(context) { const queryClient = new QueryClient(); await queryClient.prefetchQuery( useGetMeQuery.getKey(), () => useGetMeQuery.fetcher(graphqlRequestClient, { authorization: Bearer ${getToken(context)}, })() ); return { props: { dehydratedState: dehydrate(queryClient) } }; } // 클라이언트 컴포넌트는 나머지 데이터를 CSR로 로딩 function HomeBoard() { const { data, isLoading } = useGetHomeBoardQuery(); return isLoading ?
더핑크퐁컴퍼니 기술 블로그 - Medium2025년 9월 26일GPT-Codex 실무에 몰래 사용 경험기
Codex 는 과연 얼마나 생산성을 향상시켰을까? 안녕하세요, 크몽 프론트엔드 팀 bk 입니다. 이전 글(Cursor 없으면 개발자 때려친다)에서 Cursor에 대해 이야기했었습니다. 이번에는 open ai 에서 2025년 5월 17일 출시한 Codex에 대해 이야기해보려 합니다. 이건 뭐 하루가 멀다하고 자꾸 이상한 것들이 나오니 이제 정말 개발자 때려 쳐짐 당할것 같네요. 그럼 Codex 이건 뭔가 한번 살펴봅시다. 이럴때 일수록 더 따라가야 합니다. 이번엔 글이 좀 깁니다. 갑시다. https://openai.com/index/introducing-codex/ — 또 그냥 요즘 흔해빠진 코딩 도우미 나왔구먼? Codex라는건 대충보면 그냥 또 뭐 코딩해주는 ai 또 뭐 나왔네 싶겠지만 이건 Cursor나 Copilot과는 근본적으로 다른 개념입니다. Codex는 ‘에디터’가 아니라 ‘비동기 에이전트’ 입니다. 그게 뭐가 다르냐구요? Cursor, Copilot과 비교해보겠습니다. Cursor는 내가 직접 코딩하는 중에 옆에서 실시간으로 도와주는 도구입니다. 코드 편집기 위에서 컨텍스트를 읽고, 자동완성을 제안하거나 기존 코드를 리팩토링해주는 보조자 같은 역할이죠. 반면 Codex는 작업을 ‘맡기고 떠날 수 있는’ 도구입니다. 아니 맡기고 떠나야 하는 도구입니다. 맡겨놓고 작업을 기다리고 있으면 이 도구를 쓰는 이유가 없습니다. 예를 들어 “테스트코드 작성해줘”, “이 폴더 안에 있는 Next.js 페이지 중 app router로 옮길만한 애들 리스트업 해줘” 같은 요청을 Codex에 요청하고 나는 다른 브랜치에 있거나, 다른 일을 하고 있어도 Codex가 해당 작업을 알아서 처리해줍니다. 작업을 시작하지 않았을 때도, 해당 브랜치로 checkout하지 않아도, 심지어 내가 잠을 잘 때도 일을 시킬 수 있는 구조입니다. Cursor: ‘나와 함께 작업하는 든든한 부사수’ Codex: 작업 지시하면 내일 아침 책상에 보고서(Pull Request) 올려놓는 직원 우리 회사에 이제 막 들어온 5년차 개발자, 근데 이 개발자는 24시간 자지도 않으며 불평도 안함 — Codex 의 작동방식 엑기스 설명 한줄 요약하면 Codex는 격리된 오프라인 상태의 가상 머신안에서 codex-1 모델 (암튼 똑똑하다함)이 작업하는 것입니다. 클라우드에서 git repository 를 클론한 뒤 기초 VM 설정 후 바로 offline 상태로 전환 된 이후에 실제 작업이 진행되는 ‘에어갭’ 구조를 기반으로 동작합니다. 이로 인해 악성 소프트웨어 요청등은 근본적으로 거부되는 구조입니다. — Codex가 사고하는 과정 살펴보기 Codex 가 참 재밌는게, 프롬프트를 받으면 처음부터 끝까지 사고 하는 과정이 나옵니다. 이걸로 리버스엔지니어링 하는게 참 재밋더라구요. 아래는 우리 repository 의 코드베이스를 설명하라는 하나의 task 대화의 일부입니다. 작업을 요청하고 모두 분석하고 응답이 올때까지 9분 21초가 걸렸습니다. 일단 아묻따 AGENTS.md 를 찾는것으로 항상 시작을 합니다. 루트에서 AGENTS.md를 찾지 못하자 다른 방법을 시도합니다. 하지만 아직 우린 AGENTS.md 를 만들어놓지 않았습니다. Codex 는 적당히 찾아보고 없다 싶으니 readme.md 를 읽는 모습입니다. 공식문서에도 AGENTS.md 로 안내하라고 나와있다 아무튼 계속 진행하는 모습을 지켜보겠습니다. ls 를 수행하여 레포 구조 살펴보기tsconfig 를 열어 ts 구조 확인각 앱의 README.md 를 확인하여 앱별 지침 찾기어떤 nextjs 앱이 있는지 MFA 구조 확인디렉토리가 비어보여 -al 붙히는 모습cursor rule 을 위해 작성해둔 convention, structure 문서 확인 cursor 를 위해 만들어둔 .cursor/rules/*.mdc 파일을 읽기 시작합니다. Codex 를 위해 작성했던 건 아니었는데.. 최종 결과 한줄평: 첫 작품치곤 그럴싸 했다. — Agent 를 위한 네비게이션을 만들어야겠다. 여러 작업을 하
kmong - Medium2025년 9월 1일버즈빌 프론트엔드 변천사
버즈빌 Supply 그룹의 Product Growth 팀의 Luke입니다. 저희 버즈빌에서 지난 몇 년간 겪어온 프론트엔드 아키텍처 변화를 공유하려 합니다. AngularJS에서 시작해 Vue, React를 거쳐 Next.js까지, 각 전환점에서의 고민과 선택 과정을 솔직하게 담았습니다. AngularJS에서 Vue로: 통합 어드민의 시작 초기 버즈빌은 광…
Buzzvil Tech2025년 8월 4일Serverless Postgres Neon으로 Next.js 환경에서 Short-URL 구현하기
Photo by Steve Johnson on Unsplash 안녕하세요. 스푼랩스 비글루 Client Team에서 프론트엔드 개발을 담당하고 있는 Drew(이서용)입니다. 비글루는 글로벌 숏폼 드라마 서비스로 다양한 콘텐츠를 쉽고 빠르게 즐길 수 있도록 iOS / Android 앱과 웹사이트에서 스트리밍 서비스를 제공하고 있습니다. 이번 글에서는 더 많은 사람들이 손쉽게 비글루 콘텐츠에 접근할 수 있도록 프론트엔드에서 서버리스 DB Neon을 이용해 간단한 커스텀 Short-URL을 구현하는 과정에 대해 다루었습니다. Short-URL 도입 계기 기존 비글루 웹 서비스 콘텐츠 페이지 URL은 다음처럼 불필요하게 많은 정보를 노출하는 구조로 되어있어 가독성 및 보안 측면에서 적절하지 않았습니다. // 콘텐츠 URL ex) www.video.com/ko/content/10001?season=10001&episode=1 이에 비해 타 서비스 웹 URL의 경우 UUID 형태로 정보를 숨기거나 마케팅 용도로 읽을 수 있도록 만드는 등, 유연하게 여러 가지 형태의 URL을 사용하고 있었습니다. // UUID 형태의 타 서비스 콘텐츠 URL ex) www.video.com/content/1523cb9c-f1ad-41f1-81bc-2be08c92d381 // Semantic한 형태의 타 서비스 콘텐츠 URL ex) www.play.com/ko/ep/41000110515_escape-with-boss-baby 이를 보완하기 위해서는 실제 정보를 가진 원본 URL과 외부에 노출되는 URL의 구분이 필요하다는 사실을 알게 되었고, 자체적인 커스텀 Short-URL 도입을 검토하게 되었습니다. // 짧아진 Short-URL ex) www.video.com/content/1fja491 일반적으로 Short-URL은 다음 과정을 통해 구현됩니다. 1. URL 단축 먼저 원본 URL을 대체할 단축된 Short-URL을 생성합니다. Short-URL은 서로 충돌이 발생하지 않도록 crypto나 nanoid와 같은 난수 생성 패키지를 이용해 생성합니다. 생성된 URL은 이후 조회를 위해 서버 저장이 필요합니다. 2. URL 조회 이제 단축된 URL을 조회하여 실제 URL을 찾을 수 있도록 서버 요청을 구현합니다. 실제 URL로 단순히 Redirect 시킬 수도 있지만, Short-URL을 유지하면서 원본 URL 정보만 가져오고 싶다면 이를 API 요청을 통해 조회하도록 설정할 수도 있습니다. 3. 추적 및 통계 추가로 Short-URL 변환 시점에 클릭 수 등의 데이터를 수집하도록 설정할 수도 있습니다. 이는 기존 이벤트 트래킹 툴과 연동하면 보조적인 데이터로 활용이 가능합니다. 이제 구체적인 구현 방법에 대해 살펴보겠습니다. Vercel Storage와 Neon 가장 먼저 찾아보았던 것은 Short-URL을 저장하고 불러올 수 있는 DB 서버에 대한 구현 방법이었습니다. 현재 비글루 웹 서비스는 서버사이드 렌더링을 지원하는 React 프레임워크 Next.js를 이용해 개발되었고, Vercel을 통해 배포하도록 구성하였습니다. Vercel의 경우 서비스의 배포뿐만 아니라 Analytics 및 Firewall 등 다양한 기능을 지원합니다. 이 중에서도 Storage 서비스는 서버리스 DB와의 연동을 지원하며 별도의 인프라 환경 구성없이 사용할 수 있다는 장점이 있어서 이를 사용해 보기로 하였습니다. 참고로 Vercel은 Framework-Defined Infrastructure(FDI)를 표방합니다. FDI는 프레임워크가 인프라 구성을 자동으로 관리하는 개념으로, 개발자가 애플리케이션 코드를 작성하면 해당 프레임워크가 필요한 인프라를 자동으로 설정, 배포, 관리하는 방식입니다. 기존 Infrastructure as Code(IaC)는 개발자가 직접 명시적으로 인프라를 정의하고 관리해야 했지만, FDI는 프레임워크 자체가 인프라 요구사항을 이해하고 자동으로 최적화된 설정을 적용합니다. 인프라가 프레임워크에 종속되는 것이 적절한지에 대해서는 여러
SpoonLabs - Medium2025년 3월 14일똑닥닷컴 SEO(a.k.a. 네이버 월 노출 수 1000만 달성기)
똑닥닷컴 커뮤니티 페이지의 네이버 월 노출 수를 2만에서 1,000만으로 끌어올린 검색엔진 최적화 작업 기록입니다. 색인 요청과 사이트맵, 메타데이터 설계, 인기 키워드 분석, Next.js App Router에서 겪은 이슈를 다룹니다.
비브로스 기술 블로그2025년 3월 4일기존 서비스 국제화(i18n) 작업 쉽게 덜어내기: t 함수 자동 래핑 스크립트 만들기
안녕하세요. 랠릿 셀 프론트엔드 개발자 고슈, 도니, 루시입니다. 2024년 초, 연간 플래닝에서 CTO인 향로에게서 예상치 못한 발표를 듣게 됩니다. 올해 인프런 글로벌 서비스를 출시할 예정이에요. 랠릿 셀도 함께 투입됩니다. 네? 저희도요? 이렇게 랠릿을 포함한 인프랩 개발파트는 레거시 코드 정리부터 국제화 작업까지, 인프런의 글로벌 서비스 출시를 위한 새로운 도전을 시작하게 되었습니다. 프롤로그 i18n을 서비스에 적용하는 전체 과정보다는, 기존 서비스를 다국어 서비스로 전환하는 과정에서 i18n 을 효율적으로 적용하는 방법에 대해 공유하고자 합니다. i18n은 internationalization의 줄임말입니다. ‘i’와 ‘n’ 사이에 18개의 글자가 있어서 i18n이라고 부릅니다. Next.js 다국어 처리 들어가기 앞서, Next.js 기반의 프로젝트에서 다국어 지원을 위해 일반적으로 사용되는 next-i18next 라이브러리에 대해 먼저 살펴보겠습니다. next-i18next는 Next.js 애플리케이션에서 i18n 기능을 구현하는 라이브러리입니다. 주요 특징 useTranslation hook을 통해 번역 함수(t) 제공 언어 파일을 JSON으로 관리 서버사이드 렌더링 지원 동적 번역 및 네임스페이스 지원 간단한 사용 예시를 보면 다음과 같습니다. // public/en/sample.json { "안녕하세요": "hi" } import { useTranslation } from 'next-i18next'; const Component = () => { const { t } = useTranslation(); return ( <p>{t('안녕하세요')}</p> // hi 라고 노출 ); } 이제 이 라이브러리를 활용하여 어떻게 효율적으로 기존 서비스에 국제화를 적용했는지 살펴보도록 하겠습니다. 언어 자원의 키 기존 인프런 담당 셀에서 레거시 코드의 React 마이그레이션이 진행을 진행중에 있어서 랠릿 셀은 이미 React로 전환된 코드들에 대한 i18n 적용을 가장 먼저 담당하게 되었습니다. 따라서 다른 셀과 함께 작업 하면서 사용할 효율적인 컨벤션을 먼저 결정할 필요가 있었습니다. 이 과정에서 가장 중요한 초기 결정 사항 중 하나는 다음과 같았습니다. 언어 자원(번역을 위한 JSON 파일)의 키를 어떤 방식으로 정의할 것인가? 이 문제에 대한 해답을 찾기 위해 다양한 개발자들과의 네트워킹을 하며 인사이트를 얻었습니다. 그 중 기억에 남는 의견이 있었습니다. 다음에 국제화를 진행한다면, 반드시 키값은 한글로 설정할 거예요. 이 의견에 많은 개발자들이 동의했고, 그 이유를 물어보니 다음과 같은 공통된 피드백을 얻을 수 있었습니다. 영문 키를 사용할 경우 대응되는 번역 키를 찾는 과정이 번거로움 이로 인한 개발 생산성 저하 발생 이러한 인사이트를 바탕으로, 랠릿셀은 함께 언어 자원의 키 정의에 대한 세 가지 컨벤션을 수립하고, 각각의 장단점을 분석하여 PM과 PD에게 제안하게 되었습니다. 컨벤션 종류 서비스의 국제화를 위한 언어 자원 키 정의 방식을 세 가지로 분류하여 분석했습니다. 1. 한글 키 방식 한국어 텍스트를 그대로 키로 사용하는 방식입니다. { "MY 카테고리": "MY 카테고리", "나만의 강의 카테고리를 구성해보세요!": "나만의 강의 카테고리를 구성해보세요!" } // 구현 예시 <Text>{t("MY 카테고리")}</Text> // MY 카테고리 <Text>{t("나만의 강의 카테고리를 구성해보세요!")}</Text> // 나만의 강의 카테고리를 구성해보세요! 장점 키 정의 과정 생략 가능 빠른 다국어 전환 가능 직관적인 코드 가독성 단점 텍스트 중복 가능성 원본 텍스트 변경 시 키도 함께 수정 필요 언어별 1:1 매칭이 어려운 경우 존재 (개행 등) 2. 역할군 기반 키 방식 {페이지 | 도메인}.{섹션}.{역할}.{서브} 형태의 구조화된 한글 키 { "계정정보.마이카테고리.제목": "MY 카테고리", "계정정보.마이카테고리.설명": "나만의 강의 카테고리를 구성해보세요!" } // 구
tech.inflab.com2025년 2월 6일Refine 이관 작업 ( feat. 중고나라 — 셀러지원센터 )
Refine 이관 작업 ( feat. 셀러지원센터 ) 📍 이관을 하게 된 배경 기존에 셀러지원센터는 Next.js, react-query, shadcn/ui 의 환경에서 개발을 진행했었다. 짧은 시간 안에 빠른 개발, 빌드 시간 단축, 확장 할 수 있는 커스텀 조건이 위 기술의 채택 이유이기도 했다. (참고 아티클) 1차,2차 배포까지만 해도 우리가 선택한 기술이 올바르다고 판단했다. 3차 오픈을 준비하기 전에, 이전에 빠른 개발로 인해 미뤄두었던 코드 개선작업을 시작한 것이 이관의 시초점이다. 1️⃣ 개발자마다 다른 코드 스타일 우리의 컨벤션을 정하긴 했지만, 페이지마다 작성한 개발 코드의 스타일이 온전히 일치하지는 않았다. 그래서 오류가 발생 했을때 해당 코드를 작성하지 않은 사람이 개선을 진행하려고 하면 개발 비용이 많이 필요했다. 2️⃣ 직관적이지 않은 코드 베이스 테이블 자체에 대한 공통 컴포넌트는 직접 구현해 두었고, 외부에서 테이블 리스트 데이터를 불러오고 주입하는 방식으로 사용했었다. 하지만, API마다 데이터를 변환하는 방식, 페이지 수를 가져오는 방식이 달라 페이지 내부에 단순히 리스트 컴포넌트만 보여주는 것이 아닌 데이터를 클라이언트 환경에 맞게 변환하는 로직들이 섞여 있어 페이지 동작을 직관적으로 파악하기 어려웠다. 3️⃣ API마다 다른 스펙에 맞춰 변환하는 과정의 분산화 셀러지원센터에서 호출하는 API 도메인은 아래와 같다. seller-api (셀러) partner-api (관리자) order-api (주문/결제 ) main-api (중고나라 메인) edge-api (이미지) 해당 API를 개발한 팀들이 다르다 보니 데이터를 반환하는 형식이 다르게 설계되어 있었다. 그래서 클라이언트 내부적으로 공통 컴포넌트를 만들어놓았지만, 만약 한 페이지에 여러 도메인의 API를 호출했을 경우에는 이를 클라이언트 형식에 맞게 변환하는 과정이 페이지 내부에 여러 유틸이 들어감으로써 가독성이 떨어지는 현상이 발생하였다. 더불어 변환하는 과정을 모두 모듈로 관리하지 않았기 때문에, 해당 방식 또한 개발자마다 스타일이 달라져 코드의 흐름을 파악하기 어려웠다. 하지만, 어드민 시스템의 특성상 테이블을 사용하는 페이지, 정보를 보여주는 페이지는 일관성을 가지도록 구현되는 것이 필요했고 뷰의 요소만이 아닌 내부 코드 시스템도 동일하게 관리되어야 추가 기능에 대해 여러 페이지를 한 번에 대응하는 것이 가능해진다고 느껴졌다. 이 3가지의 이유로 나는 어떤 특정 규격에 따른 코드 베이스를 가지면서 확장성을 고려한 기술의 도입이 필요하다고 판단했다. 🖤 Refine의 간략한 특징 그렇게 찾게 된 기술이 바로 Refine이다. 공식 문서에는 아래와 같이 설명되어 있다. React 기반 내부 도구, 관리자 패널, 대시보드 및 엔터프라이즈급 비즈니스 애플리케이션을 구축하도록 설계된 오픈소스 프레임워크이다. CRUD, 상태 관리와 같은 일반적인 기능을 처리하기 위한 자동화 세트를 제공하여 개발 프로세스를 간소화한다. 이를 통해 개발자는 반복적인 코딩 작업을 피하고 프로젝트의 더 복잡한 측면에 집중할 수 있다. 기본적으로 해당 기술은 Ant Design, Material UI, Shadcn/ui와 같은 UI 프레임워크와 통합도 가능했다. Next.js, React Router, Remix도 지원하는 강력한 tool로 사용되고 있었다. 그렇다면 어떤 반복적인 코딩 작업을 피할 수 있는 것일까? refine이 제시하고 있는 컨셉은 Headless, Resource, Provider, Hook 총 4가지이며 자세한 내용은 문서를 통해 확인할 수 있기에 핵심 컨셉인 provider와 resource만 살펴보겠다. 1️⃣ Provider의 개념 provider에도 data-provider, authentication-provider, access control-provider, notification-provider등 다양한 provider가 존재한다. 핵심은 data-provider이며 이는 백엔드 데이터와 get, post, pat
중고나라 기술 블로그2024년 11월 26일[ 셀러지원센터 ] 신입 개발자의 프로젝트 첫 시작
2023.09–2023.12 , 중고나라 웹 개발팀에서의 4개월 이라는시간 동안 인턴십을 수행하고 나서, 정규직 전환이 이루어져 2024.02.01에 신입 웹 개발자로 입사를 하게 되었다. 2024년도 중고나라의 핵심 프로젝트인 셀러지원센터를 웹 개발팀 리딩의 자리에서 이끌어가면서 느꼈던 부분들을 회고로 기록하고자 이 글을 작성하였다. 셀러 지원센터의 시작 한 달의 공백기 이후 입사하게 되었지만, 인턴의 경험이 있었기 때문에 그간의 중고나라 웹 개발팀의 작업 내용들을 수월하게 따라올 수 있었다. 올해의 중고나라 핵심 프로젝트는 셀러 지원센터와 J쿠폰 이었다. 물론 두 가지 프로젝트에 관심이 있었지만, 웹 개발팀 전체가 비슷한 수요를 가지고 있었기에 우리는 공정하게 사다리 타기를 진행해서 어떤 프로젝트를 맡게 될지 선정하게 되었다. 그렇게 나와 다른 매니저님들과 함께 셀러 지원센터에 합류하게 되었고, 그때부터 해당 서비스에 대한 설계와 프로젝트 방향성을 잡는 과정이 시작되었다. 우리 팀은 해당 서비스를 온전히 이해하기 위해 PM 팀 과의 회의에 선택적으로 참여하곤 했다. 개발자인데 굳이 참여해야 하나..?라는 생각이 들 수도 있겠지만, 서비스를 온전히 이해하고 장기적인 개선 방향을 도출해내는데 기여하기 위해서는 이 과정이 필요하다고 생각했다. 신입 개발자의 프로젝트 리딩 사내에서 진행하는 프로젝트에 참여하는 것도 처음이어서 설레는 마음이면서도 중요한 프로젝트에서 웹 개발팀의 리딩의 자리를 맡게 되어서 책임감을 느끼고 있기도 했다. 우선, 셀러 지원센터가 어떤 특성을 가진 서비스이며, 우리는 어떤 기술을 선정해야 하고, 개발 일정과 방식은 어떻게 진행할 예정인지 수립하는 과정이 필요했다. Tech Stack 논의 셀러 지원센터의 기술적인 특징은 아래와 같다. 유저는 셀러 / 관리자로 나누어지므로 2개의 페이지가 필요 로그인 이후 접속해야 하는 페이지들이기에 SEO 대응이 중요하지 않음 다만, 추후 커뮤니티성이 도입된다면 미리 고려는 해야 하는 부분 빠른 작업 속도를 위해 빌드 시간 단축 필요 디자인 투입 리소스가 없으므로 웹 개발팀 내부적으로 쉽게 만들 수 있는 컴포넌트와 페이지 제작 필요 위 특징들을 토대로 우리는 또 다른 질문들을 아래와 같이 도출했다. 어떤 패키지 매니저를 선택할 것인가..? Headless UI로 shadcn/ui 가 있는데, react-admin 보다 용이할까? SEO가 중요하지는 않지만, Next.js 를 사용해야 할까? 페이지를 나눠야 한다면, repository를 2개를 생성해야 할까? 총 4가지 안건에 대해 레퍼런스를 찾고 회의를 진행했다. ✅ 어떤 패키지 매니저를 선택할 것인가? npm, yarn, yarn-berry, pnpm 중에서 패키지 매니저를 선정하기로 했다. 우선, npm은 기본적인 패키지 관리가 모두 가능하며 package.json안에서 관리할 수 있다는 장점이 있었지만, 일관적이지 않은 패키지 버전을 사용하고 있고, 순차적인 설치로 인한 긴 소요 시간을 가진다는 단점이 있었다. 그래서 yarn을 살펴보았고, 해당 패키지 매니저는 yarn.lock을 사용하기에 사용할 모듈의 버전 지정이 가능하다는 것과 캐시를 사용한 설치 속도 향상이라는 장점을 가지고 있었다. 하지만 여전히 무거운 node_modules를 가진다는 것과 유령 의존성이 발생한다는 단점으로 인해 우리는 yarn-berry로 접근하게 되었다. yarn berry는 yarn v2 이상의 버전인 yarn이며 Plug’n’Play 기능을 지원하여 기존의 node_modules 대신 패키지에 대한 정보를 .zip 파일로 압축해 .yarn/cache 폴더에서 관리한다. 큰 이점이 있었지만, 만약 PnP를 지원하지 않는 패키지가 존재한다면 버전을 올리거나 다른 패키지로 이전하는 방법을 선택해야 한다. 개발 도중 위와 같은 문제가 발생하면 어떻게 해결할 수 있을까..? 에 대해 웹 개발팀 내부적으로 완벽한 답을 도출해내지 못했다. 그래서 우리는 yarn berry의 이점을 가지면서 다른 라이브러리 사용에 덜 영향을 줄 수
중고나라 기술 블로그2024년 11월 26일Front-end 개발자가 회고하는 기획전 개편
안녕하세요. 질문을 사랑하는 올리브영 프론트엔드 개발자 “우문Hyun답”입니다.😁 스토어전시 스쿼드에서는 24년 2-3분기에 기존 JSP로 구현된 기획전 시스템을 Next.js…
올리브영 테크블로그2024년 11월 1일