[시리즈] 클립보드 공유 시스템
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>"
}
다음 내용은 데이터베이스 설계이다.
이후 본격적으로 개발을 진행한다.