Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

Envflow 구축기: Laravel과 Upstash Redis로 환경 변수를 안전하게 공유하는 방법

최근 저는 Nuno Maduro의 프로젝트인 Pyre에서 큰 영감을 받았습니다. Pyre는 짧은 수명의 비밀 메시지를 원하는 사람에게 전송할 수 있는 웹 앱으로, 저장 시점에 암호화되며 복호화 링크를 가진 사람만 내용을 읽을 수 있습니다.

저도 Upstash Redis를 활용해 비슷한 것을 만들어 보고 싶었고, 그중에서도 환경 변수 공유라는 틈새 영역을 선택했습니다. 팀 동료와 시크릿(비밀값)을 안전하게 공유해야 했던 순간이 한 번쯤은 있으셨을 텐데요, 이를 위한 시스템을 어떻게 만들면 좋을지 고민해 보셨을 겁니다.

Envflow는 제가 직접 만든 Laravel 샘플 프로젝트로, Upstash Redis를 기본 데이터베이스로 사용해 암호화된 데이터를 저장하고 공유합니다. 지금부터 이 프로젝트를 처음부터 끝까지, 지루한 세부 사항은 건너뛰며 빌드 과정을 소개하겠습니다.

기술 스택

먼저 PHP를 선택하고, 유명한 TALL 스택을 기반으로 프로젝트를 구축했습니다.

  • Tailwind CSS
  • Alpine JS
  • Laravel
  • Livewire
  • Upstash Redis

데이터베이스: Upstash Redis

암호화된 데이터를 저장하면서 일정 시간이 지나면 자동으로 만료되고, 빠르면서도 비용 효율적인 저장소가 필요했습니다. 예상하셨듯이 Upstash Redis를 선택했습니다.

Upstash Redis는 서버리스(Serverless) 방식의 Redis 호환 데이터베이스로, 이번 사용 사례에는 정말 완벽하게 부합했습니다.

참고: Upstash Redis와 Laravel을 함께 시작하는 방법을 다룬 공식 시작 가이드도 준비되어 있으니 확인해 보세요!

라우트 / 엔드포인트

Envflow는 세 개의 주요 라우트와, 프로젝트 소개를 담당하는 보조 라우트 하나로 구성됩니다. 모든 라우트는 routes/web.php 파일에서 확인할 수 있습니다.

홈페이지

홈페이지는 프로젝트의 랜딩 페이지 역할과 동시에, 환경 변수를 암호화할 수 있는 Livewire 폼을 포함합니다. 이 페이지에서는 환경 변수가 복호화될 수 있는 횟수유효 기간을 설정할 수 있습니다.

Envflow 구축기: Laravel과 Upstash Redis로 환경 변수를 안전하게 공유하는 방법

관련 Livewire 페이지 컴포넌트는 app/Livewire/EncryptEnvPage.php, 템플릿은 resources/views/livewire/encrypt-env-page.blade.php에서 찾을 수 있습니다.

성공 페이지

성공 페이지는 복호화 링크를 공유하는 두 가지 방식을 보여주는 간단한 페이지입니다. 하나는 복호화 키가 링크에 포함된 형태이고, 다른 하나는 링크와 복호화 키를 분리해서 전달하는 형태입니다.

Envflow 구축기: Laravel과 Upstash Redis로 환경 변수를 안전하게 공유하는 방법

컴포넌트는 app/Livewire/SuccessPage.php, 템플릿은 resources/views/livewire/success-page.blade.php에 위치합니다.

복호화 페이지

복호화의 모든 마법이 일어나는 곳입니다. 우리는 암호화 키를 Upstash Redis에 저장하지 않고, 오직 의미를 알 수 없는 문자열인 암호화된 값만 저장한다는 점을 기억하세요. 복호화 페이지의 핵심 역할은 입력받은 복호화 키로 환경 변수를 복호화하는 데 시도하는 것입니다.

Envflow 구축기: Laravel과 Upstash Redis로 환경 변수를 안전하게 공유하는 방법

컴포넌트는 app/Livewire/DecryptEnvPage.php, 템플릿은 resources/views/livewire/decrypt-env-page.blade.php에서 확인할 수 있습니다.

Actions 패턴

이번 프로젝트에서는 핵심 비즈니스 로직을 정리하기 위해 Action/Executor 패턴을 사용했습니다. 코드가 커져도 재사용성, 테스트 용이성, 유지보수성을 확보할 수 있고, 애플리케이션의 여러 부분 간에 동일한 동작을 공유할 수 있다는 장점도 있습니다. 예를 들어 미래에 API를 추가한다면 말이죠. 누가 알겠습니까?

모든 Action은 app/Actions 디렉터리에 있으며, 그중에서도 환경 변수의 암호화와 복호화를 담당하는 핵심 컴포넌트인 EncryptDecrypt 액션을 살펴볼 필요가 있습니다.

암호화 구현

Laravel에는 내장된 암호화 헬퍼가 있어 운이 좋았지만, 저는 실행 시점에 생성된 커스텀 암호화 키를 사용하고 싶었습니다. 몇 가지 조사 끝에 방법을 찾았습니다. 바로 Laravel의 하위 클래스인 Illuminate\Encryption\Encrypter를 활용하는 것입니다.

use Illuminate\Encryption\Encrypter;

$encrypter = new Encrypter(
    'custom-encryption-key', // 실행 시점에 생성하고 싶은 커스텀 키
    config('app.cipher'),    // Laravel 기본 암호화 알고리즘 사용
);

// 성공! 이제 값을 암호화할 수 있습니다
$encryptedValue = $encrypter->encryptString($value);

자, 암호화가 잘 작동합니다. 앞서 소개한 파일들을 살펴보셨다면 이 코드가 Encrypt 및 Decrypt 액션에 들어 있는 것을 발견하셨을 겁니다.

Redis 저장소 처리

Action과 Laravel의 네이티브 Encrypter 클래스를 사용해 값을 암호화·복호화하는 방법을 살펴봤습니다. 이제 이 값들을 Upstash Redis에 어떻게 저장하는지 알아보겠습니다.

해당 로직은 StoreEnvFile 액션에 담겨 있으며, 그중 아래 코드가 핵심입니다.

// ...

RedisFacade::pipeline(function (Redis $pipe) use (...) {
    $options = ['EX' => $ttl]; // 여기서 만료 시간을 설정합니다
    $pipe->set("envfile:$id", $encrypted->value, $options);
    $pipe->set("envfile:$id:shareLimit", $shareLimit, $options);
});

// ...

위 코드에서 Redis 파이프라인(pipeline)을 사용하는 것을 볼 수 있습니다. 이렇게 하면 모든 명령어가 단일 트랜잭션으로 실행됩니다. set 명령 중 하나라도 실패했을 때 암호화된 값이 불완전하게 저장되는 상황을 막아야 하기 때문에 매우 중요한 부분입니다.

배포

배포는 최근 출시된 Laravel Cloud를 활용했습니다.

Laravel Cloud 배포는 놀랄 만큼 쉬웠습니다. 저장소에서 Redis 인스턴스가 연결되고 도메인까지 프로비저닝된 완전히 배포된 앱까지 걸린 시간은 1분 미만이었습니다. 지금도 배포 한 번에 30초도 걸리지 않습니다. 🚀

Envflow 구축기: Laravel과 Upstash Redis로 환경 변수를 안전하게 공유하는 방법

배포된 실제 서비스는 https://envflow.laravel.cloud 에서 직접 확인해 보실 수 있습니다.

마무리

이 글이 즐거운 읽기 거리였고, Envflow를 어떻게 만들었는지 이해하는 데 도움이 되었기를 바랍니다.

개인적으로는 Upstash Redis를 기본 데이터베이스로 활용할 수 있는 애플리케이션이 정말 많다고 생각합니다. 이번 프로젝트에서는 Redis를 KV 스토어로 사용했지만, 사실 그 이상의 강력한 기능을 갖추고 있습니다. 앞으로 진행할 또 다른 프로젝트를 통해 이 부분을 반드시 다룰 예정이니 기대해 주세요.

이 프로젝트의 소스 코드는 GitHub에서 공개되어 있습니다. 아이디어나 제안(혹은 버그 발견)이 있다면 언제든지 기여해 주세요.