글로벌하게 유니키한 키를 만들어야 할때, 보통은 uuid를 떠올리지만 snowflake방식을 선택하면 아래와 같은 장점이 있다.

 

비교 항목 UUIDv4 Snowflake
크기(Storage) 128 bit (16 바이트) 64 bit (8 바이트)
인덱스 단편화 완전 랜덤 삽입 → B-tree 인덱스 단편화↑ 시간순으로 순차적 증가 → 단편화↓
순차성(Time-sortable) 불가능 상위 비트에 밀리초 타임스탬프 내장 → 정렬 가능
생성 비용 랜덤 엔트로피 생성 → CPU & 메모리 부하 다소 높음 단순 비트 연산 + 시퀀스 → 매우 경량
메타데이터 내장 없음 타임스탬프·데이터센터ID·노드ID·시퀀스 정보 포함
충돌 위험 충돌 확률 극히 낮으나 완전히 배제 불가 노드ID+시퀀스 조합으로 충돌 사실상 0 (전제: 노드ID 관리)
디버깅·추적 편의성 ID만으로 “언제 생성됐는지” 파악 불가 ID만으로 생성 시각·생성 주체(노드) 추적 가능

 

언제 UUID를 쓰고, 언제 Snowflake를 쓰나?

  • UUIDv4
    • 단순 분산 식별자(ID)만 필요하고, 시간순 정렬·인덱스 단편화 이슈가 크지 않은 애플리케이션
    • 예: 각종 리소스(사용자·세션·토큰) 식별 등
  • Snowflake
    • 고TPS 분산 시스템에서 시간순 처리·인덱스 효율·멱등 ID가 중요할 때
    • 예: 이벤트 로깅, 메시징 시스템, 주문·트랜잭션 ID
반응형

'System Architect' 카테고리의 다른 글

OIDC(Open ID Connect)  (0) 2025.06.18
outbox 패턴  (0) 2025.06.16
쿠버네티스(K8s, kubernetes)  (0) 2025.06.01
업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
딥링크  (0) 2025.05.23

OAuth2.0위에서 추가로 설계된 스펙으로 기존 엑세스토큰, 리프레시토큰과 더불어 ID Token을 발행하여 “인증(Authentication)” 기능을 추가한 표준 프로토콜입니다.

 

  • OAuth 2.0이 “리소스 접근 권한(Authorization)”을 다룬다면,
  • OIDC는 “사용자 인증(Authentication)”을 다룹니다.

 

 

 

필수 클레임(iss, sub, aud, exp 등) + 요청한 소수의 추가 클레임(예: email, name)

 

ID Token에 담기는 필드 예시

{
  "iss": "https://auth.gangnamunni.com/",     // 토큰 발급자(Identity Provider)  
  "sub": "248289761001",                       // 사용자 고유 식별자  
  "aud": "points-service-prod",                // 토큰 대상(클라이언트 ID)  
  "exp": 1718865600,                           // 토큰 만료 시각 (Unix timestamp)  
  "iat": 1718862000,                           // 토큰 발급 시각  
  "auth_time": 1718861990,                     // 사용자가 실제 인증한 시각  
  "nonce": "n-0S6_WzA2Mj",                      // 리플레이 공격 방지용 값  
  "email": "janedoe@example.com",              // 요청한 추가 클레임: 이메일  
  "email_verified": true,                      // 이메일 검증 여부  
  "name": "Jane Doe",                          // 요청한 추가 클레임: 이름  
  "preferred_username": "j.doe"                // 요청한 추가 클레임: 사용자명
}

 

하지만 아래 이유로..

정적 정보: 발급 시점의 정보만 담겨, 사용자가 프로필을 변경해도 토큰에는 반영되지 않음
사이즈 한계: 너무 많은 필드를 넣으면 JWT가 커져 네트워크/성능 부담 ↑
보안 고려: 민감 정보(주소, 휴대폰 등)를 토큰에 영구 저장하면 위험

 

UserInfo Endpoint 추가

자세한건 다시 api찔러서 확인

 

서비스 특성에 따라

  • ID 토큰만,
  • UserInfo만,
  • 혹은 둘 다 쓰는 패턴을 자유롭게 선택하시면 됩니다.

 

UserInfo Endpoint를 왜 추가했나?

  • 목적: “로그인한 사용자에 대한 동적·확장 프로필”을 안전하게 조회”
  • 동작 방식:
    1. 클라이언트가 access_token을 이용해 /userinfo 호출
    2. 서버가 현재 스코프(scope)·권한에 맞는 최신 프로필(JSON) 반환
  • 장점:
    • 최신성: 호출 시점의 유저 정보를 그대로 반영
    • 선택적 노출: scope(email profile phone 등)에 따라 필요한 정보만 제공
    • 토큰 경량화: 민감·대용량 데이터는 토큰이 아니라 API로 분리

/userinfo라는 엔드포인트 이름 자체도 OIDC Core 1.0 사양(섹션 5.3)에 명시된 표준 필드(userinfo_endpoint)입니다. 클라이언트는 .well-known/openid-configuration에서 이 URL을 동적으로 조회(discovery)하도록 되어 있고, 실제 경로는 /userinfo가 아니어도 메타데이터에 정의된 대로 호출하면 됩니다. 즉, /userinfo는 OIDC 스펙에 포함된 공식 기능이며, “스펙 확장”이 아니라 인증과 프로필 조회를 분리하기 위해 설계된 표준입니다

반응형

'System Architect' 카테고리의 다른 글

snowflake  (0) 2025.06.23
outbox 패턴  (0) 2025.06.16
쿠버네티스(K8s, kubernetes)  (0) 2025.06.01
업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
딥링크  (0) 2025.05.23

“아웃박스 패턴은 분산 트랜잭션을 쓰지 않고도 데이터베이스 업데이트와 외부 시스템(Kafka나 REST API 등) 호출을 사실상 하나의 트랜잭션처럼 보이게 하는 기법입니다.

  1. 비즈니스 로직 DB 쓰기와 동일한 DB 트랜잭션에서 ‘Outbox’ 테이블에 이벤트 메시지를 append(INSERT)
  2. 트랜잭션 커밋 시점에 비즈니스 데이터와 Outbox INSERT가 함께 커밋됨
  3. 별도 프로세스(Outbox Poller)가 이 테이블을 폴링해서 메시지를 읽고 Kafka 프로듀서나 외부 API를 호출
  4. 호출 성공 시 Outbox 레코드의 status=PROCESSED(또는 sent_at) 같은 플래그를 업데이트”

 

“Outbox 패턴으로 비즈니스 데이터와 이벤트 기록을 하나의 DB 트랜잭션에 묶어 최소-Once 전송을 확보합니다.
이후 Outbox Poller가 Kafka에 이벤트를 보낼 때는 Idempotent Producer(enable.idempotence=true)와 Kafka Transaction API를 활용해, ‘메시지 전송 + 소비 오프셋 커밋’을 하나의 카프카 트랜잭션으로 처리합니다.
마지막으로, 소비 측에서 claimId를 키로 사용하는 idempotent 처리 로직을 적용하면, 네트워크 오류나 재시도 상황에서도 정확히 한 번만 downstream에 반영되는 구조를 완성할 수 있습니다.”

반응형

'System Architect' 카테고리의 다른 글

snowflake  (0) 2025.06.23
OIDC(Open ID Connect)  (0) 2025.06.18
쿠버네티스(K8s, kubernetes)  (0) 2025.06.01
업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
딥링크  (0) 2025.05.23

Cluster vs Service 개념

Cluster는 물리적 Node들의 집합으로 그 안에 여러 논리적 서비스가 구성될수 있다.

 

  • Cluster: 여러 Node와 그 위의 Pod, 제어부(API 서버/스케줄러 등)를 합친 개념
  • Node: 실제 컨테이너가 실행되는 물리 서버 또는 VM
  • Pod: 최소 실행 단위(컨테이너 그룹), Node 위에 스케줄링됨
  • Service:
    • “ClusterIP, NodePort, LoadBalancer” 중 하나를 선택하여 Pod 집합에 가상 IP/포트 제공
    • 레이블 셀렉터로 뒤쪽 Pod들을 묶어 로드밸런싱 수행
  • 실제 흐름:
    • 클러스터 내부 → Pod간 통신 → Service로 묶어 부하 분산
    • 클러스터 외부 → (Ingress/LB) → Service → Pod
[Cluster]
 ├─ Node-A
 │    ├─ Pod-frontend-1  (레이블: app=frontend, 내부 포트 8080)
 │    └─ Pod-backend-1   (레이블: app=backend, 내부 포트 9090)
 └─ Node-B
      └─ Pod-frontend-2  (레이블: app=frontend, 내부 포트 8080)

 

 

LB(L4) vs Ingress controller(L7) vs Service(L4) 개념

Service가 L4레벨 LB/리버스 프록시 역할을 해주지만 그 앞단에서 L7레벨로 LB/리버스프록시 역할을 해주는게 Ingress controller(이역시 Pod안에 설치된다) 이게 있으면 Rest api별로 어느 service에서 수행할지 지정가능하다.

예를 들어 /api/user 요청은 user-service로, /api/order 요청은 order-service로 보내도록 설정

 

Ingress controller앞단에 LB가 보통 다시 붙는데 다음 역할을 수행한다

  • 가용성(HA) 확보
  • 고정된(또는 제한 가능한) 퍼블릭 엔드포인트 - 이건 특히 Ingress controller가 하기 힘든 부분
  • TLS 종료(SSL Termination)
  • DDoS 보호 및 WAF 연동
[클라이언트]
    ↓  (HTTPS)
[외부 LoadBalancer  (L4)]
    ↓  (HTTP/HTTPS or TCP)
[Ingress Controller Pod (L7)]
    ↓  (HTTP/HTTPS)
[Kubernetes Service (ClusterIP, L4)]
    ↓  (TCP/UDP)
[Pod (컨테이너)]
반응형

'System Architect' 카테고리의 다른 글

OIDC(Open ID Connect)  (0) 2025.06.18
outbox 패턴  (0) 2025.06.16
업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
딥링크  (0) 2025.05.23
OAuth2.0  (0) 2025.05.23

 

  • 네트워크·인터넷 맥락
    • 업스트림(upstream): upload 일반 사용자의 PC·모바일에서 데이터가 서버로 올라가는 방향 (upload)
    • 다운스트림(downstream): download 서버에서 사용자 쪽으로 내려오는 방향 (download)
    예) 내가 클라우드에 사진을 올리면 “업스트림”, 그 사진을 다른 사람이 내려받으면 “다운스트림”이죠.
  • 마이크로서비스·MSA 맥락
    • 업스트림(upstream): caller “지금 이 서비스를 호출해 주는(요청을 보내는)” 상위 서비스나 클라이언트
    • 다운스트림(downstream): callee “지금 이 서비스가 호출하는(요청을 보내는)” 하위 서비스
사용자(업스트림) → 웹앱 서비스(내 서비스) → 상품 서비스(다운스트림) → DB 서비스(더 아래 다운스트림)

 

 

일반적인 IT·네트워크 분야에서는 업로드/다운로드 맥락으로 “업스트림/다운스트림” 용어가 훨씬 오래, 더 많이 쓰였어요. 파일 전송이나 통신 장비 스펙에서도 수십 년 전부터 쓰여 왔으니까요.

하지만 백엔드 MSA 설계나 API 설계 문서에서는 서비스 간 호출 방향을 설명할 때 “업스트림 서비스/다운스트림 서비스” 표현이 이미 표준처럼 굳어졌습니다. 즉,

  • 네트워크 전반에서는 파일 전송·통신 기준의 업스트림·다운스트림이 더 보편적이고,
  • MSA 설계 분야에서는 서비스 호출 기준의 업·다운스트림이 주로 쓰입니다.

결국 “어느 쪽이 더 많이 쓰인다”는 기준이

  • 범용 IT·네트워크 분야를 말하면 첫 번째(업로드/다운로드 맥락)이고,
  • 마이크로서비스·백엔드 설계 분야를 말하면 두 번째(서비스 호출 맥락)입니다.
반응형

'System Architect' 카테고리의 다른 글

outbox 패턴  (0) 2025.06.16
쿠버네티스(K8s, kubernetes)  (0) 2025.06.01
딥링크  (0) 2025.05.23
OAuth2.0  (0) 2025.05.23
시스템설계 Q&A 3  (0) 2025.04.06

Q. 웹에서 로그인하고 앱으로 딥링크를 눌렀을때 로그인 된상태로 유지해주는 기술을 어떻게 구현할까?

 

A1. 만약 앱에서 이미 로그인이 되어 있거나, refresh_token이 있어서 자체적으로 access_token 재발급 받을 수 있는 경우 웹->앱간의 로그인 유지는 별다른 추가 처리없이 가능하다.

A2. 하지만 앱을 처음 설치했거나 해서 access_token/refresh_token이 앱에 없는 경우는 다음 과정을 거친다.

  • 로그인 된 상태의 웹벡앤드에서 인증서버에 짧은 주기의 인증코드개념의 로그인토큰을 발급받는다. 
  • 웹백엔드에서는 이 토큰을 딥링크에 실어서 앱에 보낸다.
  • 앱은 이 로그인토큰을 인증서버에 보내서 access_token/refresh_token을 발급 받는다.

 

반응형

'System Architect' 카테고리의 다른 글

쿠버네티스(K8s, kubernetes)  (0) 2025.06.01
업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
OAuth2.0  (0) 2025.05.23
시스템설계 Q&A 3  (0) 2025.04.06
위임(delegate) 패턴  (0) 2024.02.17

 

grant_type

 

간단흐름(쿠팡기준으로 설명 grant_type = password기준)

  • 고객, 앱, 앱개발자, 인증서버, 자원서버(api서버) 이렇게 5가지 주체가 있다.
  • 앱개발자는 인증서버에 admin페이지에서 client_id/secret_id를 발급받는다. (고객이 발급받는게 아님에 주의)
  • 앱에서 고객이 id/pwd를 넣고 로그인하면(인증서버에 api를 보내면) 인증서버에는 고객id/고객pwd, (앱개발자가앱에넣은) client_id/secret_id 이렇게 4가지 정보를 받는다. 모두 이상 없는경우 앱에게 access token을 넘겨준다. 
  • 그럼 앱은 고객에게 권한을 위임받는 것이고, 이 이후로는 특정시간동안 자원서버에 access token을 보내서 api호출이 가능하다.
  • 하지만 이 방식은 앱이 고객의 비밀번호를 직접 다루게 되므로 보안상 위험이 커서, 요즘은 거의 사용되지 않는다.

grant_type = authorization_code

  • 앱에서 고객 id/pwd를 받고 인증서버에 api로 전달하는게 위험하니..
  • 앱이 아닌 인증서버쪽 로그인 화면으로 url redirect를 시키는게 authrization_code방식이다.
  • 로그인후에 앱에 다시 인증코드가 담긴 url을 불러주면
  • 앱은 짧은 생명주기를 가진 이 인증코드로 서버에 api호출을 해서 access token을 받아온다.
  • (딥링크 방식에서도 이 인증코드 → access token 교환 구조가 유사하게 사용된다.)

grant_type = client_credentials

  • 서버 간(M2M) 통신 – 사용자 개입 없이 서비스 간 호출

 

PKCE(Proof Key for Code Exchange)

PKCE는 공개 클라이언트에서 Authorization Code Grant를 안전하게 사용할 수 있게 해주는 확장입니다.
클라이언트가 매 인가 요청 시 고유한 code_verifier를 만들고, 이를 SHA-256 해시한 code_challenge를 전달합니다.
토큰 발급 단계에서 클라이언트는 원본 code_verifier를 보내고, 인증 서버는 해시 값을 비교해 검증합니다.
이렇게 함으로써 인가 코드가 중간에 탈취되더라도, 올바른 code_verifier 없이는 토큰을 발급받을 수 없게 되어 보안성이 크게 향상됩니다.PKCE는 RFC 7636에 정의되어 있으며, 요즘은 SPA·모바일 앱용 OAuth 표준으로 자리 잡았습니다.

(모바일앱의 경우 client_secret을 탈취할 가능성이 커서 따로 저장하지 않기 위함)

 

state 검증

CSRF 공격 방지를 위해 인가 요청 시 생성한 state 값을 콜백에서 체크

인가요청시 state=난수를 client가 넣고, 콜백에서도 전달받는 state가 그 난수가 맞는지 체크.

반응형

'System Architect' 카테고리의 다른 글

업스트림(upstream)/다운스트림(downstream)  (0) 2025.05.30
딥링크  (0) 2025.05.23
시스템설계 Q&A 3  (0) 2025.04.06
위임(delegate) 패턴  (0) 2024.02.17
Application  (1) 2023.10.28

 

 

TLS Termination

원래 서버가 처리하던 TLS 암호화/복호화를 CDN 이 대신 수행하는 방식입니다. Redirect Service 는 트래픽이 매우 많고 요청이 단순하기 때문에, CDN 레이어에서 SSL 종료를 하면 서버가 암호화 작업을 하지 않아도 되어 부하를 줄일 수 있고, 글로벌 사용자 입장에서도 TLS 핸드셰이크가 CDN 엣지 서버에서 빠르게 처리되어 응답 속도도 개선됩니다. 또한, SSL 인증서 관리나 갱신을 CDN 에서 자동으로 해주기 때문에 운영 효율성도 좋아집니다.

 

사용자 ── TLS 암호화 ──> CDN (CloudFront, Fastly 등) ── HTTP 평문 ──> Redirect Service

 

Redis vs Cassandra

Redis는 key-value중심에 메모리에 들어갈 사이즈일때 효율 극대화

Cassandra는 RDB와 Redis중간정도에서 적당히 빠르고 메모리가 아닌 디스크기반이며 단순 key-value가 아니어도 SQL비슷한 느낌지원

 

Redis심화

Redis Cluster에서 채널개념

3개의 Redis server로 클러스터를 구성하면 이걸 Node라고 하는데, 

레디스키를 해시해서 어떤 노드에서 어떤 키를 처리할지 맵을 만들어서 클라이언트가 들고 있음

따라서 특정 키에 대한 처리는 특정 노드에서만 하고 클라이언트에서는 직접 이서버로 요청해서 key-value조회를 함(DNS같은것 필요없는 정적인 구조)

Pub/Sub개념

이건 Redis cluster에서는 모든 노드를 구독하지 않는한 전달이 안되서 비추,

단일노드 Redis나 Sentinel 구조에서는 kafka비슷하게 사용가능(근데 이거 키에 종속적인 개념은 아니다)

 

 

반응형

'System Architect' 카테고리의 다른 글

딥링크  (0) 2025.05.23
OAuth2.0  (0) 2025.05.23
위임(delegate) 패턴  (0) 2024.02.17
Application  (1) 2023.10.28
graphQL  (1) 2023.10.12

여기 참조

객체가 직접적으로 기능을 수행하는 대신에 다른 객체에 해당 기능을 위임

인터페이스를 이용하여 구현하는 경우가 많음

 

예시

public enum PrinterType {
    LASER, INKJET
}

public interface Printer {
    void printDocument(String document);
    PrinterType getType();
    boolean isSameType(PrinterType type);
}

public class LaserPrinter implements Printer {
    @Override
    public void printDocument(String document) {
        System.out.println("Laser Printer printing: " + document);
    }
    
    @Override
    public PrinterType getType() {
        return PrinterType.LASER;
    }
    
    @Override
    public boolean isSameType(PrinterType type) {
        return PrinterType.LASER.equals(type);
    }
}

public class InkjetPrinter implements Printer {
    @Override
    public void printDocument(String document) {
        System.out.println("Inkjet Printer printing: " + document);
    }

    @Override
    public PrinterType getType() {
        return PrinterType.INKJET;
    }
    
    @Override
    public boolean isSameType(PrinterType type) {
        return PrinterType.INKJET.equals(type);
    }
}

public class PrinterManager {
    private final List<Printer> printers;
    
    public PrinterManager() {
        printers = new ArrayList<>();
        printers.add(new LaserPrinter());
        printers.add(new InkjetPrinter());
    }

    public void print(String document, PrinterType type) {
        printers.stream()
                .filter(printer -> printer.isSameType(type))
                .forEach(printer -> printer.printDocument(document));
    }
}

public class Client {
    public static void main(String[] args) {
        PrinterManager manager = new PrinterManager();
        manager.print("Hello, world!", PrinterType.LASER); // "Laser Printer printing: Hello, world!" 출력
        manager.print("Hello, world!", PrinterType.INKJET); // "Ink
    }
}

 

위임의 장점

  • 객체간 결합도가 낮아짐
  • 런타임에 구현체를 변경 가능(어차피 빌드는 다시해야하지 않나?)
  • 위임하는 객체의 코드를 변경할 필요 없이 구현체를 추가하거나 교체하기 쉬움
반응형

'System Architect' 카테고리의 다른 글

OAuth2.0  (0) 2025.05.23
시스템설계 Q&A 3  (0) 2025.04.06
Application  (1) 2023.10.28
graphQL  (1) 2023.10.12
gRPC  (0) 2023.10.11

"응용 프로그램"은 사용자가 특정 작업을 수행하기 위해 실행하는 소프트웨어를 가리킵니다.

이 응용 프로그램은 전통적인 모놀리식 구조일 수도 있고, MSA(Microservices Architecture)와 같은 구조일 수도 있습니다.

따라서 Application은  MSA보다 더 넓은 범위를 가집니다.


응용 프로그램(Application)

사용자가 특정 작업을 수행하기 위해 실행하는 소프트웨어의 집합.

전통적인 모놀리식 구조일 수도 있고, MSA(Microservices Architecture)와 같은 구조일 수도 있습니다.

 

MSA (Microservices Architecture)

응용 프로그램을 작은 서비스들로 분리하는 아키텍처 스타일.
각 서비스는 특정 기능에 초점을 맞추며 독립적으로 동작합니다.

반응형

'System Architect' 카테고리의 다른 글

시스템설계 Q&A 3  (0) 2025.04.06
위임(delegate) 패턴  (0) 2024.02.17
graphQL  (1) 2023.10.12
gRPC  (0) 2023.10.11
시스템설계 Q&A 2  (0) 2023.09.20

+ Recent posts