기능 플래그 저장소 만들기

CloudflareBeginner
지금 연습하기

소개

기능 플래그는 애플리케이션 코드를 변경하지 않고 기능을 켜거나 끄는 설정입니다. 새 공지 배너를 준비한다고 가정해 보겠습니다. 연습 환경에서는 배너를 테스트하되 공개 버전에서는 꺼 두고 싶을 수 있습니다. Workers KV는 키라는 이름 아래에 작은 값을 저장합니다. Worker 는 응답을 결정해야 할 때 banner:new와 같은 키를 읽을 수 있습니다. 자주 읽지만 가끔 변경하는 설정에 유용한 방식입니다.

이 과정을 시작하기 전에 LabEx 를 Cloudflare 계정에 연결하기를 완료하세요. 이 실습에서는 LabEx VM 터미널, 디바이스 인증, 계정 확인, account_id를 설명합니다. 이 과정으로 바로 들어왔다면 먼저 해당 실습을 완료하세요. 또한 Workers 초급 과정에서 작은 JavaScript Worker 를 작성하고 Wrangler 로 배포하는 방법을 알아야 합니다. Worker 는 서버를 직접 관리하지 않고도 Cloudflare 에서 요청 처리 코드를 실행합니다.

이 실습에서는 다른 컬렉션과 분리된 키 모음인 네임스페이스를 만듭니다. 구성된 리소스 접근 이름인 바인딩을 통해 네임스페이스를 Worker 에 연결합니다. 로컬 및 클라우드 작업을 연습하고, 읽기 전용 배너 엔드포인트를 배포한 다음, 실습용 리소스를 삭제합니다.

본인의 학습용 계정을 사용하세요. 새 VM 에서는 Workers 및 KV 권한이 있는 별도의 로그인이 필요합니다. 이 실습은 하나의 Worker, 하나의 네임스페이스, 그리고 KV 무료 사용량 범위 내의 몇 가지 테스트 값을 사용합니다. 따라서 이 작은 실습에는 구매한 도메인이나 유료 업그레이드가 필요하지 않습니다. 기존 계정의 사용량은 여전히 무료 사용량에 포함됩니다. 공개 엔드포인트에는 개인정보가 포함되지 않습니다.

설정 과정에서 /home/labex/project/feature-flags에 Node.js 22.22.0 과 프로젝트 로컬 Wrangler 4.131.1 을 설치합니다. 직접 의존성 버전을 고정하고 npm install을 실행하므로 도구를 다시 설치할 필요가 없습니다. 클라우드 삭제와 로그아웃 확인이 끝날 때까지 VM 을 종료하지 마세요.

전용 플래그 네임스페이스 연결하기

이 단계에서는 이 실습 전용 리소스 이름을 만들고 클라우드 네임스페이스를 프로젝트에 연결합니다. 네임스페이스를 분리하면 연습용 키가 기존 애플리케이션의 키와 섞이지 않습니다.

준비된 프로젝트로 이동합니다.

cd /home/labex/project/feature-flags

고유한 이름을 한 번 생성합니다. openssl rand -hex 6은 무작위 접미사를 출력하고, $(...)는 그 값을 이름에 삽입합니다. 셸 변수에 이름을 저장하면 이 터미널에서 이어지는 명령에 사용할 수 있습니다.

WORKER_NAME="labex-flags-$(openssl rand -hex 6)"
printf '%s\n' "$WORKER_NAME"

이 VM 을 인증합니다. 계정 ID 를 읽는 것 외에도 Workers Scripts Write 권한은 배포 및 삭제를 허용하고, Workers KV Write 권한은 이 실습의 네임스페이스와 키를 관리할 수 있게 합니다.

npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_kv:write

브라우저에서 표시된 디바이스 링크를 열고 현재 코드를 입력합니다. 요청된 권한과 학습용 계정을 확인한 다음 Wrangler 를 승인합니다. 동의 페이지에 백그라운드 액세스 권한이 표시될 수도 있습니다. 터미널로 돌아와 로그인이 완료될 때까지 기다립니다.

동의 페이지에서 Developer Platform을 펼치고 요청된 권한을 다음 예시와 비교합니다. 이 실습에는 두 가지 쓰기 권한이 모두 필요합니다. 이 권한은 플래그를 읽는 것뿐 아니라 리소스를 관리하는 데 사용됩니다.

Wrangler consent lists Workers Scripts Write and Workers KV Storage Write

npx wrangler whoami --json

loggedIn: true와 학습용 계정의 name을 확인합니다. 계정이 하나만 표시되더라도 확인하세요. 해당 계정의 id를 복사합니다. 아래 구성에서 YOUR_ACCOUNT_ID를 복사한 값으로 바꾼 다음 명령을 실행합니다. 여기서 cat의 here-document 는 두 JSON 줄 사이의 모든 내용을 파일에 기록하고, >는 파일을 덮어씁니다. 따옴표가 없는 구분자는 셸이 $WORKER_NAME을 삽입하도록 합니다.

cat > wrangler.jsonc <<JSON
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-07-30",
  "account_id": "YOUR_ACCOUNT_ID",
  "workers_dev": true
}
JSON

해당 계정에 네임스페이스를 만듭니다. 나중에 두 리소스를 쉽게 구분할 수 있도록 네임스페이스의 제목에 Worker 의 고유 이름을 포함합니다. --update-config=false를 지정하면 바인딩이 자동으로 파일에 추가되지 않고 직접 수정할 수 있습니다.

npx wrangler kv namespace create "$WORKER_NAME-flags" --update-config=false

출력에 새 네임스페이스 ID 가 포함됩니다. ID 를 복사한 다음, 완성된 구성에서 YOUR_ACCOUNT_ID와 YOUR_NAMESPACE_ID를 각각 실제 값으로 바꿉니다. FLAGS 바인딩 이름은 코드에서 사용할 이름이고, ID 는 실제 Cloudflare 리소스를 식별합니다.

cat > wrangler.jsonc <<JSON
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-07-30",
  "account_id": "YOUR_ACCOUNT_ID",
  "workers_dev": true,
  "kv_namespaces": [
    { "binding": "FLAGS", "id": "YOUR_NAMESPACE_ID" }
  ]
}
JSON
npx wrangler kv namespace list

이 실습에서 만든 네임스페이스의 제목을 찾아 파일에 기록한 ID 와 비교합니다. 다른 네임스페이스가 표시되더라도 그대로 두세요. 이 구성은 이후 명령에서 사용할 계정과 리소스를 지정합니다. 바인딩은 네임스페이스에 대한 참조이며, 네임스페이스 데이터의 복사본이 아닙니다.

로컬 플래그와 원격 플래그 분리하기

이 단계에서는 같은 키에 서로 다른 값을 저장하고 로컬에서 변경한 내용이 클라우드 데이터에 영향을 주지 않는지 확인합니다. 로컬은 이 LabEx VM 내부의 저장소를 의미합니다. 원격은 Cloudflare 계정의 네임스페이스를 의미합니다. Wrangler 는 바인딩으로 저장소를 식별하고, --local 또는 --remote 옵션으로 작업할 위치를 선택합니다.

먼저 공개 기능을 비활성화된 상태로 둡니다.

npx wrangler kv key put banner:new disabled --binding FLAGS --remote

VM 의 로컬 저장소에서는 같은 기능을 활성화합니다.

npx wrangler kv key put banner:new enabled --binding FLAGS --local

두 값을 읽습니다. put은 키를 저장하고 get은 값을 가져옵니다. banner:new의 콜론은 관련 키를 묶기 위한 이름 지정 규칙일 뿐이며, 디렉터리를 만들지는 않습니다.

--text를 사용하면 저장된 값을 UTF-8 텍스트로 디코딩하여 별도 줄에 표시합니다.

npx wrangler kv key get banner:new --binding FLAGS --local --text

enabled가 출력되어야 합니다.

npx wrangler kv key get banner:new --binding FLAGS --remote --text

disabled가 출력되어야 합니다. 실수로 원격 값을 변경했다면 disabled를 지정한 put 명령을 다시 실행한 후 값을 다시 읽습니다. 프로젝트 폴더만 보고 대상 위치를 추측하지 마세요.

이제 더 이상 사용하지 않는 플래그를 삭제해 봅니다. 다음 명령은 FLAGS에 연결된 이 실습용 원격 네임스페이스에만 영향을 줍니다.

npx wrangler kv key put banner:old retired --binding FLAGS --remote
npx wrangler kv key list --binding FLAGS --remote

목록에는 저장된 값이 아니라 banner:new, banner:old와 같은 키 이름이 표시됩니다. 값이 필요할 때는 get을 사용합니다.

npx wrangler kv key delete banner:old --binding FLAGS --remote
npx wrangler kv key list --binding FLAGS --remote
npx wrangler kv key list --binding FLAGS --local

이제 두 목록 모두 banner:new만 포함해야 합니다. 두 값이 여전히 다른지 확인하려면 값을 다시 읽습니다. 키를 삭제하면 하나의 항목이 삭제되고, 나중에 네임스페이스를 삭제하면 전체 컨테이너가 삭제됩니다.

KV 는 **최종적 일관성 (eventual consistency)**을 사용합니다. 변경 사항이 다른 위치의 읽기 결과에 표시되기까지 시간이 걸릴 수 있습니다. Worker 가 일시적으로 이전 값을 읽을 수도 있고, 이전에는 없었던 키를 계속 없다고 볼 수도 있습니다. 값이 나타나도록 반복해서 덮어쓰지 마세요. 이 실습에서 사용하는 표시용 플래그는 이러한 지연을 허용하지만, 즉시 접근 권한을 철회해야 하는 결정에는 적합하지 않습니다. 이후 실습에서 이 동작을 살펴봅니다. 저장 모델은 KV 작동 방식을 참고하세요.

로컬 Worker 에서 플래그 읽기

이 단계에서는 저장된 설정에 따라 애플리케이션 동작이 달라지도록 만듭니다. Worker 는 env.FLAGS를 읽습니다. 여기서 env에는 구성된 리소스 바인딩이 들어 있습니다. get()은 비동기 작업이므로 await를 사용해 값을 받은 후 반환할 응답을 결정합니다.

핸들러를 작성합니다. 따옴표로 묶은 JS 구분자는 셸 변수를 확장하지 않고 JavaScript 를 그대로 보존합니다.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    if (new URL(request.url).pathname !== "/banner") {
      return new Response("Not found", { status: 404 });
    }
    const value = await env.FLAGS.get("banner:new");
    return Response.json({
      feature: "new-banner",
      enabled: value === "enabled"
    });
  }
};
JS

키가 없으면 null을 반환합니다. "enabled"와 정확히 비교하므로 키가 없거나 예상하지 못한 값이면 선택적 배너가 꺼진 상태로 유지됩니다. 이는 간단한 **안전한 기본값 (safe default)**입니다. 설정이 제공되지 않아도 애플리케이션을 사용할 수 있습니다. 연결 실패를 숨기는 것은 아닙니다. 연결 실패는 키가 없는 경우와 다른 문제입니다.

로컬 개발을 시작합니다. --local은 로컬 바인딩을 사용해 이 VM 에서 Worker 를 실행합니다. > local.log 2>&1은 출력과 오류를 로그로 보내고, &는 터미널에서 추가 명령을 입력할 수 있게 합니다. $!는 백그라운드 프로세스 ID 이며, 나중에 이 프로세스를 중지할 수 있도록 저장합니다.

npx wrangler dev --local --ip 0.0.0.0 --port 8080 > local.log 2>&1 &
DEV_PID=$!
cat local.log

포트 8080 에서 준비 완료 메시지가 표시될 때까지 기다립니다. 아직 시작 중이라면 계속하기 전에 로그를 다시 읽습니다.

curl -i http://127.0.0.1:8080/banner

curl -i는 응답 헤더와 본문을 함께 표시합니다. HTTP 200, JSON 콘텐츠 유형, 다음 응답이 출력되어야 합니다.

{"feature":"new-banner","enabled":true}

true는 로컬 KV 저장소에서 읽은 값으로부터 나온 결과입니다. 개발 서버를 실행했다고 해서 원격의 disabled 값이 VM 으로 복사된 것은 아닙니다. 다음 비교를 위해 서버를 계속 실행해 둡니다.

배포하고 공개 응답 비교하기

이 단계에서는 같은 코드를 배포하고 클라우드 네임스페이스를 읽는지 확인합니다. 배포는 Worker 와 바인딩 구성을 업로드하지만, 로컬 KV 항목은 업로드하지 않습니다.

npx wrangler deploy

배포 출력을 확인합니다. Worker 이름, FLAGS 바인딩, 공개 workers.dev 주소를 확인합니다. 아래 주소에는 실제 배포 주소를 입력해야 하므로, 예시를 실제 주소로 바꾼 다음 실행합니다. 셸 변수에 저장하면 긴 URL 을 다시 입력하지 않아도 됩니다.

WORKER_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$WORKER_URL/banner"

HTTP 200과 다음 응답이 출력되어야 합니다.

{"feature":"new-banner","enabled":false}

클라우드 설정이 disabled이므로 공개 응답의 false가 됩니다. 새 호스트 이름에 아직 연결할 수 없다면 잠시 기다렸다가 다시 시도합니다. 응답에 이전 값이 반영되어 있다면 원격 키를 한 번 확인하고, 빠르게 값을 다시 쓰지 말고 KV 에 변경 사항이 표시될 때까지 기다립니다. 네트워크 오류는 성공적인 테스트 결과가 아닙니다.

curl -i http://127.0.0.1:8080/banner

로컬 응답은 여전히 true여야 합니다. 이제 하나의 핸들러와 서로 분리된 두 저장소가 있습니다. 로컬 개발에서는 VM 의 데이터를 읽고, 배포된 Worker 에서는 바인딩으로 식별한 네임스페이스를 읽습니다.

Cloudflare Dashboard 에서 동일한 학습용 계정을 선택하고 Storage & databases → Workers KV를 엽니다. 이 실습의 이름과 일치하는 네임스페이스를 찾아 키를 확인합니다. banner:new만 남아 있고 원격 값이 disabled인지 확인합니다. 다음으로 Workers & Pages를 열고 이 실습의 Worker 를 선택한 후 Bindings 화면을 확인합니다. FLAGS 바인딩을 방금 확인한 네임스페이스와 비교합니다. 이 단계는 읽기 전용 확인 과정입니다. 변경 작업은 터미널에서 수행합니다.

네임스페이스는 Metrics 탭에서 열립니다. KV Pairs를 선택해 실제 항목을 확인하세요. 사용량 통계는 쓰기 작업보다 늦게 갱신될 수 있습니다. 새 Worker 가 Workers & Pages에 보이지 않으면 Refresh를 클릭하세요. Bindings에서는 표까지 아래로 스크롤하여 바인딩 이름과 네임스페이스를 비교하세요.

원격 네임스페이스에는 값이 disabled 인 banner:new 만 남음

FLAGS 가 Worker 를 이 실습의 네임스페이스에 연결함

생성된 이름, 네임스페이스 ID, 공개 서브도메인은 예시와 다릅니다. Dashboard 에 네임스페이스가 표시되면 해당 네임스페이스가 있는 위치를 확인할 수 있고, HTTP 요청이 성공하면 애플리케이션이 해당 네임스페이스를 사용할 수 있음을 확인할 수 있습니다.

실습용 클라우드 리소스 삭제하기

이 단계에서는 Wrangler 인증이 유지되는 동안 두 리소스를 모두 삭제합니다. 네임스페이스는 Worker 보다 오래 남을 수 있으므로 애플리케이션만 삭제해서는 데이터가 정리되지 않습니다.

이 터미널에서 시작한 로컬 개발 프로세스를 중지합니다.

kill "$DEV_PID"

삭제하기 전에 저장된 리소스 참조를 확인합니다.

cat wrangler.jsonc

labex-flags-... Worker 이름과 FLAGS 네임스페이스 ID 를 확인합니다. 이 구성으로 선택되는 Worker 를 삭제합니다.

npx wrangler delete

확인 메시지가 표시되면 이름이 이 실습의 Worker 와 일치하는지 확인하고 y를 입력합니다. 그런 다음 FLAGS가 참조하는 네임스페이스만 삭제합니다.

npx wrangler kv namespace delete --binding FLAGS

확인 메시지가 표시되면 삭제 대상 네임스페이스를 검토한 후 승인합니다. 독립적인 확인 과정에서 삭제되어야 할 리소스를 식별할 수 있도록 wrangler.jsonc는 그대로 둡니다.

npx wrangler kv namespace list

이 실습의 네임스페이스가 목록에서 사라져야 하며, 관련 없는 네임스페이스는 그대로 남아 있어야 합니다. Dashboard 의 목록을 새로 고쳐 이 실습의 Worker 와 네임스페이스가 사라졌는지 확인합니다. 요청 실패나 로그인 만료만으로는 삭제가 확인되지 않습니다. 인증된 리소스 목록을 검사할 수 있도록 로그아웃하기 전에 이 단계의 확인을 실행합니다.

VM 인증 종료하기

이 단계에서는 정리 확인이 통과된 후 Wrangler 연결을 끊습니다. 로그아웃하면 이 VM 에 저장된 Wrangler 인증이 종료되지만, 클라우드 리소스가 삭제되거나 일반적인 Dashboard 브라우저 세션에서 로그아웃되는 것은 아닙니다.

npx wrangler logout
npx wrangler whoami --json

구조화된 결과에 "loggedIn": false가 표시되는지 확인합니다. 인증되지 않은 이 명령은 0 이 아닌 종료 상태로 끝날 수 있으며, 여기서는 정상입니다. 연결 오류만 표시되고 인증 상태가 명시되지 않는다면 연결이 복구된 후 다시 시도합니다.

남아 있는 로컬 파일과 로컬 KV 상태는 이 실습용 VM 에 속합니다. 이미 삭제한 클라우드 리소스와는 별개입니다. 이제 실습을 종료할 수 있습니다.

요약

격리된 KV 네임스페이스를 만들고 바인딩으로 연결한 다음, 명시적인 로컬 및 원격 명령을 사용해 키를 쓰고, 읽고, 나열하고, 삭제했습니다. Worker 는 서로 분리된 저장소에서 같은 키를 읽었습니다. 로컬 배너는 활성화되어 있었지만 공개 배너는 비활성화된 상태였습니다. 또한 플래그가 없을 때 사용할 안전한 기본값을 적용했고, KV 업데이트를 즉시 전체에 반영되는 전역 스위치로 취급해서는 안 되는 이유를 배웠습니다.

마지막으로 공개 응답을 확인하고, 인증된 상태에서 Worker 와 네임스페이스를 삭제한 뒤 Wrangler 에서 로그아웃했습니다. 다음에는 민감하지 않은 계정 환경설정을 제공하기 위해 구조화된 JSON 값을 사용합니다.