본문으로 건너뛰기
코드룸CODE ROOMTENMO ↗

기술 블로그

웹과 앱을 만들며 남긴 기록 447편입니다.

프로덕션 필수 보안 헤더 설정하기

Lighthouse로 프로덕션 서비스를 감사하다 보면 Best Practices 항목에서 감점이 발생하는 경우가 많습니다. 대부분의 원인은 보안 헤더 미설정입니다. 최근 코드 리뷰 중 next.config.ts에 보안 헤더가 전혀 설정되어 있지 않은 프로젝트를 발견했습...

동적 공략 페이지를 ISR로 되돌리기

들어가기 전에 ISR에 대한 간단한 설명 ISR(Incremental Static Regeneration)은 Next.js의 렌더링 전략 중 하나다. 이름이 길지만 개념은 단순하다. 빌드 시점에 정적 HTML을 미리 만들어두되, 일정 시간이 지나면 백그라운드에서 조용히...

웹앱 성능 개선에 중요한 TTFB, 캐시 적중률, 그리고 검색 봇 응답 안정성

웹앱을 운영하면서 마주한 가장 큰 숙제는 "느리다"는 사용자 피드백과, SEO 성과 지표에서 조용히 쌓여가던 크롤링 오류입니다. 원인을 추적해 보니 세 가지 지표가 서로 맞물려 있었습니다. TTFB(Time To First Byte), 캐시 적중률, 그리고 검색 봇 재...

MongoDB Atlas에서 `Indexes`와 `Search Indexes`는 무엇이 다를까?

MongoDB Atlas를 쓰다 보면 컬렉션 화면에서 `Indexes`와 `Search Indexes`라는 두 가지 메뉴를 보게 된다. 이름이 비슷해서 같은 기능의 확장판처럼 느껴질 수 있지만, 실제로는 해결하는 문제가 꽤 다르다. 특히 검색 기능을 붙이려는 시점에는 ...

Vercel 서버리스 컴퓨팅이 무엇인지 알아보자

웹사이트나 앱을 만들려면 "서버"라는 게 필요합니다. 서버는 쉽게 말해 여러분의 서비스를 24시간 돌려주는 컴퓨터입니다. 카페로 비유하면, 손님(사용자)이 언제 와도 커피를 내려줄 수 있도록 항상 켜져 있는 커피머신과 같습니다. 그런데 문제가 있습니다. 이 커...

Cursor 작업물 보호하기 (Save, Save As, Save All 살펴보기)

우선 글을 작성하게 된 이유는 많은 분들이 Cursor Save As에 대해서 검색을 하시길래 작성해봤습니다. "버전 관리는 Git이 다 해주는데, 굳이 '다른 이름으로 저장(Save As)'을 쓸 일이 있을까?" 의문도 존재하지만 Git Repository를 세탕...

axios 사용자라면 반드시 읽어야 할 긴급 경고

이번에 정말 충격적인 사건이 터졌습니다. 전 세계에서 가장 많이 쓰이는 HTTP 클라이언트 라이브러리 axios가 npm 공급망 공격을 당했습니다. 이번 공격은 단순한 버그가 아니라, maintainer 계정을 해킹해 악성 버전을 직접 배포한 전형적인 Supply ...

[SQL 입문] 필요한 데이터만 콕 집어 가져올 수 있는 WHERE 절

사용자는 테이블에 있는 모든 데이터를 다 보고 싶어 하지는 않습니다. 오히려 특정 항목에 대한 데이터만 가져오고 싶을 때가 훨씬 많습니다. 예를 들어, 어떤 사용자의 이메일이나 ID는 알고 있는데, 그 사람이 언제 우리 앱에 가입했는지 확인하고 싶다고 가정해 봅시다...

SQL에서 SELECT란 무엇인가?

데이터베이스를 거대한 서류 보관함이라고 생각하면 됩니다. 보관함 안에는 수많은 데이터가 차곡차곡 쌓입니다. SELECT는 이 보관함에서 "내가 원하는 정보를 찾아줘!"라고 요청하는 명령어입니다. 이 과정을 전문 용어로 '쿼리(Query)'라고 부릅니다. &nbs...

Antigravity의 역대급 '디자인 지능' 업데이트 분석

Claude나 GPT를 활용해 UI/UX 디자인이나 웹페이지 코드를 생성해보면 결과물을 실제로 서비스에 적용하기에는 어딘가 미학적 완성도가 결여되어 있거나 UI 컴포넌트 간의 응집력이 부족한 느낌을 지우기 어렵습니다. AI가 논리적인 코드는 잘 짤지 몰라도, 인간 디자...

[SQL 기초] "언제 하나씩 다 넣어?" 데이터 한 번에 넣기

개발을 하다 보면 데이터베이스(DB)에 샘플 데이터를 대량으로 넣어야 할 때가 있습니다. 메뉴 100개를 추가해야 하는데 INSERT 문을 100번 쓰고 있다면? 너무 비효율적이죠! 오늘은 SQL에서 여러 데이터를 한 번에 넣는 '다중 삽입(Multiple Inse...

SQL 데이터 삽입하기

데이터가 없는 데이터베이스는 연료 없는 로켓과 같습니다. 이제 'Missions' 테이블에 새로운 행(row)을 추가하는 방법을 알아보겠습니다. "삽입(Inserting)"은 '데이터 추가'를 의미합니다. 기존 Missions 테이블 ...

[DB 설계 기초] createdAt과 updatedAt이 필수인 이유

데이터베이스 설계의 '기본 중의 기본'이자, 실무에서 결코 빠질 수 없는 두 필드 createdAt과 updatedAt에 대해 알아보겠습니다. 단순히 날짜를 기록하는 것을 넘어, SQL의 '절' 기능을 이용해 어떻게 이 과정을 자동화하는지도 함께 살펴볼까요? &...

SQL 테이블 생성 시 제약 조건

이번에는 데이터베이스 테이블 생성 시 제약 조건에 대해서 설명 드리겠습니다. 테이블 생성 시 몇 가지 규칙을 더해보려고 합니다. 모든 상품은 반드시 상품명과 상품 코드를 가져야 한다고 가정할 때, 데이터가 비어 있는 상태로 저장되는 것을 방지하기 위해, 필수 ...

SQL 테이블 생성하기

데이터베이스에 데이터를 저장하기 위한 첫 번째 단계는 '테이블'을 만드는 것입니다. 아래는 상품 정보를 저장할 Products 테이블을 만드는 기본 코드입니다. CREATE TABLE Products ( id INT PRIMARY KEY AUTO_IN...

SQL이란 무엇인가?

SQL의 기초에 대한 설명입니다. SQL은 Structured Query Language의 약자입니다. 데이터베이스와 소통하기 위해 사용하는 특별한 언어죠. 우리가 다른 나라 사람들과 대화하기 위해 외국어를 배우는 것처럼, SQL은 데이터베이스와 대화하기 위해 사용...

SQL 기초, 데이터베이스와 활용하는 방법

SQL의 기초를 알아보겠습니다. SQL 전문가를 대상으로 글을 작성한 것이 아니라, SQL이 무엇인지, 어떻게 작동하며, 왜 중요한지에 대한 핵심적인 이해를 돕기 위해 작성하였습니다. 앞으로 데이터베이스를 다룰 때 필요한 든든한 기초가 될 것이며, 기회가 된다면...

데이터베이스 구성에 대해서 알아보자

설명에 앞서, 데이터베이스에서 사용하는 몇 가지 명칭(용어)을 먼저 정리해 보겠습니다. 데이터베이스는 여러 개의 테이블(Table)로 구성됩니다. 테이블은 서로 연관된 데이터들의 집합입니다. 예를 들어 '사용자(Users)' 테이블, '게시물(Posts)' 테...

왜 데이터베이스를 사용해야 할까요?

데이터베이스는 매우 방대한 주제입니다. 처음 접하신다면 조금 막막하게 느껴질 수도 있죠. 하지만 데이터베이스의 핵심 아이디어는 의외로 매우 간단합니다. 바로 '어떤 값을 어딘가에 저장했다가, 나중에 그 값을 다시 꺼내오는 것'입니다. 데이터베이스는 방대한...

Redis 캐시 키 보안 강화

Redis 캐시를 사용하는 애플리케이션에서 캐시 키 주입 공격 등의 보안 취약점을 예방하고, 안정적인 캐시 시스템 운영을 위해 안전하지 않은 외부 입력값이 캐시 키로 사용될 때 위험을 최소화하는 것을 목표로 하는 기본적인 방법입니다. 보안 강화를 통해 캐시 키 주입 공...