본문 바로가기
금융IT/생활 속 금융 기술

생활 속 금융 기술 #26 | 카드사 개인정보 보호 방법: 마스킹·토큰화·SQL 접근 권한 실습

by IT BRIAN 2026. 11. 4.

카드사 고객센터에 전화하면 상담원이 고객의 카드 이용 내역을 확인해 줍니다.

그런데 여기서 한 가지 궁금한 점이 생깁니다.

상담원은 고객의 카드번호 16자리와 모든 개인정보를 볼 수 있을까요?

일반적으로 업무에 필요한 정보와 접근 권한은 역할에 따라 제한하도록 설계합니다. 상담원이 고객의 거래 내역을 확인할 필요가 있더라도 카드번호 전체나 불필요한 개인정보까지 조회할 필요는 없습니다.

금융 IT 시스템에서는 이러한 문제를 해결하기 위해 데이터 마스킹, 토큰화, 접근 권한 관리 등의 기술을 사용합니다.

이번 글에서는 카드사에서 발생할 수 있는 가상의 업무 상황을 통해 개인정보 보호 원리를 알아보고, PostgreSQL SQL 실습으로 실제 구현 방법을 살펴보겠습니다.

※ 이 글의 고객 정보, 카드번호, SQL 테이블 및 업무 사례는 모두 교육용 가상 데이터입니다. 실제 금융회사 내부 시스템이나 고객 정보를 사용하지 않았습니다.

개인정보


1. 카드사에는 어떤 개인정보가 저장될까?

카드사는 카드 발급과 결제 처리, 고객 상담 등의 업무를 수행하기 위해 다양한 정보를 처리합니다.

대표적으로 다음과 같은 정보가 있습니다.

정보 유형 예시 보호 필요성
고객 식별 정보 이름, 연락처, 고객번호 개인 식별 가능
카드 관련 정보 카드번호, 유효기간 결제수단 관련 민감한 보안 정보
거래 정보 결제 일시, 금액, 가맹점 개인의 소비 활동 추정 가능
인증 관련 정보 인증 결과, 인증 식별자 계정 및 거래 보안과 관련
시스템 로그 접속 기록, 거래 추적 ID 다른 정보와 결합 시 개인 식별 가능성

이러한 정보를 모두 같은 방식으로 보호하는 것은 아닙니다.

정보의 성격, 법적 요구사항, 업무 목적, 접근 필요성에 따라 저장·조회·전송·보존 정책을 달리 적용해야 합니다.

특히 카드번호와 인증 관련 데이터는 일반적인 고객 정보와 별도로 적용되는 결제 보안 요구사항까지 고려해야 합니다.

2. 데이터 마스킹: 필요한 부분만 보여주기

데이터 마스킹은 개인정보의 일부를 가려 화면이나 조회 결과에 표시하는 방법입니다.

예를 들어 카드번호가 다음과 같다고 가정하겠습니다.

원본: 4111-1111-1111-1111

마스킹 표시: 4111---1111

이렇게 표시하면 사용자는 카드의 일부 정보를 확인할 수 있지만 전체 번호는 노출되지 않습니다.

다만 카드번호의 앞자리와 뒷자리를 얼마나 표시할 수 있는지는 적용되는 보안 기준과 업무 목적에 따라 달라집니다. 위 표기는 원리를 설명하기 위한 예시이며, 모든 환경에서 허용되는 표시 형식을 의미하지는 않습니다.

마스킹은 특히 고객센터 화면, 운영자 조회 화면, 보고서 등에서 활용할 수 있습니다.

중요한 점은 마스킹이 암호화와 같지 않다는 것입니다.

마스킹은 주로 표시되는 값을 제한하는 것이며, 원본 데이터의 저장 방식이나 접근 통제를 자동으로 해결하지는 않습니다.


3. SQL 실습 ① 카드번호 마스킹

이번 실습에서는 PostgreSQL을 이용해 고객별 카드번호를 일부만 표시해 보겠습니다.

실습은 반드시 별도의 테스트 데이터베이스에서 진행해야 합니다.

① 가상 고객 테이블 생성

CREATE TABLE demo_customer_cards (
    customer_id INTEGER PRIMARY KEY,
    customer_name VARCHAR(50) NOT NULL,
    card_number VARCHAR(19) NOT NULL
);

② 가상 데이터 입력

INSERT INTO demo_customer_cards
(customer_id, customer_name, card_number)
VALUES
(1, '고객A', '4111111111111111'),
(2, '고객B', '5555555555554444'),
(3, '고객C', '4000000000000002');

이 값은 실습용 예시 번호이며 실제 고객의 카드정보가 아닙니다. 실제 운영 환경에서는 카드번호 전체를 이런 형태의 일반 테이블에 저장하는 설계를 그대로 사용해서는 안 됩니다.

③ 마스킹 SQL 실행

SELECT
    customer_id,
    customer_name,
    LEFT(card_number, 4)
        || '********'
        || RIGHT(card_number, 4) AS masked_card_number
FROM demo_customer_cards
ORDER BY customer_id;

예상 실행 결과

고객번호고객명마스킹 카드번호

고객번호 고객명 마스킹 카드번호
1 고객A 4111********1111
2 고객B 5555********4444
3 고객C 4000********0002

SQL의 LEFT() 함수는 문자열 앞부분을 가져오고, RIGHT() 함수는 뒷부분을 가져옵니다.

가운데 부분은 별표로 대체하여 출력합니다.

이렇게 하면 상담원 화면이나 보고서에서 카드번호 전체를 표시하지 않는 조회 결과를 만들 수 있습니다.

하지만 이 SQL만으로 보안이 완성되는 것은 아닙니다.

원본 테이블에 직접 접근할 권한이 있는 사용자는 여전히 전체 카드번호를 조회할 수 있습니다.

따라서 실제 시스템에서는 원본 데이터 접근을 제한하고, 허용된 화면이나 뷰를 통해 필요한 정보만 제공하도록 설계해야 합니다.


4. 토큰화: 실제 카드번호 대신 다른 값을 사용하기

마스킹이 데이터를 일부 가려 보여주는 방식이라면, 토큰화는 원본 정보를 다른 식별값으로 대체하는 기술입니다.

예를 들어 다음과 같습니다.

원본 카드번호 토큰
4111111111111111 TOKEN-A001
5555555555554444 TOKEN-B002

일반 업무 시스템에서는 카드번호 대신 토큰을 저장하거나 전달하도록 설계할 수 있습니다.

토큰 자체만으로 원본 카드번호를 알아낼 수 없도록 만들고, 원본과 토큰의 대응 관계는 별도의 보호된 시스템에서 관리하는 방식입니다.

예를 들어 카드 이용 내역을 분석하는 DW 시스템에서는 카드번호 전체가 필요하지 않을 수 있습니다.

이 경우 적절하게 설계된 토큰이나 별도의 가명 식별자를 활용하면 원본 카드정보에 접근해야 하는 시스템과 사용자를 줄일 수 있습니다.

다만 토큰화에도 여러 구현 방식이 있으며, 모든 토큰이 자동으로 안전한 것은 아닙니다.

토큰의 생성 방식, 원본 데이터 저장 위치, 토큰 매핑 정보 보호, 재식별 권한 등이 함께 관리되어야 합니다.


5. SQL 실습 ② 토큰을 이용한 거래 조회

이번에는 원본 카드번호 없이 토큰만으로 거래 내역을 조회하는 가상 환경을 만들어 보겠습니다.

여기서는 이해를 돕기 위해 이미 발급된 토큰을 사용합니다. 실제 토큰 생성과 보안 저장소 구현은 포함하지 않습니다.

① 토큰 기반 거래 테이블 생성

CREATE TABLE demo_token_transactions (
    transaction_id INTEGER PRIMARY KEY,
    card_token VARCHAR(30) NOT NULL,
    transaction_amount INTEGER NOT NULL,
    transaction_date DATE NOT NULL
);

② 가상 거래 데이터 입력

INSERT INTO demo_token_transactions
(transaction_id, card_token, transaction_amount, transaction_date)
VALUES
(1001, 'TOKEN-A001', 15000, '2026-11-01'),
(1002, 'TOKEN-A001', 32000, '2026-11-02'),
(1003, 'TOKEN-B002', 45000, '2026-11-02'),
(1004, 'TOKEN-A001', 18000, '2026-11-03');

③ 토큰별 거래 금액 조회

SELECT
    card_token,
    COUNT(*) AS transaction_count,
    SUM(transaction_amount) AS total_amount
FROM demo_token_transactions
GROUP BY card_token
ORDER BY card_token;

예상 실행 결과

카드 토큰 거래 건수 거래 합계
TOKEN-A001 3건 65,000원
TOKEN-B002 1건 45,000원

이 실습에서는 원본 카드번호를 조회하지 않고도 카드별 거래 건수와 금액을 계산할 수 있습니다.

이것이 토큰을 활용한 데이터 처리의 중요한 장점입니다.

그러나 토큰도 거래 내역과 결합하면 특정 고객의 행동을 추적할 수 있는 식별자가 될 수 있습니다.

따라서 토큰이라고 해서 무조건 개인정보 보호 대상에서 제외되는 것은 아닙니다.


6. 접근 권한 관리: 누구에게 어떤 데이터를 보여줄 것인가?

개인정보 보호에서 마스킹과 토큰화만큼 중요한 것이 접근 권한 관리입니다.

금융 IT 시스템에서는 업무 담당자에게 필요한 범위의 권한만 부여하는 **최소 권한 원칙(Principle of Least Privilege)**을 적용합니다.

예를 들어 다음과 같이 역할을 구분할 수 있습니다.

사용자 역할 필요한 접근 범위
고객센터 상담원 업무에 필요한 고객정보와 마스킹된 카드정보
데이터 분석 담당자 승인된 분석용 데이터와 가명 식별자
시스템 운영자 장애 처리에 필요한 로그와 시스템 상태
보안 관리자 접근 기록, 권한 변경 이력, 보안 이벤트

여기서 중요한 것은 시스템 운영자라고 해서 모든 고객정보를 볼 수 있어야 하는 것은 아니라는 점입니다.

운영 목적과 개인정보 조회 권한은 별도로 설계할 수 있습니다.

7. SQL 실습 ③ PostgreSQL 뷰로 조회 범위 제한하기

이번에는 상담원에게 카드번호 전체 대신 마스킹된 값만 보여주는 조회 뷰를 만들어 보겠습니다.

① 마스킹 뷰 생성

CREATE VIEW demo_customer_cards_masked AS
SELECT
    customer_id,
    customer_name,
    LEFT(card_number, 4)
        || '********'
        || RIGHT(card_number, 4) AS masked_card_number
FROM demo_customer_cards;

② 상담원 역할 생성 및 권한 부여

아래 코드는 실습 데이터베이스에서 역할 생성 권한이 있는 계정으로 실행하는 예시입니다.

CREATE ROLE demo_support_role NOLOGIN;

GRANT USAGE ON SCHEMA public
TO demo_support_role;

GRANT SELECT ON demo_customer_cards_masked
TO demo_support_role;

이 실습은 새로 만든 역할에 뷰 조회 권한을 부여하는 과정입니다.

다만 실제 보안 효과는 역할이 원본 테이블에 접근할 수 없는 상태에서 확인해야 합니다. 다른 역할에서 상속받은 권한이나 PUBLIC 권한이 있다면 추가 검토가 필요합니다.

또한 PostgreSQL의 일반적인 뷰는 기본적으로 뷰 소유자의 권한으로 기초 테이블에 접근할 수 있으므로, 뷰 소유자와 권한 구조를 올바르게 구성해야 합니다.

③ 권한 확인

SELECT
    has_table_privilege(
        'demo_support_role',
        'demo_customer_cards',
        'SELECT'
    ) AS can_read_original,
    has_table_privilege(
        'demo_support_role',
        'demo_customer_cards_masked',
        'SELECT'
    ) AS can_read_masked;

예상 실행 결과

원본 테이블 조회 마스킹 뷰 조회
false true

이 결과는 실습 역할이 다른 경로로 원본 테이블 조회 권한을 받지 않았다는 전제에서 성립합니다.

즉, 상담원 역할에는 마스킹된 조회 결과만 제공하고, 원본 데이터 접근은 별도로 제한하는 구조를 설계할 수 있습니다.

실제 운영에서는 권한 상속, 뷰 소유자, 기본 권한, 접근 로그, 데이터 반출 경로까지 함께 검토해야 합니다.


8. 개인정보 보호는 조회 화면에서 끝나지 않는다

개인정보 보호는 데이터베이스의 조회 권한만으로 해결되지 않습니다.

실제 금융 IT 시스템에서는 데이터가 여러 경로로 이동합니다.

예를 들어 다음과 같습니다.

카드 승인 시스템 → 거래 데이터 저장소 → DW → 분석 시스템 → 보고서

이 과정에서 원본 카드번호가 필요하지 않은 시스템에까지 전달된다면 불필요한 노출 위험이 커집니다.

따라서 개인정보 보호는 데이터의 전체 생명주기를 기준으로 설계해야 합니다.

수집 단계: 필요한 정보만 수집하고 처리 목적을 명확히 합니다.

저장 단계: 적절한 암호화와 접근 통제를 적용합니다.

이용 단계: 업무별 최소 권한을 부여하고 조회 이력을 관리합니다.

전송 단계: 안전한 통신 방식과 시스템 간 인증을 적용합니다.

보존·파기 단계: 법령과 업무상 보존 의무에 맞춰 보존 기간을 관리하고, 기간이 종료된 데이터는 적절하게 처리합니다.

특히 금융회사에서는 개인정보 보호법, 신용정보 관련 법령, 전자금융 관련 규정, 적용 가능한 결제 보안 기준 등을 함께 고려해야 합니다.


9. 카드 승인 로그에도 개인정보가 남을 수 있다

앞선 #25편에서는 카드 승인 장애를 분석하기 위해 거래번호와 Trace ID를 이용하는 방법을 살펴봤습니다.

그런데 로그를 많이 남기면 장애 분석이 쉬워지는 대신 개인정보 노출 위험이 커질 수도 있습니다.

예를 들어 승인 요청 전문 전체를 로그에 기록하면 카드번호나 기타 보호 대상 정보가 포함될 수 있습니다.

따라서 운영 로그에는 장애 분석에 필요한 식별자와 처리 결과를 남기되, 불필요한 카드정보나 인증정보는 기록하지 않는 방향으로 설계해야 합니다.

또한 Trace ID 자체는 일반적으로 기술적인 추적 식별자이지만, 거래번호나 고객정보와 연결할 수 있다면 접근 통제와 보존 정책의 적용 대상이 될 수 있습니다.

장애 분석에 필요한 정보와 개인정보 보호 사이에서 적절한 균형을 찾는 것이 금융 IT 로그 설계의 중요한 과제입니다.


10. 마무리: 개인정보 보호는 데이터 설계에서 시작된다

카드사 시스템에서 개인정보를 보호하는 방법은 단순히 카드번호 일부를 별표로 가리는 것에 그치지 않습니다.

마스킹은 화면에 표시되는 정보를 제한하는 데 도움이 되고, 토큰화는 원본 카드정보에 대한 의존도를 낮추는 데 활용할 수 있습니다.

접근 권한 관리는 업무 담당자가 필요한 데이터에만 접근하도록 제한하는 역할을 합니다.

이 세 가지 기술은 서로 대체하는 관계가 아니라 함께 적용할 수 있는 보호 수단입니다.

이번 SQL 실습에서는 다음 내용을 확인했습니다.

  • 카드번호의 일부를 가려 조회하는 방법
  • 토큰을 이용해 거래를 집계하는 방법
  • PostgreSQL 뷰와 역할을 이용해 조회 범위를 제한하는 방법

금융 IT 시스템에서 중요한 것은 개인정보를 많이 보유하거나 모든 담당자가 쉽게 조회할 수 있도록 만드는 것이 아닙니다.

필요한 데이터를 필요한 사람과 시스템에만 제공하고, 그 사용 과정을 관리할 수 있도록 설계하는 것이 개인정보 보호의 출발점입니다.


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 브라이언의 금융 IT 노트. All rights reserved.