Get-and-Set

“Get-and-Set"은 전통적인 CRUD(Create, Read, Update, Delete) 방식을 개선한 REST API 디자인 패턴으로, 리소스의 존재 여부와 관계없이 단순화된 작업 흐름을 제공한다.

기본 개념

두 가지 핵심 연산

  • Get: 리소스의 현재 상태 조회 (CRUD의 Read와 동일)
  • Set:
    • Create/Update: 리소스 존재 여부와 무관하게 값을 설정 (Last-Write-Wins 정책)
    • Delete: null 값을 전달하여 리소스 삭제

동작 원리

1
2
3
4
[클라이언트]           [서버]
   Get 요청 → 리소스 상태 확인
   Set 요청 → 값 설정/삭제
   ← 최종 상태 반환 (옵션: 이전 값 포함)

CRUD와의 차이점

기능CRUD APIGet-and-Set API
생성/수정POST/PUT/PATCH 분리단일 Set 연산으로 통합
삭제DELETE 메서드 사용Set(null)으로 처리
동시성 제어복잡한 버전 관리 필요Last-Write-Wins 기본 적용
에러 처리상태 코드 404/409 등 다양단순화된 200/400/500
사용 사례복잡한 비즈니스 로직단순 리소스 관리 시스템

작동 원리 상세

Set 연산의 3가지 시나리오

  1. 리소스 없음 + 값 전달: 새 리소스 생성 (201 Created)
  2. 리소스 존재 + 값 전달: 기존 리소스 덮어쓰기 (200 OK)
  3. 리소스 존재 + null 전달: 리소스 삭제 (204 No Content)

Last-Write-Wins 동시성 제어

  • 타임스탬프 기반: 최종 쓰기 요청이 우선 적용

  • 옵션 반환 값:

    1
    2
    3
    4
    
    {
      "previous_value": "old_data",
      "current_value": "new_data"
    }
    

구현 예시 (Node.js/Express)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 데이터 저장소
const resources = new Map();

// Get 핸들러
app.get('/:id', (req, res) => {
  const value = resources.get(req.params.id) ?? null;
  res.json({ value });
});

// Set 핸들러
app.put('/:id', (req, res) => {
  const { value } = req.body;
  const previous = resources.get(req.params.id) ?? null;
  
  if (value === null) {
    resources.delete(req.params.id);
    res.status(204).end();
  } else {
    resources.set(req.params.id, value);
    res.json({ previous, current: value }); // 옵션: 이전 값 반환
  }
});

장단점 분석

장점

  1. 단순한 API 계약: 클라이언트가 2개의 엔드포인트만 이해하면 됨
  2. 원자적 연산: 한 번의 요청으로 생성/수정/삭제 가능
  3. 네트워크 효율성: 요청 횟수 감소 (CRUD 대비 33% 절약)
  4. 충돌 최소화: Last-Write-Wins로 복잡한 충돌 해결 불필요

단점

  1. 부분 업데이트 불가: 전체 리소스 덮어쓰기만 가능
  2. 감사 추적 어려움: 상세한 변경 이력 관리가 복잡함
  3. 낙관적 동시성 제한: 동시 수정 시 데이터 손실 가능성

적합한 사용 사례

  1. 분산 캐시 시스템 (Redis, Memcached)
  2. 파일 스토리지 서비스 (S3-like APIs)
  3. 실시간 설정 관리 (플러그인/마이크로서비스 구성)
  4. 검색 엔진 인덱싱 (Elasticsearch 문서 업데이트)

고급 활용 전략

조건부 Set 구현

1
2
3
4
5
6
7
PUT /configs/theme
Content-Type: application/json
If-Match: "a1b2c3d4"

{
  "value": "dark_mode"
}
  • ETag/버전 번호를 사용한 조건부 업데이트

배치 Set 연산

1
2
3
4
5
6
7
8
9
POST /batch
Content-Type: application/json

{
  "operations": [
    { "id": "res1", "value": "A" },
    { "id": "res2", "value": null }
  ]
}

이벤트 소싱 연계

1
2
Set 요청 → 이벤트 저장소에 변경 이력 기록
           → Materialized View 갱신

용어 정리

용어설명

참고 및 출처