[시리즈] 클립보드 공유 시스템

1. 시퀀스 다이어그램

마지막 수정

시퀀스 다이어그램은 손으로 일일히 작성하기에는 매우 힘들고 귀찮은 일이니, 플로우와 필요 API를 전달해서 AI로 생성했다.


필요 API

  • 그룹 가입 확인
  • 그룹 생성 요청
  • 연동 코드 생성 요청
  • 그룹 가입 요청
  • 그룹 기기 목록 조회
  • 그룹 탈퇴 요청
  • 그룹 이동 요청
  • SSE 연결 요청
  • 클립보드 데이터 전달 요청 (암호화해서 전달)

시퀀스 다이어그램

1. A 기기에서 연동 코드·QR 생성

sequenceDiagram
    autonumber
    actor User as 사용자
    participant A as A 기기
    participant S as 서버
    participant DB as DB

    Note over A: 앱 설치 시 UUID, 공개키, 기기 이름 생성 및 고정

    User->>A: 기기 연동 화면 열기
    A->>S: 그룹 가입 확인(UUID)
    S->>DB: 기기의 그룹 조회
    DB-->>S: 그룹 정보 또는 없음
    S-->>A: 그룹 가입 여부 및 그룹 정보

    A->>S: 그룹 생성 요청(UUID, 공개키, 기기 이름)
    S->>DB: 기존 그룹 조회

    alt 기존 그룹 있음
        DB-->>S: 기존 그룹 정보
    else 기존 그룹 없음
        S->>DB: 그룹 생성 및 A 기기 등록
        DB-->>S: 새 그룹 정보
    end

    S-->>A: 그룹 정보(동일한 응답 형식)
    A->>S: 연동 코드 생성 요청
    S->>DB: 코드와 그룹 정보 저장(유효기간 10분)
    DB-->>S: 저장 완료
    S-->>A: 연동 코드 및 만료 시각
    A->>A: 연동 코드로 QR 생성
    A-->>User: QR 및 연동 코드 표시

2. B 기기에서 QR 인식·코드 입력 후 가입

sequenceDiagram
    autonumber
    actor User as 사용자
    participant B as B 기기
    participant S as 서버
    participant DB as DB

    alt QR로 연동
        User->>B: A 기기의 QR 인식
        B->>B: QR에서 연동 코드 추출
    else 코드로 연동
        User->>B: 연동 코드 직접 입력
    end

    B->>S: 그룹 가입 요청(코드, UUID, 공개키, 기기 이름)
    S->>DB: 코드 유효성 및 대상 그룹 조회
    DB-->>S: 코드 및 대상 그룹 정보

    alt 코드가 없거나 만료됨
        S-->>B: 유효하지 않거나 만료된 코드 오류
        B-->>User: 코드 재확인 또는 재생성 안내
    else 유효한 코드
        S->>DB: B 기기의 현재 그룹 조회
        DB-->>S: 현재 그룹 정보 또는 없음

        alt 이미 대상 그룹에 소속
            S-->>B: 이미 가입한 그룹 오류
            B-->>User: 이미 연동된 기기 안내
        else 다른 그룹에 소속
            S-->>B: 다른 그룹 소속 응답(기존 그룹 ID)
            B-->>User: 기존 그룹 유지 또는 대상 그룹으로 이동 선택

            alt 기존 그룹 유지
                User->>B: 기존 그룹 다시 사용
                Note over B,S: 추가 API 호출 없이 종료
            else 대상 그룹으로 이동
                User->>B: 대상 그룹으로 이동
                B->>S: 그룹 이동 요청(UUID, 연동 코드)
                S->>DB: 코드 및 현재 그룹 재검증

                alt 코드가 없거나 만료됨
                    S-->>B: 유효하지 않거나 만료된 코드 오류
                    B-->>User: 코드 재생성 안내
                else 이동 가능
                    S->>DB: 기존 그룹 탈퇴 및 대상 그룹 가입(트랜잭션)
                    DB-->>S: 이동 완료
                    S-->>B: 대상 그룹 정보
                    B-->>User: 기기 연동 완료
                end
            end
        else 소속 그룹 없음
            S->>DB: 대상 그룹에 B 기기 등록
            DB-->>S: 가입 완료
            S-->>B: 대상 그룹 정보
            B-->>User: 기기 연동 완료
        end
    end

3. 그룹 기기 목록 조회·그룹 탈퇴

sequenceDiagram
    autonumber
    actor User as 사용자
    participant D as 기기
    participant S as 서버
    participant DB as DB

    opt 그룹 기기 목록 조회
        User->>D: 연동된 기기 목록 열기
        D->>S: 그룹 기기 목록 조회(UUID)
        S->>DB: UUID로 소속 그룹 및 기기 목록 조회
        DB-->>S: 조회 결과
        S-->>D: 그룹 정보 및 기기 목록
        D-->>User: 연동된 기기 목록 표시
    end

    opt 그룹 탈퇴
        User->>D: 그룹 탈퇴
        D->>S: 그룹 탈퇴 요청(UUID)
        S->>DB: 기기의 그룹 소속 해제
        DB-->>S: 탈퇴 완료
        S->>S: 해당 기기를 그룹 SSE 전송 대상에서 제거
        S-->>D: 탈퇴 완료
        D->>D: SSE 연결 종료
        D-->>User: 그룹 탈퇴 완료 표시
    end

4. SSE 연결 및 클립보드 전달

sequenceDiagram
    autonumber
    participant A as A 기기
    participant S as 서버
    participant DB as DB
    participant B as B 기기

    Note over A,B: 앱 실행 시 각 기기가 그룹 가입 여부 확인
    A->>S: 그룹 가입 확인(UUID)
    S-->>A: 그룹 정보
    B->>S: 그룹 가입 확인(UUID)
    S-->>B: 그룹 정보

    Note over A,B: 소속 그룹이 있는 경우 SSE 연결
    A->>S: SSE 연결 요청
    S-->>A: SSE 연결 유지
    B->>S: SSE 연결 요청
    S-->>B: SSE 연결 유지

    Note over A,B: 새 그룹 가입 또는 이동 완료 시에도 SSE 연결 상태 갱신

    A->>A: 시스템 클립보드 변경 감지
    A->>A: 텍스트를 UTF-8 바이트로 변환 후 Base64 인코딩
    A->>S: 클립보드 데이터 전달(UUID, 데이터 유형, Base64 데이터)
    S->>DB: A 기기의 소속 그룹 확인
    DB-->>S: 그룹 정보
    S-->>A: 데이터 접수 완료

    S-->>B: SSE 클립보드 이벤트(발신 기기, 데이터 유형, Base64 데이터)
    Note over S,B: 동일 그룹의 다른 연결 기기에 전달
    B->>B: Base64 디코딩 후 UTF-8 텍스트 복원
    B->>B: 시스템 클립보드에 저장
    Note over B: 수신 데이터 저장으로 발생한 변경은 재전송하지 않음

5. E2E 암호화 및 클립보드 전달

sequenceDiagram
    autonumber
    participant A as A 기기
    participant S as 서버
    participant DB as DB
    participant B as B 기기

    Note over A,B: 각 기기의 개인키는 해당 기기에만 보관
    Note over B,S: B 기기는 SSE 연결 상태

    A->>A: 클립보드 텍스트 변경 감지
    A->>S: 그룹 기기 목록 조회(UUID)
    S->>DB: 소속 그룹의 기기 UUID 및 공개키 조회
    DB-->>S: 기기 목록 및 공개키
    S-->>A: 기기 목록 및 공개키

    A->>A: 텍스트를 UTF-8 바이트로 변환
    A->>A: 메시지 전용 랜덤 대칭키 K 및 nonce 생성
    A->>A: AES-256-GCM으로 본문 암호화
    Note over A: 암호문과 인증 태그 생성

    loop 자신을 제외한 각 수신 기기
        A->>A: 수신 기기의 공개키로 K 암호화(RSA-OAEP)
        A->>A: UUID별 key, nonce, data 구성
    end

    Note over A: key와 nonce는 Base64로 인코딩
    Note over A: data는 암호문과 인증 태그를 합쳐 Base64로 인코딩

    A->>S: 클립보드 전달 요청(UUID별 암호화 데이터)
    S->>DB: 발신 및 수신 기기의 동일 그룹 소속 확인
    DB-->>S: 확인 결과

    alt 전달 대상 유효
        S-->>A: 데이터 접수 완료
        S-->>B: SSE 이벤트(B UUID에 해당하는 데이터)
        B->>B: key, nonce, data를 Base64 디코딩
        B->>B: 자신의 개인키로 key 복호화하여 K 획득
        B->>B: K와 nonce로 data 복호화 및 인증 태그 검증

        alt 복호화 및 검증 성공
            B->>B: UTF-8 텍스트 복원
            B->>B: 시스템 클립보드에 저장
            Note over B: 수신 데이터로 발생한 변경은 재전송하지 않음
        else 복호화 또는 검증 실패
            B->>B: 데이터 폐기
        end
    else 전달 대상 유효하지 않음
        S-->>A: 그룹 소속 오류
    end

    Note over S: 서버는 개인키와 평문 대칭키를 보유하지 않음

전달 데이터 형태

{
  "keys": {
    "<B 기기 UUID>": "<B 공개키로 암호화한 대칭키의 Base64>",
    "<C 기기 UUID>": "<C 공개키로 암호화한 대칭키의 Base64>"
  },
  "nonce": "<AES-GCM nonce의 Base64>",
  "data": "<대칭키로 암호화한 본문 + 인증 태그의 Base64>"
}

다음 내용은 데이터베이스 설계이다.
이후 본격적으로 개발을 진행한다.