Files
tdc114plus/docs/00_guide_tdc114plus_profile_image_identifier_mapping_2026-07-14.md
T

17 KiB

tdc114plus 프로필 이미지 관리 정책 및 단계별 진행안

작성일: 2026-07-14 최종 개정일: 2026-07-20 상태: v2.2 관련 Phase: Phase 7-C

1. 목적

신규앱의 직원 프로필 이미지를 어떤 우선순위와 어떤 식별 기준으로 운영할지 고정한다.

본 문서는 아래 사항을 최신 기준으로 정리한다.

  • 프로필 이미지 노출 우선순위
  • 네이버웍스와 Baron SSO 조직도 응답의 역할
  • R2 버킷 파일명 정책
  • 앱과 중계서버가 직접 하지 않아야 할 일
  • 현재까지 확인된 검증 결과
  • 다음 작업 순서

2. 현재 확정 정책

2-1. 이미지 노출 우선순위

신규앱의 프로필 이미지 우선순위는 아래처럼 고정한다.

  1. 네이버웍스 프로필 사진
  2. Baron SSO 조직도 members[].id 기준 UUID 파일명 이미지
  3. 신규앱 기본 아바타

즉, R2 버킷 이미지는 유지하되, 더 이상 이메일 또는 해시 매핑 DB를 기본 경로로 사용하지 않는다.

2-2. 기본 식별자 정책

  • 직원 프로필 이미지의 2순위 식별자는 Baron SSO 조직도 응답의 members[].id를 사용한다.
  • 이 값은 includeUsers=true, includeUserIds=true 조건의 org-context 응답에서 확인되는 사용자 고정 식별자다.
  • 신규앱은 이메일 @앞부분.jpg를 직접 만들지 않는다.
  • 신규앱은 해시 파일명도 직접 계산하지 않는다.
  • 신규앱은 직원별 Baron UUID를 확보한 뒤 https://baroncs.co.kr/employee_img/{uuid}.jpg 규칙으로만 2순위 이미지를 시도한다.

2-3. DB 사용 정책

  • 현재 운영 기본안에서는 프로필 이미지 전용 매핑 DB를 두지 않는다.
  • tdc114plus-auth 내부 PostgreSQL 기반 fallback 구현은 검토/검증 결과물로만 남기고, 현재 채택안의 기본 경로로 사용하지 않는다.
  • 추후 Baron SSO UUID를 안정적으로 받을 수 없는 별도 화면이나 별도 운영 요구가 생기면 그때 보조안으로만 재검토한다.

3. 현재까지 확인된 사실

3-1. 네이버웍스 문서 및 실연동 검토 결과

2026-07-15 기준 네이버웍스 개발자 문서와 실제 서비스 계정 호출 기준으로 아래를 확인했다.

  • 구성원 프로필 조회 endpoint: GET /users/{userId}
  • 구성원 사진 조회 endpoint: GET /users/{userId}/photo
  • userId에는 구성원 ID, 메일, 리소스 ID, externalKey:{externalKey} 형식 사용 가능
  • 사진 조회 응답은 HTTP 302, HTTP 400, HTTP 404 규칙을 가진다

실제 1차 호출 결과:

  • 서비스 계정 토큰 발급: HTTP 200
  • GET /users/{userId} 샘플 1
    • 입력: khkang@samaneng.com
    • 결과: HTTP 200
  • GET /users/{userId}/photo 샘플 1
    • 입력: khkang@samaneng.com
    • 결과: HTTP 404
  • GET /users/{userId} 샘플 2
    • 입력: thlee3@samaneng.com
    • 결과: HTTP 200
  • GET /users/{userId}/photo 샘플 2
    • 입력: thlee3@samaneng.com
    • 결과: HTTP 302
    • Location 헤더에 실제 이미지 접근 URL 반환 확인

현재 판단:

  • 네이버웍스 사진 연동은 1순위 경로로 실제 성립한다.
  • 현재까지의 1차 검증 기준으로는 사진 있음 -> 302, 사진 없음 -> 404 흐름이 확인됐다.

3-2. R2 버킷과 공개 경로

현재 프로필 이미지 파일은 Cloudflare R2 Object Storage에 적재되어 있다.

  • 공개 도메인 prefix: https://baroncs.co.kr/employee_img/
  • 현재부터는 UUID 파일명 기준으로 관리한다.
  • 목표 URL 규칙: https://baroncs.co.kr/employee_img/{uuid}.jpg

2026-07-15 기준 UUID 파일명 샘플 공개 URL 검증 결과:

  • https://baroncs.co.kr/employee_img/bebb832c-052e-493d-b5a9-732518d67685.jpg
    • HTTP 200
    • content-type: image/jpeg
  • https://baroncs.co.kr/employee_img/cc2db80c-5a18-4439-8026-22dd06d6452f.jpg
    • HTTP 200
    • content-type: image/jpeg

현재 판단:

  • UUID 파일명으로 변경된 2순위 이미지가 실제 공개 경로에서 응답하는 것을 확인했다.
  • 따라서 2순위 경로는 문서상 계획이 아니라 실배치/실응답까지 확인된 상태로 본다.

3-3. Baron SSO 조직도 UUID 실검증 결과

2026-07-15 기준 org-context 실조회로 아래 사실을 확인했다.

  • 조회 대상: tenantSlug=hanmac-family
  • 옵션: includeUsers=true, includeUserIds=true
  • members[].id가 실제 응답에 포함된다
  • 해당 값은 예시 문자열이 아니라 UUID 형식이다
  • 예:
    • c6ac492a-d4f3-4fff-8409-b50e317ca793
    • 73f80ef0-62ec-49b2-a8eb-1f4de52966b7
    • bebb832c-052e-493d-b5a9-732518d67685

현재 판단:

  • members[].id는 2순위 프로필 이미지 파일명 기준으로 사용할 수 있다.
  • 이메일 local-part보다 보안성과 변경 내성이 높다.

3-4. 가족사 전인원 UUID 매핑 확인 결과

2026-07-15 기준 가족사 전체 org-context 응답과 기존 파일 매핑 CSV를 대조해 아래를 확인했다.

  • 기준 원본: docs/references/file_rename_hash_results.csv
  • 기존 원본 행 수: 2457
  • org-context 고유 이메일 수: 2610
  • UUID 매핑 성공 행 수: 2457
  • 미매핑 행 수: 0

생성한 참고 산출물:

  • docs/references/profile_image_uuid_rename_candidates.csv

이 CSV에는 아래 컬럼을 포함했다.

  • comp
  • employee_name
  • employee_email
  • employee_email_local_part
  • legacy_photo_file_name
  • hashed_photo_file_name
  • baron_user_uuid
  • target_uuid_file_name
  • rename_ready

현재 판단:

  • 기존 사진 파일을 UUID 파일명으로 재정리하는 작업은 충분히 진행 가능하다.
  • 현재 확보된 CSV만으로 기존 파일명 -> UUID 파일명 변경 작업 계획을 잡을 수 있다.

4. 채택안 기준 연동 구조

4-1. 신규앱 기본 흐름

직원 DTO 수신
-> 앱이 직접 네이버웍스와 외부 이미지 서버를 각각 판단하지 않음
-> 중계서버 /api/v1/profile-image 호출
-> 중계서버가 네이버웍스 사진 조회 시도
-> 실패 시 Baron UUID 기준 https://baroncs.co.kr/employee_img/{uuid}.jpg 판단
-> 둘 다 없으면 found=false 반환
-> 앱은 기본 아바타 표시

현재 시점의 가장 효율적인 구현안은, 앱이 직접 1순위/2순위를 분기하지 않고 기존 tdc114plus-authGET /api/v1/profile-image endpoint를 유지한 채 내부 우선순위만 네이버웍스 -> UUID 이미지 -> 기본 미발견으로 바꾸는 방식이다.

2026-07-20 기준 네이버웍스 1순위 이미지는 외부 Location URL을 앱에 그대로 전달하지 않는다.

이유:

  • 네이버웍스 GET /users/{userId}/photo는 사진이 있으면 302 Location을 반환한다.
  • 일부 Location URL은 앱이나 일반 HTTP 클라이언트가 인증 없이 직접 열면 400 Authentication failed가 발생한다.
  • 따라서 앱이 네이버웍스 원본 URL을 직접 표시하는 방식은 안정적이지 않다.

현재 확정 처리:

  • tdc114plus-auth가 네이버웍스 사진 존재 여부를 확인한다.
  • 네이버웍스 사진이 있으면 앱에는 tdc114plus-auth의 프록시 URL을 반환한다.
  • 앱은 이 프록시 URL을 일반 이미지 URL처럼 표시한다.
  • 프록시는 내부에서 네이버웍스 Access Token을 사용해 실제 이미지 바이너리를 받아 앱에 image/jpeg로 내려준다.
  • 네이버웍스 사진이 없거나 프록시 확인이 실패하면 UUID 이미지 2순위로 내려간다.

이 방식의 장점은 아래와 같다.

  • 앱 계약을 크게 흔들지 않는다.
  • 네이버웍스 서비스 계정/토큰 처리 로직을 앱에 넣지 않아도 된다.
  • 추후 우선순위가 바뀌어도 서버만 수정하면 된다.
  • UUID 이미지 경로 변경, 캐시 정책, timeout 정책을 서버에서 통제할 수 있다.

4-2. 신규앱이 직접 하지 않아야 하는 일

  • 이메일 @앞부분.jpg 직접 조합
  • 해시 파일명 직접 계산
  • 별도 프로필 이미지 매핑 DB 직접 조회
  • 버킷 내부 경로 추론

4-3. 중계서버 역할

현재 채택안 기준 중계서버의 역할은 아래처럼 정리한다.

  • Baron SSO 로그인/세션 유지
  • 필요 시 조직도 org-context proxy 제공
  • GET /api/v1/profile-image 단일 endpoint 제공
  • 네이버웍스 1순위 경로 처리
  • 네이버웍스 사진 원본 URL을 앱에 직접 노출하지 않고 GET /api/v1/profile-image/naver-photo 프록시로 이미지 바이너리 제공
  • Baron UUID 기준 2순위 이미지 경로 판단
  • 앱에는 최종 found/source/imageUrl 결과만 반환

현재 채택안 기준으로는 중계서버가 프로필 이미지 전용 매핑 DB를 운영 기본 구조로 갖지 않는다. 다만 기존 tdc114plus-auth/api/v1/profile-image endpoint는 유지하고, 내부 로직만 새 우선순위로 재정리하는 것이 가장 효율적이다.

5. PostgreSQL 검토 결과 정리

2026-07-15 기준 tdc114plus-auth에 PostgreSQL 기반 fallback 검토를 이미 진행했다.

확인된 내용:

  • 로컬 PostgreSQL 컨테이너 구성
  • profile_image_mapping 스키마 초안 작성
  • CSV 2457건 적재 검증
  • GET /api/v1/profile-image?comp=...&email=... 샘플 검증

현재 정책 판단:

  • 위 결과는 기술 검증 자료로는 유효하다.
  • 하지만 운영 기본안은 아니다.
  • 현재 기준 주 경로는 네이버웍스 -> UUID 파일명 이미지 -> 기본 아바타다.
  • 따라서 PostgreSQL 경로는 보류된 대안으로만 기록한다.
  • 실제 구현은 기존 tdc114plus-auth endpoint를 재사용하되, PostgreSQL 분기는 기본 비활성 또는 최후 예비안으로만 남기는 편이 적절하다.

6. 단계별 진행작업 타임테이블

단계 상태 작업 구분 작업 내용 완료 기준
Step 1 완료 문서/정책 프로필 이미지 우선순위와 기본 검토 구조를 정리했다 초기 문서 기준선 확보
Step 2 완료 네이버웍스 문서 검토 GET /users/{userId}, GET /users/{userId}/photo, scope, 302/404 구조를 확인했다 1순위 경로 성립 가능 조건 확인
Step 3 완료 R2 자산 점검 공개 prefix https://baroncs.co.kr/employee_img/ 와 공개 응답을 확인했다 2순위 파일 배치 경로 확인
Step 4 완료 Baron UUID 실검증 org-context 실응답에서 members[].id가 UUID 형식으로 내려오는 것을 확인했다 2순위 식별자 확정
Step 5 완료 가족사 전인원 매핑 검증 기존 CSV 2457건을 Baron UUID와 대조해 전건 매핑 성공을 확인했다 profile_image_uuid_rename_candidates.csv 생성
Step 6 완료 외부 파일 재배치 기존 사진 파일명을 [uuid].jpg로 변경하고 employee_img/ 하위에 재배치했다 샘플 URL 2건 HTTP 200 image/jpeg 검증 완료
Step 7 완료 앱 공통 resolver 정리 앱은 GET /api/v1/profile-image를 우선 호출하고, 응답 실패 또는 미발견 시에는 profileImageUrl -> UUID 파일명 -> 기본 아바타 순서의 보조 fallback을 사용하도록 정리했다 앱 공통 resolver와 보조 fallback 반영 완료
Step 8 완료 네이버웍스 실연동 검증 개발자 계정 기준으로 사진 조회를 실제 호출해 302404 규칙을 확인했다 1순위 경로 실응답 규칙 1차 확정
Step 9 완료 이력 서버 구현 및 실검증 2026-07-15 시점에는 tdc114plus-auth GET /api/v1/profile-imageNAVER WORKS -> Baron UUID 이미지 -> DEFAULT 순서로 동작하는 구현과 샘플 응답을 확인했다 2026-07-15 기준 실검증 이력
Step 10 완료 현재 기동 정합성 검증 2026-07-20 기준 tdc114plus-auth/api/v1/profile-image/api/v1/profile-image/naver-photo 프록시 route를 복구/보강했다 go test ./cmd/server 통과, 5001 health 정상
Step 11 완료 네이버웍스 프록시 검증 네이버웍스 302 Location을 앱에 직접 주지 않고 중계서버 프록시가 image/jpeg 바이너리로 내려주는 것을 확인했다 한치영, 이태훈 프록시 200 OK image/jpeg 확인
Step 12 진행 중 실기기 화면 확대 검증 직원검색 목록에서 NAVER_WORKS와 BARON_UUID_R2가 동시에 정상 표시되는 것을 확인했다. DEFAULT 기본 아바타 케이스는 추가 샘플로 계속 확인한다 1순위/2순위 화면 확인 완료, 3순위 확대 검증 필요

7. 다음 작업 순서

  1. DEFAULT 기본 아바타 케이스를 명시 샘플로 추가 확인한다.
  2. 직원 상세/조직도/즐겨찾기 화면에서도 동일 이미지 규칙이 유지되는지 확인한다.
  3. 화면 전환 후 이미지 캐시가 잘못된 null 상태를 유지하지 않는지 확인한다.
  4. adb reverse 5001/5000이 끊겼을 때 로그인 실패처럼 보일 수 있으므로, 실기기 검증 전 reverse 상태를 먼저 확인한다.
  5. 검증 결과를 본 문서와 타임테이블 문서에 즉시 반영한다.

8. 현재 시점 결론

  • 프로필 이미지 1순위는 네이버웍스다.
  • 2순위는 Baron SSO 조직도 members[].id를 파일명으로 사용하는 UUID 이미지다.
  • 현재 운영 기본안에서는 프로필 이미지 전용 DB를 두지 않는다.
  • 기존 PostgreSQL fallback 검토는 예비안으로만 남긴다.
  • 2026-07-20 기준 tdc114plus-auth/api/v1/profile-image route와 네이버웍스 프록시 route는 복구/보강됐다.
  • 네이버웍스 사진 원본 URL은 앱에 직접 주지 않고 tdc114plus-auth 프록시 URL로 제공한다.
  • 현재 가장 중요한 다음 단계는 실기기 기준으로 DEFAULT 3순위와 직원 상세/조직도/즐겨찾기 화면의 동일 규칙 유지 여부를 확대 검증하는 것이다.

9. 2026-07-20 검증 및 보강 메모

2026-07-20 기준 아래를 확인했다.

  • tdc114plus-auth GET /api/v1/profile-image route 복구 및 유지
  • tdc114plus-auth GET /api/v1/profile-image/naver-photo 프록시 route 추가
  • cyhan@samaneng.com, thlee3@samaneng.com 네이버웍스 사진 존재 확인
  • 네이버웍스 Location 원본 URL 직접 접근 시 400 Authentication failed가 발생할 수 있음 확인
  • 프록시 route에서 두 사용자 모두 200 OK, Content-Type: image/jpeg 확인
  • 실기기 직원검색 화면에서 기존에 기본 이니셜로 떨어지던 인원의 네이버웍스 사진 표시 정상화 확인
  • BARON_UUID_R2 source 로그도 동시에 확인되어 2순위 경로가 유지됨을 확인

검증한 자동 테스트:

  • tdc114plus-auth: GOCACHE=/tmp/go-build-cache go test ./cmd/server
  • tdc114plus: ./scripts/flutter-docker.sh test test/directory/profile_image_api_client_test.dart

주의:

  • 로컬 실기기 검증 중 adb reverse tcp:5001 tcp:5001, adb reverse tcp:5000 tcp:5000이 끊기면 앱 화면에는 인증 서버에 연결하지 못했습니다처럼 보일 수 있다.
  • 이 경우 프로필 사진 코드 문제가 아니라 실기기와 로컬 중계서버 연결 문제일 수 있으므로, 먼저 adb reverse --list를 확인한다.

10. 2026-07-15 실기기 확인 메모

2026-07-15 기준 Android 실기기 직원검색 화면에서 실제 프로필 사진 노출을 확인했다.

확인 내용:

  • 로그인 후 직원검색 목록 진입 확인
  • 원형 기본 이니셜 아바타 대신 실제 사진 노출 확인
  • 확인 화면에는 여러 직원의 사진이 동시에 표시됐다
  • 현재 앱은 tdc114plus-auth /api/v1/profile-image를 우선 호출하고, 응답 실패 또는 미발견 시 UUID 공개 경로 fallback을 사용한다

현재 판단:

  • 정책 문서상 구조가 아니라, 실기기 화면 기준으로도 프로필 사진 표시가 동작하는 상태다
  • 다만 어떤 직원이 NAVER_WORKS로 해석됐는지, 어떤 직원이 BARON_UUID_R2로 해석됐는지는 추가 로그/샘플 검증으로 더 구분해 둘 필요가 있다

9. 2026-07-15 자격값 재검증 메모

2026-07-15 오후 기준, 갱신된 네이버웍스 서비스 계정 자격값을 다시 반영한 뒤 실제 호출을 재검증했다.

확인 결과:

  • 서비스 계정 토큰 발급: HTTP 200
  • 샘플 사용자 thlee3@samaneng.com 프로필 조회: HTTP 200
  • 샘플 사용자 thlee3@samaneng.com 사진 조회: HTTP 302
  • Location 헤더로 실제 이미지 접근 URL 반환 확인

현재 판단:

  • 최신 자격 세트는 유효하다.
  • tdc114plus-auth 서버가 이 자격 세트를 사용해 1순위 경로를 실제 구현할 수 있는 준비가 됐다.
  • 이후 로컬 auth 서버 실기동 검증에서도 아래를 확인했다.
    • GET /api/v1/profile-image?email=thlee3@samaneng.com
      • found=true
      • source=NAVER_WORKS
    • GET /api/v1/profile-image?email=khkang@samaneng.com
      • found=true
      • source=BARON_UUID_R2

10. 관련 문서

  • docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md
  • docs/00_guide_tdc114plus_org_context_mapping_2026-07-08.md
  • docs/00_contract_tdc114plus_api_2026-07-02.md