페더레이티드 러닝의 Secure Aggregation과 차등 개인정보보호 설계

페더레이티드 러닝에서 DP-SGD와 Secure Aggregation을 결합해 개별 업데이트 노출을 줄이고 프라이버시 예산과 탈락 내성을 운영하는 방법

2026-08-14 · 최초 발행 2024-04-29

업데이트를 숨겨야 하는 이유

페더레이티드 러닝(FL)은 데이터를 각 클라이언트에 보관한 채 모델 업데이트만 교환하는 분산 학습 방식이다. 중앙 서버는 가중치를 집계하고, 클라이언트는 로컬 데이터로 미니배치 학습을 수행한다.

데이터를 중앙으로 옮기지 않는다고 해서 업데이트가 안전한 것은 아니다. honest-but-curious 서버, gradient inversion 같은 악의적 가십 공격, 트래픽 도청, 일부 클라이언트의 탈락이나 지연을 함께 고려해야 한다. 이 설계의 목적은 개별 업데이트를 보이지 않게 만들고 재식별·역추론 위험을 줄이는 데 있다.

차등 개인정보보호(Differential Privacy, DP)는 업데이트 또는 통계에 확률적 노이즈를 더해 개별 샘플의 기여도를 수학적으로 은닉한다. L2 클리핑, 가우시안 노이즈, 프라이버시 예산(ε, δ) 회계가 핵심 구성이다.

Secure Aggregation(SecAgg)은 서버가 클라이언트별 업데이트 평문을 보지 않고도 전체 합 또는 평균만 복구하도록 만드는 암호 프로토콜이다. 쌍대 마스킹, 비밀분산, 탈락 내성을 포함한다.

DP와 안전 집계를 결합하는 흐름

아니오예산 초과정상입력: 클라이언트 로컬 데이터,초기 모델클라이언트 로컬 학습Per-sample GradientClippingGaussian Noise 주입(DP-SGD)Secure Aggregation 마스크생성 (쌍대/비밀분산)마스크 적용 업데이트 전송드롭아웃 발생?마스크 복구 절차 실행 (조각공개/키 재합성)집계 준비서버: 마스크 상쇄, 안전집계(합/평균)프라이버시 회계(ε, δ) 검증라운드 중단/재설계모델 갱신 배포출력: 갱신된 글로벌 모델,예산/운영 로그

클라이언트는 per-sample gradient clipping으로 민감도의 상한을 정한 뒤 가우시안 노이즈를 추가한다. 라운드와 스텝마다 소모되는 예산은 합성 정리로 관리하며, 목표 ε 범위는 예: 2~8 안에서 수렴을 달성하도록 잡는다.

그 다음 각 클라이언트는 쌍대 마스크를 생성한다. 마스크는 합산 시 sum-to-zero로 상쇄되므로 서버는 전체 합만 얻는다. 드롭아웃이 발생하면 비밀분산 조각 공개 또는 키 재합성으로 남은 마스크를 제거한다.

서버는 세션과 라운드를 관리하고 키·메타데이터를 배포하며, 안전 집계와 프라이버시 회계를 맡는다. 클라이언트 쪽에는 로컬 학습, DP-SGD 적용, 마스크 생성·적용, 실패 시 재참여 정책이 필요하다.

통신 실패에는 라운드 타임아웃을 두고 부분 집계 임계치(t-of-n)를 충족하면 진행한다. 참여 확정→키 교환→업데이트 커밋→집계 완료→모델 배포 순서도 보장해야 한다. 라운드별 세션 키와 참여자 스냅샷을 고정해 중복 업데이트를 막는다.

보호 강도와 운영 부담의 차이

구분 성능(시간) 확장성 일관성/정확성 안정성/보안 운영 편의
FL 베이스라인 ★★★★ ★★★★ ★★★★ ★★ ★★★★
FL + DP ★★★ (노이즈/클리핑 오버헤드) ★★★★ ★★★ (약간의 정확도 저하) ★★★★ (개인정보 보호 강화) ★★★ (예산 관리 필요)
FL + DP + SecAgg ★★☆ (암호 연산/드롭 복구 비용) ★★★ (탈락 내성 설계 필요) ★★★ (집계만 관찰 가능) ★★★★★ (개별 업데이트 비가시) ★★☆ (키/프로토콜 운영)

주: 별점은 상대 비교 목적이며 실제 값은 데이터·인프라에 의존한다.

통신량은 업데이트 양자화·스파스화와 서버 측 평균 전송으로 줄일 수 있다. 암호 연산은 PRG 기반 마스크와 배치형 집계로 다룰 수 있지만, 스트림 키를 재사용해서는 안 된다. 프라이버시 예산 대시보드, 클라이언트 참여율·드롭율, 라운드 실패 재시도 정책도 운영 범위에 포함된다. 키 수명, DP 파라미터, 승인된 클라이언트 세트를 규정 준수 로그로 남긴다.

분산 환경에서의 적용 장면

모바일 키보드나 음성 모델 개선에서는 수천만 단말이 참여할 수 있다. DP-SGD로 개인 입력을 보호하고 SecAgg로 서버 노출을 최소화하며, 드롭율이 높은 환경에는 t-of-n 집계와 타임아웃 재스케줄링을 적용한다.

의료·금융 크로스-사일로 학습은 기관 간 업데이트를 SecAgg로 합산하고 중앙 서버의 호기심 모델을 가정한다. DP는 재식별 리스크를 낮추고 규정 준수 보고 자동화에 활용할 수 있다.

페더레이티드 분석에서는 평균, 분산, 히스토그램 같은 집계 통계에 DP와 SecAgg를 적용한다. 데이터셋을 이동하지 않고 개인정보보호형 KPI를 산출하는 방식이다.

DP-SGD를 적용한 FL 시뮬레이션

아래 코드는 교육 목적의 최소 예시다. 프로덕션에서는 검증된 프로토콜과 라이브러리를 사용하고 최신 보안 업데이트를 확인해야 한다.

Python 3.10, torch >= 2.2, opacus >= 1.4.1, numpy >= 1.24를 전제로 한다. 클리핑 노름, 노이즈 멀티플라이어, 샘플링률로 ε를 조정하고, 라운드 수와 클라이언트 수에 따른 합성 회계를 적용한다.

# pip install torch==2.2.2 opacus==1.4.1 numpy==1.26.4
import copy, math, random
import numpy as np
import torch
from torch import nn, optim
from torch.utils.data import TensorDataset, DataLoader
from opacus import PrivacyEngine

DEVICE = "cpu"

def make_client_data(n=512, d=10, seed=0):
    rng = np.random.default_rng(seed)
    X = rng.normal(size=(n, d)).astype(np.float32)
    w_true = rng.normal(size=(d, 1)).astype(np.float32)
    y = (X @ w_true + 0.1 * rng.normal(size=(n, 1))).astype(np.float32)
    return TensorDataset(torch.from_numpy(X), torch.from_numpy(y))

class SimpleReg(nn.Module):
    def __init__(self, d):
        super().__init__()
        self.lin = nn.Linear(d, 1)
    def forward(self, x): return self.lin(x)

def local_train_dp(model, dataset, epochs=1, batch_size=64, lr=0.05,
                   max_grad_norm=1.0, noise_multiplier=1.0, sample_rate=0.1, delta=1e-5):
    model = copy.deepcopy(model).to(DEVICE)
    loader = DataLoader(dataset, batch_size=batch_size, shuffle=True, drop_last=True)
    opt = optim.SGD(model.parameters(), lr=lr)
    privacy_engine = PrivacyEngine()
    model, opt, loader = privacy_engine.make_private_with_epsilon(
        module=model,
        optimizer=opt,
        data_loader=loader,
        target_epsilon=None,   # 직접 noise_multiplier 사용
        target_delta=delta,
        epochs=epochs,
        max_grad_norm=max_grad_norm,
        noise_multiplier=noise_multiplier
    )
    loss_fn = nn.MSELoss()
    model.train()
    for _ in range(epochs):
        for xb, yb in loader:
            xb, yb = xb.to(DEVICE), yb.to(DEVICE)
            opt.zero_grad()
            pred = model(xb)
            loss = loss_fn(pred, yb)
            loss.backward()
            opt.step()
    return model, privacy_engine

def fedavg(models, weights=None):
    avg = copy.deepcopy(models[0])
    with torch.no_grad():
        for k, p in avg.state_dict().items():
            ps = [m.state_dict()[k] for m in models]
            if weights is None:
                p.copy_(torch.mean(torch.stack(ps), dim=0))
            else:
                wsum = sum(w * t for w, t in zip(weights, ps))
                p.copy_(wsum)
    return avg

# 시뮬레이션 파라미터
K = 5            # 클라이언트 수
ROUNDS = 5
DIM = 10
clients = [make_client_data(n=1024, d=DIM, seed=i) for i in range(K)]
global_model = SimpleReg(DIM)
delta = 1e-5
noise_multiplier = 1.2   # 예시 값
max_grad_norm = 1.0

for r in range(ROUNDS):
    local_models, eps_list = [], []
    selected = random.sample(range(K), k=K)  # 전원 참여 예시
    for i in selected:
        m, pe = local_train_dp(
            global_model, clients[i],
            epochs=1, batch_size=64, lr=0.05,
            max_grad_norm=max_grad_norm,
            noise_multiplier=noise_multiplier,
            sample_rate=64/1024, delta=delta
        )
        # 단순 에포크 기준 ε 추정 (Opacus Accountant 사용 시 get_epsilon 가능)
        # 여기서는 placeholder: 실전에서는 privacy_engine.accountant.get_epsilon(delta) 사용
        try:
            eps = pe.accountant.get_epsilon(delta)
        except Exception:
            eps = float("nan")
        eps_list.append(eps)
        local_models.append(m)
    global_model = fedavg(local_models)
    print(f"Round {r+1} done. epsilon (approx per client): {eps_list}")

실제 ε 산출은 accountant 구현에 의존한다. 프레이밍에 맞는 정확한 회계 모듈을 사용해야 하며, 노이즈를 늘리면 정확도는 낮아지고 프라이버시는 강화된다. 적정 ε를 탐색하는 과정이 필요하다.

쌍대 마스크가 합계만 남기는 방식

각 클라이언트 i는 모든 j>i와 공유한 시드로 마스크 m_ij를 만든다. i는 m_ij를 더하고 j는 같은 마스크를 빼므로 합산에서는 마스크가 상쇄된다. 드롭아웃이 발생하면 관련 마스크 조각 공개 또는 복구 프로토콜로 합을 복구한다.

import numpy as np
from hashlib import sha256

def prg(seed: bytes, size: int) -> np.ndarray:
    # 간단 PRG: 시드 해시를 반복하여 유사난수 생성 (데모용)
    out = bytearray()
    ctr = 0
    while len(out) < size * 4:
        out += sha256(seed + ctr.to_bytes(4, 'big')).digest()
        ctr += 1
    arr = np.frombuffer(out[:size*4], dtype=np.uint32).astype(np.float32)
    return (arr / np.float32(2**32) - 0.5)  # [-0.5, 0.5)

def secagg_masked_updates(updates, shared_seeds):
    """
    updates: list[np.ndarray], 길이 K
    shared_seeds: dict[(i,j)] = bytes with i<j
    반환: 마스크 적용된 업데이트 리스트
    """
    K = len(updates)
    d = updates[0].size
    masked = [u.copy() for u in updates]
    for i in range(K):
        for j in range(i+1, K):
            m = prg(shared_seeds[(i,j)], d)
            masked[i] += m
            masked[j] -= m
    return masked

# 데모
K, d = 4, 8
rng = np.random.default_rng(0)
updates = [rng.normal(size=d).astype(np.float32) for _ in range(K)]
# 쌍대 시드 생성
shared_seeds = {}
for i in range(K):
    for j in range(i+1, K):
        shared_seeds[(i,j)] = sha256(f"key-{i}-{j}".encode()).digest()

masked = secagg_masked_updates(updates, shared_seeds)
server_sum = np.sum(masked, axis=0)  # 마스크 상쇄
true_sum = np.sum(updates, axis=0)
print("sum diff (should be ~0):", np.max(np.abs(server_sum - true_sum)))

프로덕션에서는 드롭아웃 내성을 가진 프로토콜(예: SecAgg, SecAgg+)과 적절한 키 교환·비밀분산을 사용한다. 난수 생성에는 암호학적으로 안전한 PRG가 필요하고, 시드 관리와 키 수명 정책도 필수다.

예산·탈락·비용을 함께 조정하기

프라이버시 강도는 목표 ε 범위와 δ=1/N² 같은 보수적 설정을 바탕으로 설계한다. 학습률, 라운드 수, 클리핑 노름, 노이즈 멀티플라이어를 동시에 최적화해야 한다. ε↓ → 정확도↓, 수렴 지연↑의 트레이드오프가 따른다.

탈락 내성에서는 임계치 t-of-n, 재시도 윈도, 부분 집계 허용 정책을 정한다. t↑ → 보안↑, 성공률/지연 악화라는 관계를 고려한다.

통신·암호 비용은 업데이트 스파스화·양자화, 서버 측 압축 해제, 배치 집계로 조정할 수 있다. 압축↑ → 정보 손실↑, 수렴 영향이라는 비용이 있다.

DP 파라미터를 바꿀 때는 승인 워크플로우를 두고, 키 롤오버를 자동화하며, 감사 로그의 불변성을 확보한다. 운영 복잡도↑ ↔ 규정 준수·리스크↓의 균형을 선택하는 문제다.

기대할 수 있는 보호 효과와 오버헤드

재식별·역추론 공격 성공률은 공격 설정에 따라 수배수십 배 감소 보고가 있으며 최신 정보 확인이 필요하다. ε를 28 범위로 제어할 때 정상 수렴을 달성한 사례도 다수다. 오버헤드는 시간 1.22.0배, 통신 1.11.5배 수준으로 관찰 가능하며 환경에 의존한다.

서버와 운영자가 다루는 정보를 최소화하면 법적·평판 리스크를 줄일 수 있다. 멀티 파티 간 신뢰를 단순화하고, 데이터 이동 없이 협업하는 기반도 마련된다. 보안 사고가 발생했을 때 파급 범위를 제한하는 효과도 기대할 수 있다.

페더레이티드 러닝차등 개인정보보호Secure AggregationDP-SGD프라이버시 예산