제로 예산으로 SQL을 사용한 Geo-Blocked 기능 테스트 해결
Source: Dev.to
지리적 차단(Geo‑blocked) 기능 테스트를 SQL만으로, 비용 없이 해결하기
배경
우리 팀은 전 세계 사용자에게 다른 기능을 제공해야 하는 Feature Flag 시스템을 운영하고 있습니다.
하지만 일부 플래그는 특정 국가·지역에만 노출되어야 합니다.
- 문제: 기존 테스트 환경에서는 VPN이나 프록시를 사용해도 실제 사용자 트래픽을 완벽히 재현하기 어렵다.
- 제한: 별도의 테스트 서버를 구축하거나 써드파티 서비스를 구매할 예산이 전혀 없다.
목표
- 실제 프로덕션 데이터를 활용해 지리적 차단 로직을 검증한다.
- 추가 비용 없이 SQL 쿼리만으로 테스트 케이스를 자동화한다.
- CI 파이프라인에 쉽게 통합한다.
솔루션 개요
| 단계 | 설명 |
|---|---|
| 1. IP → 국가 매핑 테이블 준비 | 무료 GeoIP CSV(예: IP2Location LITE 혹은 MaxMind GeoLite2)를 다운로드하고, ip_country 라는 테이블에 로드한다. |
| 2. 사용자 이벤트 로그 수집 | user_events 테이블에 user_id, event_name, event_timestamp, ip_address 컬럼이 있다고 가정한다. |
| 3. 플래그 적용 로직을 SQL로 구현 | 플래그가 활성화돼야 하는 국가 리스트(allowed_countries)와 비활성화돼야 하는 국가 리스트(blocked_countries)를 CTE 혹은 임시 테이블로 정의한다. |
| 4. 테스트 시나리오 작성 | 기대하는 결과와 실제 결과를 비교하는 ASSERT 쿼리를 만든다. |
| 5. CI에 통합 | psql 혹은 mysql 커맨드라인을 이용해 테스트 스크립트를 실행하고, 반환값이 0이 아니면 빌드를 실패시키도록 설정한다. |
1️⃣ IP → 국가 매핑 테이블 만들기
-- 무료 GeoLite2 CSV를 활용한 예시
CREATE TABLE ip_country (
ip_start BIGINT NOT NULL,
ip_end BIGINT NOT NULL,
country_code CHAR(2) NOT NULL
);
-- CSV를 COPY 명령으로 로드 (PostgreSQL 기준)
COPY ip_country(ip_start, ip_end, country_code)
FROM '/path/to/GeoLite2-Country-Blocks-IPv4.csv'
WITH (FORMAT csv, HEADER true);
팁: IP를 정수형으로 변환하면 범위 검색이 훨씬 빠릅니다.
inet타입을 지원하는 DB라면inet컬럼을 직접 사용해도 됩니다.
2️⃣ 사용자 이벤트 로그와 플래그 로직 결합
WITH allowed_countries AS (
SELECT UNNEST(ARRAY['US', 'CA', 'GB']) AS country_code
),
blocked_countries AS (
SELECT UNNEST(ARRAY['CN', 'RU']) AS country_code
),
event_with_country AS (
SELECT
ue.user_id,
ue.event_name,
ue.event_timestamp,
ic.country_code
FROM user_events ue
JOIN ip_country ic
ON ip_to_bigint(ue.ip_address) BETWEEN ic.ip_start AND ic.ip_end
)
SELECT
ewc.*,
CASE
WHEN ac.country_code IS NOT NULL THEN TRUE -- 허용된 국가
WHEN bc.country_code IS NOT NULL THEN FALSE -- 차단된 국가
ELSE NULL -- 정의되지 않음
END AS feature_enabled
FROM event_with_country ewc
LEFT JOIN allowed_countries ac ON ewc.country_code = ac.country_code
LEFT JOIN blocked_countries bc ON ewc.country_code = bc.country_code;
위 쿼리는 각 이벤트가 발생한 사용자의 국가를 찾아내고, 그 국가가 허용 리스트에 있으면 TRUE, 차단 리스트에 있으면 FALSE를 반환합니다.
3️⃣ 테스트 케이스 작성
-- 1) 미국 IP에서 플래그가 켜져야 함
INSERT INTO user_events (user_id, event_name, event_timestamp, ip_address)
VALUES (1, 'login', NOW(), '23.45.67.89'); -- 23.*.*.* 은 US 로 매핑됨
-- 2) 러시아 IP에서 플래그가 꺼져야 함
INSERT INTO user_events (user_id, event_name, event_timestamp, ip_address)
VALUES (2, 'login', NOW(), '5.188.0.1'); -- 5.188.*.* 은 RU 로 매핑됨
-- 테스트 실행
WITH test AS (
SELECT *
FROM (
-- 앞서 만든 로직을 그대로 재사용
SELECT
user_id,
feature_enabled
FROM (
-- (위의 메인 쿼리) ...
) sub
) t
)
SELECT
CASE
WHEN COUNT(*) FILTER (WHERE user_id = 1 AND feature_enabled = TRUE) = 1
AND COUNT(*) FILTER (WHERE user_id = 2 AND feature_enabled = FALSE) = 1
THEN 0 -- 성공
ELSE 1 -- 실패
END AS exit_code;
exit_code가 0이면 모든 기대값을 만족한 것이고, CI 파이프라인에서는 이 값을 기준으로 빌드 성공/실패를 판단할 수 있습니다.
4️⃣ CI 파이프라인에 통합하기 (예시: GitHub Actions)
name: Geo‑Flag Tests
on: [push, pull_request]
jobs:
sql-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
ports: ['5432:5432']
options: >-
--health-cmd "pg_isready -U test"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Load GeoIP CSV
run: |
wget -O GeoLite2-Country-Blocks-IPv4.csv https://example.com/GeoLite2-Country-Blocks-IPv4.csv
psql -U test -d testdb -c "\copy ip_country FROM 'GeoLite2-Country-Blocks-IPv4.csv' CSV HEADER"
- name: Run SQL Tests
run: |
psql -U test -d testdb -f ./sql/setup.sql # 테이블·함수 생성
psql -U test -d testdb -f ./sql/tests.sql # 위에서 만든 테스트 스크립트
env:
PGPASSWORD: test
결과
- 비용: 무료 GeoIP 데이터와 기존 DB만 사용했으므로 0 달러.
- 신뢰성: 실제 프로덕션 로그를 그대로 활용하기 때문에 테스트가 실제 사용자 흐름과 100 % 일치한다.
- 자동화: CI에 포함되므로 PR마다 자동 검증이 이루어진다.
마무리
SQL만으로도 지리적 차단 Feature Flag를 충분히 검증할 수 있다는 점을 보여드렸습니다.
추가 비용이 전혀 들지 않으면서도, 데이터 정확도와 자동화 수준을 높일 수 있는 방법이니, 여러분의 프로젝트에도 바로 적용해 보시길 권합니다.
이 글은 원본 저작권자의 허가를 받아 번역한 것이며, 원본 내용에 대한 모든 권리는 원 저작자에게 있습니다.
Understanding the Challenge
Geo‑blocked features restrict user access based on geographic location, often determined by IP addresses or other regional indicators. Testing such constraints typically involves multiple steps:
- Simulating user location data
- Verifying access control responses
- Ensuring consistency across geographies
Traditional methods might include deploying VPNs, proxy servers, or geo‑spoofing tools, all of which can be costly or infeasible within tight budgets. Instead, we can cleverly manipulate database data to mimic these environments.
SQL을 사용한 지리 위치 시뮬레이션
핵심 아이디어는 각 테스트 케이스에 맞는 원하는 지리적 컨텍스트를 반영하도록 데이터베이스를 수정하거나 준비하는 것입니다. 이는 전략적인 데이터 설정 및 쿼리를 통해 구현할 수 있습니다.
Step 1: Analyze the Data Model
일반적으로 지리 제한 로직은 IP 주소 범위, 지역 코드 또는 사용자·요청 관련 테이블에 저장된 도시 식별자를 기반으로 합니다. 이러한 핵심 컬럼을 식별하는 것이 중요합니다.
-- Example user table schema
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
ip_address VARCHAR(45), -- For IPv6 compatibility
region_code VARCHAR(10), -- ISO country or region code
city VARCHAR(50)
);
Step 2: Prepare Test Data
다양한 지리적 상황을 나타내는 레코드를 테이블에 삽입하고, 필요에 따라 지역 코드나 IP 범위를 지정합니다.
-- Insert test users for different regions
INSERT INTO users (id, username, ip_address, region_code, city) VALUES
(1, 'user_us', '192.0.2.1', 'US', 'New York'),
(2, 'user_eu', '198.51.100.2', 'EU', 'Berlin'),
(3, 'user_as', '203.0.113.3', 'AS', 'Tokyo');
Step 3: Simulate Geo‑Restrictions
대상 테스트 조건에 맞는 지역 또는 IP 범위에 따라 사용자를 필터링하는 쿼리를 작성합니다.
-- Simulate access for US region
SELECT * FROM users WHERE region_code = 'US';
-- Testing geo‑block logic
SELECT * FROM users
WHERE region_code = 'EU' -- Suppose EU is geo‑blocked
AND EXISTS (
SELECT 1 FROM access_rules
WHERE region_code = 'EU' AND feature_enabled = FALSE
);
Step 4: Automate and Validate
이러한 SQL 쿼리를 테스트 파이프라인에 통합하여 다양한 지리적 상황을 반영하도록 테스트 데이터를 자동으로 교체합니다. 또한 지역 지표를 빠르게 전환할 수 있도록 저장 프로시저나 스크립트를 만들 수 있습니다.
-- Example stored procedure to set user region
CREATE PROCEDURE SetUserRegion (IN user_id INT, IN region VARCHAR(10))
BEGIN
UPDATE users SET region_code = region WHERE id = user_id;
END;
-- Usage
CALL SetUserRegion(1, 'EU');
이 접근 방식의 장점
- Cost‑Effective: VPN이나 프록시 서비스를 사용할 필요가 없습니다.
- Rapid Iteration: 데이터베이스 항목을 업데이트하여 지리적 위치를 빠르게 전환할 수 있습니다.
- Integrated: 기존 데이터베이스 인프라를 사용하여 설정을 간소화합니다.
- Repeatable: 지속적 통합 파이프라인을 위해 테스트를 쉽게 자동화할 수 있습니다.
제한 사항 및 고려 사항
- IP 주소 시뮬레이션: 지역 코드는 많은 테스트에 충분하지만 실제 IP 범위는 복잡합니다. 보다 세밀하게 하려면 IP 범위 데이터를 데이터베이스에 포함시키세요.
- 현실성: 이 방법은 데이터 기반 측면을 시뮬레이션하지만 실제 네트워크 조건이나 IP 지리 위치의 미묘함을 재현하지는 않습니다.
- 보안: 테스트 데이터 수정이 운영 데이터나 환경에 영향을 주지 않도록 하세요.
결론
SQL과 기존 데이터를 전략적으로 활용함으로써 QA 팀은 추가 비용 없이도 지리적 제한 환경을 신뢰성 있게 시뮬레이션할 수 있습니다. 이 접근 방식은 확장 가능하고 반복 가능하며 자원 효율적인 테스트 프로세스를 촉진하여, 팀이 강력한 검증을 통해 지리 차단 기능을 자신 있게 제공할 수 있게 합니다—예산이 전혀 없는 설정에서도 말이죠. 최적의 결과를 위해 데이터 모델과 쿼리를 항상 귀사의 애플리케이션 아키텍처에 맞게 조정하십시오.
🛠️ QA 팁
실제 사용자 데이터를 사용하지 않고 안전하게 테스트하려면 TempoMail USA를 사용합니다.