MyStock - .env를 없애려다 계좌 구조의 문제를 발견하다

MyStock은 한국투자증권을 비롯해 여러 OpenAPI를 사용한다. App Key, Secret Key, API Key 같은 인증 정보가 필요했고, 초기에는 이런 값과 계좌 관련 설정을 .env 파일에 넣어 사용했다.

 

.env에는 외부에 공개하면 안 되는 인증 정보가 들어 있기 때문에 GitHub에는 포함하지 않았다. 소스 코드는 GitHub를 통해 여러 PC에서 쉽게 맞출 수 있었지만, .env만큼은 새 환경마다 따로 복사하거나 다시 만들어야 했다. 처음 문제로 느낀 건 딱 그 정도였다. 여러 PC에서 MyStock을 사용하다 보니 소스는 자동으로 맞춰지는데 인증 정보와 계좌 설정만 따로 관리해야 하는 게 점점 번거로워졌다. 그래서 사용자가 프로그램 안에서 OpenAPI의 App Key와 Secret Key, 계좌정보를 직접 등록하고, 그 내용을 PC별 로컬 설정 파일로 관리하는 쪽이 더 자연스럽겠다고 생각했다.

.env에서 JSON Local Config로

처음 예상한 구조는 단순했다.

.env
↓
Local JSON Config

환경변수에서 값을 읽던 부분을 JSON에서 읽도록 바꾸고, 이후 설정 화면을 붙이면 끝날 것 같았다. GitHub에는 소스만 두고 인증 정보는 각 PC에 남기면 된다. 이 방향은 내가 정했고, ChatGPT와 작업 범위를 정리하면서 .env를 완전히 제거하고 JSON Local Config를 production 설정의 기준으로 바꾸는 흐름을 잡았다. 실제 repository에서 환경변수에 의존하는 코드가 어디까지 퍼져 있는지는 Codex를 통해 추적하기 시작했다. 그리고 여기서 예상과 달라지기 시작했다.

.env 의존성과 하드코딩된 계좌 슬롯

처음에는 App Key, Secret Key 같은 인증 정보를 읽는 코드가 주로 걸릴 거라고 생각했는데 실제 의존성을 따라가 보니 .env에는 인증 정보만 들어 있는 것이 아니었다. MyStock은 초창기부터 여러 계좌를 사용하면서 STOCK, ETF, ISA, IRP, FINANCIAL 같은 이름으로 계좌를 나눠왔다. .env에서도 각각의 계좌를 별도 슬롯처럼 정의했고, 코드 역시 오랫동안 그 구조를 기준으로 확장되어 있었다.

 

처음에는 이것도 단순한 설정값 정도라고 생각했지만 Codex가 실제 consumer들을 추적하면서 상황이 달라졌다. 고정된 이름과 슬롯은 어떤 App Key를 사용할지 결정하는 데만 쓰이는 것이 아니었다. 계좌를 선택하는 로직, API 요청 대상, 화면에 표시되는 그룹, 정렬 순서, worker의 owner를 구분하는 과정 등 여러 곳에서 사실상 계좌의 정체성처럼 사용되고 있었다. 즉 .env를 없애려면 환경변수를 JSON으로 옮기는 것만으로는 부족했다.

STOCK
ETF
ISA
IRP
FINANCIAL

이 이름 자체를 전제로 만들어진 코드가 생각보다 훨씬 많았다. 사용자가 ETF라는 이름을 다른 이름으로 바꾸면 어떻게 되는지, 같은 종류의 주식계좌를 하나 더 추가하면 어떻게 구분할지 생각하기 시작하자 문제가 바로 보였다. 이름이 단순한 표시용 문자열이어야 하는데, 실제로는 프로그램의 여러 판단 기준으로 사용되고 있었다.

계좌 이름과 Account Identity의 충돌

여기까지 확인했을 때만 해도 문제의 범위는 application code 안에 있다고 생각했다. 계좌를 이름이나 고정 슬롯으로 찾는 코드를 걷어내고 실제 계좌 식별자를 기준으로 구분하도록 바꾸면 해결할 수 있을 것 같았다. 그래서 계좌의 이름과 종류, 실제 계좌 식별자를 분리하는 방향을 검토하기 시작했다.

 

사용자가 붙이는 이름은 언제든 바꿀 수 있어야 한다. ETF, 연금, 매매용, 장기투자처럼 무엇이라고 부르든 실제 계좌가 달라져서는 안 된다.

STOCK 계좌가 두 개 있다고 해서 둘 중 하나가 특별한 STOCK 슬롯을 차지해서도 안 된다. 향후 다른 증권사를 연결할 가능성까지 생각하면 계좌를 STOCK, ISA 같은 이름 자체로 식별하는 방식은 더 이상 유지하기 어려웠다.

 

여기서부터 작업이 처음 예상보다 커지는 느낌은 있었지만, 그래도 아직은 계좌 routing과 application 구조를 정리하는 수준이라고 생각했다. 그런데 persistence 쪽을 확인하면서 한 번 더 문제가 커졌다.

SQLite DB까지 이어진 계좌 하드코딩

계좌 관련 데이터가 DB에 어떻게 저장되고 다시 복원되는지 확인하면서 고정된 계좌 구조가 application layer에만 있는 것이 아니라는 사실이 드러났다. DB에는 내부 관계를 관리하기 위한 account_id가 있었고, 계좌 종류와 계좌를 구분하기 위해 사용해온 metadata도 있었다.

 

문제는 application에서 사용하던 고정 계좌 개념과 persistence 내부의 식별 개념이 충분히 분리되어 있지 않았다는 점이었다. 지금까지 등록된 몇 개의 계좌를 계속 사용하는 동안에는 별문제가 없었다. 하지만 앞으로 사용자가 자유롭게 계좌를 추가하고 이름을 바꿀 수 있다고 생각하면 얘기가 달라진다.

 

같은 종류의 계좌가 여러 개 존재할 수도 있고, PC마다 표시 이름이 달라질 수도 있다. 나중에 다른 증권사를 지원한다면 계좌번호 형식이나 provider 자체도 달라진다. 그런 상황에서 기존의 이름이나 계좌 종류, DB 내부 account_id 중 하나를 application의 계좌 identity처럼 계속 사용하는 것은 위험해 보였다.

 

설정을 자유롭게 만들기 위해 .env를 없애려 했는데, 오히려 그 순간 기존 구조가 얼마나 고정된 전제에 기대고 있었는지가 드러난 셈이었다. 솔직히 여기서 한 번 멘붕이 왔고, 시작은 API Key를 JSON에 저장하는 일이었는데 확인할수록 문제는 이렇게 내려갔다.

.env
↓
계좌별 환경변수
↓
고정된 계좌 이름과 슬롯
↓
API routing / owner / UI
↓
Persistence
↓
DB의 계좌 식별과 복원

이쯤 되니 더 이상 .env 파일 하나를 교체하는 작업이라고 부르기 어려웠다.

MyStock 계좌 Identity 재정의 필요성

처음에는 .env를 없애고 JSON 설정으로 바꾸는 정도의 작업이라고 생각했지만 실제 구조를 따라가 보니 계좌 이름, 계좌 종류, .env의 슬롯, DB 내부 account_id가 서로 다른 역할을 해야 하는데도 여러 곳에서 계좌를 구분하는 기준처럼 섞여 있었다. 이 상태에서 설정 화면만 새로 만드는 것은 기존 하드코딩 위에 JSON을 하나 더 얹는 것과 크게 다르지 않았다. 사용자가 계좌 이름을 바꾸거나 같은 종류의 계좌를 추가하면 다시 같은 문제가 생길 가능성이 높았고, 이후 다른 증권사까지 고려하면 더 이상 그대로 둘 수 없는 구조였다.

 

결국 .env 제거 작업은 잠시 멈추고, 먼저 계좌의 identity와 종류, 표시 이름, DB 내부 식별자의 역할을 분리한 뒤 persistence 구조까지 다시 검토하기로 했다. 처음 예상보다 훨씬 큰 작업이 됐지만, 문제를 확인한 이상 .env만 JSON으로 옮기고 끝낼 수는 없었다. 다음 단계는 자연스럽게 하드코딩된 계좌 구조를 걷어내고 DB까지 다시 설계하는 작업으로 이어졌다.