본문으로 건너뛰기

User API 엔드포인트

목차

접근 권한 매트릭스

엔드포인트시스템 관리자사용자 (자신)서비스 계정 (제한적)비고
GET /v1/users✓ (제한적)
POST /v1/usersAuth 연동, 직접 호출 시 강력 권한
GET /v1/users/lookup-by-email이메일로 userId 조회
GET /v1/users/{userId}
GET /v1/users/me
자신만✓ (제한적)accountType, guestExpiresAt, upgradedAt 포함
PATCH /v1/users/{userId}
PATCH /v1/users/me
자신만✓ (제한적)이름, profileData 수정 (계정 타입 직접 수정 불가)
DELETE /v1/users/{userId}
DELETE /v1/users/me
자신만비활성화 요청 (Soft delete)
DELETE /v1/users/{userId}/data개발 환경 전용, 데이터 완전 삭제
POST /v1/users/service-accounts
GET /v1/users/{userId}/profile
GET /v1/users/me/profile
자신만✓ (제한적)
PATCH /v1/users/{userId}/profile
PATCH /v1/users/me/profile
자신만✓ (제한적)언어, 타임존 수정
GET /v1/users/{userId}/status-history
GET /v1/users/me/status-history
자신만
POST /v1/users/{userId}/status/activate내부 시스템/관리자
POST /v1/users/{userId}/status/deactivate내부 시스템/관리자
POST /v1/users/{userId}/status/reactivate관리자
POST /v1/users/{userId}/status/lock관리자, Auth 연계
POST /v1/users/{userId}/status/unlock관리자, Auth 연계
POST /v1/users/{userId}/status/suspend관리자
POST /v1/users/{userId}/status/unsuspend관리자
POST /v1/users/{userId}/status/ban관리자
POST /v1/users/{userId}/account/guest-expiry/cancelStep-up 이후 게스트 만료 타이머 해제
POST /v1/users/{userId}/account/cleanup-guest만료된 게스트 계정 정리 (관리자/스케줄러용)
GET /v1/users/state/current자신만사용자 현재 상태 조회
GET /v1/users/{userId}/day-mapping
GET /v1/users/me/day-mapping
자신만현재 활성 주기의 일차-날짜 매핑
POST /v1/users/{userId}/service-period/suspend
POST /v1/users/me/service-period/suspend
자신만
POST /v1/users/{userId}/service-period/resume
POST /v1/users/me/service-period/resume
자신만
GET /v1/users/{userId}/service-period/status
GET /v1/users/me/service-period/status
자신만
POST /v1/users/{userId}/tester/mark관리자
POST /v1/users/{userId}/tester/unmark관리자
GET /v1/users/{userId}/data-access
GET /v1/users/me/data-access
자신만GDPR
POST /v1/users/{userId}/data-deletion
POST /v1/users/me/data-deletion
자신만GDPR

참고:

  • ✓: 접근 가능
  • ✘: 접근 불가
  • (내부): 내부 시스템 간 호출 가능성
  • (제한적): 특정 필드만 조회/수정 가능 (예: 서비스 계정은 자신의 이름 등)
  • (자신만): 자신의 데이터에만 접근 가능

사용자 계정 관리 API

📌 기술 구현 문서: 사용자 계정 관리 API 구현

사용자 생성

  • HTTP 메서드: POST
  • 경로: /v1/users
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {appToken 또는 internalToken}
  • 비고: 주로 Auth 도메인의 회원가입(/auth/register) 프로세스 내부에서 호출될 수 있음. 직접 노출 시 강력한 권한 필요.

요청 (Request) - Auth 도메인에서 전달하는 예시

{
"email": "user@example.com",
"name": "Initial Name", // Auth에서 기본값 또는 사용자 입력값 전달
"userType": "USER",
"initialStatus": "PENDING" // Auth에서 이메일 인증 필요시 PENDING으로 요청
// Auth에서 관리하는 password 필드는 여기서 처리하지 않음
}

응답 (Response)

  • 성공 응답 (201 Created)
{
"id": "user_123",
"email": "user@example.com",
"name": "Initial Name",
"status": "PENDING",
"userType": "USER",
"createdAt": 1711011600000,
"updatedAt": 1711011600000
}
  • 오류 응답 (400 Bad Request)
{
"code": 4001,
"message": "INVALID_INPUT_DATA",
"detail": "요청 데이터가 유효하지 않습니다. (예: 필수 필드 누락)"
}
  • 오류 응답 (409 Conflict)
{
"code": 4002,
"message": "USER_EMAIL_ALREADY_EXISTS",
"detail": "이미 사용 중인 이메일입니다."
}

서비스 계정 생성

  • HTTP 메서드: POST
  • 경로: /v1/users/service-accounts
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"name": "Backend Service A",
"description": "Service account for internal backend communication"
}

응답 (Response)

  • 성공 응답 (201 Created)
{
"id": "sa_abc",
"email": "sa_abc@service.welt", // 시스템에서 자동 생성된 이메일 형식
"name": "Backend Service A",
"status": "ACTIVE", // 서비스 계정은 생성 시 바로 ACTIVE
"userType": "SERVICE_ACCOUNT",
"createdAt": 1711011800000,
"updatedAt": 1711011800000
// API Key 정보는 별도 관리 또는 응답 포함 (설계 필요)
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "서비스 계정을 생성할 권한이 없습니다."
}

사용자 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId} 또는 /v1/users/me
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me는 현재 로그인한 사용자 자신의 정보를 조회할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"id": "user_123",
"email": "user@example.com",
"name": "홍길동",
"status": "ACTIVE",
"userType": "USER",
"accountType": "REGISTERED",
"guestAccountId": null,
"guestExpiresAt": null,
"upgradedAt": 1714600000000,
"profileData": { "customField": "value" },
"createdAt": 1711929600000,
"updatedAt": 1714600050000,
"deletedAt": null
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}
  • 오류 응답 (403 Forbidden) - 다른 사용자 조회 시도 시
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 정보를 조회할 권한이 없습니다."
}

이메일로 사용자 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/lookup-by-email
  • Query Parameters:
    • email: 조회할 사용자의 이메일 주소 (필수)
  • Headers:
    • Authorization: Bearer {adminToken}
  • 비고: 관리자만 접근 가능. 이메일을 통해 사용자 ID 및 기본 정보를 조회합니다.

요청 (Request) 예시

GET /v1/users/lookup-by-email?email=user@example.com

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123"
}
  • 오류 응답 (400 Bad Request) - 이메일 파라미터 누락 또는 형식 오류
{
"code": 7010,
"message": "INVALID_EMAIL_PARAMETER",
"detail": "이메일 주소가 필요하거나 형식이 올바르지 않습니다."
}
  • 오류 응답 (403 Forbidden) - 권한 없음
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "이메일로 사용자를 조회할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found) - 사용자 없음
{
"code": 7002,
"message": "USER_NOT_FOUND",
"detail": "해당 이메일의 사용자를 찾을 수 없습니다."
}

사용자 정보 수정

  • HTTP 메서드: PATCH
  • 경로: /v1/users/{userId} 또는 /v1/users/me
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}
  • 비고: 사용자는 자신의 이름(name)과 확장 필드(profileData)만 수정 가능. 이메일, 비밀번호, 상태 등은 다른 API 또는 프로세스를 통해 변경됨. 관리자는 추가 필드 수정 가능. /v1/users/me는 현재 로그인한 사용자 자신의 정보를 수정할 때 사용합니다.

요청 (Request) - 사용자가 이름 수정 시

{
"name": "김길동"
}

요청 (Request) - 관리자가 profileData 수정 시

{
"profileData": {
"customField": "newValue",
"anotherField": 123
}
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"id": "user_123",
"email": "user@example.com",
"name": "김길동", // 수정된 이름
"status": "ACTIVE",
"userType": "USER",
"profileData": { "customField": "newValue", "anotherField": 123 }, // 수정된 profileData
"createdAt": 1711929600000,
"updatedAt": 1714525000000, // 업데이트 시간 변경
"deletedAt": null
}
  • 오류 응답 (400 Bad Request)
{
"code": 4001,
"message": "INVALID_INPUT_DATA",
"detail": "수정할 수 없는 필드를 포함하고 있거나 데이터 형식이 잘못되었습니다."
}
  • 오류 응답 (403 Forbidden) - 권한 없는 필드 수정 시도 시
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "요청한 정보를 수정할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}

사용자 비활성화 요청

  • HTTP 메서드: DELETE
  • 경로: /v1/users/{userId} 또는 /v1/users/me
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: 실제 데이터 삭제가 아닌, statusINACTIVE로 변경하고 deletedAt 타임스탬프를 설정하는 Soft Delete 방식. 사용자는 자신의 계정만 비활성화 가능. /v1/users/me는 현재 로그인한 사용자가 자신의 계정을 비활성화할 때 사용합니다.
  • 게스트 계정 지원: 게스트 계정(guests.* IAM Group 소속)도 동일한 API를 통해 자발적 탈퇴가 가능합니다. 게스트 탈퇴 시 기존 만료 타이머(TimeMachine 스케줄)는 자동으로 해제됩니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"message": "사용자 계정이 성공적으로 비활성화 요청되었습니다.",
"userId": "user_123",
"status": "INACTIVE", // 변경된 상태
"deletedAt": 1714526000000 // 설정된 시간
}
  • 오류 응답 (403 Forbidden) - 다른 사용자 비활성화 시도 시
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "다른 사용자를 비활성화할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}
  • 오류 응답 (409 Conflict) - 이미 비활성 상태일 경우
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이미 비활성화된 사용자입니다."
}

개발용 사용자 데이터 삭제

  • HTTP 메서드: DELETE
  • 경로: /v1/users/{userId}/data
  • Headers:
    • Authorization: Bearer {adminToken}
  • 비고: 개발 및 테스트 환경에서만 사용 가능한 API. 프로덕션 환경에서는 접근 불가. 사용자 데이터를 데이터베이스에서 완전히 삭제함. 관련된 모든 도메인 연관 데이터도 함께 삭제됨.

응답 (Response)

  • 성공 응답 (200 OK)
{
"message": "사용자 데이터가 성공적으로 삭제되었습니다.",
"userId": "user_123",
"deletedAt": 1714538000000
}
  • 오류 응답 (403 Forbidden) - 권한 없음 또는 프로덕션 환경
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "개발 환경에서만 사용 가능한 API이거나, 해당 작업에 대한 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 7002,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}
  • 오류 응답 (500 Internal Server Error)
{
"code": 5000,
"message": "INTERNAL_SERVER_ERROR",
"detail": "삭제 처리 중 서버 오류가 발생했습니다."
}

게스트 계정 API

📌 관련 문서: Auth 게스트 Step-up 설계, User 도메인 요구사항

게스트 만료 스케줄 취소

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/account/guest-expiry/cancel
  • 권한: 시스템 관리자 또는 자동화 서비스 (Auth Step-up 흐름)
  • 설명: 게스트 계정이 Step-up 인증에 성공했을 때 호출하여 guestExpiresAt 타이머를 해제하고 만료 스케줄을 취소합니다.

요청 예시

{
"reason": "STEP_UP_COMPLETED",
"triggeredBy": "auth.identity-level.changed",
"identityLevel": "registered"
}

응답 예시 (200 OK)

{
"userId": "user_123",
"accountType": "REGISTERED",
"guestExpiresAt": null,
"upgradedAt": 1714600000000,
"processedBy": "system"
}

게스트 계정 정리

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/account/cleanup-guest
  • 권한: 시스템 관리자 또는 백그라운드 스케줄러
  • 설명: 만료된 게스트 계정에 대해 토큰 폐기, 그룹/플랜 제거, 삭제 또는 익명화 프로세스를 실행합니다.

요청 예시

{
"reason": "EXPIRED_NOT_UPGRADED",
"strategy": "ANONYMIZE"
}

응답 예시 (202 Accepted)

{
"userId": "user_456",
"guestAccountId": "guest-4f52c7fa",
"groupIds": ["guests.kr"],
"guestExpiresAt": 1714300000000,
"cleanupStrategy": "ANONYMIZE",
"status": "SCHEDULED"
}

참고: v1.2.0부터 게스트 식별은 groupIdsguests.* 패턴이 포함되어 있는지로 판단합니다.

⚠️ 주의사항

  • 게스트 정리 API는 guestExpiresAt이 현재 시간보다 이전인 경우에만 실행해야 합니다.
  • 정리 완료 후 GuestAccountLifecycleCLEANED 이벤트를 기록하고 Audit 로그를 남겨야 합니다.
{
"code": 7004,
"message": "USER_DATA_HARD_DELETION_FAILED",
"detail": "사용자 데이터 삭제 중 오류가 발생했습니다."
}

개발용 이메일 기반 사용자 데이터 삭제

  • HTTP 메서드: DELETE
  • 경로: /v1/users/data
  • Headers:
    • Authorization: Bearer {adminToken}
  • Query Parameters:
    • email: 삭제할 사용자의 이메일 주소 (필수)
  • 비고: 개발 및 테스트 환경에서만 사용 가능한 API. 프로덕션 환경에서는 접근 불가. 사용자 ID를 모르는 경우, 이메일을 통해 사용자를 찾고 데이터를 완전히 삭제함.

요청 (Request) 예시

DELETE /v1/users/data?email=user@example.com

응답 (Response)

  • 성공 응답 (200 OK)
{
"message": "사용자 데이터가 성공적으로 삭제되었습니다.",
"email": "user@example.com",
"userId": "user_123", // 삭제된 사용자 ID
"deletedAt": 1714538000000
}
  • 오류 응답 (403 Forbidden) - 권한 없음 또는 프로덕션 환경
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "개발 환경에서만 사용 가능한 API이거나, 해당 작업에 대한 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4007,
"message": "USER_EMAIL_NOT_FOUND",
"detail": "해당 이메일의 사용자를 찾을 수 없습니다."
}
  • 오류 응답 (500 Internal Server Error)
{
"code": 4080,
"message": "USER_DATA_DELETION_FAILED",
"detail": "사용자 데이터 삭제 중 오류가 발생했습니다."
}

사용자 프로필 관리 API

프로필 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId}/profile 또는 /v1/users/me/profile
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/profile은 현재 로그인한 사용자 자신의 프로필을 조회할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"userName": "홍길동",
"language": "ko-KR",
"timezoneId": "Asia/Seoul",
"offsetInMinutes": 540,
"createdAt": 1711929600000,
"updatedAt": 1714523700000
}
  • 오류 응답 (404 Not Found) - 사용자 또는 프로필 없음
{
"code": 4004, // USER_PROFILE_NOT_FOUND
"message": "USER_PROFILE_NOT_FOUND",
"detail": "사용자 프로필을 찾을 수 없습니다."
}
  • 오류 응답 (403 Forbidden) - 다른 사용자 프로필 조회 시도 시
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 프로필을 조회할 권한이 없습니다."
}

프로필 수정

  • HTTP 메서드: PATCH
  • 경로: /v1/users/{userId}/profile 또는 /v1/users/me/profile
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/profile은 현재 로그인한 사용자 자신의 프로필을 수정할 때 사용합니다.

요청 (Request) - 사용자 이름만 수정하는 경우

{
"userName": "김길동"
}

요청 (Request) - 언어만 수정하는 경우

{
"language": "en-US"
}

요청 (Request) - 타임존만 수정하는 경우

{
"timezoneId": "Europe/Berlin"
}

요청 (Request) - 모든 필드 수정하는 경우

{
"userName": "김길동",
"language": "en-US",
"timezoneId": "Europe/Berlin"
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"userName": "김길동",
"language": "en-US",
"timezoneId": "Europe/Berlin",
"offsetInMinutes": 60,
"createdAt": 1711929600000,
"updatedAt": 1714527000000
}
  • 오류 응답 (400 Bad Request)
{
"code": 4001,
"message": "INVALID_INPUT_DATA",
"detail": "지원하지 않는 언어 코드 또는 타임존 ID 형식입니다."
}
  • 오류 응답 (403 Forbidden) - 다른 사용자 프로필 수정 시도 시
{
"code": 2060, // Auth 에러 코드 재사용
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 프로필을 수정할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found) - 사용자 또는 프로필 없음
{
"code": 4004,
"message": "USER_PROFILE_NOT_FOUND", // 또는 USER_NOT_FOUND
"detail": "사용자 또는 프로필을 찾을 수 없습니다."
}

사용자 상태 관리 API

상태 변경 이력 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId}/status-history 또는 /v1/users/me/status-history
  • Query Parameters:
    • page: 페이지 번호 (기본값: 1)
    • pageSize: 페이지 크기 (기본값: 10)
    • sortBy: 정렬 기준 (기본값: changedAt)
    • sortOrder: 정렬 순서 (기본값: DESC)
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/status-history는 현재 로그인한 사용자 자신의 상태 변경 이력을 조회할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"items": [
{
"id": "hist_abc",
"userId": "user_123",
"oldStatus": "PENDING",
"newStatus": "ACTIVE",
"reason": "Email verified",
"changedBy": "system",
"changedAt": 1711012000000
},
{
"id": "hist_def",
"userId": "user_123",
"oldStatus": "ACTIVE",
"newStatus": "INACTIVE",
"reason": "User requested deactivation",
"changedBy": "user_123",
"changedAt": 1714526000000
}
// ... other history items
],
"metadata": {
"totalCount": 2,
"currentPage": 1,
"pageSize": 10,
"totalPages": 1
}
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 상태 이력을 조회할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}

계정 활성화

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/activate
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken 또는 internalToken}
  • 비고: 주로 PENDING 상태의 사용자를 활성화할 때 사용. Auth 도메인의 이메일 인증 완료 이벤트에 의해 내부적으로 트리거될 수 있음.

요청 (Request)

{
"reason": "Email verified by Auth service"
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "PENDING",
"newStatus": "ACTIVE",
"changedAt": 1711012000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "현재 상태(예: BANNED)에서는 활성화할 수 없습니다."
}

계정 비활성화

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/deactivate
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken 또는 accessToken}
  • 비고: 사용자가 직접 요청 시 DELETE /v1/users/{userId} 사용. 관리자가 강제 비활성화 시 이 엔드포인트 사용 가능.

요청 (Request)

{
"reason": "Admin initiated deactivation due to policy violation."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "ACTIVE",
"newStatus": "INACTIVE",
"changedAt": 1714528000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이미 비활성화 상태입니다."
}

계정 재활성화

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/reactivate
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "User issue resolved, reactivated by admin."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "INACTIVE",
"newStatus": "ACTIVE",
"changedAt": 1714529000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "비활성화 상태가 아닌 사용자는 재활성화할 수 없습니다."
}

계정 잠금

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/lock
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken 또는 internalToken}
  • 비고: 관리자 조치 또는 Auth 도메인에서 로그인 실패 등으로 트리거될 수 있음.

요청 (Request)

{
"reason": "Multiple failed login attempts detected by Auth service."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "ACTIVE",
"newStatus": "LOCKED",
"changedAt": 1714530000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "현재 상태에서는 잠금 처리할 수 없습니다."
}

계정 잠금 해제

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/unlock
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken 또는 internalToken}
  • 비고: 관리자 조치 또는 Auth 도메인에서 시간 만료 등으로 트리거될 수 있음. 이전 상태로 복귀.

요청 (Request)

{
"reason": "User verified identity, unlocked by admin."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "LOCKED",
"newStatus": "ACTIVE", // 잠금 이전 상태로 복귀
"changedAt": 1714531000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "잠금 상태가 아닌 사용자는 잠금 해제할 수 없습니다."
}

계정 이용 정지

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/suspend
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "Temporary suspension due to terms of service violation.",
"suspendUntil": 1717200000000 // 선택적: 정지 만료 시간
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "ACTIVE",
"newStatus": "SUSPENDED",
"changedAt": 1714532000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "현재 상태에서는 이용 정지 처리할 수 없습니다."
}

계정 정지 해제

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/unsuspend
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "Suspension period ended or issue resolved."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "SUSPENDED",
"newStatus": "ACTIVE",
"changedAt": 1714533000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이용 정지 상태가 아닌 사용자는 정지 해제할 수 없습니다."
}

계정 영구 정지

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/status/ban
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "Permanent ban due to repeated severe violations."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"oldStatus": "SUSPENDED", // 또는 ACTIVE 등 이전 상태
"newStatus": "BANNED",
"changedAt": 1714534000000
}
  • 오류 응답 (409 Conflict) - 상태 전이 불가
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이미 영구 정지된 사용자입니다."
}

치료 주기 관리 API

사용자 현재 상태 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/state/current
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: 현재 로그인한 사용자의 상태 정보와 일차-날짜 매핑 정보를 함께 조회합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"userCycleId": "cycle_456",
"planId": "plan_789",
"startedDate": 1714521600000,
"currentUserTime": 1715126400000,
"currentDayIndex": 4,
"isSuspended": false,
"language": "ko",
"timezoneId": "Asia/Seoul",
"isTimeMachineActivated": false,
"suspensions": [
{
"sequence": 1,
"startDate": 1714521600000,
"endDate": 1714694400000,
"durationDays": 2
}
],
"dayMappings": [
{
"dayIndex": 1,
"date": "2025-05-03"
},
{
"dayIndex": 2,
"date": "2025-05-04"
},
{
"dayIndex": 3,
"date": "2025-05-07"
},
{
"dayIndex": 4,
"date": "2025-05-08"
}
],
"suspensionPeriods": [
{
"startDate": 1714867200000,
"endDate": 1714953600000,
"reason": "휴가"
}
]
}
  • 오류 응답 (404 Not Found) - 활성 주기가 없는 경우
{
"code": 4041,
"message": "ACTIVE_CYCLE_NOT_FOUND",
"detail": "현재 활성화된 치료 주기가 없습니다."
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "사용자 상태를 조회할 권한이 없습니다."
}

현재 활성 주기의 일차-날짜 매핑 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId}/day-mapping 또는 /v1/users/me/day-mapping
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: 현재 활성화된 치료 주기의 일차(dayIndex)와 실제 날짜의 매핑을 조회합니다. 치료 활동 일시 정지 기간은 제외되어 일차가 계산됩니다. /v1/users/me/day-mapping은 현재 로그인한 사용자 자신의 치료 주기 정보를 조회할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"cycleId": "cycle_456",
"currentDayIndex": 4,
"dayMappings": [
{
"dayIndex": 1,
"date": "2025-05-03"
},
{
"dayIndex": 2,
"date": "2025-05-04"
},
{
"dayIndex": 3,
"date": "2025-05-07"
},
{
"dayIndex": 4,
"date": "2025-05-08"
}
],
"suspensionPeriods": [
{
"startDate": 1714867200000,
"endDate": 1714953600000
}
]
}
  • 오류 응답 (404 Not Found) - 활성 주기가 없는 경우
{
"code": 4041,
"message": "ACTIVE_CYCLE_NOT_FOUND",
"detail": "현재 활성화된 치료 주기가 없습니다."
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "다른 사용자의 치료 주기 정보를 조회할 권한이 없습니다."
}

서비스 이용 기간 관리 API

📌 기술 구현 문서: User 서비스 중단/재개 구현

서비스 중단

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/service-period/suspend 또는 /v1/users/me/service-period/suspend
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/service-period/suspend는 현재 로그인한 사용자가 자신의 서비스를 중단할 때 사용합니다.

요청 (Request)

{
"durationDays": 7, // 선택적: 중단 기간(일). 없으면 수동 재개 필요.
"reason": "개인 사정" // 선택적: 중단 사유
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"isSuspended": true,
"suspendedAt": "2025-07-29T10:00:00.000Z",
"resumedAt": null,
"expiresAt": "2025-10-27T00:00:00.000Z", // 만료일은 변경되지 않거나, 재계산 로직에 따라 다름
"remainingServiceDays": 60 // 남은 일수는 재계산 로직에 따라 다름
}
  • 오류 응답 (400 Bad Request)
{
"code": 4001,
"message": "INVALID_INPUT_DATA",
"detail": "durationDays는 1 이상 90 이하의 정수여야 합니다."
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "서비스 기간을 중단할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}
  • 오류 응답 (409 Conflict)
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이미 중단된 상태입니다."
}

서비스 재개

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/service-period/resume 또는 /v1/users/me/service-period/resume
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/service-period/resume은 현재 로그인한 사용자가 자신의 서비스를 재개할 때 사용합니다.

요청 (Request)

{
"reason": "서비스 다시 이용 시작" // 선택적: 재개 사유
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"isSuspended": false,
"suspendedAt": "2025-07-29T10:00:00.000Z", // 마지막 중단 시작 시각
"resumedAt": "2025-08-05T11:30:00.000Z", // 재개 시각
"expiresAt": "2025-11-03T00:00:00.000Z", // 중단 기간만큼 연장된 새 만료일
"remainingServiceDays": 60 // 재개 시점 기준 남은 일수
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "서비스 기간을 재개할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}
  • 오류 응답 (409 Conflict)
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "현재 중단 상태가 아닙니다."
}

서비스 상태 조회

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId}/service-period/status 또는 /v1/users/me/service-period/status
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: /v1/users/me/service-period/status는 현재 로그인한 사용자 자신의 서비스 상태를 조회할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"isSuspended": false,
"suspendedAt": "2025-07-29T10:00:00.000Z", // 마지막 중단 시작 시각
"resumedAt": "2025-08-05T11:30:00.000Z", // 마지막 재개 시각
"expiresAt": "2025-11-03T00:00:00.000Z", // 현재 유효한 만료일
"remainingServiceDays": 60 // 현재 기준 남은 일수
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "서비스 상태를 조회할 권한이 없습니다."
}
  • 오류 응답 (404 Not Found)
{
"code": 4003,
"message": "USER_NOT_FOUND",
"detail": "사용자를 찾을 수 없습니다."
}

테스터 관리 API

테스터 지정

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/tester/mark
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "Assigning user to QA testing group."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"updatedAt": 1714535000000
}
  • 오류 응답 (400 Bad Request) - 이미 테스터일 경우
{
"code": 4031, // USER_ALREADY_TESTER
"message": "USER_ALREADY_TESTER",
"detail": "사용자가 이미 테스터로 지정되어 있습니다."
}

테스터 지정 해제

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/tester/unmark
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {adminToken}

요청 (Request)

{
"reason": "Removing user from QA testing group."
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"updatedAt": 1714536000000
}
  • 오류 응답 (400 Bad Request) - 테스터가 아닐 경우
{
"code": 4032, // USER_NOT_TESTER
"message": "USER_NOT_TESTER",
"detail": "사용자가 테스터로 지정되어 있지 않습니다."
}

개인정보 보호 API (GDPR 등)

데이터 접근 요청 처리

  • HTTP 메서드: GET
  • 경로: /v1/users/{userId}/data-access 또는 /v1/users/me/data-access
  • Headers:
    • Authorization: Bearer {accessToken}
  • 비고: 사용자가 자신의 모든 데이터에 대한 사본을 요청합니다. (구현 우선순위 낮음) /v1/users/me/data-access는 현재 로그인한 사용자 자신의 데이터 접근을 요청할 때 사용합니다.

응답 (Response)

  • 성공 응답 (200 OK) - 예시: JSON 형식
{
"userId": "user_123",
"requestedAt": 1714537000000,
"data": {
"account": {
"id": "user_123",
"email": "user@example.com", // 마스킹 처리 필요할 수 있음
"name": "홍길동",
"status": "ACTIVE",
"userType": "USER",
"createdAt": 1711929600000,
"updatedAt": 1714536000000
},
"profile": {
"language": "ko",
"timezone": "Asia/Seoul",
// ... profileData 포함 여부 결정
},
"statusHistory": [
// ... 상태 변경 이력 배열
]
// IAM, Sleep 등 다른 도메인 데이터 포함 여부는 별도 논의 필요
}
}
  • 오류 응답 (403 Forbidden)
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "데이터에 접근할 권한이 없습니다."
}

데이터 삭제 요청 처리

  • HTTP 메서드: POST
  • 경로: /v1/users/{userId}/data-deletion 또는 /v1/users/me/data-deletion
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}
  • 비고: 사용자가 자신의 모든 데이터 삭제를 요청합니다. (구현 우선순위 낮음) /v1/users/me/data-deletion은 현재 로그인한 사용자 자신의 데이터 삭제를 요청할 때 사용합니다.

요청 (Request)

{
"reason": "User requested data deletion under GDPR.",
"requestorId": "user_123" // 요청자 ID (본인 또는 관리자)
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"message": "사용자 데이터 삭제 요청이 접수되었으며, 비활성화 및 삭제/익명화가 스케줄링됩니다.",
"userId": "user_123",
"status": "INACTIVE", // 즉시 비활성화
"deletionScheduledAt": 1717209600000 // 예상 삭제/익명화 시점 (예: 30일 후)
}
  • 오류 응답 (403 Forbidden) - 권한 없음 또는 프로덕션 환경
{
"code": 2060,
"message": "PERMISSION_DENIED",
"detail": "데이터 삭제를 요청할 권한이 없습니다."
}
  • 오류 응답 (409 Conflict) - 이미 비활성화 또는 삭제 처리 진행 중
{
"code": 4011,
"message": "INVALID_STATUS_TRANSITION",
"detail": "이미 비활성화되었거나 삭제 절차가 진행 중인 사용자입니다."
}

오류 코드

User 도메인 API에서 사용하는 주요 오류 코드는 다음과 같습니다. (User 도메인 오류 관리 가이드 참조)

HTTP 상태 코드오류 코드 (User: 4xxx)메시지 (Error Class)설명
500(공유) 2000SERVER_ERROR서버 내부 오류
401(Auth) 2001UNAUTHORIZED인증이 필요합니다
403(Auth) 2002FORBIDDEN권한이 없습니다
403(Auth) 2060PERMISSION_DENIED요청한 작업/리소스에 대한 권한이 없습니다
4004001INVALID_INPUT_DATA (InvalidUserInputError)요청 본문 또는 쿼리 파라미터가 유효하지 않음
4094002USER_EMAIL_ALREADY_EXISTS (UserEmailAlreadyExistsError)이미 사용 중인 이메일 주소
4044003USER_NOT_FOUND (UserNotFoundError)요청한 사용자를 찾을 수 없음
4044004USER_PROFILE_NOT_FOUND (UserProfileNotFoundError)요청한 사용자 프로필을 찾을 수 없음
5004005SERVICE_ACCOUNT_CREATION_FAILED (ServiceAccountCreationError)서비스 계정 생성 실패 (내부 오류)
4044007USER_EMAIL_NOT_FOUND (UserEmailNotFoundError)요청한 이메일 주소로 사용자를 찾을 수 없음
4094011INVALID_STATUS_TRANSITION (InvalidStatusTransitionError)현재 사용자 상태에서 요청한 작업 불가
4034012CANNOT_DEACTIVATE_SELF (CannotDeactivateSelfError)자기 자신을 비활성화할 수 없음 (관리자 등)
4004021INVALID_LANGUAGE_CODE (InvalidLanguageCodeError)유효하지 않은 언어 코드 (프로필 수정 시)
4004022INVALID_TIMEZONE_FORMAT (InvalidTimezoneFormatError)유효하지 않은 타임존 ID 형식 (프로필 수정 시)
4004031USER_ALREADY_TESTER (UserAlreadyTesterError)사용자가 이미 테스터로 지정됨
4004032USER_NOT_TESTER (UserNotTesterError)사용자가 테스터로 지정되어 있지 않음
4044041ACTIVE_CYCLE_NOT_FOUND (ActiveCycleNotFoundError)현재 활성화된 치료 주기가 없음
5004042DATA_ACCESS_REQUEST_FAILED (DataAccessRequestError)GDPR 데이터 접근 요청 처리 실패 (내부 오류)
5004043DATA_DELETION_REQUEST_FAILED (DataDeletionRequestError)GDPR 데이터 삭제 요청 처리 실패 (내부 오류)
4034051INVALID_USER_TYPE_FOR_OPERATION (InvalidUserTypeForOperationError)해당 사용자 유형으로 작업 수행 불가
5004080USER_DATA_DELETION_FAILED (UserDataDeletionFailedError)사용자 데이터 완전 삭제 실패 (개발 환경용)
5004099UNKNOWN_USER_ERROR (UnknownUserError)알 수 없는 사용자 관련 내부 오류 발생

참고: 위 목록은 User 도메인 고유 오류 중심으로 작성되었으며, Auth 도메인 오류 등 다른 공통 오류 코드도 함께 사용될 수 있습니다.

변경 이력

버전날짜작성자변경 내용
0.1.02025-04-17bok@weltcorp.com최초 작성
0.2.02025-07-29AI Assistant서비스 중단/재개 API 추가, 오류 코드 업데이트, 접근 권한 매트릭스 수정, 전체 구조 재정렬
0.2.12025-07-30AI AssistantGET /v1/users/{userId}/profile 엔드포인트 명세 추가 및 접근 권한 매트릭스 업데이트
0.2.22025-05-08bok@weltcorp.com개발 환경용 사용자 데이터 삭제 API 엔드포인트 및 오류 코드 추가
0.2.32025-05-08bok@weltcorp.com개발 환경용 이메일 기반 사용자 데이터 삭제 API 엔드포인트 및 오류 코드 추가
0.4.12025-07-21bok@weltcorp.com프로필 수정 API 필드명을 schema.prisma와 일치하도록 수정 (timezone → timezoneId, userName 필드 추가, offsetInMinutes 응답 포함)
0.5.02025-10-27bok@weltcorp.com게스트 계정 조회 필드 및 만료/정리 API 추가, Step-up 후 만료 취소 API 추가
0.6.02025-12-17bok@weltcorp.com게스트 계정 자발적 탈퇴 지원 명시 (DELETE /v1/users/me)