9WAY 2.0.0 - 프로젝트 타임라인
프로젝트 요약
전체 티켓 목록 (224)
활동 타임라인 (892)
-
2026년 11월 05일
-
팀팀리드 배포 완료 - STEP 6 강의 안내 줄이기 · 리포트 카드 구성 제목 빼기(013fa4f7)
상세 보기
## 나간 것
- `013fa4f7` fix(strengths): STEP 6 강의 안내를 줄이고 리포트 카드의 구성 제목을 뺀다
- STEP 6 「자세히 보기」를 새 조각 `_course_offer`로 다시 짰어요. PC 높이가 884px에서 244px로 줄었어요.
- 묶음 할인은 카드 아래 한 줄로 남겼어요. 강의 페이지 안내는 그대로예요.
- 리포트 선택 · 잠긴 탭 · 업그레이드 카드에서 구성 제목을 뺐어요. 요금 페이지는 그대로예요.
- 마이그레이션 없음. 안 쓰게 된 번역 키 14개를 5개 언어에서 지웠어요.## 운영 확인
- 이미지 `013fa4f7`, `/up` 200
- BASIC 샘플 계정으로 5개 언어 HTML 확인: 업그레이드 카드 1장, 구성 제목 없음, 번역 누락 없음
- 한국어 STEP 6: FULL 추가 결제 79,200원, 목록 4줄, 묶음 할인 한 줄, 차액 안내 있음
- 다른 언어: STEP 6 강의 안내 없음
- 요금 페이지: 설명 문장 ko 3개 · en 2개, 구성 제목 그대로## 확인 못 한 것
- 운영 무료 상태 · PRO 보유 상태(샘플 계정이 모두 BASIC). 개발에서만 봤어요.
- 실제 폰 -
팀팀리드 배포 완료 - 결과 화면 리포트 선택 카드 줄이기(d7a4dd12)
상세 보기
## 나간 것
- `d7a4dd12` fix(strengths): 결과 화면 리포트 선택을 위 STEP 카드에 맞춰 줄인다
- 설명 문장을 빼고 목록을 한 줄씩으로 줄였어요. 가격은 상품 이름과 같은 줄로 올렸어요.
- 마이그레이션 없음. 요금 페이지는 그대로예요.## 운영 확인
- 이미지 `d7a4dd12`, `/up` 200
- 샘플 계정으로 5개 언어 업그레이드 안내 HTML 확인: 카드 1장, 설명 문장 0, 목록 3개(ko) · 2개(다른 언어), 차액 안내 있음
- 요금 페이지 설명 문장: ko 3개, en 2개 그대로
- CSS에 `report-package--wide` 있음## 확인 못 한 것
- 운영 무료 상태 카드(샘플 계정이 모두 리포트 보유). 개발에서만 봤어요.
- 실제 폰 -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 배포 완료 - 다음 단계 버튼 한 줄 · 다른 언어 상품 버튼, 번역 주석 삭제, 서비스 가이드 갱신
상세 보기
## 배포 정보
- 배포 시각: 2026-11-05 17시 무렵
- 배포 환경: production (27320cb6)## 포함된 커밋
- 5ede7f57 폰 다음 단계 버튼을 어느 언어든 40px 로 맞춘다
- dd040c5d 폰 다음 단계 STEP 1 · 4 버튼을 가로 2칸 · 3칸으로 놓고 글자를 줄인다
- 27320cb6 다음 단계 버튼을 PC에서도 한 줄로 놓고 다른 언어에 상품 버튼을 연다## 변경된 기능
- 다음 단계: PC · 폰 모두 STEP 1 · 3 버튼 2칸, STEP 4 버튼 3칸
- 다른 언어 STEP 3에 상품 버튼(강의 상품은 한국어에만)## 운영 데이터
- `strength_descriptions` 187행 수정: 번역 작업 주석 186행 삭제(en 49 · ja 45 · zh 47 · vi 45), 베트남어 글 1행의 한글 「헌신」을 「Cống hiến」으로 수정
- 고치기 전 원본: `E:\backup\9way-strength-comments-20261105\before.json`## 서비스 가이드
- `strength-report` 갱신. 버튼 이름 두 문장과 기준 날짜만 바뀜. 캡처는 10/15 그대로## 확인 사항
- 운영 SHA = 27320cb6, /up 200
- 운영 BASIC 샘플 5개 언어: STEP 1 · 3 2칸, STEP 4 3칸, 상품 버튼 있음, 코칭 제안 있음, 강의 상품은 한국어에만, 주석 0
- 운영 문구: 주석 0행, 다른 언어 한글 0행. 결과 화면 생성 36회에 주석 0
- 서비스 가이드: 폭 390 · 1024 깨진 이미지 0, 가로 스크롤 없음
- 시험 로그인 삭제 완료## 확인 못 한 것
- 운영 무료 상태의 비교 표(샘플 계정이 모두 리포트 보유). 개발에서만 눌러 봄
- 실제 폰, 번역 원어민 검수 -
CClaude 다음 단계 버튼을 PC에서도 한 줄로 놓고, 다른 언어에 상품 버튼을 염
상세 보기
## 변경 사항
- `_next_steps_cta.html.erb`: PC · 폰 모두 STEP 1 · 3 버튼 2칸, STEP 4 버튼 3칸. STEP 3은 리포트 · 상품(앞에 아이콘)
- 상품 버튼 조건을 강의 판매(`course_sales?`)에서 리포트 판매(`enabled?`)로 옮겨 다른 언어에도 나옴. 강의 상품은 한국어 전용 그대로
- `strength_sales.next_steps.upgrade` 삭제, `choose` 하나로 합침
- `db/coach_materials/strength_report_guide.html.erb`: 서비스 가이드 생성기 문장 수정## 확인
- 폭 390 · 360 · 320 · 768 · 1024 · 1280 · 1600 × 5개 언어 × 무료 · BASIC 보유 · 심화 진단 완료: 버튼 전부 40px, 넘침 0
- 다른 언어에서 상품 버튼을 눌러 비교 표 · 코칭 업그레이드가 펼쳐지고 강의 상품이 없음을 확인
- 전체 테스트 6,763개 실패 0## 남은 일
- 배포 말씀 대기
- 운영 서비스 가이드 `strength-report` 글은 옛 버튼 이름이라 배포 뒤 갱신 필요(대표님 확인 후) -
CClaude 폰 다음 단계 STEP 1 · 4 버튼을 가로 2칸 · 3칸으로 놓고 글자를 줄임(카드 2열 유지)
상세 보기
## 변경 사항
- `app/views/diagnoses/_next_steps_cta.html.erb`: 폰에서 STEP 1 버튼 2칸, STEP 4 버튼 3칸. PC는 그대로
- `app/views/diagnoses/_social_image_cta.html.erb`: 폰 칸용 짧은 글자, 만드는 동안 도는 표시만
- `config/locales/diagnosis/*.yml`: 폰 전용 짧은 문구 6개를 5개 언어에 추가
- `test/controllers/strengths/next_steps_test.rb`: 배치 · 5개 언어 문구 테스트## 확인
- 폭 390 · 360 · 320 · 768 · 1164 · 1455 × 5개 언어 × 무료 · 리포트 · 심화 진단 완료: 버튼 전부 40px, 넘침 0
- 폭 360 아래는 세로로 쌓음
- 전체 테스트 첫 실행 2건 실패(Windows 시계 8.7초 늦음, 권한 시각 비교), 다시 실행 6,754개 실패 0## 남은 일
- 배포 말씀 대기 -
팀팀리드 폰 다음 단계 버튼을 5개 언어 모두 40px로 맞춤(5ede7f57, 미배포)
상세 보기
대표님 «버튼 크기를 최적화 하라고...».
## 고치기 전
폭 390에서 40~67px, 360에서 40~84px. 글자가 2~4줄로 접힘.## 고친 것
- xl 아래에서 버튼 글자 12px, 카드 · 버튼 여백 축소
- 아이콘 버튼은 왼쪽 정렬, 심화 진단은 이름 왼쪽 · 가격 오른쪽
- 베트남어 몰입도 버튼 이름을 Mức độ gắn kết로 줄임## 확인
- 폭 390 · 360 · 1280 · 1600 × 5개 언어 × 무료 · 리포트 상태에서 버튼 전부 40px, 문서 폭 넘침 없음
- 전체 테스트 6,748개 실패 0, 건너뜀 51 -
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 AI에게 물어보기 다이얼로그 · 8단계 카드 · 4개 언어 번역 커밋(미배포)
상세 보기
## 커밋
- `1d7cb52b` 결과 맨 위 AI 아이콘 · 다이얼로그, STEP 5 「내 AI 도구와 대화하기」(강의는 STEP 6으로 밀어 8단계), 다음 단계 PC 4열 · 폰 2열 카드, 친구 안내 1번 문구
- `65834ce5` 영어 · 일본어 · 중국어 · 베트남어로 열기(화면 + 프롬프트 + 강점 질문 54개)## 확인
- 전체 테스트 6,748개 실패 0, 건너뜀 51. Zeitwerk · Rubocop · Brakeman 통과
- 한국어 프롬프트 36개 경우를 바꾸기 전과 대조해 글자까지 같음(코치 카드 · 캔버스 경로 포함)
- 4개 언어 PC · 폰에서 넘침 없음, 복사되는 글의 입력 칸 · HTML 부탁이 그 언어로 들어감(클립보드는 가로채서 확인)## 안 한 것
- 원어민 검수, 실제 폰의 공유 창 · 클립보드
- 운영 배포(대표님 말씀 대기). 배포하면 다른 세션 캔버스 커밋 `afee5a8b`, `e7e5940d`도 같이 나감## 따로 발견
운영 강점 문구 번역 65행에 한글이 남아 있음: 번역 작업 주석 64행(en 9 · ja 24 · zh 7 · vi 24), 베트남어 조합 글에 한글 단어 1행. 대표님께 보고. -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 배포 완료 - 다른 언어 화면에서 「강점 개발」 탭과 「강의실」 메뉴 숨기기
상세 보기
## 배포 정보
- 배포 일자: 2026-11-05
- 배포 환경: production
- 운영 이미지: `df5106517cb4b6856892c05f184894dc4a887d66`## 포함된 커밋
- `1aee58e5` fix(strengths): 직장인 역할 글 소제목이 한 글자씩 나오지 않게 한다
- `df510651` fix(strengths): 다른 언어 화면에서 강의 · 코칭 · 입문 과정 입구를 뺀다## 변경된 기능
- 다른 언어: 「강점 개발」 탭, 사이드바 「강의실」, 다음 단계의 강의 · 코칭 받기 · 입문 과정을 뺐다. 다음 단계는 4단계다
- 직장인 역할 글 소제목: T · r · a · n 글자 대신 성인 소제목이 나온다. 결과 캐시 v19 · v20## 확인 사항
- `/up` 200, 컨테이너 시작 후 500 · FATAL 로그 0건
- 운영 로그인 계정으로 en · ja · zh · vi: 탭 4개, 강의실 메뉴 없음, 다음 단계 4단계
- 운영 ko: 탭 5개, 강의실 메뉴 있음, 다음 단계 7단계 그대로
- 운영 포매터에서 직장인 소제목 5개 언어 정상, 운영 직장인 한국어 PDF 3.2쪽 라벨 정상## 안 본 것
- 운영 일본어 PDF는 뽑지 않았다(개발 서버에서 확인). 강의실 주소를 직접 치면 다른 언어에서도 열리는 건 그대로다 -
Cclaude-code 상태 변경: 할 일 → 리뷰
-
Cclaude-code 커밋 완료 · 배포 대기: 다른 언어 입구 정리 + 직장인 소제목 수정
상세 보기
## 고친 것
- 다른 언어 결과 화면 「강점 개발」 탭, 사이드바 「강의실」, 다음 단계 메뉴의 강의 · 코칭 · 입문 과정을 뺐다
- 직장인 역할 글 소제목이 글자 하나씩(T · r · a · n) 나오던 버그를 고치고 결과 캐시 버전을 올렸다(`diagnoses_controller` v19 · v20)## 확인
- 전체 테스트 6,711개 실패 0 · 오류 0 · 건너뜀 51
- `bin/rails test:pdf` 49개 통과
- Rubocop · Brakeman 통과
- 개발 서버에서 5개 언어 화면, 직장인 PDF(ko · ja) 확인## 배포 뒤 할 일
- 운영 이미지 SHA 대조, 직장인 PDF · 영어 결과 화면 확인 -
Cclaude-code 상태 변경: 리뷰 → 완료
-
Cclaude-code 운영 배포 확인: f904de54에 포함(11/5 13:35, 다른 세션 배포)
상세 보기
## 운영에서 확인한 것
- `_prepurchase_field.html.erb` 칸에 `max-w-full`이 붙어 있다
- 운영 CSS(`tailwind-3e9f550c.css`)에 `max-w-full` 규칙이 있다
- `/up` 200, 컨테이너 시작 후 500 · FATAL 로그 0건## 안 본 것
- 운영 화면을 폰 폭으로 직접 열어 보지는 않았다. 폭 측정은 배포 전 개발 서버에서 했다(461px · 622px → 390px) -
Cclaude-code 운영 배포 확인: f904de54에 포함(11/5 13:35, 다른 세션 배포)
상세 보기
## 운영에서 확인한 것
- 회원: `Marketing::SegmentQuery`의 `created_after` 2026-03-01이 `created_at >= '2026-02-28 15:00:00'`으로 나온다
- 리드: `Marketing::LeadRecipients#apply_created_after`에 `in_time_zone`이 들어가 있다(코드 확인, 실행은 안 함)
- `/up` 200, 컨테이너 시작 후 500 · FATAL 로그 0건 -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 배포 완료 - 세그먼트 날짜 필터 수정(62d468cc, 브랜딩 배포 f904de54에 함께 나감)
상세 보기
## 배포 정보
- 배포 시각: 2026-11-05 13:35
- 배포 환경: production (f904de54)## 포함된 커밋
- 62d468cc fix(marketing): 세그먼트 날짜 필터를 한국 날짜로 자른다## 확인 사항
- 대표님 확인을 받고 브랜딩 수정과 같이 배포했다
- 전체 테스트에 이 커밋을 포함해 돌렸다. 운영 세그먼트 화면은 직접 열어 보지 않았다 -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 배포 완료 - 브랜딩 문장 언어 수정 · 취약 젬 업데이트
상세 보기
## 배포 정보
- 배포 시각: 2026-11-05 13:35
- 배포 환경: production (f904de54)## 포함된 커밋
- ab78bc87 fix(branding): 고른 언어로 브랜딩 문장을 만든다
- cd04021b fix(pdf): K 표지 한 문장 요약이 아래 표를 덮지 않게 한다
- f904de54 chore(deps): 보안 취약점이 있는 젬을 올린다
- 다른 세션 커밋 함께 배포(대표님 확인): 62d468cc, dd5455eb## 변경된 기능
- 브랜딩 문장: 한국어 외 언어는 지시문을 영어로 보내고 쓸 언어를 직접 지정. 규칙을 한국어에 맞춤
- 위저드 칸: 문장 길이만큼 늘어남
- K PDF 표지: 겹칠 때만 글자를 줄임
- 젬: Rails 8.1.4.1 등. bundler-audit 46건 → 0건## 확인 사항
- 운영에서 영어 · 일본어 문장을 직접 생성해 언어와 수식어 반영 확인(저장 안 함)
- /up, /ko, /en, /ja, /en/pricing 200, 이미지 변환 200
- 배포 후 5xx 0건, IpSpoofAttackError 0건 -
Cclaude 상태 변경: 할 일 → 리뷰
-
Cclaude 폰 상품 칸 수정, 커밋 dd5455eb, 배포 대기
상세 보기
## 고친 것
- `_prepurchase_field.html.erb`: 칸에 `max-w-full`
- `_invitation_link.html.erb` 수정 폼: 칸에 `max-w-full`, 줄바꿈 허용, 버튼을 오른쪽에 유지## 측정
- 새 초대 폼: 고치기 전 문서 폭 461px(360~430 폭 모두), 고친 뒤 화면 폭과 같음
- 수정 폼: 고치기 전 622px, 고친 뒤 390·360 폭에서 화면 폭과 같음, 저장 버튼 화면 안
- 1280px·768px의 새 초대 폼 칸과 1280px의 수정 폼 칸 위치 변화 없음
- 개발 DB 시험 초대·로그인 기록 삭제, 건수 원래대로## 상태
운영 미반영. 다른 세션 작업 종료 후 함께 배포. -
Cclaude 커밋 62d468cc, 배포 대기(다른 세션 작업 종료 후)
상세 보기
## 상태
- main 커밋 62d468cc, 운영 미반영
- 전체 테스트 6,694개: 실패 0, 오류 0, 건너뜀 51
- Rubocop(바꾼 Ruby 파일), Brakeman 통과## 배포 대기 이유
main에 다른 세션의 미배포 커밋 ab78bc87, cd04021b가 있다. 대표님이 그 세션이 끝날 때까지 기다리기로 결정했다.## 배포할 때 할 일
- `bin/rails test:pdf` 실행(cd04021b가 PDF 레이아웃을 고침)
- 운영 SHA 대조 후 main 전체 배포 -
Cclaude 상태 변경: 할 일 → 리뷰
-
Cclaude 세그먼트 날짜 필터 수정 완료, 커밋·배포 전
상세 보기
## 원인
`where(column => date..)`가 `>= '2026-10-30'`로 나가 UTC 0시(한국 오전 9시)부터 잘렸다.## 고친 곳
- `app/services/marketing/segment_query.rb` `apply_date_after`
- `app/services/marketing/lead_recipients.rb` `apply_created_after`
- 둘 다 `in_time_zone`으로 한국 날짜 0시부터 포함## 확인
- 새 테스트 3개가 수정 전 실패, 수정 후 통과
- 기존 `first_diagnosis_after` 테스트: 0:30, 8:30, 9:30, 12:30, 23:30 모두 통과
- 전체 테스트 6,689개: 실패 1, 건너뜀 46
- 실패 1개 `StrengthNextStepsTest#test_강의를_볼_수_있으면_STEP_5_는_내_강의로_보낸다`: 단독 3회 통과, 전체 실행에서만 1회 실패, 원인 미확인## 운영 영향(수정 전 코드 기준 읽기 전용 조회)
- 세그먼트 67개 중 날짜 필터 사용 1개: 「무료 진단 (3개월, W미소속)」(created_after 2026-03-01)
- 회원 6,250명 중 빠진 사람 8명, 연결 캠페인 1개는 failed 상태
- 리드 수는 세지 않음 -
2026년 11월 04일
-
팀팀리드 상태 변경: 리뷰 → 완료23:56 워크스페이스 초대에 언어 선택 추가
-
팀팀리드 배포 완료 - 워크스페이스 초대에 언어 선택 추가23:56 워크스페이스 초대에 언어 선택 추가
상세 보기
## 배포 정보
- 배포 시각: 2026-11-05 08:52 (KST)
- 배포 환경: production## 포함된 커밋
- fe685c63 feat(workspace): 초대할 때 언어를 고른다## 변경된 기능
- 초대 언어 칸: 링크·이메일·대량 이메일 초대, 기본 한국어
- 초대 링크·QR·관리자 화면·CSV·초대 메일: 고른 언어를 따름
- 결과 메일: 진단을 본 언어로 발송, 5개 언어 번역
- 일본어·중국어 `.break-keep` 해제## 확인 사항
- 운영 이미지 fe685c63, `/up` 200
- `workspace_invitations.locale` 칸 추가 확인, 기존 초대 584건 모두 ko
- 운영에서 `/ko`·`/ja`·`/zh` 초대 화면이 각 언어로 열림
- 운영에서 초대 메일·결과 메일을 5개 언어로 렌더링(발송 안 함), 외국어 메일에 한글 없음
- 운영 CSS에 줄바꿈 규칙 반영, 배포 후 10분 로그에 오류 없음## 못 한 것
- 운영에서 초대를 새로 만들어 끝까지 응시, 실제 메일 수신## 별도 문제
- 전체 테스트 1건 실패: `Marketing::SegmentQueryTest#test_first_diagnosis_after_filters_by_first_diagnosis_date`. 시각을 옮겨 8:30 실패, 9:30·12:30 통과 확인. 이번 변경과 무관
- `apply_date_after`가 오전 9시(KST)를 날짜 경계로 삼음. 미수정
- 폰에서 「리포트 제공」 상품 칸 넘침. 미수정 -
Cclaude 결과 메일 다섯 언어 번역 완료, 커밋 fe685c63 배포 시작23:49 워크스페이스 초대에 언어 선택 추가
상세 보기
## 추가로 바꾼 것
- `DiagnosisResultMailer`가 진단 언어(`session.locale`)로 제목·본문·링크를 보낸다. 모르는 언어면 한국어
- 템플릿 문구를 번역 키로 옮기고 en·zh·vi·ja 번역 추가
- 이름 없을 때 「안녕하세요님」으로 나가던 인사말 수정
- 결과 메일 맨 아래 문구를 결과 안내로 수정
- Brakeman 기존 예외 지문 갱신(`:locale` 추가로 지문이 바뀜)## 배포 전 확인
- 전체 테스트 6,681개: 실패 1, 건너뜀 46
- 실패 1개 `Marketing::SegmentQueryTest#test_first_diagnosis_after_filters_by_first_diagnosis_date`: 이번 변경과 무관한 코드. 오전 9시(KST) 전에 UTC 날짜 차이로 실패하는 것으로 보여 9시 이후 재실행 예정
- 운영 스키마 기준 마이그레이션 통과, 차이는 PG 표기 3줄
- Rubocop(바꾼 Ruby 파일), Brakeman, bundler-audit, importmap audit 통과
- 운영 SHA 88887a7f = 직전 main, 함께 나가는 다른 커밋 없음 -
Cclaude 상태 변경: 할 일 → 리뷰13:00 워크스페이스 초대에 언어 선택 추가
-
Cclaude 초대 언어 칸 구현 완료, 커밋·배포 전13:00 워크스페이스 초대에 언어 선택 추가
상세 보기
## 바꾼 것
- `workspace_invitations.locale` 추가(기본 ko, 마이그레이션 20261104090000)
- 링크·이메일·대량 이메일 초대 폼에 언어 칸 추가
- 복사 링크·QR·관리자 화면·CSV·초대 메일 링크가 초대 언어를 따름
- 초대 메일을 초대 언어로 발송, 중국어·베트남어 메일 문구 추가, 메일 하단 문구 번역
- 맞춤 문구는 한국어 초대에만 사용
- 결과 메일 링크가 진단 언어를 따름
- 일본어·중국어에서 `.break-keep` 해제(폰에서 일본어 초대 카드 넘침 수정)## 확인
- 전체 테스트 6,673개: 실패 0, 오류 0, 건너뜀 46
- 개발 서버에서 데스크톱·폰 캡처, 5개 언어 폰 너비 측정
- 캡처용 개발 데이터 삭제, 건수 원래대로## 남은 일
- 결과 메일 본문 번역 여부 결정
- 커밋·배포 -
2026년 10월 15일
-
팀팀리드 배포 완료 - 「진단 코드」 문구 · 운영 리더 책 묶음 slug book
상세 보기
## 배포 정보
- 배포 시각: 2026-10-15
- 운영 SHA 62c48b6f## 포함된 커밋
- 62c48b6f 「내 코드」→「진단 코드」, 입력 칸 안내 「받은 진단 코드 입력」(5개 언어, 입력 칸 14ch)## 운영 데이터
- 「테스트 묶음」(리더의 2가지 책무)에 slug book 설정 → 9way.co.kr/code/book 열림. 실제 1,000개 묶음을 만들면 옮길 것## 확인 사항
- /up 200, /ko/code/book 「진단 코드 · 받은 진단 코드 입력」, /en/code/book 「Diagnosis code · Enter code」, 배포 뒤 500 오류 0건, 운영 화면 캡처 확인 -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 배포 완료 - 책 · 이벤트 첫 화면 + 코드 화면 다국어
상세 보기
## 배포 정보
- 배포 시각: 2026-10-15 16:55
- 배포 환경: production (운영 SHA 6a79f4af)## 포함된 커밋
- b0890e0b feat(report-codes): 책 · 이벤트 첫 화면(9way.co.kr/code/book)에서 코드를 넣고, 코드 화면을 다른 언어로도 연다
- 6a79f4af chore(brakeman): 이벤트 코드 관리자 화면의 오탐 두 건을 이유와 함께 예외로 둔다
- (같이 올라감) 790bba57 서비스 가이드 「성과 관리」 생성기 — 다른 세션 작업## 변경된 기능
- 마이그레이션 20261015100000: report_code_batches.slug(유일)
- /code/ = 코드가 아니면 그 묶음 첫 화면(「내 코드」 자리 입력 칸). slug는 코드 · 공유 코드 · 새 코드와 겹치지 않게 막음
- 관리자: 수정 화면 「첫 화면 주소」, 나눠 줄 파일에 주소 · 「첫 화면 QR 받기」
- 코드 화면 한국어 고정(korean_only) 해제, report_codes 문구 5개 언어 같은 칸## 확인 사항
- 테스트: 이벤트 코드 89개 통과, 전체 6,322개 중 팀 리포트 PDF(Chromium) 1건은 따로 돌리면 통과
- 운영 스키마로 빈 DB 마이그레이션 검증(PG 표기 3줄 외 차이 없음)
- 운영: /up 200, 마이그레이션 버전 20261015100000, /code/book → /ko/code/book(아직 slug 없음 → 404 정상), /en/code 영어, 배포 뒤 8분 500 오류 0건
- 남은 일: 실제 책 묶음에 slug book 넣기(대표님), 출판사용 PDF 왼쪽 QR을 첫 화면 QR로 바꿀지 결정 대기 -
Cclaude 상태 변경: 할 일 → 완료06:59 서비스 가이드 「성과 관리」 새로 쓰기
-
Cclaude 성과 관리 가이드 세 편 운영 발행 · 운영 주소 검사 통과06:59 서비스 가이드 「성과 관리」 새로 쓰기
상세 보기
## 운영 주소
- https://futuretalent.co.kr/services/performance-management (사진 19)
- https://futuretalent.co.kr/services/performance-weekly-check (사진 14)
- https://futuretalent.co.kr/services/performance-quarter-review (사진 7)## 확인
- dry run 세 편 모두 새 가이드 · 사진 수 일치 → APPLY
- 운영 check_page: 데스크톱 · 폰 모두 깨짐 0 · 가로 스크롤 없음 · 번호/점 없는 목록 0, 사진 자리 눈으로 확인
- 운영 서버 /tmp/feature_guide 정리 완료## 남은 것
- 분기 마감 편의 「주기 넘기기」 · 「이어 가기」 화면은 데모 조직에 지난 주기가 없어 사진 없이 글로만 씀 -
Cclaude 성과 관리 가이드 세 편 생성기 · 캡처 완료, 개발 서버 발행 · 검사 통과(대표님 확인 대기)06:48 서비스 가이드 「성과 관리」 새로 쓰기
상세 보기
## 한 일
- 서비스 가이드 세 편: 「성과 관리」(performance-management, 사진 19) · 「성과 관리 이번 주 점검」(performance-weekly-check, 14) · 「성과 관리 분기 마감」(performance-quarter-review, 7)
- 생성기 `lib/tasks/performance_guides.rake` + 본문 `db/coach_materials/performance_*guide.html.erb` + 테스트 `test/lib/performance_guides_test.rb` + 캡처 `.claude/skills/feature-guide/captures/performance.js` (커밋 790bba57)
- 공용 josa: 짝 없는 조사는 멈춤, O · KR · TASK · CSV 읽는 소리 추가
- 개발 서버 check_page: 세 편 모두 깨짐 0 · 가로 스크롤 없음 · 번호/점 없는 목록 0## 찾아서 고친 화면 결함
- 이번 주 화면이 1024~1279px에서 KR · TASK 제목이 한 글자씩 세로로 쌓임 → 팀원 목록을 1280부터 옆에(e0c4ca91, 대표님 승인, 운영 배포 완료)## 남은 일
- 대표님 캡처 확인 후 운영 발행 → 운영 주소 check_page -
Cclaude-code 강점 리포트 · 조직 진단 · 조직 진단 결과 가이드 운영 발행, 조직 진단 화면 고침 운영 반영(81699064)
상세 보기
## 운영 반영
- 화면 고침 81699064: ko-KR 브라우저 영어 결함(compatible_language_from), 「Back」→돌아가기(5개 언어), 응답 시간 약 3분 통일(운영 응답 137건 중앙 2.2분), 강점·주의 카드 이름표를 점수 등급으로, v2 추세 제목 「점수」, v2 하단 모델 이름, 시작 전 링크 「아직 시작하지 않은 진단」. 다른 대화의 배포 ff8594ca에 포함돼 운영에 올라감(확인 완료)
- 서비스 가이드 발행: strength-report(새 글, 9WAY 강점 진단 묶음), guide-969d4313 「조직 진단」 · guide-a149d6f7 「조직 진단 결과」(제목 바꿈, slug 유지)
- 운영 check_page: 세 편 모두 깨짐 0 · 가로 스크롤 없음
- 개발 DB 임시 상품(PRO 9f6eca33 · FULL 025ad4f2) 삭제## 남은 것
- 「성과 관리」 가이드 새로 쓰기 -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 배포 완료 - 책 묶음 출판사용 PDF ZIP
상세 보기
## 배포 정보
- 배포 시각: 2026-10-15 12:19
- 배포 환경: production (운영 SHA ff8594ca)## 포함된 커밋
- a1e635e3 feat(report-codes): 책 묶음에 「출판사용 PDF ZIP 받기」를 단다 — 코드마다 책 속지 PDF 한 장씩
- ff8594ca fix(report-codes): 출판사용 PDF의 QR 아래 주소를 9way.co.kr/code 로 바꾼다## 변경된 기능
- 양식 `lib/print_templates/report_code_book.pdf`: 원본에서 견본 QR 둘과 「개별 코드」 글자만 지움
- `ReportCodes::PrintPdf`: prawn 2.4로 QR(벡터 · K100) · 주소 · 코드를 덧그리고 combine_pdf로 2쪽에 얹음
- `ReportCodes::PrintZipJob`: 「번호_코드.pdf」 ZIP(1,000개 40초 · 240MB), 받기는 send_file
- 책 묶음은 만들 때 자동, 예전 묶음은 「출판사용 PDF 만들기」 버튼## 확인 사항
- 이벤트 코드 테스트 72개 통과, 전체 6,311개 중 Chromium 시간 초과 2건은 따로 돌리면 통과(이번 변경과 무관)
- 개발 서버에서 만들기 → ZIP 받기 → PDF 2쪽 QR 두 개 읽힘 확인, 데스크톱 · 폰 캡처
- 운영: /up 200, 배포 뒤 10분 500 오류 0건, 운영 안에서 PDF 렌더 확인(prawn 2.4.0, 2쪽, 264KB) -
2026년 10월 14일
-
Cclaude-code 조직 진단 가이드 두 편 다시 씀 — 개발 서버 발행, 운영은 승인 대기(커밋 0bd8d52b)
상세 보기
## 한 일
- 운영 「조직문화 진단」(guide-969d4313) · 「조직문화 진단 결과」(guide-a149d6f7)를 몰입도 v2 화면으로 다시 씀. slug 유지, 제목은 메뉴 이름 「조직 진단」 · 「조직 진단 결과」
- 생성기 `lib/tasks/engagement_guides.rake`(guides:engagement), 본문 `db/coach_materials/engagement_run_guide.html.erb` · `engagement_result_guide.html.erb`, 테스트 `test/lib/engagement_guides_test.rb`, 캡처 `.claude/skills/feature-guide/captures/engagement.js`
- 이름은 화면 문구 · 뷰에서, 기준 숫자는 계산기 · 뷰에서 읽음. 문항 원문 유출 검사(0/47)
- 개발 서버 발행 · check_page 통과(깨짐 0 · 가로 스크롤 없음), 데스크톱 · 폰 화면 확인## 남은 것
- 대표님 「올려」 뒤 운영 반영(강점 리포트 가이드도 대기 중)
- 찍다가 찾은 화면 문제(영어 Back · Close, 응답 시간 3분/5분, 강점 카드 이름표, 추세 제목 「전체 만족도」, 하단 옛 모델 이름, 준비 중 링크가 「마감」 안내) — 고칠지 결정 대기
- 브라우저 언어가 「ko-KR」 하나면 locale 없는 화면(/engage 등)이 영어로 잡히는 결함(preferred_language_from) — 결정 대기 -
팀팀리드 배포 완료 - 서비스 가이드 사진 순서 고침 + 화면 문구 4건 (f71e8b64)
상세 보기
## 배포 정보
- 배포 시각: 2026-10-14 22:04
- 배포 환경: production (ghcr.io/daniel-kim-9way/nineway:f71e8b64)## 포함된 커밋
- 6ed364e3 서비스 가이드 본문 이미지 자리를 올린 순서로 채운다(운영 25편 어긋남)
- 83e336a6 고객 화면 옛 문구 넷: Big5 안내 「15개 중 3개」, 심화 진단 부제 행복도, 결과 화면 행복도 카드 → 몰입도 검사, 대량 이메일 초대 영어 → 번역 문구(다섯 언어)
- f71e8b64 가이드 생성기 테스트가 다른 rake 테스트 6건을 깨던 것 고침
- db62f1c0 · e559dfba · 77ae2208 가이드 생성기와 feature-guide 스킬(앱 동작 변화 없음)## 확인 사항
- 전체 테스트 6,297개 실패 0 · 오류 0(PDF 46개 건너뜀은 평소대로)
- 운영 /services/guide-65355828 이미지 5장이 설명 순서대로 붙음
- 운영 /ko/diagnoses 「몰입 · 성격 · 마인드셋 분석」 확인
- 운영 가이드 7편(행복도 2 · 커리어테크 5) 게시 끔 → 404 확인## 다음
- 「강점 리포트」 가이드 → 조직 진단(몰입) 가이드 → 「성과 관리」 가이드 -
Cclaude-code 상태 변경: 할 일 → 진행 중
-
Cclaude-code 상태 변경: 할 일 → 완료04:18 개발 DB 강점 문구를 운영과 맞추기
-
Cclaude-code 상태 변경: 할 일 → 완료
-
Cclaude-code 상태 변경: 할 일 → 완료
-
Cclaude-code 활용 가이드 10칸 다국어 1,080편 새로 번역 · 운영 DB 반영 · 칸 제목 배포(27c216ee)
상세 보기
## 확인
- 운영 DB 수정 날짜: 한국어 가이드 10칸은 9/18, 영 · 중 · 베는 2/25, 일본어는 7/27 그대로. 27개 DNA 첫 줄을 나란히 보니 내용도 전혀 달랐다. 칸 제목도 한국어만 9/18(4e409b37)에 바뀜.## 한 일
- 10칸 × 27 DNA × 4개 언어 = 1,080편 직접 번역(언어 4 × 묶음 2로 나눔). 검사 스크립트로 줄 모양 · 칸 이름 · 한글 잔존 · 베트남어 부호 확인, 문제 0.
- 운영 문구에 새 번역을 덮어 리포트 144번 측정: 넘침 0, 쪽 수는 같거나 줄었다(직장인 en · vi -1.2쪽).
- 운영 DB 반영(옛 글 백업 /root/guide_backup_20261014.json), 개발 DB도 반영.
- 칸 제목 7개 × 4개 언어 고쳐 배포(27c216ee). 기록 db/content/guide_translation_2026-10-14.yml. -
Cclaude-code 상태 변경: 리뷰 → 완료
-
Cclaude-code 운영 배포 확인(1794b543에 같이 실림), 운영 문구로 리포트 180번 다시 찍어 넘침 0
상세 보기
## 배포
- f06168f6(결과 화면) · c76eff16(리포트)는 다른 세션이 10/14 배포한 1794b543에 같이 실렸다. 운영 /up 200, 운영에서 청소년 진단 DNA 5개 모두 course · study 두 칸 확인.## 넘침 다시 측정(운영 문구)
- 개발 DB 문구가 운영보다 뒤처져 있어, 운영 strength_descriptions 14,390건을 읽기 전용으로 받아 개발 DB 트랜잭션에 넣고 찍은 뒤 되돌렸다(tmp/use_guide_pdf/measure_prod.rb).
- 6개 대상 × 5개 언어 × DNA 27개, 180번: 넘침 0, 오류 0.
- 한국어 DNA마다 2쪽, 성인 · 직장인 · 리더 22쪽 / 청소년 · 대학생 · 자녀 관찰 20쪽 그대로.## 남은 문제(별건)
- 청소년 · 대학생 · 직장인 · 리더 두 칸(공용 course · study · resume · grade · work · competency · leadership · management)은 영 · 중 · 일 · 베 번역이 지금 한국어보다 앞선 옛 글.
- 베트남어 leadership · management 54건은 성조 부호가 없다. -
CClaude Code 상태 변경: 진행 중 → 완료
-
CClaude Code 27DNA 활용 가이드 K·J 운영 배포(1794b543) + 다국어 욕구 표·영어 리포트 빈 쪽 고침
상세 보기
## 배포
- 운영 779294f6 → 1794b543 (12커밋, 다른 세션 「강점 활용 두 칸」 f06168f6·c76eff16 포함)
- 롤백: `kamal rollback 779294f61f2a65454984a72343524d70263ec7e9`## 10/14 추가로 고친 것
- 운영 DB 욕구(desire) 4개 언어 108건 재번역 적용(db/content/desire_translation_2026-10-14.yml). 9/22 재번역 때 욕구만 빠져 옛 번호 목록이 남아 K 욕구 표가 비었다
- K 욕구 표는 세 묶음일 때만 표, 아니면 글(리포트·가이드)
- 리포트 K DNA 쪽에 언어별 글자 비율(--gz, 영어 .82) — 영어 DNA 4~5쪽·빈 쪽 → 2쪽
- 가이드 주로 쓰는 DNA에 활용 가이드 두 칸 + 강점 개발(K·J)## 운영 확인(회사 계정)
- 리포트 K 영어·중국어: DNA마다 2쪽, 욕구 표 5개 채움, 넘침 0 / J 일본어 26쪽 넘침 0
- 가이드 K·J 한국어·영어 40~44쪽, 넘침 0(주로 쓰는 DNA 12개인 진단은 44쪽)## 남은 것
- course·decision·grade·leadership·management·resume·study 7개 대상 칸 운영 번역이 옛 글 -
2026년 10월 13일
-
Cclaude-code 상태 변경: 진행 중 → 리뷰
-
Cclaude-code 화면·리포트 커밋(f06168f6, c76eff16), 한국어 리포트 DNA당 2쪽 유지 확인 — 배포 대기
상세 보기
## 커밋
- f06168f6 결과 화면 DNA 탭(포매터·카드·캐시 v17/v18)
- c76eff16 리포트 K·J: 가이드 두 칸 + 강점 개발(따로 블록), 촘촘 모드 `data-tighten="3+"`, 이어진 그룹 머리 중복 제거## 측정(27 DNA × 6 대상 × 5 언어, `tmp/use_guide_pdf/measure.rb`)
- 한국어: DNA마다 2쪽, 전체 쪽 수 그대로(K 22 · J 20), 넘침 0
- 중·일·영·베: 원래도 DNA당 3~4쪽. 대부분 같거나 줄었고 늘어난 곳은 청소년 vi +1.5, 직장인 en +1.5, 직장인 vi +1.0, 청소년 zh +1.2, 대학생 zh +0.8. 넘침 0
- 테스트: 관련 766개 + PDF 실제 찍기·27DNA 가이드 테스트 통과## 배포 보류 이유
- 운영 779294f6 뒤로 다른 세션의 27DNA 가이드 리뉴얼 커밋 7개(2ab06503~bdf8031a)가 먼저 쌓여 있어 같이 나간다 → 대표님 확인 후 -
Cclaude-code 27DNA 활용 가이드 K·J 운영 코드 구현 완료(main 7커밋), 배포 승인 대기
상세 보기
## 커밋 (779294f6..bdf8031a)
- 2ab06503 생성기 Strengths::DnaGuidePdf·실패 안내·PDF 제목
- dbe9b526 K 양식 / 4849c3c3 J 양식
- 3ca2dd38 중·일 줄바꿈(레이아웃) — 배포한 J 일본어 리포트 해석 가이드 넘침도 고침
- 0940631c 실제 PDF 테스트, 구간 몰린 간지 / 79558a96 옛 템플릿·문구 3개 삭제
- bdf8031a 검토 고침: 영어 K 표지 범례 중복, 일·중 e2e## 확인
- 전체 테스트 6280 runs 0 failures 0 errors(다른 세션 테스트 없을 때). 개발 DB 그대로
- 운영 코드로 9개(K 성인·리더, J 청소년·자녀 관찰, 영어 K·J, 일본어 J, 베트남어 K, 중국어 J) 모두 32쪽, 넘침 0
- 새 검토자(Fable): Critical 0, Important 2(고침), Minor 4(미룸)## 주의
- 다른 세션이 레이아웃·_paginate·리포트 _dna를 미커밋으로 고치는 중(「강점 활용」을 대상별 활용 가이드로). 배포 때 섞이지 않게 확인 필요 -
Cclaude-code 화면 반영 끝, 리포트 PDF는 2쪽 유지되게 촘촘 모드로 맞추는 중
상세 보기
## 바꾼 것
- `Diagnosis::ResultFormatter`: DNA마다 `guide`(대상별 두 칸, `DNA_GUIDE_FIELD_MAP`). 요약 가이드 문안을 27개 DNA 모두 읽는다
- `_tab_domain` + `_dna_use_guide`: 가이드가 있으면 「강점 활용」 대신 칸마다 카드
- 결과 캐시 v17(본인)·v18(공유)
- 리포트 K·J `_dna`: 가이드 두 칸 나란히 + 강점 개발 한 줄 전체. 셋째 쪽으로 넘치면 둘째 쪽에 촘촘하게(tight) 합친다(K에 data-tighten 새로, J는 가이드 쪽만 더 조임)
- `_paginate`: 합칠 때 이어진 그룹(나만의 차별성) 머리가 두 번 나오지 않게## 측정(27개 DNA × 대상)
- 처음 넣었을 때: K 22→27쪽, J 20→24~25쪽(DNA마다 셋째 쪽)
- 촘촘 모드 뒤 한국어: 6개 대상 모두 DNA당 2쪽, 전체 쪽 수 그대로(K 22, J 20)
- 다른 언어(en·zh·vi·ja) 확인 중 -
Cclaude-code 상태 변경: 할 일 → 진행 중
-
Cclaude-code 상태 변경: 할 일 → 진행 중
-
Cclaude-code 27DNA 활용 가이드 K·J 시안 2벌 제작, 대표님 확인 대기
상세 보기
## 시안
- 운영 코드 수정 없음. `tmp/guide_proto/`(git 제외): views/guide_proto/{consulting,humanism}.html.erb, render.rb, measure.js(쪽 채움), merge_probe.js(한 쪽 합치기), contact.rb(모아보기)
- 회사 계정 진단(3c98433b, 이름 김서연) K 성인 · J 청소년, 둘 다 32쪽(지금 가이드와 같음), 넘침 0. K 680KB, J 1.3MB
- 다운로드 폴더 `9way-27DNA가이드-시안/`## 정한 것
- 순서·문구는 지금 가이드 그대로. 표지는 리포트 표지 + 제목 「9WAY 27DNA 활용 가이드」(기존 꼬리말 문구)
- 2쪽 읽는 법의 구간별 DNA 목록에 쪽 번호를 붙여 목차로
- 간지: 구간 안내 두 문단 + 이 구간 DNA(지금 가이드 내용)
- DNA 쪽: 리포트 DNA 부품, 중간·보완 활용 세 칸은 왼쪽 칸 이름(9/21 요청 유지). 「(이어서)」 삭제
- 주로 쓰는 DNA는 넘치면 촘촘하게(tight) 합쳐 한 쪽. 리포트 DNA 맨 위 정보 칸은 지금 가이드에 없어서 뺌 -
Cclaude-code 상태 변경: 진행 중 → 완료11:37 강점 리포트 PDF 디자인 리뉴얼
-
Cclaude-code 강점 리포트 PDF 리뉴얼 운영 배포 완료(0c158b08)11:37 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 배포
- 배포 전 운영 `7560091f`(main 조상 확인) → `0c158b08`. 마이그레이션·Gemfile·배포 설정 변경 없음. kamal deploy 152초.
- 되돌리기: `kamal rollback 7560091fc2507c7e490ef8814e03d2c20fa7cfb5`## 참고: 검토 전 코드가 2시간 먼저 나갔다
- 다른 세션이 7560091f를 배포하면서 리포트 커밋(dfd86d65~f8076589)이 검토 고침 전에 같이 나갔다.
- 그 사이 리포트 다운로드 2건(한국어, 정상 1.7MB), 자료 PDF 3건(/materials, 리포트 글꼴이 「Noto Sans KR」 이름으로 깔린 상태). 자료 PDF는 캐시 없이 매번 새로 만들어서 지금은 정상.## 운영 확인(운영 컨테이너에서 PdfGenerator#generate, DB 쓰기 없음)
- 회사 계정 K(성인 65dd3563): 22쪽, 넘침 0, 1.5MB, 6.5초
- 회사 계정 J(대학생 d4754f4f): 20쪽, 넘침 0, 2.2MB, 6.6초
- 회사 계정 K + 저장된 AI 분석(직장인 75c9535f): 27쪽, 넘침 0, AI 4섹션 앵커 정상
- 글꼴: 「9WAY Report」 8개, 「Noto Sans KR」 0개(덱과 이름 충돌 없음). /partners/proposal/company·school 200
- 표지·목차·AI 쪽 캡처가 개발판과 같다## 나중으로 미룬 것
- 배포 때마다 글꼴 58MB 다시 올림(Dockerfile 순서)
- AI 섹션 첫 문단이 두 쪽에 걸치면 제목 + 2줄만 쪽 끝에 남을 수 있음
- 27DNA 활용 가이드 PDF에 같은 방향 적용 -
Cclaude-code 운영 코드 구현 완료(main 커밋 16개) — 배포 승인 대기10:29 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 구현 (main, report-pdf 커밋 16개, dfd86d65…)
- `Diagnosis::PdfTheme`(J=student·college·parent, 나머지 K), 생성기 양식별 렌더 + 브라우저 쪽 나누기 대기(polling 100ms, raise_on_js_error)
- `pdf_shared/_paginate`: 실제 높이로 쪽 나누기·목차/쪽 번호, 문장 나누기(반씩 좁히기, 。 포함), keep-next·그룹·tighten·balance
- K·J 템플릿·레이아웃, `PdfReportHelper`·`PdfHandDrawnHelper`(무늬 채움 → 선)
- 고정 문구 5개 언어(`config/locales/pdf_report`), 해석 가이드 문구 2곳(5개 언어), PDF 실패 안내(`diagnosis.flash.pdf_failed`)
- 글꼴 `lib/fonts/pdf`(고정 굵기, 한자 뺌, 가족 이름 9WAY Report Sans/Serif — 덱의 Noto Sans KR와 안 겹침) + Dockerfile·컬러 이모지## 확인
- 전체 테스트 6241개 통과(실패 0)
- 운영판: K 성인 27쪽 1.6MB · J 청소년 26쪽 2.2MB(샘플 3.0·6.3MB), 대상 6종·일본어·영어 넘침 0, 긴 영어 역할 글 넘침 0
- 처음 보는 검토자 검토 → Critical 1·Important 4 모두 고침(역할 글 잘림, J AI 소제목, 글꼴 이름 충돌, 실패 신호, 5섹션 목차) + J 표지 긴 문장## 남은 일
- 대표님 PDF 확인 → 배포(운영 SHA 기록, kamal deploy, 9way.co.kr에서 K·J 내려받기 확인) -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 배포 완료 - 기업 제안서에 강점 리더십 기본 · 사내 강사 과정 · 마스터 과정 추가
상세 보기
## 배포 정보
- 배포 시각: 2026-10-13 18:55
- 배포 환경: production (ghcr.io/daniel-kim-9way/nineway:7560091f)## 포함된 커밋
- 320dd7a5 feat(whitepapers): 강점 리더십 기본 · 사내 강사 과정 · 마스터 과정을 기업 제안서에 넣는다
- dc5f872f feat(whitepapers): 리더십 · 사내 강사 맞춤 제안서를 두 벌로 나눈다(320dd7a5에서 다시 걷어 냄)
- 함께 나간 다른 세션 커밋: 7560091f(코치 카드 문구), f8076589 · 8540138f · 313527a7(리포트 PDF 쪽 나누기)## 변경된 기능
- 기업 강점 워크숍 도입 제안서 비용 입력란: 강점 리더십 기본 워크숍(2.5h) · 강점 사내 강사 과정(6h) · 강점 마스터 과정(12h) 추가, 진단 기본 12명
- 고르면 「제안 프로그램」 장으로 앞에 오고 안마다 비용 페이지, 안 고르면 별첨(33p)
- 따로 만든 맞춤 제안서(leadership_instructor 등)는 삭제## 확인 사항
- 전체 테스트 6,227개 통과(첫 실행 에러 2,964건은 동시 실행 충돌, 재실행 0건)
- 운영 /up 200, /materials/strength_workshop_company 33쪽 · 새 과정 장 포함, /materials/leadership_instructor 404
- 운영 runner로 기업 비용 항목 11개 · 진단 기본 12명 확인 -
Cclaude-code 샘플 확정(「이렇게 만들자」) → 운영 적용 설계서 작성08:04 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 샘플 최종 수정(10/13)
- J: 2쪽 전체 목차, 간지 쪽 목록 제거, PART 탭 모든 쪽, 원래 DNA 아이콘, 손글씨 간격(-.15em/.5em), 표지 「9WAY 강점 리포트」 + 꽃 아래 「OOO 님의 강점 꽃」, 「(계속)」 제거
- K·J: 해석 가이드 차트를 9WAY 매트릭스로, 가이드 문구 두 곳 수정(승인), 표지 문장 쉼표 뒤 줄바꿈
- K: 간지 쪽 목록 제거, 표지 한 문장 요약 위·정보 칸 아래(꼬리말 줄과 합침), 목차 옆 중복 글 제거## 설계서
- https://claude.ai/artifact/6EgRZDiuBtcSivToGCA5jm (`docs/plans/report-pdf-renewal/index.html`)
- 대상 매핑(J=student·college·parent, 나머지 K), 브라우저 측 쪽 나누기, 5개 언어 문구, 글꼴 번들, J 파일 크기 줄이기, 테스트·배포 순서
- 대표님 결정 대기: general·worker 대상 K로 찍기(추천) -
Cclaude K 목차 2쪽 분리 + K·J PART 간지 4개 반영, 샘플 PDF 재전달06:00 강점 리포트 PDF 디자인 리뉴얼
상세 보기
- K: 표지에서 목차 빼고 2쪽 목차, PART 1~4 간지, 번호 1.1~4.x로 정리. k_adult 27쪽, k_leader 22쪽
- J: PART 간지 4개(AI 없으면 3개), j_student 25쪽, humanism 19쪽
- 「이어서」 라벨 제거, K 「역할 지표」 칸 제거 유지
- 남은 과제: J PDF 용량(6MB, SVG 빗금 무늬가 그림으로 굳음) → 운영 반영 때 무늬 방식 바꾸기 -
Cclaude 양식 K·J 두 가지로 확정, AI 분석 쪽 포함 샘플 재공개05:36 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 결정(10/13)
- 양식 K(성인·리더), J(청소년·대학생·학부모 자녀 관찰). A 폐기
- AI 분석 쪽(_ai_analysis 5섹션)도 양식마다 디자인## 샘플
- K 성인 22쪽(AI 19~22), K 리더 18쪽, J 청소년 21쪽(AI 17~21). 넘침 0
- AI 샘플은 회사 계정 진단(3c98433b), 이름 김서연으로 표기
- K에 임의로 들어갔던 「역할 지표」 칸 제거(지금 리포트에 없는 내용)## 발견
- AI 제목 이모지가 운영 PDF에서도 빈칸으로 빠짐(서버 이미지에 이모지 글꼴 없음). 설계서에서 fonts-noto-color-emoji 추가 여부 결정 -
Cclaude 대상별 샘플 리포트 3벌(성인 A·리더 K·청소년 J) 실제 데이터로 완성, 대표님 검토 대기05:07 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 대표님 결정(10/13)
- 성인·학부모 = A 매거진, 리더 = K 컨설팅, 청소년·대학생 = J 데이터 휴머니즘
- 9역할 차트는 원래 차트(9WAY 원형·매트릭스)만, J의 강점 꽃은 표지 그림으로만
- 만드는 방식: 대상별 쪽 틀 따로
- 「코드 고치기 전에 대상별 샘플 리포트를 다 보여 달라」## 한 일
- 시험 폴더 tmp/report_proto (git 제외)에서 ResultFormatter 실데이터 + 새 템플릿 → Grover PDF
- 샘플 인물(교육 시연용): 윤서연(성인), 강민준(리더), 서지호(청소년). 대상만 바꿔 대상별 문장 사용
- 결과: A 18쪽, K 18쪽, J 16쪽. 넘침 0
- 보기 화면: https://claude.ai/artifact/DSEfnyTMsFA4BPakwA4yXo (지금 디자인 비교, 쪽별 의견 db feedback/samples)
- 운영 코드 변경 없음 -
Cclaude 리포트 리뉴얼 시안 12종 갤러리 공개, 대표님 선택 대기04:23 강점 리포트 PDF 디자인 리뉴얼
상세 보기
## 한 일
- 지금 강점 리포트 PDF(18쪽)·27DNA 가이드(32쪽)를 쪽별 이미지로 살펴 문제점 5가지 정리
- 레퍼런스 12종(Kinfolk/Monocle, Gallup, Spotify Wrapped, 벤토, 23andMe, 스위스 그리드, 뱅크샐러드, CliftonStrengths Journal/VIA, Oura, Dear Data, DiSC/Hogan, 토스)으로 표지·요약·DNA 상세 세 쪽씩 시안 제작
- 갤러리: https://claude.ai/artifact/1nZ3aYMYgdTbuyALzdHZ3r (좋아요/애매/별로 + 한 줄 의견, db feedback/main 에 저장)## 다음
- 대표님 선택 읽고 방향 확정 → 설계서 → app/views/diagnoses/pdf/* 반영 -
Cclaude 상태 변경: 할 일 → 진행 중04:15 강점 리포트 PDF 디자인 리뉴얼
-
2026년 10월 07일
-
Cclaude 1DAY를 「AI 반복업무 자동화」 과정으로 전환 배포(c381fa49 → f584aea2), 3기 이름 변경
상세 보기
- 기관용 「생성형 AI를 활용한 반복업무 자동화 실습(1일)」을 공개반으로: 정의서·전후 시간 측정표·스킬, 10:00~17:00
- 설치는 예전 설치 안내 그대로(대표님 정정), AI 구독 문구도 예전 그대로
- 운영 DB: 3기 이름 「AI로 서비스 만들기 1DAY 클래스」→「AI 반복업무 자동화 1DAY 클래스」. 안내 메일은 변경 없음
- 운영 확인: /vuild/1day · /vuild/1day/prepare · /vuild · /workshops/ai-1day-1 정상 -
Cclaude 상태 변경: 리뷰 → 완료
-
Cclaude 상태 변경: 할 일 → 리뷰
-
Cclaude 상태 변경: 리뷰 → 완료
-
Cclaude 피드백 반영: 역할-DNA 지도·같은 역할 다른 DNA 예시, 하루 순서를 과정 뼈대대로
상세 보기
- 「조합으로 읽습니다」: 캐릭터 9개 나열 → 3영역×9역할 카드에 DNA 3개씩(채점 코드 LOGIC_MAP과 같은 연결, 결과 화면 사전의 한 줄 설명). 폰은 영역마다 옆으로 넘김
- 같은 「촉진」, 다른 DNA 두 사람 예시(강의안 81쪽 '같은 캐릭터, 다른 아이템')
- 역할 이름 바로잡음: 조정→조율, 활동→촉진(입문 화면만. 심화·마스터 공용 화면엔 아직 옛 이름)
- 하루 순서: 강점의 중요성 → 뇌과학 → DNA 심층 분석 → 팀 → 코칭 실습 → 문장 → 현장에서 쓰기 + 마침 카드
- 입문에도 코칭 실습이 있어서 FAQ·다음 단계 문구 수정
- 테스트 63개 통과 -
Cclaude 상태 변경: 할 일 → 리뷰
-
Cclaude 입문 과정 소개 페이지 재설계 구현·검토 완료(미커밋·미배포)
상세 보기
## 근거
- 운영 신청자 71명 프로필: 강사 최다, 교육·상담·복지, 1인 교육 회사, HR 순
- 강의안(2025-11판 176장) 흐름으로 하루 순서 8단계 구성## 변경
- `app/views/study/workshops/levels/_basic_page.html.erb` 새 입문 전용 화면(카탈로그가 켜졌을 때만)
- `app/assets/stylesheets/workshop_strength_basic.css` 새 구역 스타일·움직임(/workshops 과정 카드 움직임 재사용)
- `app/views/study/workshops/level.html.erb` 입문 분기
- `app/services/expert/strength_course_catalog.rb` 입문 제목·설명·SEO·FAQ
- `test/controllers/strengths/offline_course_catalog_test.rb` 테스트 3개## 확인
- 관련 테스트 358개 통과, 데스크톱·폰·일정 없음 상태 캡처 검토
- 개발 DB 확인용 과정은 지움 -
2026년 09월 30일
-
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 진단 유형 N+1 수정 커밋(3039869a, 미배포)
상세 보기
## 확인
- `diagnosis_sessions` 는 이미 includes 로 불러 두고 있었다
- 남은 건 진단 기록 창(`_diagnosis_modal`)의 `session.diagnosis_type&.slug` — 유형마다 쿼리가 더 나감(테스트에서 17 → 19)## 변경
- `app/controllers/admin/users_controller.rb` `includes(:profile, :workspaces, diagnosis_sessions: :diagnosis_type)`
- `test/controllers/admin/users_controller_test.rb` 진단 유형이 늘어도 목록 쿼리 수가 그대로인지 확인## 참고
- 운영 diagnosis_sessions 23,250건, 사용자 17,529명. 한 쪽 50명이라 세션 전체를 불러도 부담 없음
- 다음 배포 때 함께 나간다 -
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 이미 적용돼 있어 닫음(@_answered_ids 메모)
상세 보기
2026-09-30 코드 대조
- `app/controllers/diagnosis_sessions_controller.rb:324` `@_answered_ids ||= @session.responses.pluck(:survey_question_id).to_set`
- 응답을 저장하는 액션마다 `@_answered_ids = nil` 로 비워 다시 읽는다(63 · 103 · 199 · 221 · 243행) -
Cclaude 이미 구현돼 있어 닫음(공개 응답 /engage/:access_token)
상세 보기
2026-09-30 코드 대조
- `app/controllers/engagement_survey_responses_controller.rb` + 테스트 있음
- 라우트 `scope "engage/:access_token"` 있음(config/routes.rb:1061)
- 응답 흐름은 패키지 시작(start_package) → BundleSessionManager 로 바뀌어 운영 중 -
Cclaude 이미 구현돼 있어 닫음(Workspaces::EngagementSurveysController + 테스트)
상세 보기
2026-09-30 코드 대조
- `app/controllers/workspaces/engagement_surveys_controller.rb`, `test/controllers/workspaces/engagement_surveys_controller_test.rb` 있음
- 라우트 `resources :engagement_surveys, controller: "workspaces/engagement_surveys"` 있음(config/routes.rb:959)
- 9/30 추이 계산 쿼리 정리(d674fbea)까지 반영 -
Cclaude 이미 구현돼 있어 닫음. SubmitResponseService 는 번들 방식으로 바뀌며 지움(205175fa)
상세 보기
2026-09-30 코드 대조
- `app/services/engagement_surveys/create_service.rb`, `result_aggregator.rb` + 테스트 있음
- 응답 저장은 `SubmitResponseService` 대신 `BundleSessionManager`(패키지 · 번들 응답)로 바뀌었고, 옛 서비스는 205175fa 에서 삭제
- 몰입도 v2 운영 중(2026-08-11~) -
Cclaude 이미 구현돼 있어 닫음(0b854c81 조직문화 진단 PR1~PR4)
상세 보기
2026-09-30 코드 대조
- `app/models/workspace_engagement_survey.rb`, `test/models/workspace_engagement_survey_test.rb` 있음
- DiagnosisSession `belongs_to :workspace_engagement_survey`, `:workspace_group` 있음
- Workspace `has_many :engagement_surveys` 있음
- 인덱스 [workspace_id, year, quarter] unique 있음
- 이후 몰입도 v2(2026-08-11 운영)로 이어짐 -
Cclaude 상태 변경: 리뷰 → 완료
-
Cclaude 상태 변경: 리뷰 → 완료
-
Cclaude 상태 변경: 리뷰 → 완료
-
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 설계 C 구현 완료(커밋 03560232, 미배포)
상세 보기
## 사전 확인(운영 방문 기록)
- 9/29~9/30 옛 경로 방문 15건 전부 봇, 로그인 사용자의 옛 경로 마지막 사용 9/22
- 강의 방문 20건은 새 주소(/ko/my-courses). 코치 19명은 전원 staff?(코치 17, 관리자 2)## 변경
- /courses/strength-coach-intro · /learn/courses/strength-coach-intro · 회차 주소: 권한 있으면 내 강의, 없거나 비로그인이면 판매 페이지(302). 로그인+미리 보기 회차는 내 강의
- 직원 예외 없음(코치가 전원 직원이라 예외를 두면 효과 없음)
- 판매 페이지 「미리 보기」 → my_course_lesson_path
- 이미 끝나 있던 것: /diagnoses/:id/basic_course 리다이렉트, 판매 페이지 「강의 이어서 보기」
- 일반 강의 화면 테스트는 이 강의를 복사한 강의로(test/support/study_generic_course.rb)## 검증
- 관련 테스트 1218개 통과, 로컬 3000에서 9WAY 쪽 옛 주소 → 판매 페이지 302 확인## 남은 것
- study/courses/show 의 online_strength 분기는 이제 도달 불가 → 따로 정리 -
Cclaude 추이 N+1 제거 완료(커밋 d674fbea, 미배포)
상세 보기
## 원인
- `@trends`는 이미 `ResultAggregator.bulk_for`로 한 번에 계산 중이었음
- 남은 N+1: 화면이 안 쓰는 `@trend`(6/8 대시보드 개편 뒤 미사용)를 분기마다 b2b 존재 확인 + 집계로 계산, `compute_available_categories`가 분기마다 `package_types` 조회## 변경
- `@trend` 계산 제거
- `compute_available_categories`는 미리 불러 둔 `engagement_survey_diagnosis_types`에서 읽음
- 테스트 `engagement_surveys_trend_queries_test.rb`: 분기 3개 추가해도 첫 화면 쿼리 수 동일(예전 37→43)## 검증
- 조직 진단 테스트 282개 통과
- 참고: `engagement_surveys_controller_test.rb` 564행은 UUID `.last`, 626행은 created_at `.last`라 가끔 무작위 실패(기존 문제) -
Cclaude-code 상태 변경: 할 일 → 완료
-
Cclaude-code 완료 확인 후 닫음 — 9/17~9/21 커밋으로 끝났는데 티켓만 열려 있었다
상세 보기
대표님 확인(2026-09-30 「27dna 개편했는데?」)과 커밋 기록으로 완료를 확인했다.
- 353f9d6f 27개 DNA 헤더·짧은 문구 교체 · f492b809 결과 캐시 버전 올림
- 239259df 욕구 칸 소제목마다 2줄 · 709a608a DNA 활용 안내 810건 중·베·일 번역 · 82d19355 성인 활용 안내 재번역
- 889b55d7 내 순위 해석 순위 지도 · 9983fd14 · 35fc51a8 내 순위 해석 네 언어
- a235a476 · e0ca4fad · 4352aa91 27DNA 활용 가이드 PDF(한 DNA 한 장, 리포트 판형)
- f9df9198 코치용 27 DNA 구분 가이드 part2 v3 맞춤 -
Cclaude 유형별 완료율 GROUP BY 전환 완료(커밋 1eb2a5a9, 미배포)
상세 보기
## 변경
- `Admin::StatisticsController#calculate_completion_rate_by_type`: 유형마다 COUNT 2번(7유형이면 14번) → 전체·완료 GROUP BY 2번
- 테스트 `test/controllers/admin/statistics_diagnoses_test.rb`: 숫자 동일 확인 + 유형별 COUNT 쿼리 0번## 검증
- 고치기 전 14번 → 고친 뒤 0번. 통계 테스트 37개 통과 -
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude-code 후속 운영 반영 확인(c61b2c40) — 강점 2개 이상 · 액션아이템 1~3개월 · AI 분석/코칭이 캔버스 참고 · 블로그/서비스 가이드 AI 400 수정
상세 보기
- 운영 c61b2c40(다른 세션이 배포하며 함께 나감): 154a14dd 블로그 이미지 초안 · 서비스 가이드 AI 생성 400 수정(chat_content) · 0c4f5f6d 강점 2개 이상 · 액션아이템 1~3개월 · ② 설명 ? · c61b2c40 AI 분석/코칭 캔버스 참고(ContextSummary)
- 운영 확인: chat_content 있음 · 실호출 정상, PICK_MIN 2, PROMPT_VERSION 5, CAREER_CANVAS_AI_MODEL claude-sonnet-5-5, ContextSummary 있음, /up · /ko 200
- 미배포: 66576ca0(다른 세션 워크스페이스 작업) — 그 세션 판단에 맡김 -
Cclaude-code 상태 변경: 진행 중 → 완료
-
Cclaude-code 커리어 캔버스 운영 배포(48cca715) — 브랜딩 문장 · 내 직무 · 목표 화면 · AI 붙여 넣을 글 · 제안 재료 지문 · Sonnet 5.5
상세 보기
## 배포
- 운영 a44abb24 → 48cca715 (kamal deploy 135초, 헬스체크 통과)
- 함께 나간 커밋 6개 모두 캔버스 작업: 7782b20d 브랜딩 문장 · fb6c2cff ?/초록 체크/+ 추가/내 직무(프로필) · 98306ba8 AI에 붙여 넣을 글 · 60019162 워크숍 표 열 이름 · 8081aef9 목표 화면(시간 흐름 막대 · 카드형 칸) · 48cca715 제안 재료 지문
- 마이그레이션 20260930160000(career_canvas_drafts.input_digest) — 운영 스키마 빈 DB로 먼저 돌려 확인 후 배포## 운영 확인
- schema_migrations 20260930100000~160000 적용, input_digest 칸 있음
- CAREER_CANVAS_AI_MODEL · STRENGTH_COACHING_AI_MODEL · 기본값 모두 claude-sonnet-5-5
- 운영 컨테이너에서 JSON 호출 실호출 성공(도구 강제 400 → auto 재시도)
- 9way.co.kr /up · /ko · /ko/pricing 200
- 전체 테스트 5,895개 중 1개 실패(분기 마지막 날 날짜 경계 CyclesTest, 무관)## 남은 것
- 캔버스 워크숍 보완은 보류 티켓(cf159469) -
Cclaude-code 커리어 캔버스를 결과 화면 탭 안에서 바로 쓰게 바꾸고, 입력 칸을 ? · AI · + 목록으로 정리(064b1966, 배포 전)
상세 보기
## 바꾼 것
- 결과 화면 「강점 개발 › 커리어 캔버스」 탭 안 turbo-frame(career_canvas)에서 바로 쓴다. 소개 카드 · 「이어 쓰기」 · 페이지 이동 없음. 캔버스 주소를 직접 열면 `?tab=canvas&canvas_step=N`으로 보낸다
- 칸 머리 [이름 · ? · ✓] …… [나중에 · AI]. 작성 방법은 ? 말풍선, AI 제안은 눌러야 펼치고 없으면 그 칸만 부탁
- ③ More · Change · Stop · Start, 액션아이템은 「+ 추가」 목록(plan.1~3 → plan.list)
- ④ 목표 3열 + 최소 높이 올림, 액션아이템 위 「내 목표」
- ① 강점 체크 → 「이 3개로 쓰기」 → 강점별 탭(✓) · 「다음: ○○」. 이런 순간 → 경험 → 표시한 문장 → 정의
- ② O · △ · X 설명을 목록 아래로
- AI 답이 한 겹 더 싸여 와도 읽게 고침(실호출에서 발견)## 확인
- 상태별 캡처(데스크톱 1280 · 폰 390): 오류 0, 가로 스크롤 0, 탭 안에서 주소 그대로
- 실호출: ③ 제안 27~40자 한 줄, 액션아이템 28~31자
- 테스트 170개 통과, rubocop 문제 없음, 점검용 개발 데이터 삭제 -
2026년 09월 29일
-
Cclaude 워크숍 모드(d827e4c8)와 대표님 방향 반영 5판(e6b72405) 커밋, 배포 전
상세 보기
## 워크숍 모드 (d827e4c8)
- career_canvas_workshops(차수 그룹·시각·마감·목표 기간 잠금·안내 한 줄·이직 말 안내·복사 머리말)
- 시스템 관리자 「캔버스 워크숍」: 만들기·고치기·진행 판(20초마다)·결과 CSV(3명 미만 줄 가림, 이름·글 없음)
- 전용 큐 스레드 10, 부하 시험 rake `career_canvas:load_test`## 5판 (e6b72405)
- ① 고른 DNA 하나씩 편집 칸 + 표시 문장·메모 + 오른쪽 목록
- ② 강점·의미·성과 O△X
- ③ 일마다 규칙 피드백 → More·Change·Stop·Start
- ④ 네 방향(모든 캔버스) → 10·3·1년·액션아이템 탭(✓)## 확인
- 관련 테스트 30개 통과, 전체 5,883개 중 날짜 경계 2개만 실패(새벽, 무관)
- 개발 서버 실호출·PC/폰 화면 확인, 확인용 데이터 삭제(다른 계정 캔버스 1건은 그대로)## 남은 것
- 배포, 실행(implementation) 역할 방향, ③ 초안 20초대 -
Cclaude 0·1단계 구현 커밋(6384ecc3): 「강점 개발」 탭 + 커리어 캔버스 4장, 미배포
상세 보기
## 한 것
- 결과 화면 챌린지·강의 탭 → 「강점 개발」 탭 하나(하위 탭: 커리어 캔버스·30일 챌린지·진로 설계 강의). ?tab=challenge·basic-course 유지
- 사이드바 「내 강의」 → 「강의실」
- career_canvases · career_canvas_drafts 테이블, 화면 4장, 자동 저장, AI 초안(전용 큐 career_canvas), 한 장·복사
- canvas 복수형 inflection 추가(개발 서버 재시작 필요했음)## 확인
- 새 테스트 17개 + 고친 탭 테스트, 관련 841개 통과. 전체 5,870개 중 2개 실패는 날짜 경계 테스트(새벽 0~9시, 캔버스와 무관)
- 개발 서버 실호출: 초안 묶음당 6~15초, 폰·PC 화면 확인 후 확인용 캔버스 삭제## 남은 것
- 배포(대표님 확인 후), 2단계 워크숍 모드 -
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude-code 수강 중이면 강의 탭을 누르는 즉시 내 강의로 이동(21df815b, 커밋만·미배포)
상세 보기
- 결과 화면 강의 탭: 수강 중이면 버튼이 아니라 `my_course_path` 링크로 그림(모양 동일), 패널 없음
- `?tab=basic-course`로 들어오면 내 강의로 리다이렉트
- `_continue` 파셜 삭제
- 전체 테스트 5792개 통과, 로컬 PC·폰에서 클릭 이동 확인
- 배포 보류: main에 다른 세션 워크스페이스 커밋 5개(마이그레이션 3개)가 운영 미반영 상태라 대표님 확인 필요 -
Cclaude-code 상태 변경: 할 일 → 완료
-
Cclaude-code 프로덕션 배포 완료(b3aac968), 렌더·경로 확인
상세 보기
- 프로덕션 이미지 `b3aac968` 확인(배포 전 23f4dfaf에서 이 커밋만 나감)
- 옛 `/ko/diagnoses/:id/basic_course` → 301 `/ko/my-courses/strength-coach-intro`
- 프로덕션 runner(읽기 전용)로 강의실·결과 탭 버튼 렌더 확인, 9WAY 계정 메뉴 노출 true
- 「내 강의」 메뉴가 보이는 사람 24명
- 배포 후 로그 500 0건
- 설계 문서에 목록 없음 결정 반영(6a96b478, 문서만)
- 남은 C는 티켓 a5f6abeb -
Cclaude-code 내 강의 메뉴 구현·테스트 통과·커밋(b3aac968), 배포 진행 중
상세 보기
## 바꾼 것
- `MyCoursesController`·`MyCourseLessonsController` 새로 만들고 `strengths/basic_courses`·`basic_lessons` 컨트롤러·뷰를 옮김
- 경로 `/:locale/my-courses/:slug`(+ lessons/:id, progress, beacon). 옛 `/diagnoses/:id/basic_course`는 301
- 사이드바 「내 강의」(`my_course_for_nav`, 볼 수 있을 때만). 5개 언어 메뉴 이름 추가
- 결과 탭: 수강 중이면 `diagnoses/course/_continue`(이어보기 버튼), 만료면 `my_courses/_expired`, 권한 없으면 기존 소개
- 다음 단계 카드·구매 완료·강의 단독 구매 화면의 강의 링크를 내 강의로## 검증
- 관련 테스트 35개 통과, 전체 5771개 중 실패 1건(옛 링크 기대 테스트) → 고친 뒤 통과
- 로컬 3000에서 PC·폰 캡처로 결과 탭 버튼·강의실·회차 재생·옛 주소 이동 확인
- 개발 DB 건수 테스트 전후 동일, 확인용 수강권은 지움 -
Cclaude 색인 전달 점검 + llms.txt 보강 배포(88495e2c) + 네이버 IndexNow 직접 제출
상세 보기
## 점검
- robots.txt 두 사이트 모두 /solutions 허용, 봇 9종(구글·네이버·Bing·Daum·GPT·OAI·ChatGPT-User·Claude·Perplexity) 전부 200
- noindex 없음, canonical 자기 주소, lang ko, og, 본문 서버 렌더링(3천 자대), 사이트맵 포함
- 구글 서치콘솔 DNS 소유 확인(두 도메인), 네이버 서치어드바이저 등록
- 오늘 봇 방문(proxy logs): Yandex가 IndexNow 뒤 /solutions/* 수집(공유 동작 확인), Claude·GPT는 사이트맵, Yeti는 0회## 조치
- llms.txt에 서비스 소개 4장·프로그램 상세 5장 추가 → 배포 88495e2c (다른 커밋 없음)
- 네이버 전용 IndexNow(searchadvisor.naver.com/indexnow) 11건 직접 제출 → 200## 남은 것
- 구글 서치콘솔 URL 검사 → 색인 생성 요청(다니엘 계정) 4개 소개 페이지 -
Cclaude 상태 변경: 진행 중 → 완료
-
Cclaude 2·3단계 운영 배포 완료 — 소개 페이지 4장·두 사이트 메뉴·버튼 모양, IndexNow 제출
상세 보기
## 배포
- 운영 버전 eab6edb4 (제 커밋 a6486b24·0b8bc965·220a70c4·efee426b + 다른 세션 OKR 수정 eab6edb4가 사이에 커밋되어 함께 나감)
- 배포 전 전체 테스트 5,736개 통과(다른 세션 변경은 커밋 전 작업 트리로 포함된 상태에서 통과)## 운영 확인 (GPTBot UA)
- /solutions/strength · team-strength · engagement · performance 200, 질문 h3 4 = FAQPage 4
- 9way.co.kr 상단: 인사이트 · 서비스 소개(6항목) · 가격 안내 · 강점 진단 · 로그인(버튼), 폰 하단 「무료 강점 진단 시작」
- 인사이트 상단 서비스 소개: 4개 서비스 + /programs (강점 전문가 과정 없음)
- 사이트맵에 4개 주소, 이미지 200## IndexNow
- index_now:static 26건 → futuretalent.co.kr 200 OK
- verify_key는 컨테이너 안에서 자기 도메인으로 못 나가 시간 초과(바깥 curl로 키 파일 200 확인) -
Cclaude 강점 진단 개인 중심 재구성 + 팀 강점 분석 페이지 분리(0b8bc965, 미배포)
상세 보기
## 다니엘 피드백 반영
- /solutions/strength: 개인 진단부터(3영역·9역할·27DNA, 실제 결과 화면 5장, 개인 리포트 6쪽 A4 나란히·PDF 해당 쪽 링크), 팀은 짧게 보여 주고 팀 강점 분석으로
- /solutions/team-strength 신설: 팀 화면 4장(팀역할 매트릭스는 9/28 이후 현재 화면으로 재촬영) + 팀 리포트 6쪽
- 메뉴: 강점 진단·팀 강점 분석·몰입도 관리·성과 관리. 인사이트에서만 강점 전문가 과정 제외(9WAY 상단엔 유지)## 개발 DB
- 샘플 계정(정하늘·강민준) 로그인으로 생긴 세션 삭제, 언어 ko 복구## 검증
- 전체 5,736개 통과, rubocop 통과, PC·폰 캡처 확인 -
Cclaude 2·3단계 소개 페이지 3장 + 서비스 소개 메뉴 커밋(a6486b24, 미배포) — 로컬 확인 대기
상세 보기
## 변경 사항
- `app/models/learn/solution.rb` + `learn/pages#solution` + `/solutions/:slug` (인사이트·/learn 두 경로)
- `public/images/solutions/*.webp` 11장: 로컬 데모 조직(샘플 계정 강민준·신유진)으로 캡처. 캡처 뒤 세션 3개 삭제·언어 ko 복구
- 9WAY 상단(ko): 기업·기관 → 서비스 소개 드롭다운(dropdown 컨트롤러, PC 호버·폰 탭), 주소는 문자열(/pay 사고 방지)
- 인사이트 상단: 프로그램 소개 → 서비스 소개 드롭다운, 휴대폰 하위 메뉴 줄
- 사이트맵·IndexNow 정적 목록에 세 주소## 검증
- 새 테스트 `solution_pages_test.rb`, `pages_controller_test.rb` 메뉴 순서·링크 갱신
- 전체 5,735개 통과, rubocop 통과
- 로컬 캡처로 PC·휴대폰 드롭다운 확인## 남은 것
- 다니엘 로컬 확인 → 배포 → GPTBot 확인 → IndexNow static 통보 -
Cclaude 1단계 운영 배포 완료(9bf3b725) — GPTBot으로 7곳 확인
상세 보기
## 확인 (GPTBot UA, https://futuretalent.co.kr)
- /programs h3 3 = FAQPage 3
- /programs/team-building 4 = 4 · engagement 4 = 4 · leadership 4 = 4 · career-development 3 = 3 · coaching-feedback 3 = 3
- /workshops/coach FAQ h3 6 = FAQPage 6, 첫 답에 「오프라인 1일」 있음 · 「위쪽」·「20강」 없음
- 운영 버전 9bf3b7251dc864e3b5c632650f129169459e7b74## 다음
- 2단계 소개 페이지 3장(/solutions/*) 로컬 제작 → 확인 받은 뒤 3단계 메뉴와 함께 배포 -
Cclaude 1단계 회사 페이지 7곳 FAQ 커밋(9bf3b725)·배포 시작
상세 보기
## 변경 사항
- `app/models/learn/program.rb`: 프로그램별 진행 방식 표(facts)·FAQ(faqs), 허브 FAQ(HUB_FAQS)
- `app/views/learn/pages/_faq.html.erb`: 인사이트 FAQ 모양 재사용, 질문 h3, FAQPage JSON-LD
- `app/helpers/seo_helper.rb#faq_page_json_ld`: 화면과 같은 목록에서 구조화 데이터
- `/workshops/coach`: 새 질문 2개 + 전체 FAQPage (「이 페이지 위쪽」은 JSON-LD에서만 제외)
- 요청 문구 교정 6곳(입문 오프라인 1일, 현장 진단 기본, 리더십 팀원 사전 진단, 몰입·강점 한 화면 표현 삭제, 리더십 예시 실제 결과 문장, 위쪽 문구)## 검증
- 새 테스트 `test/integration/company_page_faqs_test.rb` + 전체 5,726개 통과
- 로컬 3000 캡처로 PC·휴대폰 확인 -
Cclaude 상태 변경: 할 일 → 진행 중
-
2026년 09월 27일
-
Cclaude 상태 변경: 리뷰 → 완료14:23 워크스페이스 개선 0단계: 바로 고칠 것
-
Cclaude 운영 배포 완료(6c51e008) · 성과 관리 · 팀원 관리 첫 배포, 새 메뉴 기본 꺼짐 · 강점 코칭 이름14:23 워크스페이스 개선 0단계: 바로 고칠 것
상세 보기
## 배포
- 운영 83f94c89 → 6c51e008 (커밋 70개, 마이그레이션 8개)
- 1차 배포 실패: 20260926100000 마이그레이션이 confirmed_at 칸을 만들기 전에 UPDATE → 새 컨테이너 헬스체크 실패, 이전 버전 유지(방문자 영향 없음). 운영 DB엔 CreateOkrTables만 적용된 상태였음
- 수정 후 운영과 같은 옛 스키마(83f94c89)로 빈 DB를 만들어 남은 8개를 순서대로 돌려 검증 → 2차 배포 성공## 확인
- 마이그레이션 8개 모두 적용, 새 메뉴 기본값 performance=[] team_members=[], 운영 워크스페이스 214개 중 새 메뉴 켜진 곳 0
- /up · / · /ko · /ko/pricing · /session/new 200, 배포 후 5분 로그에 5xx 없음
- 사이드바 이름 「강점 코칭」 -
Cclaude 상태 변경: 진행 중 → 리뷰12:59 워크스페이스 개선 0단계: 바로 고칠 것
-
Cclaude 0단계 6개 항목 구현 · 전체 테스트 5,680개 통과 · 커밋 5개(미배포)12:59 워크스페이스 개선 0단계: 바로 고칠 것
상세 보기
## 커밋
- fe38e936 다음 분기 KR·TASK 집계(Okr::Cycle.live_for) + 팀원 「TASK로 만들기」, 「대화에 담기」 그 자리에서 더하기(team_notes Stimulus)
- 2a1c931d 고른 주기 쿠키 유지, 주기 없어도 관리자 「주기 관리」, 분기 마감은 보던 주기
- 8e286214 남은 할 일 팀원·팀장 몫 나눠 세기, 오늘 끝낸 할 일 되돌리기, 머리글 다음 대화, 저장 뒤 스크롤 유지(turbo morph)
- 30ce6633 주기 시작 전 체크인은 막힘·체감 신호에서 제외, 첫 주는 「이번 주 막혀 있습니다」
- 8f074b9a 문구 묶음: 질문 개수, 상대 이름, 선택 배너 이름, 「15건으로」 조사(ko_ro), 역할 칩 알림에 누구·무엇, 사이드바 역할 한국어## 확인
- 전체 테스트 5680 runs 0 failures
- 데모 조직에서 브라우저로 담기(주제·질문 유지), 사이드바 역할, 선택 배너 이름 확인 -
Cclaude 상태 변경: 할 일 → 진행 중12:46 워크스페이스 개선 0단계: 바로 고칠 것
-
2026년 09월 26일
-
Cclaude-code 성과 관리 다듬기(같이 쓰기·TASK 진척·날씨·일괄 콕 찌르기·목록/카드 연결 보기·TASK 고치기) + 팀원 관리 1차(a20eb08c). 미배포.07:04 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 성과 관리 추가(2026-09-26)
- 같이 쓰기: 초안 → 팀장 확정, 확정 뒤 수정 제안, 팀원이 TASK 바로 넣기
- TASK 진척(%), 체감 맑음·흐림·비, 점검 전 표시·일괄 콕 찌르기
- 조직 전체 연결: 목록(나무)·카드(연결 지도), 독립 KR 빨간 테두리
- TASK 고치기(제목·담당·마감일)## 팀원 관리 1차
- 메뉴 team_members(관리자·팀장), 팀원 목록(먼저 볼 사람부터)
- 상세 탭: 대화(7가지 주제·5칸·⑤ 적어야 끝남·합의 할 일→TASK) / 성과 / 역할기술서(+혼자 정해도 되는 범위)
- 질문 셋 전날 저녁 6시 메일, 팀원 본인은 성과 관리 화면에서 다음 대화·할 일 확인## 남은 것
- 팀원 관리 2차: 몰입 탭, 피드백 5단계, 대화 주제 자동 제안
- 분기 마감·CSV·바로 알림, UI 맞추기, 배포 -
2026년 09월 25일
-
Cclaude-code 상태 변경: 진행 중 → 리뷰14:22 성과 관리(OKRT) 1단계 — 뼈대 구현
-
Cclaude-code 1단계(성과 관리 뼈대) 완료 — 1e 주간 점검(4ec4a542), 1f 월요일 알림·콕 찌르기(6ee05a67). 관련 테스트 296개 통과. 미배포.14:22 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 1e 주간 점검
- 책임 KR마다 값+체감, 맡은 TASK 상태, 막힌 것 하나를 한 번에 저장(휴대폰은 세 걸음)
- 이번 주 화면 위 「이번 주 점검이 아직입니다」 카드## 1f 알림
- 월요일 8시 한 통(recurring okr_monday_digest): 점검 안내, 상속 원본 숫자 변경, 위 조직 새 KR, 남이 접은 TASK
- 콕 찌르기: 관리자·그 조직 팀장, 주 1회, 보낸 사람 비공개
- 알림톡은 기본 꺼짐 — NCP에 okrWeeklyV1·okrNudgeV1 템플릿 검수 후 OKR_ALIMTALK=on## 남은 것
- 배포(프로덕션 SHA 대조 후 kamal deploy) — 사용자 확인 필요
- 2단계 팀원 관리 1차부터 -
Cclaude-code 1d KR 상세 패널과 창 다섯 개 커밋 (4d802bd9). 관련 테스트 234개 통과, 브라우저로 체크인·접기·삭제 흐름 확인14:10 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 변경
- KR 상세: 오른쪽 패널(turbo-frame) + 전체 보기, 탭 넷(개요·TASK·이력·연결)
- 창: 체크인 / TASK 접기(이유 필수) / 진척 계산 바꾸기(전후 %와 영향) / 위 KR에 걸기 / KR 삭제(관리자만, 확인 체크)
- 변화의 첫 신호: 숫자 두 주 이상 그대로, 체감 두 주 연속 어렵다, 같은 막힌 것 계속
- 공개 범위 Okr::Visibility로 통합
- 성과 관리 하위 화면에서 사이드바·하단 탭 활성 표시## 다음
- 1e 팀원 주간 점검(책임 KR마다 숫자+체감, TASK 상태, 막힌 것)
- 1f 월요일 알림(+ 콕 찌르기) -
Cclaude-code 1c 정렬 만들기 + 빈 첫 화면 커밋 (27a224e7). 새 테스트 19개 통과, 브라우저로 5단계를 끝까지 돌려 확인13:57 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 변경
- 빈 첫 화면: 위 조직이 KR을 정했나 → 정했음 / 아직 / 맨 위 세 갈래 (팀원에게는 안내만)
- 정렬 만들기 5단계: ① 위 KR 고르기 ② O ③ KR 상속·연결 ④ TASK(담당 여럿) ⑤ KR 책임자(한 명 권장)
- 경고는 막지 않고 안내만: 위 KR 셋 초과, O에 숫자, 위 KR 그대로 옮김, KR 다섯 초과, 공동 책임, 한 사람 셋 초과, 책임자 없음
- Okr::AlignmentForm으로 한 번에 저장(트랜잭션), 분기가 없으면 저장할 때 만듦
- 권한 OkrAccess: 관리자는 어느 조직이든, 팀장은 자기 조직과 그 아래
- 이번 주 화면: + O 추가 버튼, KR 줄 진척 막대 줄바꿈 버그 수정(휴대폰은 둘째 줄)## 확인
- 개발 서버에서 데스크톱·휴대폰 너비로 전체 흐름을 스크린샷 확인, JS 오류 0
- 확인용으로 만든 개발 DB 데이터는 지움(개발 DB 건수 전후 동일)
- engagement_surveys 테스트 간헐 실패 1회는 기존 `order(:created_at).last` 문제(이번 변경과 무관, 재실행 통과)## 다음
- 1d KR 상세 패널 + 체크인 창 -
Cclaude-code 1b 메뉴·권한·「이번 주」 화면 커밋 (4486c526) — 테스트 42개 + 영향 범위 137개 통과13:38 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 변경
- 권한 키 `performance`(admin·leader·member) + MENU_FEATURES → 설정·관리자 권한 표에 노출
- 사이드바(팀 강점 다음), 폰 하단 탭(대시보드 다음, 1:1 코칭은 맨 뒤)
- `Workspaces::PerformanceController#show`, `Okr::WeekBoard`, `OkrHelper`
- 화면: O → KR → TASK(책임자 깃발·공동, TASK 담당 여럿, 진척+지금쯤 눈금) + 팀원 목록(먼저 볼 사람 순)
- `okr_week_controller.js`: 사람 선택 시 KR·TASK 강조/흐림, 팀원 줄 펼침, 「볼 것만」에서 정상 KR 접기
- 공개 범위: O·KR·TASK 전체 공개, 체감·막힌 것은 본인과 그 조직 직속 팀장·관리자만
- 문구 5개 언어(config/locales/okr/*)## 덤으로 고친 버그
- en/zh/vi/ja 설정 권한 표에 coaching 라벨 누락 → 영어 화면에도 「1:1 코칭」이 한국어로 나오던 것## 다음
- 1c 정렬 만들기(5단계) + 빈 첫 화면 -
Cclaude-code 1a 데이터 모델 커밋 (89f9efe6) — okr_ 테이블 10개, 모델 테스트 31개 통과13:30 성과 관리(OKRT) 1단계 — 뼈대 구현
상세 보기
## 변경
- `db/migrate/20260925133000_create_okr_tables.rb` — cycles, objectives, key_results, key_result_owners, alignments, milestones, tasks, task_assignees, checkins, change_logs
- `app/models/okr/*` — 진척(측정 방식 6종·자동 평균·직접 측정·상속), 상태(정상·주의·위험·달성), 연결/상속 고리 방지, TASK 접기(이유 필수), 체크인 → KR 숫자 반영(상속이면 원본)
- `app/services/okr/guardrails.rb` — O당 KR 5개, 1인 책임 3개 초과, 공동 책임 경고
- `config/locales/okr/{ko,en,zh,vi,ja}.yml`
- Workspace/WorkspaceMember/WorkspaceGroup 연관 추가(멤버 삭제 시 정리, 조직 삭제 시 O는 보존)## 검증
- test/models/okr 31개 통과, 기존 워크스페이스 테스트 46개 통과
- 개발 DB 건수 전후 동일(11073·159·4580)
- 테스트가 잡은 버그: 새 KR id=nil 비교로 모든 상속을 고리로 막던 문제 수정 -
Cclaude-code 상태 변경: 할 일 → 진행 중13:24 성과 관리(OKRT) 1단계 — 뼈대 구현
-
2026년 09월 21일
-
Cclaude-code 내 순위 해석 보강(순위 지도 + 88칸 세 문단) · 27DNA 가이드 PDF 리포트 양식 적용 완료 (889b55d7 배포)
상세 보기
## 화면 (배포 889b55d7)
- `_rank_insight.html.erb` 신규: 구간별 27개 DNA 칩(영역 색), 주로 쓰는 DNA의 영역 막대, 같은 역할 2개 이상 묶음 — ResultPresenter#rank_overview 로 계산(캐시 밖이라 즉시 반영)
- RankInsight에 영역 카드(rank_domain: thinking/relationship/execution/balanced) 추가 → 카드가 최대 4장
- 해석 카드가 없어도 순위 지도는 보이게, 구간 버튼 옆 '내 순위 해석' 노출 조건 변경## 문안 (DB 적용)
- rank_* 88칸: 기존 84칸을 세 문단(무엇이 보이는지 / 잘 풀리는 장면·걸리는 장면 / 이번 주 행동·신호) 380~600자로 교체 + 영역 카드 4칸 신규. 평균 421자
- 백업 `docs/plans/dna-description-review/backups/2026-09-21-v15-rank-short.json`, dev 동기화
- CopyLint rank_* 상한 230→600, rank_domain 추가## 가이드 PDF
- `strengths/dna_guides/show.html.erb` 전면 교체: 인라인 스타일 제거, 리포트 토큰(.section-header/.detail-box/.dna-header) 사용, 표지·구간 요약·DNA당 새 장
- 컨트롤러: 리포트와 같은 여백 + Chromium 푸터 쪽번호## 검증
- 운영 구매 세션 60건: 카드 4장 21건·3장 33건·2장 6건, 한 사람당 1,600~1,900자
- 실제 FULL 세션에서 순위 지도 데이터 확인(구간 6/5/16, 영역 사고1·관계0·행동5, 역할 추진 3개)
- 테스트 254건 통과 -
2026년 09월 18일
-
Cclaude-code 내 순위 해석 84칸 신규 작성·프로덕션 적용 완료 (버튼이 처음으로 노출됨)
상세 보기
## 적용
- rank_focus 18 · rank_tension 12 · rank_split 54 = 84행 신규 생성(ko, target_slug nil). 기존 행 없음 확인 후 create, dev 동기화
- 원고 `tmp/dna_copy/v15/all.json`, 지시문·점검 `docs/plans/dna-description-review/v15-rank/`
- 페이지: https://claude.ai/artifact/WtDxETSaLNm7qtVKD32s7b## 검증
- 최근 구매 세션 80건 기준 카드 장수 분포: 3장 27건 · 2장 41건 · 12건 1장 (0장 없음)
- 실제 조합 예: exploration_2 + intuition__effectiveness + intuition__creativity## 남은 것
- en·zh·vi·ja 재번역 (한국어 확정본 기준, 약 2,400칸 × 4언어) -
Cclaude-code 요약 탭·중위/하위 카드·강점 조합·역할×DNA 1,917칸 프로덕션 적용 + 코드 배포(4e409b37) 완료
상세 보기
## DB 적용
- StrengthDescription ko 1,917건 (요약 270 · 중위/하위 810 · 조합 702 · 역할×DNA 135)
- SHA 대조 → dry run(오류 0) → 적용(오류 0) → 검증 1,917/1,917 일치, dev 동기화 완료
- 백업: `docs/plans/dna-description-review/backups/2026-09-18-v10-v13.json`## 배포 4e409b37
- 요약 탭 칸 제목 10개, 영역 3·역할 9 소개 문구(ko.yml)
- 역할 탭 형광펜 복원을 DNA 탭 방식으로(문장 재탐색 + 자리 잃은 형광펜 목록), 레이아웃 테스트 추가
- CopyLint: 요약 330자·역할×DNA 1,600자 + 테스트
- 결과 캐시 v13→v15, v14→v16 (코드 문구 교체 반영)
- 운영 이미지 = 4e409b37 확인, I18n·DB 실값 확인## 진행 중
- 내 순위 해석 84칸(쏠림 18·대비 12·갈림 54) 작성 시작 — 지금은 문안이 0건이라 버튼 자체가 안 보임
- 그다음: en·zh·vi·ja 재번역 -
2026년 09월 17일
-
Cclaude-code 한국어 초안 4단계 완료: 요약 탭 270 · 중위/하위 카드 810 · 강점 조합 702 · 역할×DNA 135 + 영역/역할 소개 16 (전부 점검 0건, 승인 대기)
상세 보기
## 초안·비교 페이지
- 요약 탭 270: `tmp/dna_copy/v10/all.json` — https://claude.ai/artifact/SyUKsUrNKeHN9xWhkShsjx
- 중위·하위 카드 810: `tmp/dna_copy/v11/all.json` — https://claude.ai/artifact/KxaC89h2A2tzeW9JWf8Utm
- 강점 조합 702: `tmp/dna_copy/v12/all.json` — https://claude.ai/artifact/3P4AHVgJbtuVMUkqcx34ER
- 역할×DNA 135 + 영역·역할 소개 16(i18n): `tmp/dna_copy/v13/all.json`, `v13/i18n.json` — https://claude.ai/artifact/VHJN8aGSNnaaQ6avMLfa1M## 작성 중 추가한 규칙
- 성인·리더 고객·거래처·영업·매출·민원 장면 금지(일부 직무만 해당)
- DNA 이름을 주어로 움직이게 쓰지 않기(강점 조합 초안 대부분이 해당 → 전면 수정, 점검 규칙화, 메모리 기록)## 미커밋 코드 변경 (적용 시 함께 배포)
- `app/services/strengths/copy_lint.rb`: SUMMARY_MAX 330, WAY_COMBO_MAX 1600 + 테스트
- `app/javascript/controllers/way_annotate_controller.js`: DNA 탭과 같은 형광펜 복원(문장 텍스트 재탐색·자리 잃은 형광펜 목록) — 운영 역할 형광펜 622개 보호
- `app/views/diagnoses/_tab_way.html.erb`: orphans 자리 + 레이아웃 테스트
- 예정: ko.yml 요약 탭 칸 제목 10개, 영역 3·역할 9 소개 문구## 다음
- 승인 후 SHA 대조 적용 + 배포, 한국어 확정 후 en/zh/vi/ja 재번역 -
Cclaude-code 요약 탭 270칸·중위/하위 카드 810칸 초안 완료(점검 0건), 강점 조합 702칸 작성 중
상세 보기
## 요약 탭 (v10)
- 10칸 × 27 DNA = 270, 원고 `tmp/dna_copy/v10/all.json`, 지시문·점검 `docs/plans/dna-description-review/v10-summary/`
- 전공은 계열 2~3개, 자소서는 경험 찾는 질문 2개, 성인·리더는 일 장면(고객·거래처·영업 장면 14칸 추가 수정)
- 칸 제목 정리 제안(ko.yml, 적용 시 배포 필요)
- 비교 페이지: https://claude.ai/artifact/SyUKsUrNKeHN9xWhkShsjx## 중위·하위 카드 (v11)
- 6칸 × 27 × 5대상 = 810, 원고 `tmp/dna_copy/v11/all.json`, 지시문·점검 `docs/plans/dna-description-review/v11-usage/`
- 두 문단(사례+반복 설명, 해요체·~해보세요) → 한 문단 합니다체, 247,759자 → 111,463자
- 특수 장면(줄넘기·아르바이트 후임 등) 직접 교체
- 비교 페이지: https://claude.ai/artifact/KxaC89h2A2tzeW9JWf8Utm## 강점 조합 (v12)
- 702칸, 역할별 9묶음 작성 중. 지시문·점검 `docs/plans/dna-description-review/v12-combination/`## 다음
- 역할(WAY) 설명 27 + 역할-DNA 조합 135(평균 2,233자·9소제목) 구조 확인
- 승인 후 SHA 대조 적용, 한국어 확정 후 4개 언어 -
Cclaude-code 대상별 강점 활용·개발 270칸 + 공통 목표지향 발현 1칸 프로덕션 적용 완료
상세 보기
## 적용
- 프로덕션 StrengthDescription ko 271건 갱신 (use/development 5대상 × 27 × 2 = 270, goal_driven positive 1)
- 기존 내용 SHA256 대조 → dry run(오류 0) → 트랜잭션 적용(오류 0)
- 백업: `docs/plans/dna-description-review/backups/2026-09-17-v9-target.json` (적용 전 271건)
- 검증: 운영 DB 271건 원고와 일치, 최근 성인 세션 ResultFormatter 출력에 새 성인 문구 54칸 모두 포함
- 결과 캐시 키(v13/v14)에 StrengthDescription updated_at 포함 → 코드 배포·캐시 버전 올림 불필요
- dev DB 동기화 271건## 최종 원고 기준
- 성인·리더 = 직장인. 보고서·결재·기획안·협업 장면 유지, 엑셀·피벗·PPT 등 특정 도구 이름 제거, 특수 직군 장면 제거
- 대학생: 동아리·대외활동·MT·축제 부스·공모전·룸메이트·중고 거래 제거
- 공통 목표지향 발현: “석 달 안에 10km 완주” → “일주일에 세 번, 30분씩 걷기” -
Cclaude-code 대상별 강점 활용·개발 270칸 3차 수정 완료 — 특수 장면 제거, 비교 페이지 갱신(적용 승인 대기)
상세 보기
## 변경 사항
- 성인·리더: 주방·현장·연구소·공연·매장 등 특수 직군 장면 → 회의·보고·메일·인수인계 같은 사무실 일로 전면 교체 (check.py SPECIAL_JOB 0건)
- 대학생: 동아리 13칸·대외활동·행사 스태프·MT·축제 부스·공모전 → 수업·조별 과제·도서관·생활비·중고 거래·친구 모임 등 보편 장면 (동아리 0칸)
- 성인 외향성 활용: 업계 행사 → 다른 팀과 첫 회의
- 원고 `tmp/dna_copy/v9/all.json` (270칸), check.py 5대상 0건, CopyLint 위반 0건
- 비교 페이지 재게시: https://claude.ai/artifact/EaLdf6w1iTNLL7PYmtFPCX## 다음
- 다니엘 승인 후 프로덕션 use/development 270칸 SHA 대조 적용 + 백업, dev DB 동기화 -
CClaude Code 27 DNA 공통 설명 새 버전 운영 반영 완료 (헤더·짧은 문구 54 배포 + DB 108칸)
상세 보기
## 반영
- 커밋 353f9d6f 배포(운영 이미지 확인, 9way.co.kr 200). 함께 나간 다른 세션 커밋: 8c892b2b(챌린지 알림 수정), 90b21556(문서)
- `config/locales/dna/ko.yml` 헤더(description)·짧은 문구(short) 27×2
- 문안 점검에 번역투 목록(TRANSLATIONESE) 추가 + 테스트
- 운영 DB StrengthDescription ko 공통(정의·강점 발현·욕구·약점 발현) 108칸: SHA 대조 적용, 108/108 일치 확인, 백업 `docs/plans/dna-description-review/backups/2026-09-17-v8-common.json`
- 개발 DB도 동기화## 과정
- 페르소나 11명 2회 읽기(v6-read, v7-read) → 반복 틀·헤더 중복·장면 편중 수정
- 원고: `tmp/dna_copy/v8/all.json`## 남은 일
- 대상별 강점 활용·개발, 중·하위 카드, 요약 탭, 조합, 순위 카드
- en/zh/vi/ja 재번역(현재 옛 문구)
- 하이라이트 재배치 영향 측정 -
CClaude Code 27 DNA 공통 칸 162개 새 버전 작성 완료 · 비교 페이지 공유(운영 미반영)
상세 보기
## 작업
- 승인된 논리성 v5 방식으로 27 DNA × (헤더·짧은 문구·정의·강점 발현·욕구·약점 발현) = 162칸을 API 없이 세션에서 직접 작성
- 파일: `tmp/dna_copy/v6/{ideation,exploration,evaluation,connect,coordination,activation,implementation,drive,finish}.json`, 합본 `tmp/dna_copy/v6/all.json`
- `strengths:lint_copy` 162건 위반 0건
- 문항 국면(FACETS.md)과 어긋나는 문장, DNA끼리 겹치는 장면·표현(4어절 n-gram 교차 점검)을 고침
- 비교 페이지: https://claude.ai/artifact/Lg5fRrjkG323i4w3JhCycj (DNA별 지금 vs 새 버전 + 형광펜 5명 이상 문장)## 다음
- 다니엘 검토 → 수정 반영 → SHA 대조 적용(DB 108칸 + ko.yml 헤더/짧은 문구 54) → 배포
- 운영 미반영 상태 -
Cclaude 다니엘 피드백으로 단계 3 반영 중단·헤더 배포 되돌림 — 정의의 이웃 DNA 비교, 강점 개발 '조절' 방향이 잘못됨
상세 보기
## 피드백 (2026-09-17)
- 강점 개발은 "더 키우기"가 맞다. 조절·주의는 약점 발현, 필요할 때 쓰는/보완할 DNA 카드의 몫
- 정의에서 다른 DNA와 경계·비교하는 것은 의미 없다 — 독자는 27개 DNA를 모른다
- 국면은 쉽게 설명하기 위한 바탕이지 국면을 설명하는 글이 아니다. 첫 독자에게 "나한테 어떤 의미·가치"가 전해져야 한다## 조치
- 운영 DB 공통 칸 108건 반영 **중단**(시험 반영까지만, 운영 변경 없음 확인)
- 헤더·짧은 문구 배포(010e0fe1) → 되돌림 커밋 7217645c 배포, 운영 원래 헤더 복구 확인
- WRITING_GUIDE: 첫 독자 관점 규칙 추가, 정의 ③을 "나에게 주는 의미"로, 강점 개발을 더 키우기로, 볼륨 조절 규칙 폐기
- 린트: 다른 DNA 이름·비교 문장 금지 규칙(:other_dna), 조합·순위 해석 카드는 예외 — 멈춘 원고에서 63건 검출
- 메모리: feedback_dna_copy_customer_first## 원인
- 코치·페르소나 테스트에 "헷갈리는 DNA 쌍" 질문을 넣어 내부자 관점의 경계 문장을 부추김
- 완벽주의 페르소나 1명의 반응을 강점 개발 칸 전체 방향으로 일반화## 다음
- 고친 방향의 샘플을 다니엘에게 먼저 확인받은 뒤 27개 재작성 -
Cclaude 단계 2 파일럿 통과 — 새 설명 33/33 선호, 나를 이해 3.88·인사이트 3.73(기준 3.5·3.2), 순위 해석 카드 22/26 "그래서 그랬구나"
상세 보기
## 파일럿 원고 (Claude Code 서브에이전트 작성, API 키 미사용, 린트 위반 0)
- 논리성·친밀감·집요함 × 20칸(공통 4 + 성인·청소년 대상별 16) = 60
- 내 순위 해석 카드 21종## 블라인드 재테스트 (페르소나 11명: 기존 9 + 데이터 분석가·극작 리더)
| | 읽기 | 나를 이해 | 인사이트 | 실천 |
|---|---|---|---|---|
| 새 설명 | 3.97 | 3.88 | 3.73 | 3.27 |
| 옛 설명 | 2.12 | 2.06 | 2.06 | 2.15 |
- 선호: 새 설명 33/33
- 카드 26장: 이해 3.81 · 인사이트 3.62 · 실천 3.38, "그래서 그랬구나" 22, 더 이해됨 yes 20 / little 6 / no 0
- 주의: A1·A3의 집요함 옛 버전에 단계 0에서 고친 CSV 잔재가 스냅샷에 남아 있었음(옛 버전에 불리하게 작용 가능)## 반영한 공통 지적
1. 욕구 칸 라벨 없음(11/11) → '바라는 것 / 채워질 때 / 힘이 빠질 때' 형식, 린트 검사
2. 헤더가 새 정의와 어긋남(11/11) → 단계 3에서 정의와 한 벌로 재작성
3. 어려운 말(견주다·까닭·인연·몇 해) → 린트 금지어
4. 성인 칸 일 장면, 강점 개발 첫 문장 중복, 카드 역할명 풀이·판단 신호 → WRITING_GUIDE 5장
5. 약한 카드 4장(직관력>유연함, 갈등해소>협업, 집중>계획성, 창의성×계획성) → 단계 5에서 재작성·대비 쌍 재검토## 코드 (미배포 커밋)
- df581361 자리를 잃은 형광펜 "예전 설명에서 표시한 문장" 목록(헤드리스 Chromium 검증)
- df421676 '내 순위 해석' 버튼·Strengths::RankInsight(59,400원 이상, 카드 없으면 숨김), 린트 보강## 진행 중
- 단계 3: 역할별 작성자 9명이 27 DNA 공통 칸 + 헤더·짧은 문구 작성 중
- 반영 순서: 코드 배포(형광펜 보존 먼저) → 공통 칸 DB 108 + ko 헤더 → 대상별 칸(단계 4) -
Cclaude 단계 1 코드 배포(bf915d8a) — 형광펜 보존·욕구 칸 위치·보완할 DNA 표시·PDF 순서·문안 점검 도구, 기준안 검토 페이지 공개
상세 보기
## 배포 (bf915d8a, 전체 테스트 5,139 통과)
- `dna_annotate_controller.js`: 형광펜을 저장 위치가 아니라 문장 텍스트로 다시 찾아 복원(문구 수정 후에도 유지), mark 번호를 서버 배열 순서로 고정. 헤드리스 Chromium으로 문장 추가·삭제 상황 검증
- `_tab_domain.html.erb`: 욕구를 강점 발현 뒤로, 보완할 DNA는 칭찬형 헤더 숨김 + 정의 첫 문단만, 핵심 칸 원문 해시
- `pdf/_dna_detail.html.erb`: 정의 → 강점 발현 → 욕구 → 약점 발현 / 강점 활용 | 강점 개발 → 조합
- `diagnoses_controller#shared`: 캐시 키 v10 + 설명 편집 시각
- `Strengths::CopyLint` + `strengths:lint_copy`: 합니다체(권유 해요체 포함), 자기보고 어미, 금지 표현, 인격 판단어, 공통 칸 직장·학교 어휘, 문항 원문 4어절 겹침, 분량
- 테스트: copy_lint_test(13), dna_description_layout_test(4)## 기준안
- 검토 페이지: https://claude.ai/artifact/LPKLBYkpQnW9aRrXV7TMPF (27개 정의·욕구, 점검 54건 위반 0)
- 작성 지침: docs/plans/dna-description-review/WRITING_GUIDE.md## 진행 중
- 단계 2 파일럿 작성(논리성·친밀감·집요함 각 20칸, 순위 해석 카드 21종) — Claude Code 서브에이전트, API 키 미사용
- 후속 커밋 4efe349d(순위 해석 카드 점검 규칙)는 다음 배포에 포함 -
Cclaude 단계 0 완료 — 화면에 보이던 DNA 설명 결함 6건 운영 DB 수정
상세 보기
## 수정 (ko, 운영 DB)
- 유연함 정의: 114자에서 잘린 문장 뒤를 이어 붙임(222자, 단계 3에서 전면 재작성 예정). 다른 언어판은 온전해 수정 안 함
- 집요함 강점 개발(성인·리더): 끝의 CSV 잔재 "Unique,강점 개발 방법" 제거
- 철저함 강점 활용(대학생): "B+과 A+을" → "B+와 A+를"
- 논리성 강점 개발(대학생): "균형과。포괄성" → "균형과 포괄성"
- 협업 강점 개발(대학생): 속담 오기 "함께 빨리 가려면 혼자 가고" → "빨리 가려면 혼자 가고"## 안전장치
- 스냅샷 SHA256 대조 후 트랜잭션 반영(드라이런 → 적용), 원문 백업 `docs/plans/dna-description-review/backups/2026-09-17-phase0.json`
- 형광펜 영향 확인: 같은 글자 수 치환이거나 해당 원문 형광펜 0건
- 공유 결과 캐시(v9) 328건 삭제, 본인 결과 캐시는 updated_at 키로 자동 무효화
- 재조회 검증: 잔재·오자·오기 0건 -
Cclaude 상태 변경: 할 일 → 완료
-
Cclaude 재촬영 대상 5편 숨김 구현·전체 테스트 통과, 커밋 1f35a57f 배포 중
상세 보기
## 변경 사항
- `study_lessons.is_hidden` 추가 (마이그레이션 20260917140000): Intro(0-1)·3-1·3-2·3-3·Outro(10-1) 숨김 + 과정 합계 재계산 (19편 176분 → 14편 146분)
- `Study::Course`/`Study::Chapter`: `lessons`·`chapters`는 보이는 것만, 관리자는 `all_lessons`·`all_chapters`
- 결과 페이지 강의 목록·강의 수/시간·미리보기·레슨 직접 주소(404)·진도율에서 모두 빠짐
- 관리자 레슨 편집에 "숨김" 체크박스, 과정 상세에 숨김 배지
- `db/seeds/seed_study_courses.rb`: 배포마다 chapters destroy_all → 재생성하던 것을 없는 행만 만들도록 수정 (수강 기록·관리자 수정 보존)## 검증
- 새 테스트 9개 RED 확인 후 GREEN, 전체 5,118 runs 0 failures
- dev DB 카운트 전후 동일## 참고
- 프로덕션 study_progresses 0건 — 기존 seed가 배포마다 시청 기록을 지워 온 것으로 보임 -
2026년 06월 10일
-
Cclaude PR4 캠페인 작성·발송(Resend 배치) TDD 구현 완료 — MVP 완성 (커밋 3ccbcf1)
상세 보기
## 변경 사항
- resend gem 1.3.0 + config/initializers/resend.rb (마케팅 전용, delivery_method 전역 변경 X).
- email_campaigns 테이블 + EmailCampaign 모델(enum status, deliveries 연관, sendable?). email_deliveries.campaign_id FK 연결(on_delete nullify) + EmailDelivery belongs_to :campaign.
- app/services/marketing/campaign_sender.rb: eligible_recipients(segment.members → marketing_subscribed & not_suppressed & email 존재) → 100명 배치 → build_email(토큰 렌더 + 레이아웃 + List-Unsubscribe 헤더 + unsubscribe URL) → ResendClient.send_batch → EmailDelivery 생성. 배치 예외 시 해당 수신자 failed(부분 성공). send_test(본인, 로그 미기록).
- app/services/marketing/resend_client.rb: Resend::Batch.send 래퍼(주입형).
- app/jobs/marketing/send_campaign_job.rb (Solid Queue): deliver/test 분기.
- Admin::Marketing::CampaignsController: CRUD + send_test/deliver(Job enqueue, 동기 발송 X), sendable? 가드.
- ⚠️ 네임스페이스 충돌 해결: Admin::Marketing 내부에서 ::Marketing::SendCampaignJob 으로 최상위 명시.
- Webhooks::ResendController: 캠페인 카운터(delivered/opened/clicked/bounced/unsubscribed) 최초 전이 시에만 증가.
- 뷰: campaigns index/_form/new/edit/show(성과 6지표 + 발송 로그). 사이드바 "캠페인". 세그먼트 show "캠페인 만들기" 버튼(PR2 보류분). ko.yml i18n.## 테스트
- 신규: email_campaign(5), campaign_sender(6: 게이트/배치분할/토큰/부분실패/send_test), campaigns_controller(10: CRUD/enqueue 검증/sent 차단), 웹훅 카운터(1).
- 전체 스위트 2793 runs, 0 errors. 실패 5건은 전부 기존 vuild 랜딩(본 작업 무관, 커밋 fd65e8b 이후 미갱신).
- 실제 Resend 호출은 FakeClient 주입 / Job enqueue 단언으로 회피(테스트에서 발송 없음).## 운영 TODO (발송 활성화 전)
- MARKETING_FROM_EMAIL=marketing@9way.co.kr, RESEND_WEBHOOK_SECRET 를 .env / .kamal/secrets / .env.deploy 에 추가.
- Resend 대시보드에서 https://9way.co.kr/webhooks/resend 웹훅 등록.## Fast-follow (범위 외)
- 진단 결과 유형(WAY/DOMAIN) 세그먼트 조건 — 결과 점수 저장 위치 스파이크 후 SegmentQuery + TokenRenderer({{primary_way}}) 추가. -
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude PR3 Resend 발송 기반(웹훅·수신거부·suppression) TDD 구현 완료 (커밋 c23026c)
상세 보기
## 변경 사항
- 마이그레이션 3종: email_deliveries(campaign_id[FK는 PR4], user, resend_email_id[uniq], status, *_at, open/click_count, error_message), email_suppressions(email_address[uniq], reason, suppressed_at), email_webhook_events(event_id[uniq] 멱등키).
- 모델: EmailDelivery(mark_delivered!/record_open!/record_click!/mark_bounced!/mark_complained!, PROGRESS 단계 역행 방지), EmailSuppression(normalizes + 멱등 suppress!), EmailWebhookEvent(already_processed?/record!).
- User: not_suppressed 스코프, unsubscribe_token/find_by_unsubscribe_token(message_verifier).
- app/services/webhooks/svix_verifier.rb: Svix HMAC-SHA256 직접 검증(svix gem 불필요).
- app/services/marketing/token_renderer.rb: {{name}}/{{funnel_stage}} 치환 + HTML 이스케이프, 미지원 토큰 원형 유지.
- Webhooks::ResendController(ActionController::Base 상속 → allow_browser/CSRF/locale 우회, skip_forgery_protection): 서명검증 → 멱등 → 이벤트 처리. bounced→hard_bounce suppression, complained→complaint suppression + email_subscription=false.
- EmailSubscriptionsController#unsubscribe(allow_unauthenticated_access) + 확인 뷰.
- 공개 라우트: POST /webhooks/resend, GET /email/unsubscribe.## 설계 결정
- resend gem + 실제 발송은 PR4로 격리(외부 의존성 최소화). 웹훅 검증은 수동 HMAC.
- 캠페인 카운터 갱신(delivered_count 등)은 EmailCampaign 생성(PR4) 후 연결.## 테스트
- 신규 67개: email_delivery(6)/email_suppression(5)/user_funnel 추가(3)/token_renderer(7)/svix_verifier(6, 공식 벡터)/resend_controller(6)/email_subscriptions(2) 등.
- 웹훅 멱등(같은 svix-id 재전송), 서명 실패 401, complained→unsubscribe 검증.## 운영 TODO (배포 전)
- RESEND_WEBHOOK_SECRET 를 .env / .kamal/secrets / .env.deploy 에 추가.
- Resend 대시보드에서 https://9way.co.kr/webhooks/resend 웹훅 등록(이벤트: delivered/opened/clicked/bounced/complained).## 참고
- 전체 스위트의 vuild 랜딩 테스트 5건 실패는 본 작업과 무관(커밋 fd65e8b가 _timeline/_claude_pro/_faq partial 삭제 후 테스트 미갱신, 증거 확인). -
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude PR2 세그먼트(조건 저장형 동적 세그먼트) TDD 구현 완료 (커밋 f5d7206)
상세 보기
## 변경 사항
- `app/services/marketing/segment_query.rb`: conditions(jsonb)→User 관계. 화이트리스트(알려진 키만 처리, 나머지 무시) + 전 바인드 파라미터 → SQL 인젝션 차단. 지원: funnel_stages(OR), facts(AND: has_completed/paid_diagnosis, is_applicant/graduate), diagnosis_target, locale, email_subscription, created_after, first_diagnosis_after, days_since_diagnosis_gte, utm_source.
- `db/migrate/20260610071005_*` + `app/models/marketing_segment.rb`: name(unique), description, conditions(jsonb), cached_count, count_refreshed_at, created_by. `members`(실시간), `refresh_count!`.
- `app/controllers/admin/marketing/segments_controller.rb`: CRUD + `refresh_count`. strong params로 conditions 구조 허용 + 빈 값 정리(cleaned_conditions).
- 뷰: index/new/edit/_form(조건 빌더: 퍼널 단계·언어·진단대상 체크박스 + 수신동의/경과일/가입일) / show(실시간 대상 수 + 샘플 20명).
- `app/helpers/admin/marketing/segments_helper.rb`: 조건 요약 칩 라벨.
- 사이드바 "세그먼트" + ko.yml i18n.## 테스트
- 신규: segment_query(11, 인젝션/OR/AND/경계값 포함), marketing_segment(5), segments_controller(8)
- 회귀: admin+models+services **1530 runs, 0 failures**## 참고
- "이 세그먼트로 캠페인 만들기" 버튼은 campaigns 라우트(PR4) 생성 후 show에 추가 예정.
- 결과유형(WAY/DOMAIN) 조건은 스파이크 후 fast-follow(범위 외). -
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 할 일 → 진행 중
-
Cclaude PR1 리드 목록 + 퍼널 스코프 TDD 구현 완료 (커밋 c65dcdf)
상세 보기
## 변경 사항
- `app/models/user.rb`: 퍼널 스코프/메서드 추가
- `FUNNEL_STAGES = %i[subscriber free paid applicant graduate]`
- fact 스코프: `marketing_subscribed`, `with_completed_diagnosis`, `with_paid_diagnosis`, `free_diagnosis_only`, `course_applicants`, `course_graduates`
- `at_funnel_stage(stage)`: 배지와 동일한 **상호배타 현재 단계** 필터
- `funnel_stage`(단건) / `self.funnel_stage_map(ids)`(배치, 목록 N+1 방지)
- `db/migrate/20260610065545_*`: `diagnosis_sessions.is_report_purchased` 부분 인덱스(`where is_report_purchased=true`, `algorithm: :concurrently`). migrate→rollback→migrate 3단계 검증 완료.
- `config/routes.rb`: `namespace :marketing { resources :leads, only: [:index] }`
- `app/controllers/admin/marketing/leads_controller.rb`: 검색(이름/이메일/전화)+퍼널 단계 필터+수신동의 필터+수동 페이지네이션. 페이지 단위 `funnel_stage_map`/진단수/last_active 일괄 조회.
- `app/views/admin/marketing/leads/index.html.erb`: 단계 칩 + 필터바 + 테이블(퍼널 배지/진단수/수신동의)
- `app/views/admin/shared/_sidebar.html.erb` + `_nav_item.html.erb`(funnel 아이콘) + `config/locales/ko.yml`(admin.nav.leads, admin.marketing.* — ko 전용)
- `docs/features/admin_lead_management.md`: 전체 기능 계획서## 설계 결정
- 스코프를 denorm(`first_diagnosis_completed_at`)이 아닌 **실제 세션 기준**으로 산출 → 마케팅 오분류(잘못된 발송) 방지. 픽스처가 콜백을 안 거치는 점도 고려.
- `NOT IN (subquery)` NULL 함정을 `where.not(user_id: nil)`로 차단.
- PR1에서는 사이드바에 leads 메뉴만 추가(segments/campaigns 경로는 PR2/PR4에서 생성, 미존재 경로 참조 방지).## 테스트
- 신규: `test/models/user_funnel_test.rb`(14), `test/controllers/admin/marketing/leads_controller_test.rb`(7)
- 회귀: `test/controllers/admin` + `test/models` 전체 **902 runs, 0 failures**
- Tailwind dev 빌드 재실행(새 배지 클래스 반영)## 완료 기준 충족
어드민 사이드바 "리드 관리"에서 퍼널 단계별 필터·검색·페이지네이션 동작. -
Cclaude 상태 변경: 진행 중 → 리뷰
-
Cclaude 상태 변경: 할 일 → 진행 중
-
2026년 04월 15일
-
팀팀리드 배포 완료 - feature/big5-report-renewal → main 머지 + kamal deploy
상세 보기
## 배포 정보
- 배포 시각: 2026-04-15
- 배포 환경: production (9way.org)
- 배포 시간: 141.3초
- 커밋: 635aafe## 포함된 주요 커밋 (이번 배포)
- `635aafe` feat: implement inline editing for blog post category and status
- `851b26d` refactor: modernize discount code service, improve UI accessibility
- `0d9bf3e` refactor: replace applies_to_all with polymorphic apply_scope
- `612cb57` fix(growth-mindset): remove all hardcoded Korean default fallbacks
- `d4e82eb` i18n: replace hardcoded Korean in summary card with t() keys
- `e0d9d53` i18n(growth-mindset): add renewal keys for zh, en, vi locales
- `2f860a2` i18n: add Big5 report renewal keys for en, zh, vi
- 외 30+ 커밋 (Big5/Growth Mindset 리포트 리뉴얼, 할인코드 확장, 블로그 인라인 편집)## 변경된 기능
- **블로그 관리**: 상태/카테고리 인라인 편집 (클릭하여 바로 변경)
- **할인코드 확장**: apply_scope enum + discount_code_items polymorphic
- **Big5 리포트**: 전면 리뉴얼 (아코디언, 레이더 차트, 요약 카드)
- **Growth Mindset 리포트**: 전면 리뉴얼 (디자인 시스템 통일)
- **i18n**: Big5/Growth Mindset 리포트 다국어 키 추가 (ko, en, zh, vi)## 확인 사항
- 컨테이너 healthy 확인
- 96 파일 변경, +6198 / -1113 lines -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 백로그 → 진행 중
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 백로그 → 진행 중
-
팀팀리드 상태 변경: 백로그 → 리뷰
-
팀팀리드 상태 변경: 백로그 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 백로그 → 진행 중
-
팀팀리드 기능 계획 수립 - 할인코드 적용 범위 확장
상세 보기
## 기능 개요
- 할인코드 적용 범위를 Product(report/credit_pack)에서 Expert::Course(교육프로그램) + Study::Course(온라인강좌)까지 확장
- apply_scope enum (all/report/education/specific) + polymorphic discount_code_items 조인테이블## 분석 결과
- 영향 범위: 모델 3개, 서비스 4개, 컨트롤러 3개, 뷰 2개, 마이그레이션 2개
- 기존 패턴: string enum, Result 패턴 (Data.define), Payments::CheckoutService 재사용
- 핵심: CheckoutService가 이미 discount_amount/discount_code_id 지원 → Expert 연동 간단## 생성된 티켓 (5개)
1. [할인코드확장 PR1] DB + 모델 (priority: high)
2. [할인코드확장 PR2] ValidationService (priority: high)
3. [할인코드확장 PR3] Expert/Study 서비스 (priority: high)
4. [할인코드확장 PR4] Admin UI (priority: medium)
5. [할인코드확장 PR5] 결제 UI + 정리 (priority: medium)## 리스크
- 기존 할인코드 깨짐 → ignored_columns + 기존 테스트 전수 통과로 방어
- 데이터 이관 → 마이그레이션 트랜잭션 + 롤백 검증## 기술적 결정
- applies_to_all → apply_scope string enum (프로젝트 컨벤션 일관성)
- 2단계 제거 패턴 (ignored_columns → 컬럼 삭제)
- polymorphic 조인테이블로 Product/Expert::Course/Study::Course 통합 -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
2026년 03월 30일
-
팀팀리드 크레딧 통합 PR1~PR5 전체 구현 완료
상세 보기
## 수정된 기능
- 2가지 개인 크레딧(리포트/진단) → 단일 크레딧으로 통합
- 1크레딧 = 19,800원, 리포트=1.0, 심화진단=0.2, 추천보상=0.2
- 워크스페이스 선물: 1크레딧 단위, 자기 선물 가능
- diagnosis_balance 컬럼 DB에서 완전 제거## 변경 규모
- 39 파일, +187 / -1,030 lines
- 삭제: DiagnosisCreditPurchaseService, DiagnosisCreditsController, 진단 크레딧 구매 뷰/JS## UX/UI 검토 결과
- 전체 평가: 기능적 통과, P2/P3 개선사항은 후속 작업
- 선물 모달 2종 통합, 사이드바 단일 뱃지, 크레딧 대시보드 단일 잔액## 테스트/보안 검증
- 1635 runs, 13 failures, 8 errors (모두 크레딧 무관 기존 이슈)
- 크레딧 관련 실패: 0건
- add!에 lock! 추가 (race condition 방지)
- BigDecimal 사용으로 부동소수점 오류 방지## 해결된 문제
- ConfirmationService 테스트가 workspace_id 분기 미반영 → 수정 완료
- admin 뷰 하드코딩 한국어 → i18n 처리## 남은 이슈
- blog/posts Dangerous Send (크레딧 무관, 별도 티켓 필요)
- Payment.diagnosis_credit enum 유지 (기존 레코드 3건 존재) -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 백로그 → 완료
-
팀팀리드 상태 변경: 백로그 → 완료
-
팀팀리드 상태 변경: 백로그 → 완료
-
팀팀리드 크레딧 통합 작업 시작 - PR1~PR5 순차 진행
상세 보기
## 작업 계획
- 목표: 2가지 개인 크레딧(리포트/진단)을 단일 크레딧으로 통합
- 접근 방식: PR1→PR2→PR3→PR4→PR5 순차 진행 (의존성 체인)## 현재 상태
- 보드 현황: backlog 9 / todo 11 / in_progress 1 / review 9 / done 158
- PR1: DB 마이그레이션 (balance decimal 변환)
- PR2: 모델 통합
- PR3: 서비스 통합
- PR4: 컨트롤러/라우트 통합
- PR5: 뷰/UI/i18n 통합 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 기능 계획 수립 — 크레딧 시스템 통합
상세 보기
## 기능 개요
- 2가지 개인 크레딧(리포트/진단)을 단일 크레딧으로 통합
- 1크레딧 = 19,800원 (세전 18,000원 + VAT 10%)
- 강점 리포트 = 1.0 크레딧, 심화 진단 = 0.2 크레딧
- 워크스페이스 → 개인 크레딧 선물 (자기 선물 포함)## 분석 결과
- 영향 범위: 모델 6개, 서비스 7개, 컨트롤러 5개, 뷰 11개, JS 1개, i18n 4언어
- 삭제 대상: DiagnosisCreditPurchaseService, DiagnosisCreditsController, 진단 크레딧 구매 뷰/JS## 생성된 티켓 (5개)
1. [크레딧통합 PR1] DB 마이그레이션 (priority: high)
2. [크레딧통합 PR2] 모델 통합 (priority: high)
3. [크레딧통합 PR3] 서비스 통합 (priority: high)
4. [크레딧통합 PR4] 컨트롤러/라우트 통합 (priority: high)
5. [크레딧통합 PR5] 뷰/UI/i18n 통합 (priority: medium)## 기술적 결정
- balance: integer → decimal(10,1) (0.2 단위 차감)
- diagnosis_balance: 2단계 제거 패턴 (ignored_columns → 별도 마이그레이션)
- credit_type: 기존 이력 유지, 신규 "unified"
- DiagnosisType#credit_cost로 진단별 차감량 캡슐화 -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 일괄다운로드 비동기 처리 전체 구현 완료
상세 보기
## 구현 완료된 PR (5개)
### PR1: BulkReportDownload 모델 + 마이그레이션
- `db/migrate/20260330012810_create_bulk_report_downloads.rb`
- `app/models/bulk_report_download.rb` (enum status, scope expired/active, has_one_attached :file)
- `test/models/bulk_report_download_test.rb` (17 tests)
- `test/fixtures/bulk_report_downloads.yml` (5 fixtures)### PR2: BulkReportGenerateJob + CleanupJob
- `app/jobs/bulk_report_generate_job.rb` (PDF→ZIP→Active Storage, 순차 처리, GC 관리)
- `app/jobs/bulk_report_cleanup_job.rb` (7일 만료 삭제)
- `config/recurring.yml` 에 매일 2am cleanup 등록
- 테스트 9 runs### PR3: BulkReportMailer
- `app/mailers/bulk_report_mailer.rb` (completed/failed)
- `app/views/bulk_report_mailer/completed.html.erb`, `failed.html.erb`
- i18n 4개 언어 (ko, en, zh, vi)
- 테스트 6 runs### PR4: Controller + Routes 비동기 전환
- `handle_bulk_download` 동기→비동기 전환 (Job enqueue)
- `bulk_download_status` (JSON 폴링), `bulk_download_file` (파일 다운로드)
- 중복 요청 방지
- 테스트 10 runs### PR5: View + Stimulus 폴링 배너
- `bulk_download_status_controller.js` (3초 폴링, 상태별 UI)
- `_bulk_download_banner.html.erb` (progress bar, download button)
- i18n 4개 언어## 전체 테스트
- **42 runs, 90 assertions, 0 failures, 0 errors** -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 작업 시작 - 일괄다운로드 PR1 (모델 + 마이그레이션)
상세 보기
## 작업 계획
- 목표: BulkReportDownload 모델 + 마이그레이션 + 테스트 + fixture
- 접근 방식: TDD (테스트 먼저 → 구현)## 전체 일괄다운로드 진행 순서
1. **PR1 (현재)**: 모델 + 마이그레이션
2. PR2 + PR3 (PR1 완료 후 병렬): Job + Mailer
3. PR4 (PR2 완료 후): Controller + Routes
4. PR5 (PR4 완료 후): View + Stimulus -
팀팀리드 티켓 클레임 완료
-
팀팀리드 기능 계획 수립 - 워크스페이스 리포트 일괄 다운로드 비동기 ��리
상세 보기
## 기능 개요
- 일괄 리포트 ��운로드 시 동기 PDF 생성으로 인한 HTTP 타임아웃 해결
- 백그라운드 Job으로 전환 + 폴링 방식 상태 표시 + 이메일 알림## 분석 결과
- 영향 범위: members_controller, PdfGenerator, routes, members views, i18n
- 기존 패턴: AiInsightGenerateJob(폴링), GiftMailer(���메일), Active Storage(4개 모델)
- Turbo Stream broadcast 미사용 → 폴링 방식 채택## 생성된 티켓 (5개)
- [PR1] BulkReportDownload 모델 + 마이그레이��� (high)
- [PR2] BulkReportGenerateJob + CleanupJob (high)
- [PR3] BulkReportMailer (medium)
- [PR4] Controller + Routes 비동기 전환 (high)
- [PR5] View + Stimulus 폴링 배너 UI (high)## 리스크
- Grover 메모리 → 순차 처리 + 주기적 GC
- 디스크 누적 → 7일 만료 CleanupJob (매일 2am)
- 중복 요청 → pending/processing 존재 시 거부## 기술적 결정
- ActionCable 인프라 없음 → Turbo Stream broadcast 대신 Stimulus 폴링 (3초)
- Active Storage local disk 사용 (프로덕션 전환 시 S3 검토) -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
2026년 03월 26일
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료06:35 마이그레이션 + 모델 구현 (TDD)
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 팀 작업 완료 - [리퍼럴 PR5] 뷰/UI
상세 보기
## 수정된 기능
- 크레딧 현황 페이지: 리포트/진단 2종류 분리 표시, 리퍼럴 현황 N/10
- 진단 크레딧 구매 페이지: 디자인 개선, 무료 획득 안내
- 크레딧 부족 안내 partial: 구매/공유 2가지 옵션
- i18n: 4개 언어 완료## 테스트 결과
- 14 runs 통과 (credits 6 + diagnosis_credits 8)## 수정 파일
- 컨트롤러 1개, 헬퍼 1개, 뷰 3개, i18n 4개 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 위임: developer-1에게 '크레딧 현황 UI + 리퍼럴 대시보드 + 구매 페이지 + 크레딧 부족 안내' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [리퍼럴 PR4] 진단 크레딧 구매
상세 보기
## 수정된 기능
- DiagnosisCreditPurchaseService: 3,000원/크레딧, Toss Payments 연동
- Payment 모델: diagnosis_credit 타입 추가
- ConfirmationService: 결제 완료 후 자동 크레딧 지급
- DiagnosisCreditsController: 구매 페이지 + checkout 연동
- 라우트 추가## 테스트 결과
- 18 runs 통과 (서비스 12 + 컨트롤러 6)## 기술적 결정
- 멱등성: metadata.credits_added 플래그로 중복 방지
- VAT 10% 포함 처리 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 위임: developer-1에게 '진단 크레딧 구매 서비스 + 컨트롤러 + 라우트' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [리퍼럴 PR3] 컨트롤러 연동
상세 보기
## 수정된 기능
- ApplicationController: ref 파라미터 → 쿠키 저장 (30일)
- DiagnosesController: Big5/성장/행복도 진단 시작 시 크레딧 차감
- DiagnosisSessionsController: 강점 진단 완료 시 리퍼럴 보상 트리거
- OAuth/매직링크 가입: 리퍼럴 추적 기록 + 쿠키 삭제
- 공유 URL: referral_url 헬퍼로 ?ref= 파라미터 자동 추가
- i18n: 크레딧 부족 메시지 4개 언어## 테스트 결과
- 22 runs 통과 (신규 10 + 기존 12)## 수정 파일
- 컨트롤러 5개, 모델 1개, 헬퍼 1개, 뷰 2개, i18n 4개, 테스트 1개 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 PART2 쌍대비교 전환 구현 완료
상세 보기
## 변경 사항
### 컨트롤러 (`diagnosis_sessions_controller.rb`)
- `PART2_DOMAIN_PAIRS`, `PART2_QUESTIONS_PER_ROUND` 상수 추가
- `prepare_part2_round_sequence`: 54라운드 사전 생성 (deterministic, session_seed 기반)
- `next_part2_round`: 시퀀스에서 미응답 페어 반환
- `setup_part2_state`: total_rounds = 시퀀스 크기
- `current_round_number`: / 2로 변경### 뷰
- `_part2_round.html.erb`: 2버튼 + "둘 다 해당 안됨" 버튼
- `_part2_guide.html.erb`: 미리보기 2개 + "해당없음"### JS (`diagnosis_controller.js`)
- `skipPart2Round` 메서드 추가
- 선택자: `[data-part2-choice]`로 구분
- response_time null 처리 개선### i18n (ko, en, zh, vi)
- `none_of_above` 키 추가
- instruction/description 텍스트 변경
- preview_3 제거### 테스트
- 기존 테스트 2개→3개로 수정 (pairwise, skip, constants)
- 진단 관련 54개 테스트 전체 통과 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 '컨트롤러 연동: ref 추적 + 크레딧 차감 + 보상 트리거 + 공유 URL' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 할 일 → 진행 중
-
팀팀리드 팀 작업 완료 - [리퍼럴 PR2] 비즈니스 로직
상세 보기
## 수정된 기능
- Referrals::TrackingService: 신규 가입 시 referral_code → Referral(pending) 생성
- Referrals::RewardService: strength 진단 완료 → referrer diagnosis_balance +1, 월 10개 상한## 테스트 결과
- 12 runs, 24 assertions, 0 failures## 기술적 결정
- DiagnosisType 연관관계: `category` (not `diagnosis_category`)
- 테스트에서 referral_code는 update_column으로 설정 (fixture에 없으므로) -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 위임: developer-1에게 'Referrals::TrackingService + RewardService TDD 구현' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [리퍼럴 PR1] DB 레이어
상세 보기
## 수정된 기능
- UserCredit에 diagnosis_balance 컬럼 추가 (진단 크레딧)
- CreditTransaction에 credit_type 컬럼 추가 (report/diagnosis 구분)
- User에 referral_code 컬럼 추가 (공유 URL용)
- Referral 모델 신규 생성 (리퍼럴 추적)## 테스트 결과
- 57 runs, 103 assertions, 0 failures (관련 테스트)
- 기존 테스트 영향 없음## 마이그레이션
- 4개 모두 가역적, rollback 검증 완료## 남은 이슈
- 기존 유저의 referral_code는 nil (필요 시 별도 마이그레이션으로 채울 수 있음) -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰05:40 마이그레이션 + 모델 구현 (TDD)
-
팀팀리드 위임: developer-1에게 '마이그레이션 + 모델 구현 (TDD)' 작업 배정
-
팀팀리드 작업 시작 - [리퍼럴 PR1] DB 레이어
상세 보기
## 작업 계획
- 목표: 진단 크레딧 + 리퍼럴 보상 시스템의 DB 기반 구축
- 접근 방식: 마이그레이션 4개 + 모델 변경/생성을 developer-1에게 위임, QA 검증 후 완료## 현재 상태
- 보드 현황: backlog 8 / todo 11 / in_progress 1 / review 4 / done 147
- 관련 기존 작업: UserCredit, CreditTransaction 모델 기존 존재 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 기능 계획 수립 - 공유 리퍼럴 크레딧 시스템
상세 보기
## 기능 개요
- 카카오톡/링크 공유로 유입된 신규 회원이 강점 진단 완료 시 공유자에게 진단 크레딧 +1 보상
- 진단 크레딧으로 Big5/성장 마인드셋/행복도 진단 가능 (1크레딧=1검사)
- 진단 크레딧 개인 구매 가능 (3,000원/개)
- 리포트 크레딧(기존 18,000원)과 분리 운영## 분석 결과
- 영향 범위: UserCredit, CreditTransaction, User, DiagnosisSession, 결제 플로우
- 기존 패턴: ReportPurchaseService, CreditPurchaseService(워크스페이스), share_token 공유## 생성된 티켓
- [리퍼럴 PR1] DB 레이어 (priority: high)
- [리퍼럴 PR2] 비즈니스 로직 (priority: high)
- [리퍼럴 PR3] 컨트롤러 (priority: high)
- [리퍼럴 PR4] 진단 크레딧 구매 (priority: medium)
- [리퍼럴 PR5] 뷰/UI (priority: medium)## 핵심 설계 결정
- UserCredit에 diagnosis_balance 컬럼 추가 (별도 모델 X)
- Referral 모델 신규 생성 (referrer/referee 추적)
- 공유 URL에 ?ref=referral_code 파라미터
- 월 10개 보상 상한, 1인 1추천인 -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
2026년 03월 17일
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-2에게 'EngagementSurveyResponsesController 공개 응답 플로우 구현' 작업 배정
-
팀팀리드 위임: developer-1에게 'Workspaces::EngagementSurveysController 구현' 작업 배정
-
팀팀리드 작업 시작 - [조직문화 PR3+PR4] 컨트롤러 레이어 (병렬 진행)
상세 보기
## 작업 계획
- PR3: Workspaces::EngagementSurveysController (관리자 CRUD + 결과)
- PR4: EngagementSurveyResponsesController (비인증 공개 응답)
- 접근 방식: developer-1 = PR3, developer-2 = PR4 병렬 진행 (파일 충돌 없음) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [조직문화 PR2] 서비스 레이어
상세 보기
## 수정된 기능
- CreateService: 설문 생성 + 중복 방지 + title 자동 생성
- SubmitResponseService: DiagnosisSession 기반 응답 저장 + EngagementCalculator 채점
- ResultAggregator: 전체/그룹별 집계, 3명 이하 필터링, 몰입 유형 비율, 3요인/9요인 분석, 강약점## 생성 파일
- `app/services/engagement_surveys/create_service.rb`
- `app/services/engagement_surveys/submit_response_service.rb`
- `app/services/engagement_surveys/result_aggregator.rb`
- `test/services/engagement_surveys/create_service_test.rb`
- `test/services/engagement_surveys/submit_response_service_test.rb`
- `test/services/engagement_surveys/result_aggregator_test.rb`## 기술적 결정
- DiagnosisSession 재사용 (context_type="b2b", scoring_framework="engagement_3factor")
- 기존 EngagementCalculator + ScoreCalculatorFactory 완전 재사용
- Data.define Result 패턴 (기존 서비스 패턴 준수)
- MINIMUM_RESPONSES=3 상수로 3명 이하 필터링## 테스트: 17 runs, 59 assertions, 0 failures
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 'EngagementSurveys 서비스 3개 TDD 구현' 작업 배정
-
팀팀리드 작업 시작 - [조직문화 PR2] 서비스 레이어
상세 보기
## 작업 계획
- 목표: 3개 서비스 객체 구현 (CreateService, SubmitResponseService, ResultAggregator)
- 접근 방식: developer-1이 TDD로 구현## 핵심 로직
- CreateService: 설문 생성 + 중복 방지
- SubmitResponseService: DiagnosisSession으로 응답 저장 + EngagementCalculator 채점
- ResultAggregator: 전체/그룹별 집계, 3명 이하 필터링, 몰입 유형 비율, 3요인/9요인 분석 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [조직문화 PR1] DB 레이어
상세 보기
## 수정된 기능
- WorkspaceEngagementSurvey 모델: 분기별 설문 관리 (draft/active/closed, access_token 자동 생성)
- DiagnosisSession 확장: workspace_engagement_survey_id, workspace_group_id FK 추가## 생성/수정 파일
- `db/migrate/20260317080753_create_workspace_engagement_surveys.rb`
- `db/migrate/20260317080816_add_engagement_survey_to_diagnosis_sessions.rb`
- `app/models/workspace_engagement_survey.rb`
- `app/models/diagnosis_session.rb` (연관관계 추가)
- `app/models/workspace.rb` (has_many :engagement_surveys)
- `test/fixtures/workspace_engagement_surveys.yml` (3개 fixture)
- `test/models/workspace_engagement_survey_test.rb` (21 tests)## 테스트 결과
- 모델 테스트: 508 tests, 0 failures, 0 errors
- 신규 테스트: 21 tests (유효성, 연관관계, enum, 스코프, access_token) -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 'WorkspaceEngagementSurvey 마이그레이션 + 모델 + DiagnosisSession 확장' 작업 배정
-
팀팀리드 작업 시작 - [조직문화 PR1] DB 레이어
상세 보기
## 작업 계획
- 목표: WorkspaceEngagementSurvey 모델 생성 + DiagnosisSession FK 확장
- 접근 방식: developer-1이 마이그레이션+모델+테스트, 완료 후 QA 검증## 서브 태스크
1. 마이그레이션 2개 생성 (WorkspaceEngagementSurvey + DiagnosisSession 확장)
2. 모델 구현 (유효성, 연관관계, 스코프, enum)
3. fixture + seed 확인
4. 테스트 작성 및 통과 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 기능 계획 수립 - 조직문화 진단 (Engagement B2B)
상세 보기
## 기능 개요
워크스페이스 대시보드에 조직문화(Engagement B2B) 진단 기능 추가. 분기별 설문 생성 → QR/링크로 익명 응답 → 결과 대시보드 집계.## 분석 결과
- 영향 범위: Workspace, DiagnosisSession, EngagementCalculator, admin/survey_questions
- 기존 패턴: engagement B2C 플로우, QrCodeHelper, WorkspaceAuthorization
- 재사용: EngagementCalculator(채점), EngagementResultFormatter(B2B 분기 지원), _engagement_question.html.erb(문항 뷰)## 생성된 티켓 (7개)
- [PR1] DB: WorkspaceEngagementSurvey + DiagnosisSession 확장 (high)
- [PR2] 서비스: 생성/응답/집계 (high)
- [PR3] 컨트롤러: 설문 관리 CRUD + 결과 (high)
- [PR4] 공개 응답 플로우: 비인증 컨트롤러 (high)
- [PR5] 뷰: 결과 대시보드 UI (medium)
- [PR6] 뷰: 공개 응답 UI (medium)
- [PR7] Admin: B2B 문항 분리 + 네비게이션 (low)## 핵심 설계 결정
- DiagnosisSession 재사용 (Option A): 기존 EngagementCalculator/ResultFormatter 완전 활용
- 익명성: user_id는 로그인 시 참고용 기록, 결과 집계에서 미사용
- 3명 이하 그룹 결과 비공개## 리스크
- 익명 응답 중복 방지: localStorage 기반 soft 방지
- 기존 EngagementCalculator는 개인용 → B2B 집계 로직은 ResultAggregator에서 별도 구현 -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 팀 작업 완료 - [함께보기 PR5] 네비게이션 + i18n
상세 보기
## 수정된 기능
- 사이드바에 "함께 보기" 메뉴 추가 (커리어테크 아래)
- 하단 탭에 "함께 보기" 메뉴 추가
- 4개 locale i18n (ko, en, zh, vi)
- "together" 그룹 아이콘 SVG 추가## 수정 파일
- `app/views/shared/_sidebar.html.erb`
- `app/views/shared/_bottom_tabs.html.erb`
- `app/views/shared/_sidebar_nav_item.html.erb`
- `app/views/shared/_bottom_tab_item.html.erb`
- `config/locales/{ko,en,zh,vi}.yml`## QA 검증 결과
- 테스트: 37/37 통과, Critical/Major 이슈 없음
- 전 locale 표시, 비로그인 미표시, active 상태 정상
- 배포 가능 상태 -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 '사이드바 + 하단탭 메뉴 추가 + 4개 locale i18n' 작업 배정
-
팀팀리드 작업 시작 - [함께보기 PR5] 네비게이션 + i18n
상세 보기
## 작업 계획
- 목표: 사이드바 + 하단탭에 "함께 보기" 메뉴 추가, 4개 locale i18n
- 접근 방식: developer 1명 구현 → QA 검증## 현재 상태
- PR1~PR4 모두 review 상태
- PR5 네비게이션: in_progress (마지막 PR) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [함께보기 PR4] 뷰 구현
상세 보기
## 수정된 기능
- 5개 뷰 완성: index(그룹 목록), show(QR코드/멤버), new(생성 폼), join(참여 확인), team_strength(팀강점 매트릭스)
- i18n 키 추가 (ko.yml)
- shared/_input.html.erb 버그 수정## UX/UI 검토 결과
- P0 border 토큰 수정, P1 반응형/빈 상태 수정, 접근성 aria-label 추가
- 잔여 Minor (shared/_button Partial 교체, 빈 상태 CTA 개선) → 별도 티켓으로## QA 검증 결과
- 테스트: 72/72 통과 (219 assertions, 0 failures)
- 보안: Brakeman 0 warnings, XSS 안전
- N+1 쿼리: index/show eager loading 수정 완료## QA/UX 피드백 반영
- N+1 쿼리 3곳 수정 (includes 추가)
- border-border-default → border-gray-200 통일
- 시너지 그리드 반응형 처리
- join 빈 세션 상태 처리 + i18n 키 추가
- aria-label 접근성 추가 (복사 버튼, DNA 매트릭스) -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 '함께 보기 전체 뷰 구현 (index, show, new, join, team_strength)' 작업 배정
-
팀팀리드 작업 시작 - [함께보기 PR4] 뷰 구현
상세 보기
## 작업 계획
- 목표: 함께 보기 기능의 전체 뷰 구현 (index, show, new, join, team_strength)
- 접근 방식: developer 1명 구현 → UX 리뷰어 검토 → QA 검증## 현재 상태
- PR1 DB: review, PR2 서비스: review, PR3 컨트롤러: review
- PR4 뷰: in_progress (현재) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [함께보기 PR3] 컨트롤러 + 라우트
상세 보기
## 수정된 기능
- ViewGroupsController 8개 액션 (index, show, new, create, destroy, join, process_join, leave, team_strength)
- 라우팅: locale scope 내 view_groups 리소스 + join/process_join 커스텀 라우트
- i18n: flash 메시지 17개 키 (ko.yml)## 생성/수정 파일
- `app/controllers/view_groups_controller.rb` (신규)
- `config/routes.rb` (수정)
- `config/locales/ko.yml` (수정)
- `app/views/view_groups/` — 최소 스텁 뷰 5개 (PR4에서 완성)
- `test/controllers/view_groups_controller_test.rb` (37개 테스트)## QA 검증 결과
- 테스트: 37/37 통과, 102 assertions, 0 failures
- 보안: Brakeman 0 warnings, IDOR 방지 확인
- Rubocop: 0 offenses (수정 후)
- Major 이슈 1건(set_view_group return 누락) → guard clause로 수정 완료## QA 피드백 반영
- set_view_group: guard clause 패턴으로 리팩토링 (DoubleRenderError 방지)
- Rubocop offense 2건 수정 -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 'ViewGroupsController + 라우트 + 컨트롤러 테스트 구현' 작업 배정
-
팀팀리드 작업 시작 - [함께보기 PR3] 컨트롤러 + 라우트
상세 보기
## 작업 계획
- 목표: ViewGroupsController CRUD, 참여(join), 나가기(leave), 팀강점(team_strength) + 라우팅
- 접근 방식: developer 1명이 TDD로 컨트롤러 + 라우트 + 테스트 구현, qa-verifier가 검증## 현재 상태
- PR1 DB 레이어: review
- PR2 서비스: review
- PR3 컨트롤러: in_progress (현재) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [함께보기 PR2] TeamStrengthAnalyzer 서비스
상세 보기
## 수정된 기능
- ViewGroups::TeamStrengthAnalyzer 서비스 구현 (Workspace 버전과 동일 출력 구조)## 생성 파일
- `app/services/view_groups/team_strength_analyzer.rb` (신규)
- `test/services/view_groups/team_strength_analyzer_test.rb` (11개 테스트)## QA 검증 결과
- 테스트: 11/11 통과, 79 assertions, 0 failures
- N+1: eager loading 올바르게 적용 (includes :user, diagnosis_session: :diagnosis_type)
- 보안: Brakeman 경고 0건, 서비스 레벨 cross-group 접근 불가
- 종합: 리뷰 진행 가능 (Critical/High 이슈 없음)## Minor 이슈 (선택적 개선)
- `view_group_members.count` 중복 호출 → 캐싱 가능
- way_scores 합계 0 케이스 테스트 없음 (코드는 방어됨) -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 'ViewGroups::TeamStrengthAnalyzer 서비스 + 테스트 구현' 작업 배정
-
팀팀리드 작업 시작 - [함께보기 PR2] TeamStrengthAnalyzer 서비스
상세 보기
## 작업 계획
- 목표: 기존 Workspaces::TeamStrengthAnalyzer를 참고하여 ViewGroups 전용 서비스 생성
- 접근 방식: developer 1명이 TDD로 서비스 + 테스트 구현, qa-verifier가 검증## 현재 상태
- PR1 DB 레이어 완료 (review 상태)
- 이번 PR2는 서비스 레이어 구현 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - [함께보기 PR1] DB 레이어
상세 보기
## 수정된 기능
- ViewGroup + ViewGroupMember 모델, 마이그레이션, 테스트, fixtures 구현 완료## 생성/수정 파일
- `db/migrate/20260317064325_create_view_groups.rb`
- `db/migrate/20260317064334_create_view_group_members.rb`
- `app/models/view_group.rb` (신규)
- `app/models/view_group_member.rb` (신규)
- `app/models/user.rb` (has_many 추가)
- `test/fixtures/view_groups.yml`, `view_group_members.yml` (신규)
- `test/models/view_group_test.rb` (13개 테스트)
- `test/models/view_group_member_test.rb` (11개 테스트)## QA 검증 결과
- 테스트: 24/24 통과, 38 assertions, 0 failures
- 보안: FK 제약, unique 인덱스, 이중 보호 모두 정상
- 종합: 리뷰 진행 가능 (Critical/High 이슈 없음)## Minor 이슈 (즉각 수정 불필요)
- `is_report_purchased` → `is_report_purchased?` 권장
- `diagnosis_session_id` 단독 인덱스 미추가 (향후 필요 시 추가) -
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: developer-1에게 '마이그레이션 + 모델 + 테스트 + fixtures 구현' 작업 배정
-
팀팀리드 작업 시작 - [함께보기 PR1] DB 레이어
상세 보기
## 작업 계획
- 목표: ViewGroup + ViewGroupMember 모델, 마이그레이션, 테스트, fixtures 생성
- 접근 방식: developer 1명이 TDD로 전체 구현, qa-verifier가 검증## 현재 상태
- 보드 현황: backlog 5 / in_progress 1 / done 137
- 관련 기존 작업: 함께보기 기능 계획 (5개 PR 시리즈의 첫 번째) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 기능 계획 수립 - 함께 보기
상세 보기
## 기능 개요
- 커리어테크 아래 "함께 보기" 메뉴 신설
- 개인이 그룹 생성 → QR코드로 초대 → 팀강점 매트릭스 함께 보기
- Workspace와 달리 경량 구조 (승인/크레딧/결제 없음)## 분석 결과
- 영향 범위: 모델 2개 신규, 컨트롤러 1개 신규, 뷰 5개, 서비스 1개, 사이드바/하단탭 수정
- 기존 패턴: Workspace의 invite_code, QrCodeHelper, TeamStrengthAnalyzer 참고
- 재사용: rqrcode gem, QrCodeHelper#qr_code_svg, 팀강점 차트 데이터 구조## 생성된 티켓 (5개)
1. [함께보기 PR1] DB 레이어 (priority: high)
2. [함께보기 PR2] TeamStrengthAnalyzer 서비스 (priority: high)
3. [함께보기 PR3] 컨트롤러 + 라우트 (priority: high)
4. [함께보기 PR4] 뷰 (priority: high)
5. [함께보기 PR5] 네비게이션 + i18n (priority: medium)## 의사결정 사항
- 참여 시 진단 세션 선택 필수 (report_purchased: true만)
- 소유자 나가기 → 그룹 삭제
- 전 locale에서 메뉴 표시
- 무료 검사로는 참여 불가## 리스크
- TeamStrengthAnalyzer 결합도 → 별도 서비스로 분리하여 기존 코드 영향 없음
- 모바일 비로그인 QR → return_to 리다이렉트 활용 -
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
2026년 03월 11일
-
팀팀리드 전체 리뷰 완료 — 25개 티켓 승인 및 이슈 수정
상세 보기
## 리뷰 결과
- bin/ci: 통과 (Rubocop 0 offenses, Brakeman 0 warnings, 테스트 전체 통과)
- 25개 티켓 모두 done 처리## 보안 수정 (Critical/High)
- `blog/posts/show.html.erb`: `raw` → `sanitize` (XSS 방지)
- `study/enrollments_controller.rb`: 무료 등록 바이패스 차단
- `study/workshop_payments_controller.rb`: IDOR 수정 (`Current.user.payments.find_by!`)
- `study/assignment.rb`: 파일 content_type 검증 추가
- `config/brakeman.ignore`: 기존 admin mass assignment 4건 무시 처리## 코드 품질 수정
- `blog/posts_controller.rb`, `admin/blog_posts_controller.rb`: LIKE wildcard injection → `sanitize_sql_like`
- `blog/posts_controller.rb`: N+1 → `includes(:author, :category)`
- `study/workshops_controller.rb`: N+1 → `includes(:course_applications)`## UX/접근성 수정
- `blog/comments/_comment.html.erb`: reply-form Stimulus scope 수정
- `study/lessons/show.html.erb`: iframe title 속성 추가
- `blog/posts/index.html.erb`, `blog/categories/show.html.erb`: 검색 aria-label
- `blog/likes/_button.html.erb`: 좋아요 버튼 aria-label
- `accordion_controller.js`: aria-expanded 토글 추가
- `video_player_controller.js`: YouTube interval cleanup in disconnect() -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료22:24 PR 5-2: 교육 공개 페이지 구현
-
팀팀리드 상태 변경: 리뷰 → 완료22:24 PR 3-3: 블로그 댓글 + 좋아요 구현
-
팀팀리드 상태 변경: 리뷰 → 완료22:23 PR 2-3: TipTap 에디터 통합 구현
-
팀팀리드 상태 변경: 리뷰 → 완료22:23 PR 3-2: 블로그 SEO + RSS 구현
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 배치 3 전체 완료 — 1266 tests, 85개 신규 테스트 추가, 기존 이슈만 잔존
상세 보기
## 배치 3 완료 요약
- PR 5-3, 7-1, 7-2, 7-3 모두 review 상태 전환
- Fixture FK 수정 (assignments, certificates)
- 병렬 테스트 워커 DB 12개 스키마 동기화
- todo 티켓 0개, 전 배치 review 대기 중 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 4개 티켓 병렬 작업 시작 (PR 5-3, 7-1, 7-2, 7-3)
상세 보기
## 작업 배정
- PR 5-3 비디오 진도 추적 → developer-1
- PR 7-1 수강료 결제 → developer-2
- PR 7-2 워크숍 결제 → developer-3
- PR 7-3 과제+인증서 → developer-4## 충돌 방지
- PR 5-3: study/progresses, video_player Stimulus
- PR 7-1: study/payments (수강료)
- PR 7-2: study/workshop_payments (워크숍)
- PR 7-3: study/assignments + study/certificates + admin
- routes.rb: 각자 담당 영역만 수정 -
팀팀리드 위임: developer-4에게 'PR 7-3: 과제 제출 + 인증서 PDF 구현' 작업 배정
-
팀팀리드 위임: developer-3에게 'PR 7-2: 워크숍 Toss Payments 결제 연동' 작업 배정
-
팀팀리드 위임: developer-2에게 'PR 7-1: 수강료 Toss Payments 결제 연동' 작업 배정
-
팀팀리드 위임: developer-1에게 'PR 5-3: 비디오 진도 추적 Stimulus + API' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰14:24 PR 5-2: 교육 공개 페이지 구현
-
팀팀리드 상태 변경: 할 일 → 리뷰14:24 PR 2-3: TipTap 에디터 통합 구현
-
팀팀리드 3개 티켓 병렬 작업 시작 (PR 2-3, 5-2, 6-2)
상세 보기
## 작업 배정
- PR 2-3 TipTap 에디터 → developer-1
- PR 5-2 교육 공개 페이지 → developer-2
- PR 6-2 Workshop Admin+공개 → developer-3## 충돌 방지
- PR 2-3: admin/blog_posts/ 영역만
- PR 5-2: study/ 컨트롤러+뷰, edu subdomain 라우트
- PR 6-2: admin/expert_courses/ + study/workshops/, admin sidebar 수정
- routes.rb: 각자 담당 영역만 수정 (admin namespace / edu subdomain) -
팀팀리드 위임: developer-3에게 'PR 6-2: Workshop Admin + 공개 페이지 구현' 작업 배정
-
팀팀리드 위임: developer-2에게 'PR 5-2: 교육 공개 페이지 구현' 작업 배정
-
팀팀리드 위임: developer-1에게 'PR 2-3: TipTap 에디터 통합 구현' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰14:02 PR 3-3: 블로그 댓글 + 좋아요 구현
-
팀팀리드 상태 변경: 할 일 → 리뷰14:02 PR 3-2: 블로그 SEO + RSS 구현
-
팀팀리드 4개 티켓 병렬 작업 시작
상세 보기
## 작업 배정
- PR 3-2 SEO+RSS → developer-1
- PR 3-3 댓글+좋아요 → developer-2
- PR 5-1 Enrollment+Progress → developer-3
- PR 6-1 Workshop 모델 → developer-4## 충돌 방지
- PR 3-2/3-3: routes.rb blog subdomain 분리 (feed vs comments/likes)
- PR 3-2: show.html.erb 수정 금지
- PR 5-1/6-1: 완전 독립 모듈 -
팀팀리드 위임: developer-4에게 'PR 6-1: Workshop(Expert) 모델 구현' 작업 배정
-
팀팀리드 위임: developer-3에게 'PR 5-1: Enrollment + Progress 모델 구현' 작업 배정
-
팀팀리드 위임: developer-2에게 'PR 3-3: 블로그 댓글 + 좋아요 구현' 작업 배정
-
팀팀리드 위임: developer-1에게 'PR 3-2: 블로그 SEO + RSS 구현' 작업 배정
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
Ddeveloper-1 Blog Admin CRUD 구현 완료 (24 tests, 0 failures)
상세 보기
## 생성된 파일
### 컨트롤러 (2)
- admin/blog_posts_controller.rb — CRUD + 필터/검색/페이지네이션
- admin/blog_categories_controller.rb — CRUD### 뷰 (9)
- admin/blog_posts/ — index, show, new, edit, _form
- admin/blog_categories/ — index, new, edit, _form### 테스트 (2파일, 24 tests)
- admin/blog_posts_controller_test.rb (14)
- admin/blog_categories_controller_test.rb (10)### 시드
- db/seeds/seed_blog_categories.rb — 12개 기본 카테고리### 수정
- routes.rb — admin blog_posts, blog_categories 추가
- sidebar — 블로그 메뉴 추가
- ko.yml — admin 번역 추가 -
Ddeveloper-1 상태 변경: 진행 중 → 리뷰
-
Ddeveloper-2 블로그 공개 페이지 구현 완료 (73 tests, 0 failures)
상세 보기
## 생성된 파일
- blog/categories_controller.rb — show (slug, 페이지네이션)
- blog/posts/show.html.erb — 상세 (breadcrumbs, 관련글)
- blog/posts/_post_card.html.erb — 카드 partial
- blog/categories/show.html.erb — 카테고리별 목록
- blog/shared/_sidebar.html.erb — 카테고리 + 최근글
- blog/shared/_pagination.html.erb — 수동 페이지네이션## 수정된 파일
- blog/posts_controller.rb — index(12/page), show(slug, 조회수), search(ILIKE)
- blog/posts/index.html.erb — Coming Soon → 실제 목록
- routes.rb — blog subdomain에 posts, categories, search 추가## 주요 구현
- 페이지네이션: 수동 offset/limit (12/page)
- 조회수: increment_counter 동시성 안전
- N+1 방지: includes(:author, :category)
- 비로그인 열람 가능 -
Ddeveloper-2 상태 변경: 진행 중 → 리뷰
-
Ddeveloper-3 Study Admin CRUD 구현 완료 (29 tests, 0 failures)
상세 보기
## 생성된 파일
### 컨트롤러 (3)
- admin/study_courses_controller.rb — CRUD + toggle_active
- admin/study_chapters_controller.rb — CRUD (nested under course)
- admin/study_lessons_controller.rb — CRUD (nested under chapter)### 뷰 (12)
- admin/study_courses/ — index, show (트리 구조), new, edit, _form
- admin/study_chapters/ — new, edit, _form
- admin/study_lessons/ — new, edit, _form### 테스트 (3파일, 29 tests)
- admin/study_courses_controller_test.rb (13)
- admin/study_chapters_controller_test.rb (8)
- admin/study_lessons_controller_test.rb (8)### 수정
- config/routes.rb — admin study routes 추가
- admin/shared/_sidebar.html.erb — 교육 메뉴 추가
- admin/shared/_nav_item.html.erb — education 아이콘 추가 -
Ddeveloper-3 상태 변경: 진행 중 → 리뷰
-
팀팀리드 작업 시작 - Blog Admin + 블로그 공개 + Study Admin 3개 병렬
상세 보기
## 작업 계획
- developer-1: PR 2-2 Blog Admin CRUD (admin/blog_posts, admin/blog_categories)
- developer-2: PR 3-1 블로그 공개 페이지 (blog/posts, blog/categories)
- developer-3: PR 4-2 Study Admin CRUD (admin/study_courses, chapters, lessons)## 파일 충돌 방지 전략
- routes.rb: 각 에이전트가 담당 영역만 수정
- admin sidebar: developer-1이 블로그 메뉴, developer-3이 교육 메뉴 담당
- developer-2는 blog subdomain 영역만 수정 (admin 미접촉) -
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 리뷰 완료 - 승인 [Phase 2] PR 2-1 + [Phase 4] PR 4-1
상세 보기
## 리뷰 결과
- 상태: 승인
- 테스트: 98 runs, 147 assertions, 0 failures## 코드 품질
- 판정: 조건부 승인 (Critical 0, High 4, Medium 6)
- High 이슈는 모두 향후 관련 PR에서 처리:
- Sluggable concern 추출 → PR 2-2/3-1
- slug 중복 suffix → PR 2-2/3-1
- 복합 인덱스 [status, published_at] → PR 3-1
- counter_cache (comments_count, likes_count) → PR 3-3## 보안
- 판정: PASS (Critical 0, High 0, Medium 2)
- Brakeman: 경고 0건
- 의존성: 취약 Gem 0개
- Medium: comment content 길이 제한, materials_url 형식 검증 권장## UX/UI
- P0/P1 이슈 5건 수정 완료
- default_scope 제거, 한글 slug fallback, Finish 레슨 추가, visible scope, inverse_of -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 팀 작업 완료 - Blog 모델 + Study 모델 병렬 구현
상세 보기
## 구현 결과
- Blog 모델 4개: Category, Post, Comment, Like (마이그레이션 + 테스트 + fixtures)
- Study 모델 3개: Course, Chapter, Lesson (마이그레이션 + 테스트 + fixtures + 시드)
- 테스트: 98 runs, 147 assertions, 0 failures## P0/P1 수정 완료
- default_scope 제거 → has_many ordering 람다로 이동
- 한글 slug fallback 추가 (Blog::Post, Category)
- Finish 레슨 시드 추가
- visible scope + published_at 자동설정
- Blog 모델 inverse_of 추가## UX/UI 검토 결과
- 모델 구조가 향후 UI 구현을 잘 지원
- P2/P3 이슈는 컨트롤러 구현 시 함께 처리 예정## 테스트/보안 검증 결과
- brakeman: 경고 0건
- FK/인덱스 모두 적절
- bin/ci rubocop 실패는 기존 코드 문제 (새 코드는 OK) -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰
-
Ddeveloper-2 상태 변경: 리뷰 → 완료
-
Ddeveloper-1 상태 변경: 리뷰 → 완료
-
Qqa-verifier 상태 변경: 할 일 → 완료
-
Uux-reviewer 상태 변경: 할 일 → 완료
-
팀팀리드 UX/QA 리뷰 완료 - P0/P1 수정 진행
상세 보기
## UX 리뷰 결과
- 평가: 개선 필요 (Minor~Medium)
- P0: default_scope 제거, 한글 slug fallback
- P1: Finish 레슨 누락, visible scope, published_at 자동설정## QA 검증 결과
- bin/ci: rubocop 실패 (기존 코드 문제, 새 코드는 OK)
- 테스트: 91 runs, 0 failures
- brakeman: 경고 0건
- 종합: 리뷰 진행 가능## 수정 계획
P0/P1 이슈 5건을 developer로 수정 후 완료 처리 -
Ddeveloper-2 Study 모델 3개 구현 완료 (46/46 테스트 통과)
상세 보기
## 생성된 파일
### 마이그레이션 (3)
- `db/migrate/20260311110000_create_study_courses.rb`
- `db/migrate/20260311110001_create_study_chapters.rb`
- `db/migrate/20260311110002_create_study_lessons.rb`### 모델 (4)
- `app/models/study.rb` — table_name_prefix "study_"
- `app/models/study/course.rb` — recalculate_totals!, slug 자동생성(한글 처리)
- `app/models/study/chapter.rb` — preview/ordered scopes
- `app/models/study/lesson.rb` — video_type enum (vimeo/youtube)### 테스트 (3파일, 46 tests)
- `test/models/study/course_test.rb` (18)
- `test/models/study/chapter_test.rb` (12)
- `test/models/study/lesson_test.rb` (16)### 시드
- `db/seeds/seed_study_courses.rb` — 강점코치 입문 과정 (11챕터, 24레슨, 353분)## 검증
- 46/46 테스트 통과
- 마이그레이션 → 롤백 → 재마이그레이션 성공
- 시드 idempotent 확인
- recalculate_totals! 정상 동작 -
Ddeveloper-2 상태 변경: 할 일 → 리뷰
-
Ddeveloper-1 Blog 모델 4개 구현 완료 (45/45 테스트 통과)
상세 보기
## 생성된 파일
### 마이그레이션 (4)
- `db/migrate/20260311100000_create_blog_categories.rb`
- `db/migrate/20260311100001_create_blog_posts.rb`
- `db/migrate/20260311100002_create_blog_comments.rb`
- `db/migrate/20260311100003_create_blog_likes.rb`
- `db/migrate/20260311123734_create_active_storage_tables.active_storage.rb`### 모델 (5)
- `app/models/blog.rb` — table_name_prefix "blog_"
- `app/models/blog/category.rb`
- `app/models/blog/post.rb`
- `app/models/blog/comment.rb`
- `app/models/blog/like.rb`### 테스트 (4파일, 45 tests)
- `test/models/blog/category_test.rb` (9)
- `test/models/blog/post_test.rb` (21)
- `test/models/blog/comment_test.rb` (9)
- `test/models/blog/like_test.rb` (6)### Fixtures (4)
- `test/fixtures/blog/categories.yml`
- `test/fixtures/blog/posts.yml`
- `test/fixtures/blog/comments.yml`
- `test/fixtures/blog/likes.yml`### 수정된 파일
- `app/models/user.rb` — has_many :blog_posts, :blog_comments, :blog_likes 추가## 검증
- 45/45 테스트 통과
- 마이그레이션 → 롤백 → 재마이그레이션 성공
- Development DB 무사 (users: 9066, sessions: 8509) -
Ddeveloper-1 상태 변경: 할 일 → 리뷰
-
팀팀리드 위임: qa-verifier에게 '테스트 및 품질 검증 (Blog + Study 모델)' 작업 배정
-
팀팀리드 위임: ux-reviewer에게 'UX/UI 디자인 검토 (Blog + Study 모델)' 작업 배정
-
팀팀리드 위임: developer-2에게 'Study 모델 3개 + 마이그레이션 + 시드 구현 (TDD)' 작업 배정
-
팀팀리드 위임: developer-1에게 'Blog 모델 4개 + 마이그레이션 구현 (TDD)' 작업 배정
-
팀팀리드 작업 시작 - Blog 모델 + Study 모델 병렬 진행
상세 보기
## 작업 계획
- PR 2-1 (Blog 모델)과 PR 4-1 (Study 모델) 병렬 구현
- developer-1: Blog::Post, Category, Comment, Like 모델 + 마이그레이션
- developer-2: Study::Course, Chapter, Lesson 모델 + 시드 데이터
- 완료 후 UX/UI 리뷰 + QA 검증## 접근 방식
- 각 developer가 독립적인 테이블/모델을 담당하여 파일 충돌 없음
- TDD 방식: 테스트 먼저 → 구현 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 리뷰 완료 - 승인 (서브도메인 라우팅 설정)
상세 보기
## 리뷰 결과
- 상태: 승인
- 테스트: 6/6 통과, regression 없음## 코드 품질
- BaseController 상속 구조 적절 (ApplicationController → BaseController → PostsController)
- default_url_options 오버라이드로 locale 파라미터 깔끔하게 제거
- skip_before_action :set_sidebar_workspaces 적절 (비인증 페이지)
- strict locals 사용 (_navbar_subdomain)## 보안
- csrf_meta_tags, csp_meta_tag 포함
- allow_unauthenticated_access 적절 (공개 페이지)
- html_safe/raw 사용 없음## UX/UI
- shared/footer 재사용 (법적 정보 포함)
- shared/_navbar_subdomain 추출로 DRY
- yield :head 추가 (SEO 확장성)
- 디자인 토큰 올바르게 사용 -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 팀 작업 완료 - 서브도메인 라우팅 설정
상세 보기
## 수정된 기능
- blog./edu. 서브도메인 라우팅 constraints
- Blog::BaseController, Study::BaseController
- blog.html.erb, study.html.erb 레이아웃
- shared/_navbar_subdomain.html.erb (공통 navbar)
- 임시 컨트롤러/뷰 (Coming Soon)## UX/UI 검토 결과
- P1 수정 완료: footer → shared/footer, yield :head 추가
- P2 수정 완료: navbar partial 추출, skip_before_action 추가
- P3 후속 처리: 배경색 토큰 통일, max-w 통일, 메타태그 보완## 테스트/보안 검증 결과
- 신규 6개 테스트 통과
- 기존 테스트 regression 없음 (기존 8개 실패는 무관)
- CSRF/CSP/XSS 보안 처리 적절## 생성/수정 파일
- config/routes.rb (서브도메인 constraints)
- config/environments/development.rb (hosts 추가)
- app/controllers/blog/base_controller.rb
- app/controllers/study/base_controller.rb
- app/controllers/blog/posts_controller.rb
- app/controllers/study/courses_controller.rb
- app/views/layouts/blog.html.erb
- app/views/layouts/study.html.erb
- app/views/shared/_navbar_subdomain.html.erb
- app/views/blog/posts/index.html.erb
- app/views/study/courses/index.html.erb
- test/controllers/blog/posts_controller_test.rb
- test/controllers/study/courses_controller_test.rb -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
Ddeveloper-1 상태 변경: 할 일 → 완료
-
팀팀리드 위임: developer-1에게 '서브도메인 라우팅 + 베이스 컨트롤러 + 레이아웃 구현' 작업 배정
-
팀팀리드 작업 시작 - 서브도메인 라우팅 설정
상세 보기
## 작업 계획
- 목표: blog./edu. 서브도메인 라우팅 인프라 구축
- 접근: developer 1명으로 라우팅+컨트롤러+레이아웃+테스트 구현## 현재 상태
- 보드: todo 17 / in_progress 1 / done 104
- 이 티켓이 모든 후속 Phase의 기반 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 블로그 + 교육 서브도메인 기능 계획 수립 완료 — 17개 백로그 티켓 생성
상세 보기
## 기능 개요
- blog.9way.co.kr: 블로그 (포스트, 카테고리, 댓글, 좋아요, SEO)
- edu.9way.co.kr: 교육 LMS (코스, 레슨, 수강, 진도추적) + 워크숍 (오프라인)## 분석 결과
- 기존 앱에 Blog/Education 관련 코드 없음 — 완전 신규
- ActiveStorage 설정됨(미사용), Grover(PDF) 사용 가능
- 기존 결제 서비스(Toss Payments) 재사용 가능## 생성된 티켓 (17개, 7 Phase)
- Phase 1: 서브도메인 라우팅 (1개, HIGH)
- Phase 2: 블로그 코어 (3개, HIGH)
- Phase 3: 블로그 퍼블릭 (3개, HIGH)
- Phase 4: 교육 코스 (2개, MEDIUM)
- Phase 5: 교육 수강 (3개, MEDIUM)
- Phase 6: 워크숍 (2개, MEDIUM)
- Phase 7: 결제+고급 (3개, LOW)## 기술적 결정
- 리치 텍스트: text 컬럼 + TipTap (ActionText 대신)
- 이미지: ActiveStorage
- PDF: Grover
- 네임스페이스: Blog::, Study::, Expert::## 계획서
- docs/plans/blog-edu-subdomain.md -
2026년 03월 10일
-
팀팀리드 k6 부하 테스트 스크립트 완료 - 스모크 테스트 통과02:58 k6 부하 테스트 스크립트 작성
상세 보기
## 변경 사항
- `test/load/diagnosis_flow.js` 생성
- slug 수정: `big5-adult` → `big5` (실제 DB slug과 일치)## 스모크 테스트 결과 (로컬 dev, 2 VU, 30초)
- 진단 시작 p95: 53ms (기준 < 2000ms)
- 문항 로드 p95: 245ms (기준 < 1500ms)
- 응답 제출 p95: 73ms (기준 < 3000ms)
- 결과 로드 p95: 16ms (기준 < 2000ms)
- 플로우 완료: 4건
- 에러: 0건## 실행 방법
```
docker run --rm --network host \
-v $(pwd)/test/load:/scripts \
grafana/k6:latest run \
--env BASE_URL=https://9way.org \
/scripts/diagnosis_flow.js
``` -
팀팀리드 상태 변경: 리뷰 → 완료02:58 k6 부하 테스트 스크립트 작성
-
2026년 03월 09일
-
팀팀리드 k6 부하 테스트 스크립트 작성 완료07:25 k6 부하 테스트 스크립트 작성
상세 보기
## 생성 파일
- `test/load/diagnosis_flow.js` (신규)## 주요 기능
- Big5 진단 전체 플로우 시뮬레이션 (5단계)
- ramp-up: 10 → 50 → 100 → 500 → 0
- 커스텀 메트릭 4개 + 실패율 메트릭
- CSRF 토큰 자동 파싱
- 실제 question ID 기반 응답 생성
- 5% 확률 "해당 사항 없음" 시뮬레이션
- thresholds: p95 < 1s, 에러율 < 1% -
팀팀리드 상태 변경: 진행 중 → 리뷰07:24 k6 부하 테스트 스크립트 작성
-
팀팀리드 작업 시작 - k6 부하 테스트 스크립트 작성07:22 k6 부하 테스트 스크립트 작성
상세 보기
## 작업 계획
- 목표: Big5 진단 전체 플로우의 부하 테스트 스크립트 작성
- 접근 방식: 에이전트가 기존 라우트와 API를 분석하여 k6 스크립트 생성## 현재 상태
- 단일 티켓으로 서브 티켓 불필요
- 코드 변경 없이 신규 파일 1개 생성 -
팀팀리드 티켓 클레임 완료07:22 k6 부하 테스트 스크립트 작성
-
팀팀리드 리뷰 완료 - 승인 (Big5 응답 일괄 제출)07:16 Big5 응답 일괄 제출 (레거시 패턴)
상세 보기
## 리뷰 결과
- 상태: 승인 (서브 티켓 2건 모두 완료)## 서브 티켓 결과
1. Server API: 승인 — upsert_all 벌크 저장, 타입 안전성 수정 완료, 테스트 12건 통과
2. Client Stimulus: 승인 — ARIA 접근성, i18n 4개 언어, 타임아웃 토스트 추가 완료## 보안
- Brakeman 0건, bundler-audit 0건
- CWE 스캔 Critical 0건
- XSS 방어 적절 (_escapeHTML, textContent, ERB 자동 이스케이프)## 성과
- HTTP 요청 30배 감소 (30라운드 × AJAX → 최종 1회 제출)
- sessionStorage crash recovery 구현
- 4개 언어 i18n 완전 지원 -
팀팀리드 상태 변경: 리뷰 → 완료07:16 Big5 응답 일괄 제출 (레거시 패턴)
-
팀팀리드 재리뷰 완료 - 승인 (Client: Stimulus 컨트롤러)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 반려사유 3건 모두 수정 확인 (ARIA 접근성, i18n 7개 value, 타임아웃 토스트)
- 보안: PASS — innerHTML은 _escapeHTML()로 보호, 토스트는 textContent 사용, ERB 자동 이스케이프 적용
- i18n: 4개 언어(ko, en, zh, vi) 모두 7개 키 존재 확인 -
팀팀리드 재리뷰 완료 - 승인 (Server: 일괄 제출 API)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 반려사유 3건 모두 수정 확인 (Boolean cast, question_id 타입 통일, index 키 타입 통일)
- 보안: PASS — ActiveModel::Type::Boolean.new.cast() 안전, .to_s 변환 SQL injection 무관
- 테스트: 타입 안전성 테스트 2건 추가, 전체 12 runs 0 failures -
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ffrontend-dev 반려 사유 3건 수정 완료
상세 보기
## 변경 사항
### big5_batch_controller.js
- ARIA: role="radiogroup", role="radio", aria-checked 추가
- ARIA: neither 버튼에 aria-label 추가
- ARIA: selectCard()/selectNeither()에서 aria-checked 토글
- i18n: 7개 Stimulus value 추가 (submittingText, completeTitle 등)
- i18n: _showSubmitting/_showComplete/_showError의 하드코딩 텍스트를 value로 교체
- 타임아웃: _showTimeoutToast() 메서드 추가, 1.5초 토스트 표시 후 다음 라운드 전환### big5_show.html.erb
- 카운트다운에 role="timer" aria-live="polite" 추가
- 7개 data-big5-batch-*-value 속성 추가 (t() 헬퍼로 번역 전달)### i18n 파일 (4개 언어)
- diagnosis.big5.batch.* 키 추가 (ko, en, zh, vi) -
Bbackend-dev 반려 사유 3건 수정 완료
상세 보기
## 변경 사항
### diagnosis_sessions_controller.rb
- `ActiveModel::Type::Boolean.new.cast(r[:selected])` 적용 — 문자열 "false" 안전 처리
- `submitted_ids`를 `.to_s` 변환하여 타입 통일
- `valid_question_id_strings` Set 생성으로 검증 로직 타입 일치
- `string_keyed_index` 변환으로 dna_type nil 방지### diagnosis_sessions_controller_test.rb
- 문자열 "true"/"false" selected 필드 테스트 추가
- 문자열 question_id 검증 및 dna_type 조회 테스트 추가## 테스트 결과
- 12 runs, 63 assertions, 0 failures, 0 errors -
Ffrontend-dev 상태 변경: 진행 중 → 리뷰
-
Bbackend-dev 상태 변경: 진행 중 → 리뷰
-
팀팀리드 리뷰 완료 - 승인 (Puma 스레드 5→7)07:06 Puma 스레드 5 → 7 증가
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 2×7=14 슬롯, 메모리 영향 미미(~14MB). DB pool 자동 연동 확인
- 보안: 이슈 없음
- UX/UI: 해당 없음
- 참고: 배포 후 메모리 사용량 모니터링 권장 -
팀팀리드 리뷰 완료 - 승인 (response_timeout 120→60초)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 이슈 없음. PDF 생성(10-30초) 고려한 60초 설정 합리적
- 보안: 이슈 없음
- UX/UI: 해당 없음 -
팀팀리드 리뷰 완료 - 승인 (Big5Description 쿼리 캐싱)07:05 Big5Description 쿼리 캐싱
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: locale별 캐싱 적절. 이중 캐싱(Rails.cache + 메모이제이션) 효율적
- 보안: 이슈 없음
- UX/UI: 해당 없음 -
팀팀리드 리뷰 완료 - 승인 (N+1 제거 + upsert_all)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: upsert_all 벌크 저장 적절. where(id:).index_by 패턴으로 N+1 제거 확인
- 보안: SQL Injection 위험 없음
- UX/UI: 해당 없음 -
팀팀리드 리뷰 완료 - 승인 (prepare_all_big5_rounds 캐싱)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 캐시 키 설계(session.id + locale) 적절. includes(:translations)로 N+1 방지
- 보안: 캐시 오염 불가 확인
- UX/UI: 해당 없음 -
팀팀리드 리뷰 완료 - 승인 (database.yml pool 키 수정)
상세 보기
## 리뷰 결과
- 상태: 승인
- 코드 품질: 이슈 없음. test 환경 url 고정으로 DATABASE_URL 침투 방지 확인
- 보안: DB 설정 적절
- UX/UI: 해당 없음 -
팀팀리드 리뷰 완료 - 반려 (Client: Stimulus 컨트롤러)
상세 보기
## 리뷰 결과
- 상태: 반려
- bin/ci: 통과## 코드 품질
- sessionStorage crash recovery 잘 구현됨
- XSS 방어 (_escapeHTML) 적절
- catch 블록 에러 무시 (medium) — console.warn 추가 권장## 보안
- CSRF 토큰 헤더 전송 OK
- sessionStorage 동일 탭 한정 OK## UX/UI
- [MUST-FIX] 진단 카드 ARIA 속성 누락 (role="radio", aria-checked, role="radiogroup")
- [MUST-FIX] locale_dropdown ARIA 누락 (aria-expanded, role="menu")
- [MUST-FIX] JS 내 한국어 텍스트 하드코딩 — 4개 언어 지원인데 i18n 미적용
- [MUST-FIX] 타임아웃 자동 스킵 시 사용자 피드백 없음## 수정 필요 사항
- ARIA 접근성 속성 추가
- Stimulus value로 번역 텍스트 전달 또는 서버 렌더링 template 사용
- 타임아웃 스킵 토스트 메시지 추가 -
팀팀리드 리뷰 완료 - 반려 (Server: 일괄 제출 API)
상세 보기
## 리뷰 결과
- 상태: 반려
- bin/ci: 통과 (payments 관련 기존 실패 제외)## 코드 품질
- [CRITICAL] r[:selected] 타입 안전성 — 문자열 "false"가 truthy로 처리되어 모든 응답이 1로 저장될 위험
- [HIGH] question_id 타입 불일치 — String vs UUID Set 비교로 검증 무력화 가능
- [HIGH] valid_questions_index 키 타입 불일치 — dna_type이 nil로 저장될 위험## 보안
- Brakeman/bundler-audit 통과
- upsert_all SQL Injection 위험 없음
- value 필드 Boolean→0/1 변환으로 임의값 주입 불가## UX/UI
- 해당 없음 (서버 API)## 수정 필요 사항
- ActiveModel::Type::Boolean.new.cast() 사용
- r[:question_id].to_s로 타입 통일
- 타입 안전성 테스트 추가 -
팀팀리드 상태 변경: 리뷰 → 진행 중
-
팀팀리드 상태 변경: 리뷰 → 진행 중
-
팀팀리드 상태 변경: 리뷰 → 완료07:04 Puma 스레드 5 → 7 증가
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료07:04 Big5Description 쿼리 캐싱
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 팀 작업 완료 - 성능 최적화 2단계 코드 변경 5건
상세 보기
## 수정된 기능
- database.yml: `max_connections` → `pool` 키 수정 (AR 표준 키)
- deploy.yml: response_timeout 120→60초, RAILS_MAX_THREADS 5→7
- prepare_all_big5_rounds: Rails.cache.fetch 캐싱 (세션별, 1일 TTL)
- build_description_cache: Rails.cache.fetch 캐싱 (locale별, 1일 TTL)## 테스트/보안 검증 결과
- bin/ci: 855 runs, 3 failures/7 errors (모두 pre-existing)
- Brakeman: 신규 이슈 없음
- N+1 쿼리: 없음
- 캐시 키 안전성: 확인 (사용자 입력 미포함)## 변경 파일
- config/database.yml
- config/deploy.yml
- app/controllers/diagnosis_sessions_controller.rb
- app/services/diagnosis/big5_result_formatter.rb
- test/controllers/diagnosis_sessions_controller_test.rb
- test/services/diagnosis/big5_result_formatter_test.rb -
Qqa-verifier 재검증 완료 - 검증 통과
상세 보기
## 재검증 결과
### ✅ 캐싱 구현 확인
**prepare_all_big5_rounds (diagnosis_sessions_controller.rb:364)**
```ruby
Rails.cache.fetch(["big5_rounds", @session.id, I18n.locale], expires_in: 1.day)
```
- 캐시 키: 세션 ID + 로케일 조합 ✅
- 만료: 1일 TTL ✅
- 사용자 입력 미포함: session.id(UUID), I18n.locale(시스템값) ✅
- RNG 시드도 `Digest::MD5.hexdigest(@session.id.to_s)` 방식으로 개선 (process 재시작에도 동일 시드 보장) ✅**build_description_cache (big5_result_formatter.rb:36)**
```ruby
Rails.cache.fetch("big5:descriptions:#{locale}", expires_in: 1.day)
```
- 캐시 키: 로케일 기반 ✅
- 만료: 1일 TTL ✅
- 사용자 입력 미포함 ✅### ✅ 테스트 결과
- 컨트롤러: 10 runs, 23 assertions, 0 failures, 0 errors ✅
- Formatter: 4 runs, 6 assertions, 0 failures, 0 errors ✅
- 전체: 855 runs, 2135 assertions, 3 failures, 7 errors (모두 pre-existing)
- CustomPayments 라우팅 7건 (pre-existing)
- Admin::Payments 3건 (pre-existing)### ✅ 보안 (Brakeman)
- 신규 이슈 없음 (기존 4건 동일)### ✅ N+1 쿼리 없음
- `includes(:translations)` 적용
- `find_quality_code`는 `Rails.cache.fetch("big5:quality_code_map")` 유지### 종합 판정
**검증 통과** — 모든 캐싱 구현이 올바르게 완료됨 -
Rrails-dev 캐싱 최적화 2건 구현 완료
상세 보기
## 변경 사항
### 1. `prepare_all_big5_rounds` 세션별 캐싱
- **파일**: `app/controllers/diagnosis_sessions_controller.rb`
- `Rails.cache.fetch(["big5_rounds", @session.id, I18n.locale], expires_in: 1.day)` 적용
- 세션 ID + locale 기반 캐시 키로 동일 세션 재방문 시 라운드 재생성 방지### 2. `build_description_cache` 쿼리 캐싱
- **파일**: `app/services/diagnosis/big5_result_formatter.rb`
- `Rails.cache.fetch("big5:descriptions:#{locale}", expires_in: 1.day)` 적용
- Big5Description 테이블 쿼리를 locale별로 1일 캐싱### 3. 테스트 추가
- **파일**: `test/controllers/diagnosis_sessions_controller_test.rb` — 캐시 히트/미스, locale별 분리 2건
- **파일**: `test/services/diagnosis/big5_result_formatter_test.rb` — 캐시 동작, DB 쿼리 스킵, locale별 분리, nil json_data 4건### 테스트 결과
- 14 runs, 29 assertions, 0 failures, 0 errors (관련 테스트 전체 통과)
- 기존 실패는 Admin::PaymentsTest, CustomPaymentsTest (변경과 무관) -
Rrails-dev 상태 변경: 진행 중 → 리뷰05:14 Big5Description 쿼리 캐싱
-
Rrails-dev 상태 변경: 진행 중 → 리뷰
-
Qqa-verifier 품질 검증 완료 - 캐싱 미구현 및 테스트 오류 2건 발견
상세 보기
## 검증 결과
### ✅ 합격 항목
- **config/database.yml**: `max_connections` → `pool` 수정 올바름 (Rails 표준 키)
- **config/deploy.yml**: `response_timeout: 60` ✅, `RAILS_MAX_THREADS: 7` ✅
- **Brakeman 보안 스캔**: 신규 이슈 없음 (기존 4건 pre-existing: admin Mass Assignment 3건, payments XSS 1건)
- **N+1 쿼리**: `prepare_all_big5_rounds`에서 `includes(:translations)` 사용 ✅
- **캐시 키 안전성**: `find_quality_code`의 `"big5:quality_code_map"` — 사용자 입력 미포함 ✅
- **Rubocop**: 기존 254건 동일 (pre-existing, 신규 없음)### ❌ 문제 발견
#### 1. 캐싱 미구현 (Critical)
- `prepare_all_big5_rounds`에 `Rails.cache.fetch`가 없음
- `build_description_cache`도 인스턴스 변수 캐시만 있고 Rails.cache 미사용
- 태스크 #2(cache-dev)가 아직 in_progress 상태#### 2. 테스트 오류 2건 (New - 테스트 코드 버그)
```
DiagnosisSessionsControllerTest#test_prepare_all_big5_rounds_caches_result_per_session_and_locale:
NoMethodError: undefined method 'stub' for module RailsDiagnosisSessionsControllerTest#test_prepare_all_big5_rounds_cache_varies_by_locale:
NoMethodError: undefined method 'stub' for module Rails
```
- 원인: `Rails.stub(:cache, cache_store)`는 Minitest에서 module에 사용 불가
- 수정 필요: `Rails.cache` stub 대신 `Rails.cache.write/read` 패턴 또는 `assert_called` 사용#### 3. 미커밋 변경사항
- `config/database.yml`, `config/deploy.yml` 변경이 staged되지 않은 상태
- 커밋 전 확인 필요### 종합 판정
**검증 미통과** — cache-dev 작업 완료 후 재검증 필요 -
Rrails-dev 설정 최적화 3건 구현 완료
상세 보기
## 변경 사항
### 1. database.yml pool 키 수정
- `config/database.yml` 4행: `max_connections` → `pool`
- `ActiveRecord::Base.connection_pool.size` = 5 확인 (pool 키 정상 인식)### 2. response_timeout 축소
- `config/deploy.yml` 17행: `response_timeout: 120` → `60`### 3. Puma 스레드 증가
- `config/deploy.yml` 47행: `RAILS_MAX_THREADS: 5` → `7`
- 배포 시 2×7=14 동시 슬롯 (40% 증가)## 테스트 결과
- 851 tests, 2114 assertions
- 실패 6건 + 에러 9건 = 모두 기존 코드 이슈 (Workspaces, CustomPayments, Admin::Payments, DiagnosisSessionsController)
- config 변경과 무관한 기존 실패
- 개발 DB 정상 (Users: 5) -
Rrails-dev 상태 변경: 진행 중 → 리뷰05:12 Puma 스레드 5 → 7 증가
-
Rrails-dev 상태 변경: 진행 중 → 리뷰
-
Rrails-dev 상태 변경: 진행 중 → 리뷰
-
Rrails-dev 캐싱 최적화 시작
상세 보기
## 작업 범위
- `prepare_all_big5_rounds` 세션별 캐싱 (diagnosis_sessions_controller.rb)
- `build_description_cache` 쿼리 캐싱 (big5_result_formatter.rb)
- 이중 쿼리 제거
- 캐싱 관련 테스트 작성 -
Rrails-dev 설정 최적화 시작
상세 보기
## 작업 범위
- `config/database.yml`: max_connections → pool 키 수정
- `config/deploy.yml`: response_timeout 120 → 60
- `config/deploy.yml`: RAILS_MAX_THREADS 5 → 7 -
팀팀리드 작업 시작 - 성능 최적화 2단계 코드 변경 5건
상세 보기
## 작업 계획
- 목표: 설정 수정 3건 + 캐싱 추가 2건
- 접근 방식: config-dev(설정 3건) + cache-dev(캐싱 2건) 병렬 → qa-verifier 검증## 작업 분배
- config-dev: database.yml pool 키 + response_timeout 60초 + Puma 스레드 7
- cache-dev: prepare_all_big5_rounds 캐싱 + Big5Description 캐싱## 현재 상태
- 보드 현황: backlog 2 / in_progress 5 / review 4 / done 93 -
팀팀리드 티켓 클레임 완료05:09 Puma 스레드 5 → 7 증가
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료05:09 Big5Description 쿼리 캐싱
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 성능 최적화 2단계 계획 수립 - 7개 백로그 생성
상세 보기
## 계획 프로세스
- 3명 에이전트 팀 (analyst, planner, critic) 비평적 상호 평가
- analyst: 10개 핵심 파일 분석, P0~P3 병목 분류
- planner: 8개 PR 분해, ROI 매트릭스 작성
- critic (Devil's Advocate): 수치 근거 검증, 과대평가 반박## 핵심 합의
- 현실적 목표: 1,000명 동시 처리 (3,000명은 단일 서버 불가)
- 가장 큰 병목: `prepare_all_big5_rounds` (300-500ms, 캐싱 가능)
- complete 비동기화: ROI 낮음 (100ms 작업), k6 결과 후 결정으로 보류
- response_timeout: 60초 (PDF 생성 안전 고려)## 생성된 백로그
1. database.yml pool 키 수정 (critical)
2. prepare_all_big5_rounds 캐싱 (critical)
3. Big5Description 캐싱 (high)
4. response_timeout 60초 (high)
5. Puma 스레드 7개 (medium)
6. Cloudflare CDN (high)
7. k6 부하 테스트 (medium) -
팀팀리드 상태 변경: 할 일 → 백로그05:04 k6 부하 테스트 스크립트 작성
-
팀팀리드 상태 변경: 할 일 → 백로그05:04 Cloudflare CDN 설정
-
팀팀리드 상태 변경: 할 일 → 백로그05:04 Puma 스레드 5 → 7 증가
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그05:04 Big5Description 쿼리 캐싱
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 팀 작업 완료 - Big5 일괄 제출 + N+1 제거02:30 Big5 응답 일괄 제출 (레거시 패턴)
상세 보기
## 수정된 기능
- Big5 일괄 제출 API (submit_all_big5_responses): 30라운드 × AJAX → 최종 1회 POST
- Stimulus big5_batch_controller: 클라이언트 라운드 전환 + sessionStorage 백업
- upsert_all: 90개 응답 1회 DB 쿼리 저장
- N+1 제거: SurveyQuestion.find × N → where(id:).index_by## 변경 파일
- app/controllers/diagnosis_sessions_controller.rb (새 액션 + N+1 수정)
- app/services/diagnosis/session_manager.rb (save_responses_bulk)
- config/routes.rb (submit_all_big5_responses 라우트)
- app/javascript/controllers/big5_batch_controller.js (새 파일)
- app/views/diagnosis_sessions/big5_show.html.erb (batch mode)
- app/views/diagnosis_sessions/_big5_guide.html.erb (시작 버튼)
- config/locales/diagnosis/ko.yml (big5_adult i18n)
- test 파일 다수## 테스트/보안 검증 결과
- 새 기능 테스트: 27 runs, 0 failures ✅
- 보안: CSRF, SQL injection, XSS 이슈 없음 ✅
- 기존 실패: CustomPayments 라우팅 (무관)## 해결된 문제
- question_id 검증 불일치: exact match → subset 검증으로 수정
- fixture 부작용: i18n 키 + assert_response 수정 -
팀팀리드 상태 변경: 진행 중 → 리뷰
-
팀팀리드 상태 변경: 진행 중 → 리뷰02:29 Big5 응답 일괄 제출 (레거시 패턴)
-
Rrails-dev fixture 부작용 테스트 2건 수정 완료
상세 보기
## 수정 1: DiagnosisFlowTest#test_index_page_renders_diagnosis_types
- **원인**: `big5_adult` fixture의 `name_key: "diagnosis.types.big5_adult"`에 대한 i18n 키가 locale 파일에 없어서 `feature_tags`가 String 반환 → `.each` 에러
- **수정**: `config/locales/diagnosis/ko.yml`에 `big5_adult` 키 추가 (title, description, features)## 수정 2: DiagnosisFlowTest#test_start_shows_confirm_resume_when_duplicate_within_1_hour
- **원인**: `confirm_resume`는 `status: :unprocessable_entity` (422)로 렌더링하지만 테스트가 `assert_response :success` (200) 기대
- **수정**: `assert_response :success` → `assert_response :unprocessable_entity`
- **추가**: big5 fixture의 `created_at`을 2~3시간 전으로 설정 (duplicate check 영향 방지)## 변경 파일
- `config/locales/diagnosis/ko.yml` — big5_adult i18n 키 추가
- `test/integration/diagnosis_flow_test.rb` — assert_response 수정
- `test/fixtures/diagnosis_sessions.yml` — big5 fixture created_at 조정## 테스트 결과
57 runs, 146 assertions, 0 failures, 0 errors -
Qqa-verifier 테스트 및 품질 검증 완료
상세 보기
## 검증 결과
### 1. 새로운 테스트 (18개 모두 통과 ✅)
- `submit_all_big5_responses` 액션 테스트 5개: 모두 통과
- `save_responses_bulk` 서비스 테스트 2개: 모두 통과
- `submit_big5_round`, `submit_part2_round` 테스트 포함### 2. N+1 쿼리 제거 확인 ✅
- `submit_big5_round`, `submit_part2_round`: `SurveyQuestion.where(id:).index_by` 패턴 사용
- `submit_all_big5_responses`: `valid_questions_index` memoization 적용### 3. 보안 점검
- **CSRF**: Stimulus 컨트롤러에서 `X-CSRF-Token` 헤더 사용 ✅
- **Strong Parameters**: `params.require(:responses)` 사용 ✅
- **SQL injection**: upsert_all에서 records 값이 서버 검증 후 빌드, unique_by/update_only 하드코딩 ✅
- **sessionStorage XSS**: `_escapeHTML()` 처리, 서버 재검증 ✅
- **subset 검증**: invalid_ids 체크로 외부 question_id 주입 차단 ✅
- **Brakeman**: 신규 코드에서 추가 이슈 없음 (기존 이슈만 존재)### 4. 기존 실패 분류
- `CustomPaymentsTest` (7개 오류): 기존 라우팅 오류, 새 코드와 무관 (stash 후 테스트로 확인)
- `DiagnosisFlowTest#test_index_page_renders_diagnosis_types`: **새 fixture(big5_adult) 추가 부작용** - i18n 번역 키 `diagnosis.types.big5_adult.features` 누락
- `DiagnosisFlowTest#test_start_shows_confirm_resume_when_duplicate_within_1_hour`: **새 fixture 부작용** - big5_in_progress 세션 추가로 인해 duplicate 체크 로직에 영향 가능성### 5. Minor 코드 이슈
- `submit_all_big5_responses`에서 `valid_question_ids`(Set)와 `valid_questions_index`(Hash)를 별도 쿼리 (통합 가능)
- question_id 타입 비교: JSON 파싱 시 Integer vs String 불일치 가능성### 종합 판정
✅ 핵심 기능 테스트 통과 | ⚠️ fixture 추가로 인한 2개 기존 테스트 실패 수정 필요 -
Rrails-dev question_id 검증 로직 subset 방식으로 수정 완료
상세 보기
## 문제
- 기존: `submitted_ids.sort == valid_question_ids.sort` (정확 일치 요구)
- 클라이언트는 90개(60긍정 + 30선택부정) 전송, 서버에는 105개(60긍정 + 45부정)
- → 항상 422 실패## 수정 내용
- subset 검증으로 변경: `submitted_ids`가 `valid_question_ids`의 부분집합인지 확인
- 최소 응답 수 검증: `valid_question_ids.size / 2` 이상 필요
- invalid ID 검증: 비-big5 문항 ID 거부## 테스트 변경
- fixture: quality당 부정 문항 1개 → 3개 (production과 동일 구조)
- 새 테스트: subset 수락, 비-big5 ID 거부, 너무 적은 응답 거부
- 48 runs, 129 assertions, 0 failures## 변경 파일
- `app/controllers/diagnosis_sessions_controller.rb`
- `test/controllers/diagnosis_sessions_controller_test.rb`
- `test/fixtures/survey_questions.yml` -
Cclient-dev Stimulus 컨트롤러 구현 완료
상세 보기
## 변경 파일
### 새 파일
- `app/javascript/controllers/big5_batch_controller.js` — Big5 일괄 처리 Stimulus 컨트롤러### 수정 파일
- `app/controllers/diagnosis_sessions_controller.rb` — `prepare_all_big5_rounds` + `generate_big5_round_sequence` private 메서드 추가, show 액션에 1줄 추가
- `app/views/diagnosis_sessions/big5_show.html.erb` — batch mode로 전면 재작성 (big5-batch 컨트롤러 사용)
- `app/views/diagnosis_sessions/_big5_guide.html.erb` — 시작 버튼 action을 big5-batch#startDiagnosis으로 변경## 주요 구현 내용
### Stimulus 컨트롤러 (big5_batch_controller.js)
- 서버에서 모든 라운드 데이터를 JSON으로 받아 클라이언트에서 라운드 전환 (서버 왕복 0회)
- 카드 선택 → 시각 피드백(250ms) → 자동 다음 라운드
- "둘 다 해당 안됨" 버튼 지원
- 30초 카운트다운 타이머 (5초 이하 빨간색 경고)
- 타임아웃 시 자동으로 "neither"로 제출### sessionStorage 관리
- 키: `big5_session_${sessionId}`
- 매 라운드 선택 시 자동 저장 (currentRound + responses 배열)
- 페이지 새로고침 시 복원하여 이어하기
- 완료 시 자동 삭제### 최종 제출
- 마지막 라운드 완료 → fetch POST `/submit_all_big5_responses` (JSON)
- 성공: server redirect_url → Turbo.visit(), 또는 완료 화면 표시
- 실패: 에러 화면 + "다시 시도" 버튼### 라운드 사전 생성 (서버)
- `prepare_all_big5_rounds`: session ID 시드 기반 결정론적 RNG 사용
- 페이지 새로고침해도 같은 라운드 순서 (sessionStorage 호환)
- N+1 방지: `includes(:translations)` 사용
- 번역 없는 문항 자동 필터링## 주의 사항
- backend-dev의 `submit_all_big5_responses` 액션이 submitted_ids == valid_question_ids 검증 사용 중. 클라이언트는 90개(60긍정 + 30선택부정)만 보내는데, valid는 105개(45부정 포함)이므로 검증 불일치 가능. 검증 로직 조정 필요.## 테스트
- 기존 controller 테스트 6개 모두 통과
- 전체 테스트 847개 중 기존 실패(custom_payments, diagnosis_e2e) 외 추가 실패 없음 -
Cclient-dev 상태 변경: 할 일 → 리뷰
-
Rrails-dev Server API 구현 완료
상세 보기
## 변경 파일
### 구현 파일
- `app/controllers/diagnosis_sessions_controller.rb` — submit_all_big5_responses 액션 추가, N+1 제거 (submit_big5_round, submit_part2_round), RecordNotUnique rescue 추가
- `app/services/diagnosis/session_manager.rb` — save_responses_bulk 메서드 추가 (upsert_all 사용), save_response에 RecordNotUnique retry 추가
- `config/routes.rb` — post :submit_all_big5_responses 라우트 추가### 테스트 파일
- `test/controllers/diagnosis_sessions_controller_test.rb` — 신규 (6개 테스트: submit_all_big5_responses 4개 + N+1 제거 검증 2개)
- `test/services/diagnosis/session_manager_test.rb` — save_responses_bulk 테스트 2개 추가
- `test/fixtures/diagnosis_categories.yml` — big5 category 추가
- `test/fixtures/diagnosis_types.yml` — big5_adult type 추가
- `test/fixtures/diagnosis_sessions.yml` — big5 세션 2개 추가
- `test/fixtures/survey_questions.yml` — big5 문항 12개 추가
- `test/controllers/admin/users_controller_test.rb` — fixture 수 변경 반영
- `test/integration/admin/users_test.rb` — fixture 수 변경 반영## 주요 변경 사항
1. **submit_all_big5_responses**: 90개 응답 일괄 제출 API. 세션 상태, question_id 유효성, 응답 수 검증 후 upsert_all로 저장 → complete 처리
2. **save_responses_bulk**: DiagnosisResponse.upsert_all로 1회 쿼리에 전체 응답 저장. unique index(idx_responses_session_question) 기반 upsert
3. **N+1 제거**: submit_big5_round와 submit_part2_round에서 SurveyQuestion.find(qid)를 SurveyQuestion.where(id:).index_by(&:id)로 변경
4. **RecordNotUnique rescue**: save_response의 find_or_initialize_by 레이스 컨디션 방어## 테스트 결과
- 46 runs, 124 assertions, 0 failures, 0 errors, 0 skips -
Rrails-dev 상태 변경: 할 일 → 리뷰
-
Cclient-dev Stimulus 컨트롤러 구현 시작
상세 보기
## 작업 시작
- Big5 일괄 처리 Stimulus 컨트롤러 구현
- sessionStorage 백업/복원
- 클라이언트 라운드 전환
- 최종 일괄 제출 (fetch POST) -
Rrails-dev Server API 구현 시작
상세 보기
## 작업 범위
- submit_all_big5_responses 컨트롤러 액션
- save_responses_bulk 서비스 메서드
- N+1 제거 (submit_big5_round, submit_part2_round)
- 라우트 추가
- TDD 기반 개발 -
팀팀리드 위임: frontend-dev에게 'Client: Stimulus 컨트롤러 + sessionStorage + 라운드 전환' 작업 배정02:00 Big5 응답 일괄 제출 (레거시 패턴)
-
팀팀리드 위임: backend-dev에게 'Server: 일괄 제출 API + upsert_all + N+1 제거' 작업 배정02:00 Big5 응답 일괄 제출 (레거시 패턴)
-
팀팀리드 작업 시작 - Big5 일괄 제출 + N+1 제거02:00 Big5 응답 일괄 제출 (레거시 패턴)
상세 보기
## 작업 계획
- 목표: Big5 진단 HTTP 요청 30배 감소 + DB 쿼리 최적화
- 접근 방식: 서버/클라이언트 분리하여 2명 병렬 개발## 서브 티켓 분해
1. Server: 일괄 제출 API + upsert_all + N+1 제거 (backend-dev)
2. Client: Stimulus 컨트롤러 + sessionStorage + 라운드 전환 (frontend-dev)## 현재 상태
- 보드 현황: backlog 0 / todo 0 / in_progress 3 / review 0 / done 93 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료01:59 Big5 응답 일괄 제출 (레거시 패턴)
-
2026년 03월 06일
-
Ccode-reviewer 캐싱 코드 품질 리뷰 완료 — Major 이슈 3건 발견
상세 보기
## 리뷰 결과: diagnoses_controller.rb + big5_result_formatter.rb
### ✅ 잘된 점
- `Big5ResultFormatter#find_quality_code`: 인스턴스 변수(`@quality_code_map`) + Redis 2단계 캐싱 설계 우수
- `build_description_cache`: locale별 일괄 로드로 N+1 완전 방지
- `expires_in: 30.days`: 불변 진단 결과에 적합한 장기 캐시 설정### 🔴 Major 이슈
**1. 캐시 무효화 전략 누락** (`diagnoses_controller.rb:58, 324`)
- 캐시 키: `["diagnosis_result", @session.id, I18n.locale]`
- 문제: `@session.updated_at` 미포함 → 데이터 변경 후 30일간 stale 캐시 노출 가능
- 수정: `["diagnosis_result", @session.id, @session.updated_at.to_i, I18n.locale]`**2. DRY 위반** (`diagnoses_controller.rb:57-75, 319-341`)
- `show`/`shared` 메서드에서 동일한 캐시+포맷터 분기 코드 약 20줄 중복
- 수정: `cached_diagnosis_result(session)` private 헬퍼 추출**3. edit_branding 캐시 미사용** (`diagnoses_controller.rb:256`)
- `show`와 동일한 포맷터를 매번 재계산 (불일관)
- 수정: `cached_diagnosis_result(@session)` 헬퍼로 통일### 🔵 Minor 이슈
**locale 파라미터 dead code** (`big5_result_formatter.rb:54,68,87,110`)
- `format_big5_chart(locale)` 등 메서드에 locale 파라미터가 있지만 내부에서 `@name_suffix` 사용
- tidy-remove-dead-code: 파라미터 제거 권장### 📋 테스트 커버리지
- 캐싱 관련 테스트: **전무**
- Big5ResultFormatter 단위 테스트: **없음**
- DiagnosesController 직접 테스트: **없음** (API v1만 존재)
- 추가 필요: 캐시 hit/miss 시나리오, 무효화 테스트### 판정: 조건부 승인 (캐시 키 무효화 전략 수정 후 승인)
-
팀팀리드 리뷰 완료 - 승인 (결과 캐싱)14:50 Big5 결과 페이지 캐싱
상세 보기
## 리뷰 결과
- 상태: 승인
- bin/ci: 기존 이슈만 (변경 파일 관련 신규 이슈 없음)## 코드 품질
- Rails.cache.fetch 키 설계 적절 (session.id + locale)
- expires_in: 30.days — 불변 데이터에 적합
- find_quality_code 2단계 캐싱 (인스턴스 + Rails.cache) 효율적
- DRY 개선 가능: show/shared 캐싱 코드 헬퍼 추출 권장## 보안
- PASS (Critical/High 0건)
- 캐시 키 조작 불가 (DB PK + 서버 locale)
- 인증/인가 정상 (set_session before_action)## 개선 제안 (별도 티켓)
- 캐싱 코드 DRY 리팩토링 (private 헬퍼 추출)
- edit_branding에도 캐시 적용 -
Ccode-reviewer Puma 설정 코드 품질 리뷰 완료 — 조건부 승인14:50 Puma 워커/스레드 + DB 풀 설정
상세 보기
## 리뷰 결과: config/puma.rb + config/deploy.yml
### ✅ 잘된 점
- `WEB_CONCURRENCY: 2`, `RAILS_MAX_THREADS: 5` — 4GB 서버(DigitalOcean) 기준 적절한 설정
- `preload_app!` 추가로 Copy-on-Write 메모리 최적화 활성화
- Solid Queue in Puma 단일 서버 배포 최적화### ⚠️ Critical 이슈 (즉시 수정 필요)
**`config/database.yml:4` — DB Connection Pool 부족**
- 현재: `max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>` = 5
- 문제: workers=2, threads=5이면 필요 연결수 = 2×5 = 10 + SolidQueue
- 위험: 프로덕션에서 `ActiveRecord::ConnectionTimeoutError` 발생 가능
- 수정 방안: `DB_POOL: 10`을 deploy.yml에 추가하고 database.yml에서 참조### 🔵 Minor 이슈
**`config/puma.rb:40` — preload_app! 조건 없음**
- workers=0일 때도 무조건 실행 (기능적 문제는 없으나 명확성 부족)
- 개선: `preload_app! if ENV.fetch("WEB_CONCURRENCY", 0).to_i > 0`### 판정: 조건부 승인 (DB pool Critical 수정 후 최종 승인)
-
팀팀리드 리뷰 완료 - 승인 (Puma 튜닝)14:50 Puma 2워커/5스레드 튜닝
상세 보기
## 리뷰 결과
- 상태: 승인
- bin/ci: 기존 이슈만 (변경 파일 관련 신규 이슈 없음)## 코드 품질
- Puma workers 2 + threads 5 설정 적절 (4GB 서버 기준)
- preload_app! Copy-on-Write 활용 정상
- database.yml `max_connections` → `pool` 키 변경 필요 (기존 이슈, 별도 티켓)## 보안
- PASS (Critical/High 0건)
- deploy.yml 시크릿 관리 정상, localhost 바인딩 확인## 개선 제안 (별도 티켓)
- database.yml pool 키 수정 -
팀팀리드 상태 변경: 리뷰 → 완료14:50 Big5 결과 페이지 캐싱
-
팀팀리드 상태 변경: 리뷰 → 완료14:50 Puma 2워커/5스레드 튜닝
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료14:50 Puma 워커/스레드 + DB 풀 설정
-
팀팀리드 팀 작업 완료 - Puma 튜닝 + 결과 캐싱10:50 Puma 2워커/5스레드 튜닝
상세 보기
## 수정된 기능
- Puma 2워커/5스레드 (동시처리 3→10)
- 진단 결과 Rails.cache.fetch 캐싱 (Big5/9Way/Engagement)
- find_quality_code 맵핑 캐시## 변경 파일
- `config/puma.rb` — workers + preload_app!
- `config/deploy.yml` — WEB_CONCURRENCY: 2, RAILS_MAX_THREADS: 5
- `app/controllers/diagnoses_controller.rb` — show/shared 캐싱
- `app/services/diagnosis/big5_result_formatter.rb` — quality_code_map 캐싱## 테스트 결과
- 839 runs, 2102 assertions, 5 failures, 7 errors (기존과 동일, 신규 회귀 없음)## QA 발견 사항
- database.yml의 `max_connections` 키가 Rails `pool`이 아님 — 기존 이슈, 별도 티켓 권장
- 캐시 무효화 로직 미구현 — 재채점 시 stale 가능, 향후 추가 권장 -
팀팀리드 상태 변경: 진행 중 → 리뷰10:49 Big5 결과 페이지 캐싱
-
팀팀리드 상태 변경: 진행 중 → 리뷰10:49 Puma 2워커/5스레드 튜닝
-
Ccache-dev 결과 캐싱 구현 완료
상세 보기
## 변경 파일
- `app/controllers/diagnoses_controller.rb` — show/shared 액션 캐싱
- `app/services/diagnosis/big5_result_formatter.rb` — quality_code_map 캐싱## 변경 내용
### diagnoses_controller.rb (show + shared)
- 3개 scoring_framework 분기 모두에 `Rails.cache.fetch` 적용
- 캐시 키: `["diagnosis_result", session.id, I18n.locale]`
- TTL: 30일 (완료된 진단 결과는 불변)
- show와 shared 액션 모두 동일 캐시 키 → 같은 결과 공유### big5_result_formatter.rb (find_quality_code)
- `Rails.cache.fetch("big5:quality_code_map", expires_in: 1.day)` 적용
- DB pluck 쿼리를 1일 캐싱으로 변경
- 인스턴스 변수(`@quality_code_map`)는 그대로 유지 → 요청 내 이중 캐싱## 테스트 결과
- `bin/rails test` 전체 통과 (기존 실패 12건은 캐싱 무관 — custom_payments, admin/payments 등) -
Ccache-dev 상태 변경: 할 일 → 리뷰
-
Iinfra-dev Puma 설정 변경 완료10:44 Puma 워커/스레드 + DB 풀 설정
상세 보기
## 변경 사항
### config/deploy.yml
- `WEB_CONCURRENCY: 2` 추가 (env.clear)
- `RAILS_MAX_THREADS: 5` 추가 (env.clear)### config/puma.rb
- `workers ENV.fetch("WEB_CONCURRENCY", 0)` 추가
- `preload_app!` 추가 (CoW 메모리 절약)### config/database.yml
- 변경 없음 (이미 `RAILS_MAX_THREADS` 기본값 5 사용 중)## 프로덕션 예상 구성
- 2 workers × 5 threads = 최대 10 동시 요청 처리
- DB pool: 5 (RAILS_MAX_THREADS와 동일)
- SOLID_QUEUE_IN_PUMA와 충돌 없음 확인## 테스트
- `bin/rails test` 실행: 기존 실패(locale 관련) 외 새로운 실패 없음 -
Iinfra-dev 상태 변경: 할 일 → 리뷰10:44 Puma 워커/스레드 + DB 풀 설정
-
Ccache-dev 결과 캐싱 구현 시작
상세 보기
## 작업 범위
- `diagnoses_controller.rb` show 액션에 Rails.cache.fetch 적용
- `big5_result_formatter.rb`의 quality_code_map 캐싱
- 캐시 키: `["diagnosis_result", session.id, locale]`, expires_in: 30.days -
Iinfra-dev Puma 설정 변경 시작10:43 Puma 워커/스레드 + DB 풀 설정
-
팀팀리드 위임: cache-dev에게 '진단 결과 Rails.cache.fetch 적용' 작업 배정10:42 Big5 결과 페이지 캐싱
-
팀팀리드 위임: infra-dev에게 'Puma 워커/스레드 + DB 풀 설정' 작업 배정10:42 Puma 2워커/5스레드 튜닝
-
팀팀리드 작업 시작 - Puma 튜닝 + 결과 캐싱 병렬 진행10:42 Puma 2워커/5스레드 튜닝
상세 보기
## 작업 계획
- 목표: Puma 2워커/5스레드 + Big5 결과 캐싱
- 접근: 2명 개발자 병렬 → QA 검증## 팀 구성
- infra-dev: Puma/DB 설정 변경
- cache-dev: 결과 캐싱 구현
- qa-verifier: 테스트/품질 검증 -
팀팀리드 티켓 클레임 완료10:42 Big5 결과 페이지 캐싱
-
팀팀리드 티켓 클레임 완료10:42 Puma 2워커/5스레드 튜닝
-
팀팀리드 상태 변경: 할 일 → 백로그10:02 Big5 결과 페이지 캐싱
-
팀팀리드 상태 변경: 할 일 → 백로그
-
팀팀리드 상태 변경: 할 일 → 백로그10:02 Big5 응답 일괄 제출 (레거시 패턴)
-
팀팀리드 상태 변경: 할 일 → 백로그10:02 Puma 2워커/5스레드 튜닝
-
2026년 03월 03일
-
Cclaude 상태 변경: 할 일 → 진행 중13:48 Big5 성격 진단 기능 구현
-
2026년 03월 01일
-
팀팀리드 팀 작업 완료 - Consumer 연동 가이드 + OmniAuth Strategy
상세 보기
## 수정된 기능
- **OmniAuth Strategy**: `lib/omniauth/strategies/nineway.rb` — PKCE 지원, /api/v1/me 기반 사용자 정보 조회
- **연동 가이드**: `docs/api/consumer_integration_guide.md` — 10개 섹션, curl + Rails 코드 예시 포함## 테스트 결과
- nineway strategy 테스트: 9개 통과
- 기존 테스트 regression 없음## 생성된 파일
- `lib/omniauth/strategies/nineway.rb`
- `test/lib/omniauth/strategies/nineway_test.rb`
- `docs/api/consumer_integration_guide.md`## 전체 OAuth2 통합 완료 요약
- 티켓 1: doorkeeper 도입 (OAuth2 Provider) — done
- 티켓 2: Resource API 구축 (/api/v1) — done
- 티켓 3: Consumer 연동 가이드 + OmniAuth Strategy — done -
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ddocs-dev 상태 변경: 할 일 → 리뷰
-
Ddocs-dev Consumer 연동 가이드 문서 작성 완료
상세 보기
## 작성 파일\n- `docs/api/consumer_integration_guide.md`\n\n## 문서 구성 (10개 섹션)\n1. 개요 - OAuth2 Provider, 지원 Grant Type\n2. 사전 준비 - Application 등록, Scopes 설명\n3. Authorization Code Grant - PKCE 포함 단계별 흐름, curl 예시\n4. Client Credentials Grant - curl 예시\n5. API Endpoints - /me, /diagnoses, /strength_profile 실제 응답 JSON\n6. 사용자 식별 - provider_uid 매핑\n7. 에러 처리 - 401/403/404, Refresh Token\n8. Rails Consumer 빠른 시작 - Gemfile, Strategy, Controller, API Client\n9. Consumer 마이그레이션 테이블\n10. CORS 설정\n\n## 실제 코드 반영\n- doorkeeper.rb: 스코프(profile, email, diagnoses, strengths), 2시간 만료, PKCE 강제\n- profiles_controller.rb: /me 응답 (id, email, name, locale, role 등)\n- diagnoses_controller.rb: diagnoses 응답 (status, locale, diagnosis_type 등)\n- strength_profiles_controller.rb: strength_profile 응답 (top_dna, top_way, scores 등)\n- kakao.rb: OmniAuth strategy 패턴 참고하여 nineway strategy 예시 작성
-
Sstrategy-dev 상태 변경: 할 일 → 리뷰
-
Sstrategy-dev OmniAuth Strategy 구현 및 테스트 완료
상세 보기
## 생성한 파일
- `lib/omniauth/strategies/nineway.rb` — OmniAuth OAuth2 Strategy
- `test/lib/omniauth/strategies/nineway_test.rb` — 9개 테스트 (전부 통과)## Strategy 구성
- **name**: `nineway`
- **site**: `ENV['NINEWAY_SITE_URL']` (기본값: `https://9way.example.com`)
- **authorize_url**: `/oauth/authorize`
- **token_url**: `/oauth/token`
- **scope**: `profile email`
- **PKCE**: 활성화 (Doorkeeper의 `force_pkce` 설정에 대응)
- **raw_info endpoint**: `/api/v1/me`
- **info 매핑**: `name` → `raw_info["name"]`, `email` → `raw_info["email_address"]`## 테스트 결과
- 9 runs, 10 assertions, 0 failures, 0 errors
- 기존 테스트 regression 없음 (기존 3 failures, 7 errors는 Payment/CustomPayment 관련 기존 이슈)## 참조한 파일
- `lib/omniauth/strategies/kakao.rb` — 기존 패턴 참조
- `config/initializers/doorkeeper.rb` — scope, PKCE 설정 확인
- `app/controllers/api/v1/profiles_controller.rb` — 응답 구조 확인 (`email_address` 필드명) -
Ddocs-dev 작업 시작 - 연동 가이드 문서
상세 보기
## 작업 계획\n- 실제 코드 파악 (doorkeeper, routes, controllers)\n- docs/api/consumer_integration_guide.md 작성\n- 한국어로 작성, 실제 응답 구조 반영
-
Sstrategy-dev 작업 시작 - OmniAuth Strategy
상세 보기
## 작업 범위
- `lib/omniauth/strategies/nineway.rb` 생성
- `test/lib/omniauth/strategies/nineway_test.rb` 테스트 작성
- 기존 kakao strategy 패턴 참조 -
팀팀리드 위임: docs-dev에게 'Consumer 서비스 연동 가이드 문서 작성' 작업 배정
-
팀팀리드 위임: strategy-dev에게 'OmniAuth Strategy (omniauth-9way) 작성 + 테스트' 작업 배정
-
팀팀리드 작업 시작 - Consumer 연동 가이드 + OmniAuth Strategy
상세 보기
## 작업 계획
- 목표: 외부 서비스가 9WAY OAuth2 Provider에 쉽게 연동할 수 있도록 Strategy + 가이드 제공
- 접근 방식: 2개 서브 티켓으로 분해
1. OmniAuth Strategy 작성 + 테스트 (strategy-dev)
2. 연동 가이드 문서 작성 (docs-dev) — 1번과 병렬 가능## 현재 상태
- doorkeeper 도입 완료 (티켓 1 done)
- Resource API 구축 완료 (티켓 2 done)
- 기존 카카오 strategy (lib/omniauth/strategies/kakao.rb) 참고 가능 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - Resource API 구축
상세 보기
## 수정된 기능
- **API Base Controller**: ActionController::API 기반, doorkeeper 토큰 인증, JSON 에러 핸들링
- **GET /api/v1/me**: 현재 사용자 프로필 (profile scope)
- **GET /api/v1/users/:id/diagnoses**: 진단 이력 조회 (diagnoses scope)
- **GET /api/v1/users/:id/strength_profile**: 강점 프로필 (strengths scope, top_dna/way/domain/scores)
- **CORS**: rack-cors gem, /api/* 경로만 허용
- **권한 제어**: Auth Code는 자기 자신만, Client Credentials는 모든 사용자 조회 가능## 테스트 결과
- API controller 테스트: 28개 통과
- API 통합 테스트: 14개 통과
- 기존 doorkeeper 테스트: 20개 통과
- 기존 인증 테스트: 11개 통과## 생성된 파일
- `app/controllers/api/v1/base_controller.rb`
- `app/controllers/api/v1/profiles_controller.rb`
- `app/controllers/api/v1/users/diagnoses_controller.rb`
- `app/controllers/api/v1/users/strength_profiles_controller.rb`
- `config/initializers/cors.rb`
- `test/controllers/api/v1/` (테스트 파일들)
- `test/integration/api_v1_test.rb`## 수정된 파일
- `Gemfile` — rack-cors 추가
- `config/routes.rb` — API namespace 추가 -
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료03:50 Resource API 통합 테스트
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ttest-dev 상태 변경: 할 일 → 리뷰03:50 Resource API 통합 테스트
-
Ttest-dev API 통합 테스트 14개 작성 완료 - 전체 통과03:49 Resource API 통합 테스트
상세 보기
## 작성된 테스트 (test/integration/api_v1_test.rb)
### GET /api/v1/me (3개)
- ✅ 유효한 profile scope 토큰으로 200 + id/email/name 확인
- ✅ 토큰 없이 401
- ✅ profile scope 없는 토큰으로 403### GET /api/v1/users/:id/diagnoses (4개)
- ✅ Authorization Code 토큰으로 자기 진단 조회 성공
- ✅ Client Credentials 토큰으로 조회 성공
- ✅ diagnoses scope 없으면 403
- ✅ 다른 사용자 진단 조회 시 403 (Authorization Code)
- ✅ 응답 필드 검증 (status, diagnosis_type, slug)### GET /api/v1/users/:id/strength_profile (3개)
- ✅ 강점 프로필 조회 성공 + 응답 구조 검증
- ✅ strengths scope 없으면 403
- ✅ 진단 결과 없는 사용자 404### 공통 토큰 검증 (3개)
- ✅ 만료 토큰 401
- ✅ 잘못된 토큰 문자열 401
- ✅ 취소된 토큰 401## 결과
- 14 tests, 40 assertions, 0 failures, 0 errors
- 기존 doorkeeper 테스트 20개와 함께 실행해도 전부 통과 -
Ttest-dev 작업 시작 - API 통합 테스트03:47 Resource API 통합 테스트
상세 보기
## 시작 계획
- GET /api/v1/me 테스트
- GET /api/v1/users/:id/diagnoses 테스트
- GET /api/v1/users/:id/strength_profile 테스트
- 공통: 만료/잘못된 토큰, scope 검증 -
Aapi-dev 상태 변경: 할 일 → 리뷰
-
Aapi-dev 진단/강점 API 구현 완료 - 테스트 20개 전체 통과
상세 보기
## 생성한 파일
- `app/controllers/api/v1/users/diagnoses_controller.rb` - 진단 세션 목록 API
- `app/controllers/api/v1/users/strength_profiles_controller.rb` - 강점 프로필 API
- `test/controllers/api/v1/users/diagnoses_controller_test.rb` - 진단 API 테스트 (10개)
- `test/controllers/api/v1/users/strength_profiles_controller_test.rb` - 강점 API 테스트 (10개)## 구현 내용
### DiagnosesController
- `GET /api/v1/users/:user_id/diagnoses`
- `doorkeeper_authorize! :diagnoses` scope 검증
- Authorization Code: 자기 자신만 조회 가능 (user_id 일치 확인)
- Client Credentials: user_id로 조회 (제한 없음)
- 응답: 진단 세션 목록 (id, status, locale, is_primary, start_time, end_time, diagnosis_type)
- 민감 정보(json_data, share_token, payment_id) 제외### StrengthProfilesController
- `GET /api/v1/users/:user_id/strength_profile`
- `doorkeeper_authorize! :strengths` scope 검증
- 가장 최근 completed 진단의 강점 결과 반환
- 진단 결과 없으면 404
- 응답: top_dna(5개), top_way, top_domain, way_scores, domain_scores, session 메타데이터## 테스트 결과
- API 전체 48개 테스트 통과 (기존 28 + 신규 20)
- 기존 테스트 regression 없음 -
Aapi-dev 작업 시작 - 진단/강점 API
상세 보기
## 구현 대상
- `app/controllers/api/v1/users/diagnoses_controller.rb` - 진단 세션 목록 API
- `app/controllers/api/v1/users/strength_profiles_controller.rb` - 강점 프로필 API## 모델 구조 파악 완료
- DiagnosisSession: status, json_data, user_id, diagnosis_type_id
- DiagnosisType → DiagnosisCategory + DiagnosisTarget
- Diagnosis::ResultFormatter → json_data에서 강점 데이터 추출
- Doorkeeper scopes: diagnoses, strengths -
Bbackend-dev 상태 변경: 할 일 → 리뷰
-
Bbackend-dev API Base Controller + /me endpoint 구현 완료
상세 보기
## 변경 사항
### 신규 파일
- `app/controllers/api/v1/base_controller.rb` — API 기본 컨트롤러
- `ActionController::API` 기반 (세션/CSRF 없음)
- `doorkeeper_authorize!` 인증
- JSON 에러 핸들링 (RecordNotFound, DoorkeeperError)
- `doorkeeper_unauthorized_render_options` / `doorkeeper_forbidden_render_options` 오버라이드
- `current_resource_owner` 헬퍼 메서드
- `app/controllers/api/v1/profiles_controller.rb` — GET /api/v1/me
- `profile` 스코프 필수
- 응답: id, email, name, locale, role, email_verified_at, created_at
- `config/initializers/cors.rb` — CORS 설정
- `/api/*` 경로만 모든 origin 허용
- `test/controllers/api/v1/base_controller_test.rb` — Base 컨트롤러 테스트 (2개)
- `test/controllers/api/v1/profiles_controller_test.rb` — Profiles 컨트롤러 테스트 (6개)### 수정 파일
- `Gemfile` — `rack-cors` gem 추가
- `config/routes.rb` — `namespace :api / :v1` 추가 (me, users/diagnoses, users/strength_profile)### 라우트
| Method | Path | Controller#Action |
|--------|------|-------------------|
| GET | /api/v1/me | api/v1/profiles#show |
| GET | /api/v1/users/:user_id/diagnoses | api/v1/users/diagnoses#show |
| GET | /api/v1/users/:user_id/strength_profile | api/v1/users/strength_profiles#show |### 테스트 결과
- API 테스트 8개 + 기존 doorkeeper 테스트 20개 = 28개 모두 통과
- 기존 테스트 regression 없음 -
Bbackend-dev 작업 시작 - API Base Controller + /me endpoint 구현
-
팀팀리드 위임: test-dev에게 'Resource API 통합 테스트' 작업 배정
-
팀팀리드 위임: api-dev에게 'diagnoses + strength_profile API endpoints' 작업 배정
-
팀팀리드 위임: backend-dev에게 'API Base Controller + routes + /me endpoint' 작업 배정
-
팀팀리드 작업 시작 - Resource API 구축
상세 보기
## 작업 계획
- 목표: doorkeeper Bearer 토큰 기반 Resource API 구축
- 접근 방식: 3개 서브 티켓으로 분해
1. API Base Controller + routes + /me endpoint (backend-dev)
2. diagnoses + strength_profile endpoints (api-dev) — 1번 의존
3. API 통합 테스트 (test-dev) — 1, 2번 의존## 현재 상태
- doorkeeper 도입 완료 (티켓 1 done)
- 현재 API 구조 없음 — 전체 신규 생성 -
팀팀리드 티켓 클레임 완료
-
팀팀리드 팀 작업 완료 - doorkeeper 도입
상세 보기
## 수정된 기능
- **OAuth2 Provider**: doorkeeper v5.8.2 설치, Authorization Code + Client Credentials Grant 지원
- **DB 마이그레이션**: oauth_applications, oauth_access_grants, oauth_access_tokens 테이블 (UUID PK)
- **PKCE 지원**: code_challenge/code_challenge_method 칼럼 추가
- **어드민 UI**: OAuth Application CRUD (검색, 정렬, 페이지네이션), client_secret 1회 노출
- **인증 통합**: 기존 Cookie Session/OmniAuth/Magic Link와 병행 운영## 테스트 결과
- doorkeeper 통합 테스트: 20개 통과
- 어드민 OAuth App 테스트: 16개 통과
- 기존 인증 회귀 테스트: 11개 통과## 생성된 파일
- `config/initializers/doorkeeper.rb`
- `db/migrate/*_create_doorkeeper_tables.rb`
- `db/migrate/*_enable_pkce.rb`
- `app/controllers/admin/oauth_applications_controller.rb`
- `app/views/admin/oauth_applications/` (5개 뷰)
- `test/integration/doorkeeper_oauth_test.rb`
- `test/controllers/admin/oauth_applications_controller_test.rb`## 수정된 파일
- `Gemfile` — doorkeeper 추가
- `config/routes.rb` — use_doorkeeper + admin routes
- `app/models/user.rb` — doorkeeper 관계 추가
- `app/views/admin/shared/_sidebar.html.erb` — OAuth 앱 메뉴
- `config/locales/ko.yml` — 번역 추가## 남은 이슈
- 기존 payments 관련 테스트 실패 10건 (doorkeeper 무관, 기존 버그) -
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료00:26 doorkeeper 통합 테스트
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Bbackend-dev PKCE 마이그레이션 추가 완료
상세 보기
## 변경사항
- `db/migrate/20260301002523_enable_pkce.rb` 실행
- `oauth_access_grants` 테이블에 `code_challenge`(string, nullable) 칼럼 추가
- `oauth_access_grants` 테이블에 `code_challenge_method`(string, nullable) 칼럼 추가
- UUID 관련 영향 없음 (칼럼 추가만)
- 인증 테스트 11/11 통과 확인 -
Aadmin-dev 상태 변경: 할 일 → 리뷰
-
Aadmin-dev OAuth Application 어드민 관리 UI 구현 완료
상세 보기
## 변경 사항
### 새로 생성한 파일
- `app/controllers/admin/oauth_applications_controller.rb` - CRUD 컨트롤러 (index, show, new, create, edit, update, destroy)
- `app/views/admin/oauth_applications/index.html.erb` - 목록 (검색, 정렬, 페이지네이션)
- `app/views/admin/oauth_applications/show.html.erb` - 상세 (client_id, secret 경고, 토큰 목록)
- `app/views/admin/oauth_applications/new.html.erb` - 생성 폼
- `app/views/admin/oauth_applications/edit.html.erb` - 수정 폼
- `app/views/admin/oauth_applications/_form.html.erb` - 공유 폼 partial
- `test/controllers/admin/oauth_applications_controller_test.rb` - 16개 테스트 (전체 통과)### 수정한 파일
- `config/routes.rb` - `resources :oauth_applications` 추가
- `app/views/admin/shared/_sidebar.html.erb` - OAuth 앱 메뉴 추가
- `app/views/admin/shared/_nav_item.html.erb` - OAuth 아이콘(key) 추가
- `config/locales/ko.yml` - 한국어 번역 추가### 주요 기능
- Doorkeeper::Application 모델 CRUD
- client_secret은 생성 직후에만 flash로 1회 표시
- 이름 검색, 정렬(name, created_at, confidential)
- Access Token 목록 (최근 10개, 상태 표시)
- 기존 어드민 UI 패턴(Tailwind) 일관성 유지
- 권한 보호 (admin only)### 테스트 결과
- 16 tests, 50 assertions, 0 failures, 0 errors -
Ttest-dev 상태 변경: 진행 중 → 리뷰00:24 doorkeeper 통합 테스트
-
Ttest-dev doorkeeper 통합 테스트 20개 작성 완료 - 전체 통과00:24 doorkeeper 통합 테스트
상세 보기
## 테스트 파일
`test/integration/doorkeeper_oauth_test.rb`## 테스트 항목 (20개, 전체 통과)
### Authorization Code Grant (5개)
- ✅ 전체 흐름: authorize → code → token 교환 (confidential client)
- ✅ token info 엔드포인트 정상 응답
- ✅ 잘못된 code → invalid_grant 에러
- ✅ 비인증 사용자 → 로그인 페이지 리다이렉트
- ✅ 잘못된 redirect_uri → 400 에러### PKCE - Public Client (2개)
- ✅ code_challenge/code_verifier 포함 시 정상 동작
- ✅ code_challenge 없는 public client 요청 → 400 에러### Client Credentials Grant (3개)
- ✅ confidential client → token 발급 성공
- ✅ 잘못된 secret → invalid_client 에러
- ✅ 존재하지 않는 client → invalid_client 에러### Refresh Token (2개)
- ✅ refresh_token → 새 access_token 발급
- ✅ 잘못된 refresh_token → invalid_grant 에러### Token Revocation (1개)
- ✅ revoke 후 token 무효화 확인### Token Expiration (1개)
- ✅ 만료된 token → unauthorized### Scope Validation (1개)
- ✅ 존재하지 않는 scope → 400 에러### Admin Application Management (2개)
- ✅ admin → OAuth 앱 관리 접근 가능
- ✅ 일반 사용자 → 리다이렉트### 기존 인증 회귀 테스트 (3개)
- ✅ magic link 로그인 정상 동작
- ✅ 세션 로그아웃 정상 동작
- ✅ 비인증 홈페이지 접근 정상 동작## 기존 인증 테스트 회귀 검증
- `test/integration/authentication_test.rb`: 11개 전체 통과 ✅## 발견 이슈 (참고)
- **PKCE 칼럼 미생성**: `oauth_access_grants` 테이블에 `code_challenge`, `code_challenge_method` 칼럼이 없어 PKCE 검증이 불완전함. `rails g doorkeeper:pkce` 마이그레이션 필요.
- 기존 실패 (doorkeeper 무관): Admin::PaymentsTest 3 failures, CustomPaymentsTest 7 errors## 전체 테스트 실행 결과
- 788 runs, 1994 assertions
- doorkeeper 관련 0 failures, 0 errors
- 기존 3 failures, 7 errors (doorkeeper 무관) -
Aadmin-dev 작업 시작 - 어드민 OAuth App UI
상세 보기
## 작업 계획
- Admin::OauthApplicationsController CRUD 생성
- 뷰 파일 생성 (index, show, new, edit, _form)
- 라우트 추가
- 사이드바 네비게이션 메뉴 추가
- 한국어 locale 추가 -
Ttest-dev 작업 시작 - doorkeeper 통합 테스트 작성00:19 doorkeeper 통합 테스트
상세 보기
## 사전 분석 완료
- 기존 인증 패턴 파악 (cookie-based session, magic link)
- test_helper.rb의 sign_in_as 헬퍼 확인
- fixtures 구조 파악 (users.yml 등)
- doorkeeper 설정 확인 (grant_flows, scopes, PKCE 등)## 작업 계획
1. doorkeeper 최종 설정 확인
2. OAuth Application fixture 생성
3. Authorization Code Grant 흐름 테스트
4. Client Credentials Grant 테스트
5. Refresh Token 테스트
6. 기존 인증 회귀 테스트
7. 전체 테스트 실행 검증 -
Ttest-dev 티켓 클레임 완료00:19 doorkeeper 통합 테스트
-
Bbackend-dev 상태 변경: 진행 중 → 리뷰
-
Bbackend-dev doorkeeper 설치 + DB 마이그레이션 + 설정 + 인증 통합 완료
상세 보기
## 변경한 파일
### 1. `Gemfile` — doorkeeper gem 추가
- `gem "doorkeeper"` 추가 (v5.8.2 설치됨)### 2. `db/migrate/20260301001535_create_doorkeeper_tables.rb` — UUID PK 마이그레이션
- `oauth_applications` — UUID PK
- `oauth_access_grants` — UUID PK, `resource_owner_id`(uuid → users FK), `application_id`(uuid → oauth_applications FK)
- `oauth_access_tokens` — UUID PK, `resource_owner_id`(uuid → users FK), `application_id`(uuid → oauth_applications FK)
- 모든 FK에 인덱스 추가### 3. `config/initializers/doorkeeper.rb` — OAuth2 Provider 설정
- `resource_owner_authenticator`: 기존 cookie 기반 세션 인증 활용 (cookies.signed[:session_id])
- `admin_authenticator`: admin? 체크
- `grant_flows`: authorization_code, client_credentials
- `access_token_expires_in`: 2시간
- `use_refresh_token`: 활성화
- `default_scopes`: :profile
- `optional_scopes`: :email, :diagnoses, :strengths
- `force_pkce`: 공개 클라이언트 보안 강화
- `force_ssl_in_redirect_uri`: production에서 강제### 4. `config/routes.rb` — `use_doorkeeper` 추가
- `/oauth/authorize`, `/oauth/token`, `/oauth/revoke`, `/oauth/introspect` 등 엔드포인트 활성화
- `/oauth/applications` 관리 UI 라우트 포함### 5. `app/models/user.rb` — doorkeeper 관계 추가
- `has_many :access_grants` (Doorkeeper::AccessGrant)
- `has_many :access_tokens` (Doorkeeper::AccessToken)### 6. `config/locales/doorkeeper.en.yml` — doorkeeper 기본 로케일 (자동 생성)
## 테스트 결과
- 기존 인증 테스트(authentication_test.rb): **11/11 통과** ✅
- 전체 테스트: 기존 실패(payments 3건, custom_payments 7건)는 doorkeeper와 무관한 기존 버그
- doorkeeper가 기존 인증(Cookie Session, OmniAuth, Magic Link)에 영향 없음 확인 -
Ttest-dev 대기 중 - #1 태스크(doorkeeper 설치) 완료 대기, 기존 테스트 패턴 사전 분석 시작00:15 doorkeeper 통합 테스트
-
Bbackend-dev 작업 시작 - doorkeeper 설치
상세 보기
## 작업 계획
1. 기존 프로젝트 구조 파악 (인증, 모델, 라우트)
2. Gemfile에 doorkeeper 추가 + bundle install
3. doorkeeper:install 제너레이터 실행
4. 마이그레이션 UUID PK로 수정
5. db:migrate 실행
6. initializer 설정
7. routes 설정
8. 기존 인증 테스트 확인 -
Bbackend-dev 티켓 클레임 완료
-
팀팀리드 위임: test-dev에게 'doorkeeper 통합 테스트' 작업 배정
-
팀팀리드 위임: admin-dev에게 'OAuth Application 어드민 관리 UI' 작업 배정
-
팀팀리드 위임: backend-dev에게 'doorkeeper 설치 + DB 마이그레이션 + 설정 + 인증 통합' 작업 배정
-
팀팀리드 작업 시작 - doorkeeper 도입
상세 보기
## 작업 계획
- 목표: 9WAY를 OAuth2 Provider로 전환 (doorkeeper gem)
- 접근 방식: 3개 서브 티켓으로 분해하여 팀 병렬 작업
1. doorkeeper 설치 + 마이그레이션 + 설정 + 인증 통합 (backend-dev)
2. OAuth Application 어드민 관리 UI (admin-dev) — 1번 의존
3. 통합 테스트 (test-dev) — 1번 의존## 현재 상태
- 보드 현황: backlog 0 / todo 2 / in_progress 1 / review 0 / done 78
- 관련 기존 작업: 기존 인증 시스템 (OmniAuth, Magic Link, Session) 유지하면서 병행 -
팀팀리드 티켓 클레임 완료
-
2026년 02월 28일
-
팀팀리드 기능 계획 수립 - Consumer 연동 가이드
상세 보기
## 배경
- 기존 카카오 OmniAuth strategy(lib/omniauth/strategies/kakao.rb) 참고하여 9WAY strategy 작성
- 티켓 1, 2 완료 후 진행## 의존성
- 티켓 1 (doorkeeper 도입) + 티켓 2 (API 구축) 완료 후 진행 -
팀팀리드 기능 계획 수립 - Resource API
상세 보기
## 배경
- 현재 API 구조 없음 (app/controllers/api/ 부재)
- 전체 신규 설계 필요
- doorkeeper 티켓 완료 후 착수## 의존성
- 티켓 1 (doorkeeper 도입) 완료 후 진행 -
팀팀리드 기능 계획 수립 - OAuth2 Provider 통합
상세 보기
## 기능 개요
- 9WAY를 OAuth2 Provider로 전환하여 커리어 관리, 채용, 교육 서비스가 9WAY 계정으로 SSO 로그인## 분석 결과
- 영향 범위: User 모델(관계 추가), routes.rb, Gemfile
- 기존 패턴: OmniAuth(Google/Kakao), Magic Link, Cookie Session — 모두 충돌 없이 병행 가능
- DB: doorkeeper 테이블 4개 추가 (기존 테이블 변경 없음, UUID 설정 필요)## 생성된 티켓
1. 9WAY에 doorkeeper 도입 (priority: high)
2. Resource API 구축 (priority: high)
3. Consumer 연동 가이드 (priority: medium)## 리스크
- 기존 인증과 충돌: 🟢 낮음 (웹=Cookie, API=Bearer 이원화)
- DB 마이그레이션: 🟢 낮음 (추가만, 변경 없음)
- UUID 호환: 🟡 중간 (doorkeeper 기본 integer → UUID 설정 필요)## 기술적 결정
- doorkeeper gem 사용 (Rails OAuth2 Provider 표준)
- 웹 인증과 API 인증 이원화 (기존 시스템 보존)
- Authorization Code Grant (사용자 로그인) + Client Credentials Grant (서버 간 통신) -
팀팀리드 팀 작업 완료 - 할인코드13:37 할인코드
상세 보기
## 수정된 기능
### 1. DB + 모델 (model-dev)
- `discount_codes` 테이블 (이름, 코드, 유형, 값, 적용상품, 사용횟수, 최소금액, 만료일, 활성화)
- `discount_code_products` 조인 테이블
- `payments.discount_code_id` string→UUID FK 변환
- DiscountCode 모델 (enum, scopes, validations, calculate_discount, usable?, use!)
- DiscountCodeProduct 모델
- Payment 모델에 belongs_to :discount_code 추가### 2. 서비스 (model-dev)
- `DiscountCodes::ValidationService` - 코드 유효성 검증 (존재, 활성, 만료, 사용횟수, 최소금액, 상품 적용)
- `DiscountCodes::ApplyService` - 사용 기록 (current_uses 증가 + payment 연결)### 3. 어드민 CRUD (admin-dev)
- `Admin::DiscountCodesController` (index, show, new, create, edit, update, toggle_active)
- 뷰: index(검색/필터/정렬/페이지네이션), show, _form, new, edit
- 사이드바에 "Discount Codes" 메뉴 추가
- 라우트: admin 네임스페이스에 discount_codes 리소스
- 로케일: en, ko, zh, vi 4개 언어### 4. 결제 통합 (payment-dev)
- `DiscountCodesController#validate` JSON API (POST /discount_codes/validate)
- Stimulus `discount_code_controller.js` (입력→검증→UI 업데이트)
- `_discount_code.html.erb` partial
- PaymentsController checkout/success에 할인코드 로직 통합
- CheckoutService에 discount_code_id 파라미터 추가
- 서버측 재검증으로 보안 강화## 테스트 결과
- 전체: **752 runs, 1916 assertions, 0 failures, 0 errors**
- 신규 테스트: 모델 37개 + 서비스 16개 + 어드민 통합 25개 + 결제 컨트롤러 16개## 남은 이슈
- 없음 -
팀팀리드 상태 변경: 진행 중 → 완료13:37 할인코드
-
팀팀리드 상태 변경: 리뷰 → 완료13:37 결제 흐름에 할인코드 통합
-
팀팀리드 상태 변경: 리뷰 → 완료13:37 할인코드 어드민 CRUD + UI
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ppayment-dev 상태 변경: 진행 중 → 리뷰13:36 결제 흐름에 할인코드 통합
-
Ppayment-dev 결제 흐름 할인코드 통합 구현 완료13:36 결제 흐름에 할인코드 통합
상세 보기
## 변경 사항
### 새 파일 생성
- `app/controllers/discount_codes_controller.rb` - 할인코드 검증 API 엔드포인트
- `app/javascript/controllers/discount_code_controller.js` - Stimulus 할인코드 UI 컨트롤러
- `app/views/payments/_discount_code.html.erb` - 할인코드 입력 재사용 Partial
- `test/controllers/discount_codes_controller_test.rb` - 검증 API 테스트 (9건)
- `test/controllers/payments_controller_test.rb` - 결제+할인코드 통합 테스트 (7건)### 수정 파일
- `config/routes.rb` - `POST /discount_codes/validate` 라우트 추가
- `app/controllers/payments_controller.rb` - checkout에 할인코드 검증/적용 로직, success에 ApplyService 호출
- `app/services/payments/checkout_service.rb` - `discount_code_id:` 파라미터 추가
- `config/locales/ko.yml` - discount_codes 번역 추가
- `config/locales/en.yml` - discount_codes 번역 추가
- `config/locales/zh.yml` - discount_codes 번역 추가
- `config/locales/vi.yml` - discount_codes 번역 추가### 보안 수정
- 클라이언트가 임의의 discount_amount를 전달해도 서버에서 항상 재검증
- discount_code_id가 유효하지 않으면 discount_amount = 0으로 강제### 테스트 결과
- 752 runs, 1916 assertions, 0 failures, 0 errors, 0 skips -
Aadmin-dev 상태 변경: 진행 중 → 리뷰13:32 할인코드 어드민 CRUD + UI
-
Aadmin-dev 어드민 할인코드 CRUD 구현 완료 - 전체 테스트 통과13:32 할인코드 어드민 CRUD + UI
상세 보기
## 구현 완료 내역
### 생성된 파일
- `app/controllers/admin/discount_codes_controller.rb` - CRUD + toggle_active (7 actions)
- `app/views/admin/discount_codes/index.html.erb` - 검색/필터/정렬/페이지네이션
- `app/views/admin/discount_codes/show.html.erb` - 상세 뷰 (적용 상품, 최근 결제)
- `app/views/admin/discount_codes/_form.html.erb` - 생성/수정 폼
- `app/views/admin/discount_codes/new.html.erb` - 신규 생성
- `app/views/admin/discount_codes/edit.html.erb` - 수정
- `test/integration/admin/discount_codes_test.rb` - 25개 통합 테스트### 수정된 파일
- `config/routes.rb` - admin 네임스페이스에 discount_codes 리소스 추가
- `app/views/admin/shared/_sidebar.html.erb` - 할인코드 네비 아이템 추가
- `app/views/admin/shared/_nav_item.html.erb` - discount_codes 아이콘 추가
- `config/locales/en.yml` - 영어 번역 추가
- `config/locales/ko.yml` - 한국어 번역 추가
- `config/locales/zh.yml` - 중국어 번역 추가
- `config/locales/vi.yml` - 베트남어 번역 추가### 테스트 결과
- 할인코드 테스트: 25 runs, 48 assertions, 0 failures, 0 errors
- 전체 테스트: 736 runs, 1876 assertions, 0 failures, 0 errors### 구현 기능
- 접근 제어 (admin only)
- 목록 (검색/필터/정렬/페이지네이션)
- 상세 조회 (적용 상품, 최근 결제 내역)
- 생성 (코드 자동생성, 상품 선택)
- 수정
- 활성/비활성 토글 -
Mmodel-dev 상태 변경: 진행 중 → 리뷰
-
Mmodel-dev 모델/서비스 구현 완료
상세 보기
## 생성한 파일
### 마이그레이션
- `db/migrate/20260228140000_create_discount_codes.rb` - discount_codes 테이블 생성
- `db/migrate/20260228140001_create_discount_code_products.rb` - 조인 테이블 생성
- `db/migrate/20260228140002_convert_discount_code_id_to_reference.rb` - payments.discount_code_id를 string→uuid FK 변환### 모델
- `app/models/discount_code.rb` - enum, validations, scopes, calculate_discount, usable?, use!, applicable_to?
- `app/models/discount_code_product.rb` - belongs_to 연관관계, uniqueness 검증### 서비스
- `app/services/discount_codes/validation_service.rb` - 할인코드 유효성 검증 (Result 패턴)
- `app/services/discount_codes/apply_service.rb` - 할인코드 적용 (current_uses 증가, payment 연결)### Fixture
- `test/fixtures/discount_codes.yml` - 7개 (percentage_active, fixed_active, expired, maxed_out, inactive, applies_to_specific, unlimited_uses)
- `test/fixtures/discount_code_products.yml` - 1개### 테스트
- `test/models/discount_code_test.rb` - 33개 테스트
- `test/models/discount_code_product_test.rb` - 4개 테스트
- `test/services/discount_codes/validation_service_test.rb` - 12개 테스트
- `test/services/discount_codes/apply_service_test.rb` - 4개 테스트### 기존 모델 수정
- `app/models/payment.rb` - `belongs_to :discount_code, optional: true` 추가## 테스트 결과
전체 711개 테스트 통과, 0 failures, 0 errors -
Ppayment-dev 결제 할인코드 통합 시작13:24 결제 흐름에 할인코드 통합
상세 보기
## 기존 코드 분석 완료
- PaymentsController: checkout/success 흐름 파악
- CheckoutService: discount_amount 이미 지원
- ConfirmationService: 결제 확인 후 후처리 흐름 파악
- config/routes.rb 구조 파악
- 결제 뷰 파악 (payments/show, custom_payments/show)## 다음 단계
- model-dev의 DiscountCode 모델/서비스 완료 대기
- 그 동안 CSRF 안전한 validate 컨트롤러 + 라우트 + Stimulus + 테스트 준비 -
Ppayment-dev 티켓 클레임 완료13:23 결제 흐름에 할인코드 통합
-
A
-
Aadmin-dev 티켓 클레임 완료13:23 할인코드 어드민 CRUD + UI
-
M
-
Mmodel-dev 티켓 클레임 완료
-
팀팀리드 위임: payment-dev에게 '결제 흐름에 할인코드 통합' 작업 배정13:20 할인코드
-
팀팀리드 위임: admin-dev에게 '할인코드 어드민 CRUD + UI' 작업 배정13:20 할인코드
-
팀팀리드 위임: model-dev에게 '할인코드 DB 마이그레이션 + 모델 + 서비스' 작업 배정13:20 할인코드
-
팀팀리드 작업 시작 - 할인코드13:19 할인코드
상세 보기
## 작업 계획
- 목표: 할인코드 테이블 생성, 결제 시 할인코드 적용, 어드민 관리 메뉴 구현
- 접근 방식: 3명의 에이전트로 병렬 작업 (모델/서비스, 어드민 UI, 결제 통합)## 코드베이스 분석 결과
- Payment 모델에 이미 `discount_amount`, `discount_code_id` 필드 존재
- CheckoutService에 `discount_amount` 파라미터 이미 지원
- 어드민 CRUD 패턴 확립됨 (Products 참고)
- DiscountCode 모델만 추가하면 기존 인프라와 자연스럽게 통합 가능## 서브 티켓 분해
1. **model-dev**: DB 마이그레이션 + 모델 + 서비스 + 테스트
2. **admin-dev**: 어드민 CRUD (컨트롤러/뷰/라우트/사이드바/로케일) + 테스트
3. **payment-dev**: 결제 흐름 통합 (할인코드 입력/검증/적용) + 테스트## 현재 상태
- 보드 현황: backlog 0 / todo 0 / in_progress 1 / review 0 / done 74
- 관련 기존 작업: 개인 결제/크레딧 기능 (done) -
팀팀리드 티켓 클레임 완료13:17 할인코드
-
Cclaude 페이지 이탈 분석 기능 구현 완료12:52 페이지 이탈 분석 기능 구현
상세 보기
## 생성된 파일
- `db/migrate/20260228124836_create_page_views.rb` - 마이그레이션
- `app/models/page_view.rb` - 모델
- `app/controllers/concerns/track_page_view.rb` - 추적 Concern
- `app/jobs/record_page_view_job.rb` - 비동기 기록 Job
- `app/jobs/cleanup_page_views_job.rb` - 90일 정리 Job
- `app/javascript/controllers/page_tracker_controller.js` - Stimulus 컨트롤러
- `app/controllers/page_views_controller.rb` - 체류 시간 업데이트 엔드포인트
- `app/views/admin/statistics/page_analysis.html.erb` - 분석 대시보드 뷰
- `test/models/page_view_test.rb` - 모델 테스트 (14건)
- `test/integration/admin/statistics_page_analysis_test.rb` - 통합 테스트 (5건)
- `test/fixtures/page_views.yml` - 테스트 fixture## 수정된 파일
- `config/routes.rb` - 페이지 분석 라우트 + sendBeacon 엔드포인트
- `app/controllers/admin/statistics_controller.rb` - page_analysis 액션
- `app/controllers/application_controller.rb` - include TrackPageView
- `app/views/admin/statistics/_tab_navigation.html.erb` - 탭 추가
- `app/views/layouts/application.html.erb` - page-tracker 부착
- `app/views/layouts/authenticated.html.erb` - page-tracker 부착
- `app/views/layouts/admin.html.erb` - page-tracker 부착
- `config/locales/ko.yml` - i18n 키 추가
- `config/recurring.yml` - 정리 Job 스케줄## 테스트 결과
636 runs, 1701 assertions, 0 failures, 0 errors -
Cclaude 상태 변경: 진행 중 → 완료12:52 페이지 이탈 분석 기능 구현
-
Cclaude 인프라 에이전트 작업 시작12:48 페이지 이탈 분석 기능 구현
상세 보기
infra-dev 에이전트가 DB 마이그레이션, 모델, Job, Concern, Stimulus 컨트롤러, PageViewsController를 구현 중
-
Cclaude 티켓 클레임 완료12:46 페이지 이탈 분석 기능 구현
-
팀팀리드 모든 서브 티켓 완료, 전체 테스트 613개 통과, 부모 티켓 완료 처리11:36 개인의 결제 크레딧, 결제
상세 보기
## 완료 요약
### 서브 티켓 1: 프로필 탭 네비게이션 (agent-nav) ✅
- `shared/_profile_tabs.html.erb` 생성 (3탭: 내 정보/결제/크레딧)
- `profiles/show.html.erb`에 탭 통합
- `routes.rb`에 credits 라우트 추가
- 4개 언어 i18n 키 추가### 서브 티켓 2: 개인 크레딧 페이지 (agent-credit) ✅
- `credits_controller.rb` 구현 (잔액 + 거래내역)
- `credits/index.html.erb` 구현 (반응형, 빈 상태 처리)
- `credits_helper.rb` 생성 (거래유형 레이블/배지)### 서브 티켓 3: 결제 UI + 취소 정책 (agent-payment) ✅
- `payments/index.html.erb`에 탭 + 영수증 링크 + 취소불가 배지
- `payments/show.html.erb`에 탭 + 리포트 취소 안내
- `payment.rb` refundable?에 REPORT 제외 조건 추가
- `cancellation_service.rb`에 REPORT 전용 에러 메시지### 테스트 결과
613 tests, 1652 assertions, 0 failures, 0 errors -
팀팀리드 상태 변경: 리뷰 → 완료11:36 결제 내역 UI 개선 + 취소 정책
-
팀팀리드 상태 변경: 리뷰 → 완료11:36 개인 크레딧 페이지 생성
-
팀팀리드 상태 변경: 진행 중 → 완료11:36 개인의 결제 크레딧, 결제
-
팀팀리드 상태 변경: 진행 중 → 리뷰11:33 결제 내역 UI 개선 + 취소 정책
-
Aagent-payment 결제 UI 개선 및 리포트 취소 불가 정책 구현 완료07:47 결제 내역 UI 개선 + 취소 정책
상세 보기
## 변경 사항
### 1. 모델 수정: `app/models/payment.rb`
- `refundable?` 메서드에 `&& !payment_type_report?` 조건 추가
- REPORT 결제는 항상 환불 불가### 2. 서비스 수정: `app/services/payments/cancellation_service.rb`
- `validate_cancellation!`에 REPORT 전용 에러 메시지 추가
- "리포트 결제는 취소할 수 없습니다" (refundable? 체크 전에 별도 체크)### 3. 뷰 수정: `app/views/payments/index.html.erb`
- 상단에 `shared/_profile_tabs` 렌더링 (current_tab: "payments")
- 리포트 결제에 빨간색 "취소불가" 배지 표시
- 영수증 URL 존재 시 "영수증 보기" 텍스트 표시### 4. 뷰 수정: `app/views/payments/show.html.erb`
- 상단에 `shared/_profile_tabs` 렌더링
- 리포트 결제: 취소 버튼 대신 "리포트 결제는 취소할 수 없습니다" 안내
- 일반 결제 + refundable?: 기존 취소 버튼 유지### 5. i18n 추가: `config/locales/payments/{ko,en,zh,vi}.yml`
- `payments.index.non_refundable` (취소불가)
- `payments.show.report_no_cancel` (리포트 결제는 취소할 수 없습니다)### 6. Fixture 추가: `test/fixtures/payments.yml`
- `completed_credit_payment` (환불 가능한 일반 결제)
- `old_completed_credit_payment` (7일 초과 결제)
- `canceled_payment` (이미 취소된 결제)### 7. 테스트 생성
- `test/models/payment_test.rb`: refundable? 5개 테스트
- `test/integration/payments_profile_tab_test.rb`: 탭/배지/취소버튼 6개 테스트## 테스트 결과
- 전체 613개 테스트 통과, 0 실패 -
Aagent-credit 상태 변경: 할 일 → 리뷰07:43 개인 크레딧 페이지 생성
-
Aagent-credit 개인 크레딧 페이지 구현 완료07:43 개인 크레딧 페이지 생성
상세 보기
## 변경 사항
- `app/controllers/credits_controller.rb` - ensure_credit!, @credit, @transactions 로드 추가
- `app/views/credits/index.html.erb` - 잔액 카드 + 거래내역 테이블(데스크톱/모바일 반응형) + 빈 상태
- `app/helpers/credits_helper.rb` - transaction_type_label, transaction_type_badge_class 헬퍼
- `test/controllers/credits_controller_test.rb` - 6개 통합 테스트 (인증, 잔액 표시, 거래내역, 빈 상태, 탭 표시)## 테스트 결과
- 전체 602 tests, 0 failures, 0 errors -
Aagent-payment 결제 UI 개선 및 취소 정책 구현 시작07:42 결제 내역 UI 개선 + 취소 정책
상세 보기
## 분석 완료
- `payment.rb`: refundable?에 REPORT 조건 추가 필요
- `cancellation_service.rb`: REPORT 전용 에러 메시지 추가 필요
- `payments/index.html.erb`: 프로필 탭 + 영수증 링크 + 취소불가 배지
- `payments/show.html.erb`: 프로필 탭 + 리포트 취소 안내
- `shared/_profile_tabs.html.erb`: 이미 완성됨 (agent-nav)## TDD 순서
1. Fixture 추가 (analysis_credit 결제)
2. 모델 테스트 작성 → RED
3. 모델 구현 → GREEN
4. CancellationService 업데이트
5. 통합 테스트 작성 → RED
6. View 구현 → GREEN -
Aagent-payment 티켓 클레임 완료07:41 결제 내역 UI 개선 + 취소 정책
-
Aagent-credit 개인 크레딧 페이지 구현 시작07:41 개인 크레딧 페이지 생성
상세 보기
## 작업 범위
- `app/controllers/credits_controller.rb` 보강
- `app/views/credits/index.html.erb` 보강
- `test/controllers/credits_controller_test.rb` 신규 작성## 접근 방식
TDD: 테스트 작성 → 구현 → 검증 -
팀팀리드 이메일 초대 기능 전체 구현 완료07:40 이메일 초대
상세 보기
## 완료 내역
### 1. Mailer 생성 및 이메일 발송 (mailer-dev)
- WorkspaceInvitationMailer 생성 (HTML/Text 템플릿)
- InvitationService.create!에서 target_email 있으면 자동 발송
- 재발송(resend) 기능 추가### 2. 벌크 이메일 초대 (bulk-dev)
- bulk_create 액션 + bulk_create! 서비스 메서드
- textarea 기반 벌크 UI + Stimulus 컨트롤러
- 이메일 파싱/검증/중복 제거### 3. 멤버 승인 상태 표시 (status-dev)
- accepted?/accepted_member 모델 헬퍼
- Pending/Accepted 배지 UI
- 4개 언어 i18n (en/ko/zh/vi)## 테스트 결과
- 모델/서비스/Mailer: 48 tests, 100 assertions, 0 failures
- 컨트롤러: 31 tests, 97 assertions, 0 failures
- **총 79 tests, 197 assertions, 0 failures** -
팀팀리드 상태 변경: 진행 중 → 완료07:40 이메일 초대
-
팀팀리드 상태 변경: 리뷰 → 완료07:40 멤버 승인 상태 표시 및 i18n
-
팀팀리드 상태 변경: 리뷰 → 완료07:40 벌크 이메일 초대 기능
-
팀팀리드 상태 변경: 리뷰 → 완료07:40 Mailer 생성 및 이메일 발송 연동
-
팀팀리드 커스텀 결제 메뉴 기능 구현 완료07:40 커스텀 결제 메뉴
상세 보기
## 완료 요약
3명의 에이전트 팀으로 작업 완료. 총 45건 테스트 통과 (0 failures).## 구현 내역
### 1. 백엔드 (모델 + 마이그레이션 + 라우팅 + 서비스)
- `CustomPaymentLink` 모델 (UUID PK, enum status, token 기반)
- DB 마이그레이션 (custom_payment_links 테이블)
- Admin + 공개 라우팅
- `CreateService`, `CancelService`
- 모델 테스트 18건 + 서비스 테스트 6건 = 24건 통과### 2. 관리자 UI
- `Admin::CustomPaymentLinksController` (index, new, create, cancel, qr_code)
- 결제 링크 목록 (테이블 + 상태 배지 + 복사/취소/QR)
- 결제 링크 생성 폼
- 사이드바 메뉴 추가
- i18n 번역
- Stimulus 컨트롤러 (clipboard, qr_modal)
- 통합 테스트 9건 통과### 3. 고객 결제 페이지
- `CustomPaymentsController` (show, checkout, success, fail)
- Toss Payments SDK 연동
- 상태별 뷰 (결제/성공/실패/만료/취소/완료)
- 전용 레이아웃 (custom_payment)
- 통합 테스트 12건 통과 -
Aagent-nav 상태 변경: 할 일 → 완료07:40 프로필 탭 네비게이션 + 라우트 + i18n
-
Aagent-nav 프로필 탭 네비게이션 + 라우트 + i18n 구현 완료07:40 프로필 탭 네비게이션 + 라우트 + i18n
상세 보기
## 완료 사항
### 생성 파일
- `app/views/shared/_profile_tabs.html.erb` - 3탭(내 정보/결제/크레딧) Partial
- `app/controllers/credits_controller.rb` - 크레딧 컨트롤러
- `app/views/credits/index.html.erb` - 크레딧 페이지 (플레이스홀더)
- `test/integration/profile_tabs_test.rb` - 통합 테스트 6개### 수정 파일
- `app/views/profiles/show.html.erb` - 탭 렌더 추가
- `config/routes.rb` - credits 라우트 추가
- `config/locales/ko.yml` - tabs i18n 추가
- `config/locales/en.yml` - tabs i18n 추가
- `config/locales/zh.yml` - tabs i18n 추가
- `config/locales/vi.yml` - tabs i18n 추가### 테스트 결과
- 6 tests, 27 assertions, 0 failures
- 전체 596 tests 통과 -
팀팀리드 상태 변경: 진행 중 → 완료07:40 커스텀 결제 메뉴
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상품 관리 기능 구현 완료07:39 상품 관리
상세 보기
## 완료 내역
### 백엔드 (backend-dev)
- `config/routes.rb`: admin/products 라우트 추가 (CRUD + toggle_active)
- `app/controllers/admin/products_controller.rb`: 신규 생성
- `app/models/product.rb`: accepts_nested_attributes_for 추가### 프론트엔드 (frontend-dev)
- `app/views/admin/products/`: index, show, new, edit, _form 5개 파일
- `app/views/admin/shared/_sidebar.html.erb`: products 메뉴 추가
- `app/views/admin/shared/_nav_item.html.erb`: products 아이콘 추가
- `config/locales/ko.yml`, `en.yml`: i18n 번역 추가### 테스트 (tester)
- `test/integration/admin/products_test.rb`: 25개 테스트, 64 assertions, 전체 통과
- fixtures 보완 (products.yml, product_prices.yml) -
팀팀리드 상태 변경: 진행 중 → 완료07:39 상품 관리
-
팀팀리드 상태 변경: 리뷰 → 완료07:39 Admin Products 통합 테스트 구현
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 통계 관리 기능 구현 완료07:39 통계 관리
상세 보기
## 구현 완료 항목
### 인프라
- Chartkick + Groupdate gem 추가
- Chart.js importmap 설정
- 4개 라우트: /admin/statistics, /users, /diagnoses, /revenue
- 사이드바에 통계 메뉴 + 아이콘 추가### 컨트롤러
- `Admin::StatisticsController` (4개 액션)
- show: KPI 카드 + 추이 차트
- users: 가입 추이, 역할 분포, 활성 사용자
- diagnoses: 완료 추이, 상태/유형 분포, 완료율
- revenue: 매출 추이, 결제 유형, 크레딧 사용### 뷰 (5개 파일)
- `show.html.erb`: 개요 대시보드 (KPI 6개 + 차트 3개)
- `users.html.erb`: 사용자 분석 (차트 3개 + 테이블)
- `diagnoses.html.erb`: 진단 분석 (차트 3개 + 테이블)
- `revenue.html.erb`: 매출 분석 (차트 5개 + 테이블)
- `_tab_navigation.html.erb`: 공유 탭 네비게이션### 테스트
- `test/integration/admin/statistics_test.rb` (17 runs, 65 assertions)### 검증
- Ruby 구문 검증: OK
- ERB 구문 검증: 5개 파일 모두 OK
- 라우트 확인: 4개 정상 등록 -
팀팀리드 상태 변경: 진행 중 → 완료07:39 통계 관리
-
팀팀리드 상태 변경: 리뷰 → 완료07:38 매출 분석 뷰 + 통합 테스트
-
팀팀리드 상태 변경: 리뷰 → 완료07:38 사용자 + 진단 분석 뷰
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ttester 상태 변경: 할 일 → 리뷰07:38 Admin Products 통합 테스트 구현
-
Ttester Admin Products 통합 테스트 구현 완료, 25개 테스트 전체 통과07:38 Admin Products 통합 테스트 구현
상세 보기
## 작업 내용
### Fixtures 보완
- `test/fixtures/products.yml`: `credit_pack_10` (크레딧팩, active), `inactive_product` (비활성 리포트) 추가
- `test/fixtures/product_prices.yml`: `credit_pack_10_krw` 추가### 통합 테스트 작성 (25개)
파일: `test/integration/admin/products_test.rb`**인증/권한 (3개)**
- 비인증 사용자 → session/new 리다이렉트
- 일반 사용자 → root_path 리다이렉트
- admin 사용자 → 접근 성공**Index (8개)**
- 목록 표시, name 검색(q 파라미터)
- product_type 필터 (report/credit_pack)
- active 필터 (true/false)
- 정렬 (name asc/created_at desc)
- 복합 검색+필터**CRUD (8개)**
- show: 상세 표시, product_prices 테이블
- new: 폼 렌더링
- create: 성공, slug 중복 실패, 필수값 누락 실패
- edit: 폼 렌더링
- update: 성공, 실패, nested product_prices**Toggle Active (2개)**
- active → inactive
- inactive → active### 결과
- 25 runs, 64 assertions, **0 failures, 0 errors** -
결결제-페이지 상태 변경: 진행 중 → 리뷰
-
결결제-페이지 고객 결제 페이지 + Toss Payments 연동 구현 완료, 12개 테스트 전부 통과
상세 보기
## 생성된 파일
- `app/controllers/custom_payments_controller.rb` - 공개 결제 컨트롤러 (show/checkout/success/fail)
- `app/views/layouts/custom_payment.html.erb` - 심플 레이아웃 (Toss SDK 포함)
- `app/views/custom_payments/show.html.erb` - 결제 페이지 (로고+상품정보+결제버튼)
- `app/views/custom_payments/success.html.erb` - 결제 성공 페이지
- `app/views/custom_payments/fail.html.erb` - 결제 실패 페이지
- `app/views/custom_payments/expired.html.erb` - 만료 안내 페이지
- `app/views/custom_payments/canceled.html.erb` - 취소 안내 페이지
- `app/views/custom_payments/completed.html.erb` - 이미 완료 안내 페이지
- `app/javascript/controllers/toss_custom_payment_controller.js` - Toss Payments Stimulus 컨트롤러
- `test/integration/custom_payments_test.rb` - 통합 테스트 12개## 테스트 결과
12 runs, 33 assertions, 0 failures, 0 errors, 0 skips## 주요 구현 내용
- `allow_unauthenticated_access`로 인증 skip (공개 페이지)
- `Payments::CheckoutService` 연동 (checkout 액션)
- `Payments::ConfirmationService` 연동 (success 액션)
- 결제 링크 상태별 분기 렌더링 (pending/completed/canceled/expired)
- Toss Payments v2 SDK + Stimulus 컨트롤러로 결제 플로우 연동
- locale scope 밖 라우트를 위해 `default_url_options` 오버라이드 -
팀팀리드 사용자 관리 기능 전체 완료07:37 사용자 관리
상세 보기
## 최종 결과
- 구현: impl-dev 완료 (5개 태스크)
- 테스트: test-dev 완료 (30 tests, 90 assertions, 0 failures)## 구현된 기능
1. 인덱스에 이름/이메일/전화번호/역할/소속워크스페이스/생성일/진단 표시
2. 역할 뱃지 클릭 시 드롭다운으로 즉시 수정 가능
3. 진단 수 클릭 시 모달로 진단 목록 표시
4. 전화번호 검색 지원
5. i18n 처리 완료## 변경 파일
- `app/controllers/admin/users_controller.rb`
- `app/views/admin/users/index.html.erb`
- `app/views/admin/users/_role_cell.html.erb` (신규)
- `app/views/admin/users/_diagnosis_modal.html.erb` (신규)
- `config/routes.rb`
- `config/locales/ko.yml`
- `test/controllers/admin/users_controller_test.rb` (신규)
- `test/integration/admin/users_test.rb` (확장)
- `test/fixtures/user_profiles.yml` (수정) -
팀팀리드 상태 변경: 진행 중 → 완료07:37 사용자 관리
-
팀팀리드 상태 변경: 리뷰 → 완료07:37 사용자 관리 기능 테스트 작성
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ttest-dev 상태 변경: 진행 중 → 리뷰07:37 사용자 관리 기능 테스트 작성
-
Ttest-dev 컨트롤러 + 통합 테스트 작성 완료 (30 tests, 90 assertions, 0 failures)07:37 사용자 관리 기능 테스트 작성
상세 보기
## 작성한 테스트 파일
### 1. test/controllers/admin/users_controller_test.rb (신규, 12 tests)
- 전화번호 검색: 전체 번호, 부분 번호, 미매칭 케이스
- 인덱스 컬럼: 전화번호, 워크스페이스명, 진단 수 표시 확인
- update_role: HTML 요청 성공, turbo_stream 응답 성공, 유효하지 않은 역할 에러
- 권한: 비admin 접근 거부, 비admin 역할 변경 거부, 미인증 리다이렉트### 2. test/integration/admin/users_test.rb (확장, 18 tests)
- 기존 9개 테스트 유지
- 추가: coach/org_admin 접근 거부, 전화번호 컬럼, 워크스페이스 컬럼, 진단 수 컬럼, 전화번호 검색, update_role 플로우 (HTML + turbo_stream), 비admin update_role 거부### 3. test/fixtures/user_profiles.yml (수정)
- daniel_profile에 phone_number/phone_country_code 추가### 인프라 이슈
- test DB에 CustomPaymentLink 테이블이 누락되어 있었음 → db:schema:load로 해결 -
Aanalytics-dev-2 상태 변경: 할 일 → 리뷰07:37 매출 분석 뷰 + 통합 테스트
-
Aanalytics-dev-2 매출 분석 뷰 + 통합 테스트 구현 완료07:37 매출 분석 뷰 + 통합 테스트
상세 보기
## 생성된 파일
### 1. app/views/admin/statistics/revenue.html.erb
- KPI 카드 3개: 총 매출, 이번달 매출, 결제 건수
- 일별 매출 추이 (area_chart, full width)
- 월별 매출 + 결제 유형별 매출 (column_chart + pie_chart)
- 결제 상태 분포 + 워크스페이스 크레딧 사용 (pie_chart + bar_chart)
- 상위 결제 사용자 테이블 (순위, 이름, 이메일, 금액)
- Tailwind CSS, i18n, Chartkick 헬퍼 활용### 2. test/integration/admin/statistics_test.rb
- 17개 테스트 케이스, 65개 assertions, 모두 통과
- 비인증 사용자 접근 차단 (4개 액션)
- 일반 사용자 접근 차단 (4개 액션)
- 관리자 정상 접근 (4개 액션 + 제목 확인)
- revenue 페이지 콘텐츠 검증 (탭, KPI, 차트, 테이블)
- show 페이지 탭 네비게이션 검증 -
백백엔드 상태 변경: 진행 중 → 리뷰
-
백백엔드 CustomPaymentLink 모델, 마이그레이션, 라우팅, 서비스 구현 완료
상세 보기
## 완료 사항
- DB 마이그레이션: `20260228072648_create_custom_payment_links.rb` 생성 및 실행 완료
- 모델: `app/models/custom_payment_link.rb` (enum, validations, scopes, callbacks)
- 서비스: `CreateService`, `CancelService` 생성
- 라우팅: admin namespace + 공개 결제 라우트 추가
- Fixture: pending/completed/canceled/expired 4종 생성
- 테스트: 모델 테스트 18건 + 서비스 테스트 6건 = 24건 전체 통과## 생성/수정 파일
- `db/migrate/20260228072648_create_custom_payment_links.rb`
- `app/models/custom_payment_link.rb`
- `app/services/custom_payment_links/create_service.rb`
- `app/services/custom_payment_links/cancel_service.rb`
- `config/routes.rb`
- `test/fixtures/custom_payment_links.yml`
- `test/models/custom_payment_link_test.rb`
- `test/services/custom_payment_links/create_service_test.rb`
- `test/services/custom_payment_links/cancel_service_test.rb` -
Mmailer-dev 상태 변경: 할 일 → 리뷰07:36 Mailer 생성 및 이메일 발송 연동
-
Mmailer-dev Mailer 생성 및 이메일 발송 연동 완료07:36 Mailer 생성 및 이메일 발송 연동
상세 보기
## 구현 완료 내역
### 1. WorkspaceInvitationMailer 생성
- `app/mailers/workspace_invitation_mailer.rb` - invitation_email 액션
- `app/views/workspace_invitation_mailer/invitation_email.html.erb` - HTML 템플릿 (MagicLinkMailer 스타일)
- `app/views/workspace_invitation_mailer/invitation_email.text.erb` - 텍스트 템플릿### 2. InvitationService 이메일 발송 연동
- `app/services/workspaces/invitation_service.rb`
- `create!` 메서드 끝에서 target_email이 있으면 이메일 발송 (`deliver_later`)
- `send_invitation_email` 클래스 메서드 추가 (resend에서도 재사용)
- rescue로 이메일 발송 실패 시에도 초대 생성은 유지### 3. resend 기능
- `config/routes.rb` - invitations에 `member { post :resend }` 추가
- `app/controllers/workspaces/invitations_controller.rb` - resend 액션 추가### 4. i18n (ko/en)
- `workspace_invitation_mailer.invitation_email.*` 키 추가 (subject, greeting, instruction, button, expires_info, ignore)
- `workspaces.invitations.flash.resent`, `no_email` 키 추가### 5. 테스트 (34 tests, 105 assertions, 0 failures)
- `test/mailers/workspace_invitation_mailer_test.rb` - 5 tests
- `test/services/workspaces/invitation_service_test.rb` - 이메일 관련 3 tests 추가
- `test/controllers/workspaces/invitations_controller_resend_test.rb` - 3 tests -
Aanalytics-dev-1 상태 변경: 할 일 → 리뷰07:36 사용자 + 진단 분석 뷰
-
Aanalytics-dev-1 사용자 + 진단 분석 뷰 구현 완료07:36 사용자 + 진단 분석 뷰
상세 보기
## 생성된 파일
- `app/views/admin/statistics/users.html.erb` - 사용자 분석 뷰
- `app/views/admin/statistics/diagnoses.html.erb` - 진단 분석 뷰## users.html.erb
- KPI 카드 3개: 프로필 완성률, 총 사용자 수, 역할 수
- 차트: 일별 가입자 추이 (line_chart), 역할 분포 (pie_chart)
- 월별 활성 사용자 (column_chart, full width)
- 상위 사용자 테이블 (이름, 이메일, 완료 수)## diagnoses.html.erb
- KPI 카드 3개: 평균 완료 시간(분 변환), 총 세션, 완료율
- 차트: 일별 완료 추이 (line_chart), 상태별 분포 (pie_chart)
- 유형별 분포 (column_chart, full width)
- 유형별 완료율 테이블 (색상 뱃지: >=70% 녹색, >=40% 노란색, 나머지 빨간색)## 공통 패턴
- show.html.erb의 디자인 패턴 일관 유지
- Tailwind CSS + Chartkick
- i18n 키 활용 (ko.yml의 statistics.users/diagnoses 키)
- 모바일 반응형 (grid-cols-1 → md/lg breakpoints) -
관관리자-UI 상태 변경: 진행 중 → 리뷰
-
관관리자-UI 관리자 커스텀 결제 링크 UI 구현 완료, 테스트 9/9 통과
상세 보기
## 생성된 파일
- `app/controllers/admin/custom_payment_links_controller.rb` - 컨트롤러 (index, new, create, cancel, qr_code)
- `app/views/admin/custom_payment_links/index.html.erb` - 목록 페이지 (테이블 + QR 모달)
- `app/views/admin/custom_payment_links/new.html.erb` - 생성 폼
- `app/javascript/controllers/qr_modal_controller.js` - QR 모달 Stimulus 컨트롤러
- `test/integration/admin/custom_payment_links_test.rb` - 통합 테스트 9개## 수정된 파일
- `app/views/admin/shared/_sidebar.html.erb` - 커스텀 결제 메뉴 추가
- `app/views/admin/shared/_nav_item.html.erb` - custom_payments 아이콘 추가
- `config/locales/ko.yml` - i18n 키 추가 (nav + custom_payment_links 전체)## 재사용한 기존 코드
- `clipboard_controller.js` - 복사 기능
- Admin::BaseController - 인증/권한
- 기존 admin 테이블 UI 패턴## 테스트 결과
- 9 runs, 31 assertions, 0 failures, 0 errors -
Aanalytics-dev-2 매출 분석 뷰 + 통합 테스트 구현 시작07:35 매출 분석 뷰 + 통합 테스트
-
Aanalytics-dev-1 사용자 + 진단 분석 뷰 구현 시작07:34 사용자 + 진단 분석 뷰
-
팀팀리드 인프라 + 컨트롤러 + 개요 대시보드 구현 완료 확인07:33 통계 관리
상세 보기
## 완료된 서브 티켓
- 서브 티켓 #1 (3fce970e): 인프라 설정 + 통계 컨트롤러 + 개요 대시보드 → review 상태## 다음 단계
- 서브 티켓 #2: 사용자 + 진단 분석 뷰 (analytics-dev-1 배정)
- 서브 티켓 #3: 매출 분석 뷰 + 테스트 (analytics-dev-2 배정)
- 두 에이전트 동시 spawn 진행 -
Bbackend-dev 상태 변경: 할 일 → 리뷰
-
Bbackend-dev 인프라 설정 + 통계 컨트롤러 + 개요 대시보드 구현 완료
상세 보기
## 변경 사항
### 1. Gemfile
- `chartkick` gem 추가 (차트 렌더링)
- `groupdate` gem 추가 (group_by_day/month 메서드)### 2. importmap + JS 설정
- `config/importmap.rb`에 chartkick, Chart.bundle pin 추가
- `app/javascript/application.js`에 import 추가### 3. 라우트
- `config/routes.rb`의 admin 네임스페이스에 statistics 라우트 4개 추가
- GET /admin/statistics → show (개요)
- GET /admin/statistics/users → users
- GET /admin/statistics/diagnoses → diagnoses
- GET /admin/statistics/revenue → revenue### 4. 사이드바 + 아이콘
- `_sidebar.html.erb`에 통계 메뉴 추가
- `_nav_item.html.erb`에 statistics 아이콘 SVG 추가### 5. 컨트롤러
- `app/controllers/admin/statistics_controller.rb` 생성
- show: KPI 메트릭 + 추이 차트 데이터
- users: 사용자 분석 데이터
- diagnoses: 진단 분석 데이터
- revenue: 매출 분석 데이터### 6. 뷰
- `app/views/admin/statistics/show.html.erb` - 개요 대시보드 (KPI 카드 6개 + 차트 3개)
- `app/views/admin/statistics/_tab_navigation.html.erb` - 탭 네비게이션 파셜### 7. i18n
- `config/locales/ko.yml`에 admin.nav.statistics 및 admin.statistics 번역 키 전체 추가### 검증
- `bin/rails routes | grep statistics` → 4개 라우트 확인
- Chartkick, Groupdate, Controller 로드 확인 -
Ffrontend-dev 상태 변경: 할 일 → 리뷰
-
Ffrontend-dev 뷰 + 사이드바 + i18n 구현 완료
상세 보기
## 변경 사항
### 뷰 파일 (app/views/admin/products/)
- `index.html.erb`: 검색/필터, 테이블(slug, name, product_type, price, active, created_at), 페이지네이션
- `show.html.erb`: 상품 정보 카드, active 토글 버튼, 다통화 가격 테이블, metadata 표시
- `new.html.erb`: 새 상품 등록 폼 래퍼
- `edit.html.erb`: 상품 수정 폼 래퍼
- `_form.html.erb`: 공유 폼 (name, slug, description, price, currency, product_type, active, nested product_prices)### 사이드바
- `_sidebar.html.erb`: diagnosis_sessions과 workspaces 사이에 products 메뉴 추가
- `_nav_item.html.erb`: "products" 쇼핑백 아이콘 SVG 추가### i18n
- `ko.yml`: admin.nav.products, admin.products 전체 번역 추가
- `en.yml`: 동일 구조 영문 번역 추가### 스타일
- 기존 admin 뷰(workspaces) 패턴과 동일한 CSS 클래스 사용
- sort_link 헬퍼 활용
- admin/shared/_pagination 사용 -
결결제-페이지 기존 코드 분석 완료, 컨트롤러/뷰/테스트 작성 시작
상세 보기
## 분석 완료 항목
- ApplicationController: `Authentication` concern, `allow_unauthenticated_access` 사용
- PaymentsController: checkout/success/fail 패턴 확인
- Payments::CheckoutService, ConfirmationService 패턴 확인
- 기존 toss_payment_controller.js Stimulus 패턴 확인
- CustomPaymentLink 모델 + fixtures 확인
- 라우트: locale scope 밖 `/pay/:token` 설정 확인## 구현 계획
1. CustomPaymentsController (인증 skip, show/checkout/success/fail)
2. custom_payment 레이아웃
3. show/success/fail/expired/canceled/completed 뷰
4. toss_custom_payment Stimulus 컨트롤러
5. 통합 테스트 -
결결제-페이지 티켓 클레임 완료
-
관관리자-UI 기존 구조 분석 완료, 코드 작성 시작
상세 보기
## 분석 완료 항목
- Admin::BaseController 패턴 확인
- 기존 payments/users 컨트롤러 패턴 확인
- _sidebar.html.erb, _nav_item.html.erb 구조 확인
- clipboard_controller.js, qr_code_controller.js 이미 존재 확인
- 기존 integration test 패턴 확인 (sign_in_as)
- ko.yml 구조 확인## 재사용할 것
- Admin::BaseController (인증/권한)
- clipboard_controller.js (복사 기능)
- qr_code_controller.js (QR 다운로드/복사)
- 기존 admin 테이블 UI 패턴 -
Bbackend-dev 상태 변경: 할 일 → 리뷰
-
Bbackend-dev 라우트 + 컨트롤러 + 모델 수정 완료
상세 보기
## 변경 사항
### 1. app/models/product.rb
- `accepts_nested_attributes_for :product_prices, allow_destroy: true` 추가### 2. config/routes.rb
- admin 네임스페이스에 `resources :products, except: :destroy` 추가
- `member { patch :toggle_active }` 추가### 3. app/controllers/admin/products_controller.rb (신규)
- Admin::BaseController 상속
- 액션: index, show, new, create, edit, update, toggle_active
- index: 검색(q→name ILIKE), 필터(product_type, active), 정렬, 페이지네이션(PER_PAGE=30)
- show: includes(:product_prices)
- create/update: nested product_prices_attributes 지원
- toggle_active: toggle!(:active)
- flash 메시지: I18n.t 사용### 참고
- workspaces_controller.rb 패턴 동일하게 적용
- 라우트 확인 완료 (bin/rails routes) -
Bbackend-dev 인프라 설정 및 통계 컨트롤러 구현 시작
-
관관리자-UI 티켓 클레임 완료
-
Aagent-nav 프로필 탭 네비게이션 구현 시작07:26 프로필 탭 네비게이션 + 라우트 + i18n
-
팀팀리드 결제 관리 기능 구현 완료07:26 결제 관리
상세 보기
## 완료된 작업
### 신규 생성 파일
- `app/controllers/admin/payments_controller.rb` - 결제 목록 조회 + 취소 컨트롤러
- `app/views/admin/payments/index.html.erb` - 결제 관리 목록 뷰 (10컬럼 테이블)
- `test/integration/admin/payments_test.rb` - 통합 테스트 18개### 수정 파일
- `config/routes.rb` - admin 네임스페이스에 payments 리소스 추가
- `app/views/admin/shared/_sidebar.html.erb` - 결제 관리 메뉴 추가
- `app/views/admin/shared/_nav_item.html.erb` - payments 아이콘 추가
- `config/locales/ko.yml` - i18n 키 추가### 테스트 결과
- 신규 테스트 18개 전부 통과
- 전체 admin 테스트 82개 전부 통과 (회귀 없음)### 구현된 기능
- 결제 목록 조회 (검색, 상태/유형 필터, 정렬, 페이지네이션)
- 관리자 결제 취소 (무료/유료 분기, PG API 연동)
- 사이드바 결제 관리 메뉴 -
팀팀리드 상태 변경: 진행 중 → 완료07:26 결제 관리
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
백백엔드 작업 시작: CustomPaymentLink 모델, 마이그레이션, 라우팅, 서비스 구현
-
백백엔드 티켓 클레임 완료
-
Sstatus-dev 상태 변경: 진행 중 → 리뷰07:25 멤버 승인 상태 표시 및 i18n
-
Sstatus-dev 멤버 승인 상태 표시 및 i18n 구현 완료07:25 멤버 승인 상태 표시 및 i18n
상세 보기
## 변경 사항
### 1. WorkspaceInvitation 모델 (`app/models/workspace_invitation.rb`)
- `accepted?` 메서드 추가: target_email의 사용자가 워크스페이스 멤버인지 확인
- `accepted_member` 메서드 추가: 수락한 멤버 객체 반환### 2. _invitation.html.erb 뷰 수정
- 이메일 초대에 승인 상태 배지 추가
- Accepted: 초록색 배지 + 체크 아이콘 + 사용자 이름
- Pending: 주황색 배지 + 시계 아이콘
- N+1 방지를 위해 accepted_member 로컬 변수 캐싱### 3. i18n 키 추가 (en/ko/zh/vi)
- `invitations.status.pending` / `accepted`
- `invitations.resend`, `resend_tooltip`
- `invitations.bulk_invite`, `bulk_placeholder`, `bulk_submit`, `bulk_email_count`
- `invitations.flash.bulk_result`, `resent`
- `invitations.mailer.invitation_email.*` (subject, greeting, body, action, expiry)### 4. 테스트 추가 (`test/models/workspace_invitation_test.rb`)
- accepted? 테스트 4건 (멤버/비멤버/blank/존재하지만비멤버)
- accepted_member 테스트 3건 (멤버/비수락/blank)
- 전체 25건 통과 -
팀팀리드 위임: tester에게 'Admin Products 통합 테스트 구현' 작업 배정07:24 상품 관리
-
Bbackend-dev 상태 변경: 진행 중 → 리뷰
-
팀팀리드 위임: agent-payment에게 '결제 내역 UI 개선 + 취소 정책' 작업 배정07:24 개인의 결제 크레딧, 결제
-
Bbackend-dev Admin::PaymentsController + 라우팅 + 테스트 구현 완료
상세 보기
## 변경 사항
### 1. 라우팅 (config/routes.rb)
- admin 네임스페이스에 `resources :payments, only: [:index]` + `member { patch :cancel }` 추가### 2. Admin::PaymentsController (app/controllers/admin/payments_controller.rb) - 신규
- `Admin::BaseController` 상속
- **index**: `Payment.includes(user: :profile).order(created_at: :desc)`
- 검색: `params[:q]` → users.name, users.email_address, user_profiles.phone_number ILIKE 검색
- 필터: `params[:status]` (validated), `params[:payment_type]` (validated)
- 정렬: created_at, amount, status / asc, desc
- 수동 페이지네이션 (PER_PAGE=50)
- **cancel**: completed 상태 확인 + free/유료 분기
- free: 바로 `payment.cancel!`
- 유료: `ProviderResolver` → `provider.cancel` 호출 후 `payment.cancel!`
- turbo_stream / html respond_to 지원
- 에러 처리: rescue → flash alert redirect### 3. 테스트 (test/integration/admin/payments_test.rb) - 신규
- 18개 테스트 전부 통과
- 접근 제어 (2), index 조회 (1), 검색 (2), 상태 필터 (3), 유형 필터 (2), 정렬 (2), 페이지네이션 (1), 취소 (5)
- PG API 호출 mock: `define_singleton_method`로 ProviderResolver 패치### 참고
- 뷰 템플릿(index.html.erb) 및 i18n 키는 이미 존재
- 기존 admin 테스트 82개 전부 통과 확인 -
팀팀리드 위임: frontend-dev에게 'Admin Products 뷰 + 사이드바 + i18n 구현' 작업 배정07:24 상품 관리
-
팀팀리드 문항 관리 언어 선택 버그 수정 완료07:24 문항 관리
상세 보기
## 수정 내용
1. `Admin::BaseController`에 `switch_locale` override 추가 → Admin 영역은 항상 기본 locale(ko) 유지
2. `SurveyQuestionsController#group_detail`에서 `params[:locale]` → `params[:lang]`으로 변경
3. 뷰 파일(index, group_detail)에서 언어 버튼 파라미터 `locale:` → `lang:` 변경## 테스트 결과
- 19 runs, 50 assertions, 0 failures, 0 errors## 수정 파일
- `app/controllers/admin/base_controller.rb`
- `app/controllers/admin/survey_questions_controller.rb`
- `app/views/admin/survey_questions/index.html.erb`
- `app/views/admin/survey_questions/group_detail.html.erb`
- `test/controllers/admin/base_controller_test.rb` (신규)
- `test/controllers/admin/survey_questions_controller_test.rb` (신규)
- `test/integration/admin/survey_questions_test.rb` (수정) -
팀팀리드 상태 변경: 진행 중 → 완료07:24 문항 관리
-
팀팀리드 위임: agent-credit에게 '개인 크레딧 페이지 생성' 작업 배정07:24 개인의 결제 크레딧, 결제
-
팀팀리드 상태 변경: 리뷰 → 완료07:24 문항 관리 뷰 언어 선택 파라미터 수정
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 위임: backend-dev에게 'Admin Products 라우트 + 컨트롤러 구현' 작업 배정07:24 상품 관리
-
팀팀리드 위임: agent-nav에게 '프로필 탭 네비게이션 + 라우트 + i18n' 작업 배정07:24 개인의 결제 크레딧, 결제
-
팀팀리드 위임: analytics-dev-2에게 '매출 분석 뷰 + 통합 테스트' 작업 배정07:24 통계 관리
-
팀팀리드 위임: analytics-dev-1에게 '사용자 + 진단 분석 뷰' 작업 배정07:24 통계 관리
-
팀팀리드 위임: backend-dev에게 '인프라 설정 + 통계 컨트롤러 + 개요 대시보드' 작업 배정07:24 통계 관리
-
Ttest-dev 테스트 작성 시작 - 기존 코드 및 패턴 분석 중07:23 사용자 관리 기능 테스트 작성
-
Ttest-dev 티켓 클레임 완료07:23 사용자 관리 기능 테스트 작성
-
Ffrontend-dev 상태 변경: 할 일 → 리뷰07:23 문항 관리 뷰 언어 선택 파라미터 수정
-
Ffrontend-dev 뷰 파일 수정 및 테스트 통과 완료07:23 문항 관리 뷰 언어 선택 파라미터 수정
상세 보기
## 변경 사항
- `app/views/admin/survey_questions/index.html.erb`: `locale:` → `lang:` 파라미터 변경
- `app/views/admin/survey_questions/group_detail.html.erb`: `locale:` → `lang:` 파라미터 변경
- `test/integration/admin/survey_questions_test.rb`: 기존 테스트 업데이트 + 3개 테스트 추가## 추가된 테스트
1. `lang parameter does not change UI locale` - lang=en으로 접속해도 UI가 한국어 유지되는지 검증
2. `index language buttons use lang parameter instead of locale` - 인덱스 페이지 링크에 locale 없고 lang 사용 확인
3. `group detail language buttons use lang parameter instead of locale` - 상세 페이지 링크에 locale 없고 lang 사용 확인## 테스트 결과
11 runs, 34 assertions, 0 failures, 0 errors -
Iimpl-dev 상태 변경: 할 일 → 리뷰
-
팀팀리드 impl-dev 구현 완료 확인, 테스트 에이전트 시작
상세 보기
## 완료된 작업
- 컨트롤러 eager loading, 전화번호 검색, update_role 액션
- 인덱스 뷰에 전화번호/워크스페이스/진단 컬럼 추가
- 인라인 역할 수정 (Stimulus inline-edit 재사용)
- 진단 목록 모달 (Stimulus toggle 재사용)
- i18n 번역 키 추가## 변경 파일
- `app/controllers/admin/users_controller.rb`
- `app/views/admin/users/index.html.erb`
- `app/views/admin/users/_role_cell.html.erb` (신규)
- `app/views/admin/users/_diagnosis_modal.html.erb` (신규)
- `config/routes.rb`
- `config/locales/ko.yml`기존 테스트 8건 통과 확인
-
Bbackend-dev 상태 변경: 진행 중 → 리뷰
-
Bbackend-dev Admin BaseController switch_locale override 및 SurveyQuestions 필터링 수정 완료
상세 보기
## 변경 사항
### 1. `app/controllers/admin/base_controller.rb`
- `switch_locale` 메서드 override 추가
- Admin 영역에서는 `params[:locale]`을 무시하고 항상 `I18n.default_locale`(ko) 사용### 2. `app/controllers/admin/survey_questions_controller.rb`
- `group_detail` 액션에서 `params[:locale]` → `params[:lang]`으로 변경
- URL 파라미터명 변경으로 locale 간섭 방지### 3. 신규 테스트 파일
- `test/controllers/admin/base_controller_test.rb` (2 tests)
- locale=en 파라미터 전달해도 Admin은 ko 유지
- locale=vi 파라미터 전달해도 Admin은 ko 유지
- `test/controllers/admin/survey_questions_controller_test.rb` (6 tests)
- group_detail에서 lang 파라미터 사용 확인
- lang 미전달 시 기본값 ko
- locale 파라미터는 무시됨
- I18n.locale은 항상 ko 유지
- index 접근 가능
- 비관리자 리다이렉트### 테스트 결과
- 8 runs, 16 assertions, 0 failures, 0 errors -
Bbulk-dev 상태 변경: 할 일 → 리뷰07:22 벌크 이메일 초대 기능
-
Bbulk-dev 벌크 이메일 초대 기능 구현 완료07:22 벌크 이메일 초대 기능
상세 보기
## 변경 사항
### 1. InvitationService (app/services/workspaces/invitation_service.rb)
- `bulk_create!` 메서드 추가: 여러 이메일을 한번에 초대, 성공/실패 결과 반환
- `parse_emails` 메서드 추가: 쉼표/세미콜론/줄바꿈/공백으로 이메일 파싱, 중복 제거, 형식 검증### 2. InvitationsController (app/controllers/workspaces/invitations_controller.rb)
- `bulk_create` 액션 추가: bulk_create! 호출 후 결과에 따른 flash 메시지 표시### 3. 라우트 (config/routes.rb)
- `post :bulk_create, on: :collection` 추가### 4. UI (app/views/workspaces/invitations/index.html.erb)
- 이메일 탭 내 "Or bulk invite" 구분선 추가
- textarea로 여러 이메일 입력 가능
- 역할/그룹 선택 옵션
- 이메일 카운트 실시간 표시### 5. Stimulus (app/javascript/controllers/bulk_invite_controller.js)
- textarea 입력 시 이메일 수 실시간 카운트
- 이메일 없으면 제출 버튼 비활성화### 6. 테스트 (test/controllers/workspaces/invitations_controller_bulk_test.rb)
- 8개 테스트 모두 통과
- 다중 이메일, 줄바꿈/세미콜론 구분, 중복 제거, 무효 이메일 무시, 빈 텍스트, 권한 검증, 역할 지정 -
Iimpl-dev Task 1~5 구현 완료, 기존 테스트 모두 통과
상세 보기
## 변경 사항
### Task 1: 컨트롤러 개선
- `app/controllers/admin/users_controller.rb`
- `includes(:profile, :workspaces, :diagnosis_sessions)` eager loading 추가
- 검색: `left_joins(:profile)` + `user_profiles.phone_number ILIKE` 추가
- `update_role` 액션 추가 (PATCH, Turbo Stream 응답)
- `before_action :set_user`에 `update_role` 추가
- `config/routes.rb`에 `patch :update_role` 라우트 추가### Task 2: 인덱스 뷰 개선
- `app/views/admin/users/index.html.erb`
- 전화번호 컬럼 추가 (phone_country_code + phone_number)
- 소속 워크스페이스 컬럼 추가 (truncate + title tooltip)
- 진단 컬럼 추가 (클릭 가능한 진단 수)### Task 3: 인라인 역할 수정
- `app/views/admin/users/_role_cell.html.erb` 생성
- 기존 `inline-edit` Stimulus 컨트롤러 재사용
- 뱃지 클릭 → select 드롭다운 표시
- 선택 시 `onchange`로 즉시 PATCH 요청
- Turbo Stream으로 뱃지 교체 응답### Task 4: 진단 목록 뷰어
- `app/views/admin/users/_diagnosis_modal.html.erb` 생성
- `toggle` Stimulus 컨트롤러로 모달 토글
- 진단 유형, 상태, 완료일, 상세 링크 표시### Task 5: i18n
- `config/locales/ko.yml`에 번역 키 추가
- phone, workspaces, diagnosis_count, role_updated
- diagnosis_modal 섹션 (title, type, status, completed_at, view, empty)## 테스트 결과
- 기존 admin 컨트롤러 테스트: 8 runs, 16 assertions, 0 failures -
Ffrontend-dev Admin Payments 뷰 + 사이드바 메뉴 구현 완료
상세 보기
## 수정/생성된 파일
### 1. app/views/admin/shared/_nav_item.html.erb (수정)
- `payments` 아이콘(credit-card SVG path) 추가### 2. app/views/admin/shared/_sidebar.html.erb (수정)
- 워크스페이스 메뉴 아래에 "결제 관리" nav_item 추가
- `admin_payments_path` 링크, `controller_name == "payments"` 활성 조건### 3. app/views/admin/payments/index.html.erb (신규 생성)
- 헤더: 제목 + 전체 건수
- 검색 & 필터: 텍스트 검색(사용자명/이메일/전화번호), 상태 필터, 결제유형 필터
- 테이블 10컬럼: 사용자, 이메일, 전화번호, 상품명, 가격, 상태, 할인금액, 결제일, 영수증, 취소
- 상태 배지: completed→green, pending→yellow, failed→red, canceled→gray
- 취소 버튼: `button_to cancel_admin_payment_path` + turbo_confirm
- 빈 상태 메시지
- 페이지네이션: `admin/shared/pagination` partial 사용
- 기존 diagnosis_sessions/index.html.erb 패턴과 완전히 일관된 Tailwind CSS### 4. config/locales/ko.yml (수정)
- `admin.nav.payments`: "결제 관리"
- `admin.payments.*`: title, subtitle, search_placeholder, all_statuses, all_types, empty, confirm_cancel, cancel_button, canceled_label, table.*, flash.* -
팀팀리드 위임: 결제-페이지에게 '고객 결제 페이지 + Toss Payments 연동' 작업 배정07:20 커스텀 결제 메뉴
-
팀팀리드 코드베이스 분석 완료, 서브 티켓 분해 시작07:20 개인의 결제 크레딧, 결제
상세 보기
## 분석 결과 요약
- 프로필 페이지: `/:locale/profile` (show/edit/update) 존재하나 결제/크레딧 정보 없음
- 결제 시스템: Payment 모델, PaymentsController (index/show/cancel), Toss PG 연동 완비
- 크레딧 시스템: UserCredit + CreditTransaction 모델 존재하나 개인 크레딧 뷰 없음
- 사이드바: 결제/크레딧 링크 없음
- 영수증: receipt_url 컬럼 존재, show 페이지에 링크 있음
- 취소: CancellationService 존재하나 상품별 분기 없음 (현재 7일 이내 completed만 체크)## 필요 작업
1. 프로필 탭 네비게이션 (내 정보/결제/크레딧)
2. 개인 크레딧 페이지 생성
3. 결제 내역 UI 개선 (프로필 탭 통합)
4. 리포트 결제 취소 불가 정책 적용
5. i18n 다국어 키 추가 -
팀팀리드 위임: 관리자-UI에게 '관리자 커스텀 결제 링크 UI (컨트롤러 + 뷰 + 사이드바)' 작업 배정07:20 커스텀 결제 메뉴
-
Ffrontend-dev 코드 분석 완료, 뷰 파일 수정 시작07:20 문항 관리 뷰 언어 선택 파라미터 수정
상세 보기
## 분석 결과
- `index.html.erb` 63행: `locale:` 파라미터 사용 → `lang:`으로 변경 필요
- `group_detail.html.erb` 32행: `locale:` 파라미터 사용 → `lang:`으로 변경 필요
- 기존 테스트 25, 31행: `locale:` 파라미터 사용 → `lang:`으로 변경 필요 -
팀팀리드 위임: 백엔드에게 'CustomPaymentLink 모델 + 마이그레이션 + 라우팅 + 서비스' 작업 배정07:20 커스텀 결제 메뉴
-
Bbackend-dev 티켓 클레임 완료
-
Sstatus-dev 멤버 승인 상태 표시 및 i18n 작업 시작07:19 멤버 승인 상태 표시 및 i18n
-
Sstatus-dev 티켓 클레임 완료07:19 멤버 승인 상태 표시 및 i18n
-
팀팀리드 에이전트 팀 구성 완료, 3명 병렬 작업 시작07:19 이메일 초대
상세 보기
## 팀 구성
- **mailer-dev**: Mailer 생성 + 이메일 발송 연동 (worktree 격리)
- **bulk-dev**: 벌크 이메일 초대 기능 (worktree 격리)
- **status-dev**: 멤버 승인 상태 표시 + i18n (worktree 격리)## 서브 티켓
1. a9e36ce3: Mailer 생성 및 이메일 발송 연동 (high)
2. c2083743: 벌크 이메일 초대 기능 (high)
3. 1bcfa5ea: 멤버 승인 상태 표시 및 i18n (medium)3명 모두 worktree 격리 환경에서 병렬 작업 중
-
Ffrontend-dev 기존 admin 뷰 패턴 분석 완료, 구현 시작
상세 보기
## 분석 완료 항목
- `_sidebar.html.erb`: nav_item partial 사용, icon SVG 경로 매핑 방식
- `_nav_item.html.erb`: icon 키 → SVG path 매핑, active 조건
- `diagnosis_sessions/index.html.erb`: 검색/필터/테이블/페이지네이션 패턴
- `_pagination.html.erb`: page/total_pages/total_count locals
- `Payment` 모델: status enum, payment_type enum, 필드 구조 확인
- i18n: admin 네임스페이스 패턴 확인## 구현 계획
1. 사이드바에 payments nav_item 추가
2. nav_item에 payments 아이콘 추가
3. admin/payments/index.html.erb 생성
4. i18n에 admin.payments 키 추가 -
Bbulk-dev 벌크 이메일 초대 기능 작업 시작07:19 벌크 이메일 초대 기능
상세 보기
## 작업 범위
- InvitationService에 bulk_create! 메서드 추가
- InvitationsController에 bulk_create 액션 추가
- 라우트 추가
- 벌크 UI (textarea + 카운트)
- Stimulus 컨트롤러
- 테스트 작성 -
Iimpl-dev 코드베이스 분석 완료, Task 1 (컨트롤러 개선) 및 Task 5 (i18n) 작업 시작
상세 보기
## 분석 완료 항목
- `app/controllers/admin/users_controller.rb` - 현재 eager loading 없음, 검색에 이름/이메일만 지원
- `app/views/admin/users/index.html.erb` - 이름/이메일/역할/가입일 4컬럼만 표시
- `app/helpers/admin_helper.rb` - role_badge_class, role_label 헬퍼 확인
- `app/javascript/controllers/inline_edit_controller.js` - 기존 인라인 편집 Stimulus 컨트롤러 존재
- `config/locales/ko.yml` - admin.users 섹션 확인
- User 모델: has_one :profile, has_many :workspaces (through), has_many :diagnosis_sessions
- UserProfile 모델: phone_number, phone_country_code 필드 확인 -
팀팀리드 코드베이스 분석 완료, 서브 티켓 설계 시작07:18 커스텀 결제 메뉴
상세 보기
## 분석 결과
- 기존 Payment 모델에 `custom` payment_type 존재
- Toss Payments 연동 완료 (providers/toss.rb)
- rqrcode gem 설치됨 (QR 코드 생성 가능)
- Admin namespace 패턴 확립## 구현 계획
- CustomPaymentLink 신규 모델 생성 필요
- Admin CRUD + 공개 결제 페이지 구현
- 3개 서브 티켓으로 분할 예정 -
Mmailer-dev Mailer 생성 및 이메일 발송 연동 작업 시작07:18 Mailer 생성 및 이메일 발송 연동
상세 보기
## 작업 범위
- WorkspaceInvitationMailer 생성
- 이메일 템플릿 (HTML/Text)
- InvitationService.create!에 이메일 발송 연동
- resend 기능
- 테스트 작성 -
팀팀리드 위임: frontend-dev에게 '문항 관리 뷰 언어 선택 파라미터 수정' 작업 배정07:18 문항 관리
-
팀팀리드 위임: backend-dev에게 'Admin BaseController switch_locale override 및 SurveyQuestions 필터링 수정' 작업 배정07:18 문항 관리
-
Bbackend-dev 티켓 클레임 완료
-
팀팀리드 통계 관리 기능 분석 시작07:17 통계 관리
상세 보기
## 코드베이스 분석 완료
### 현재 상태
- 어드민 대시보드에 기본 통계 카드 4개 (총 사용자, 완료 세션, 진단 유형, 설문 문제)
- 차트/그래프 라이브러리 없음
- Tailwind CSS + Hotwire 기반 서버사이드 렌더링### 구현 계획
- Chartkick + Chart.js로 차트 시각화
- 4개 탭: 개요, 사용자, 진단, 매출
- 서브 티켓 3개로 분할하여 팀 작업 진행 -
팀팀리드 위임: status-dev에게 '멤버 승인 상태 표시 및 i18n' 작업 배정07:17 이메일 초대
-
팀팀리드 상품 관리 기능 분석 시작07:17 상품 관리
상세 보기
## 작업 계획
- 레거시 사이트(https://9way.org/admin/workspaces) 분석
- 현재 코드베이스의 관련 모델/라우트 파악
- 서브 티켓 분해 후 에이전트 팀 구성 -
팀팀리드 위임: bulk-dev에게 '벌크 이메일 초대 기능' 작업 배정07:17 이메일 초대
-
팀팀리드 티켓 클레임 완료07:17 상품 관리
-
팀팀리드 위임: mailer-dev에게 'Mailer 생성 및 이메일 발송 연동' 작업 배정07:16 이메일 초대
-
팀팀리드 위임: test-dev에게 '사용자 관리 기능 테스트 작성' 작업 배정07:16 사용자 관리
-
팀팀리드 위임: impl-dev에게 '사용자 관리 인덱스 개선 + 인라인 역할 수정 + 진단 뷰어' 작업 배정07:16 사용자 관리
-
팀팀리드 위임: frontend-dev에게 'Admin Payments 뷰 + 사이드바 메뉴' 작업 배정07:16 결제 관리
-
팀팀리드 티켓 클레임 완료07:16 개인의 결제 크레딧, 결제
-
팀팀리드 문항 관리 버그 분석 시작07:16 문항 관리
상세 보기
## 이슈
- 문항관리에서 언어 선택 시 해당 언어의 질문만 보여야 하는데, 전체 메뉴 언어가 변경되는 버그
- 영어 선택 시 메뉴 전체가 영어로 바뀌는 문제## 계획
- 코드 분석 후 서브 태스크 분해 및 팀 구성 예정 -
팀팀리드 위임: backend-dev에게 'Admin Payments 컨트롤러 + 라우팅 + 테스트' 작업 배정07:16 결제 관리
-
팀팀리드 티켓 클레임 완료07:16 문항 관리
-
팀팀리드 사용자 관리 기능 분석 완료, 서브 티켓 생성 시작07:16 사용자 관리
상세 보기
## 현재 상태
- admin/users 컨트롤러/뷰 이미 존재
- index: 이름, 이메일, 역할, 생성일만 표시
- show: 사용자 정보 + 진단 이력## 필요 변경사항
1. index에 전화번호, 소속 워크스페이스, 진단 수 컬럼 추가
2. 역할 인라인 수정 (드롭다운)
3. 진단 클릭 시 해당 사용자 진단 목록 표시
4. 전화번호 검색 지원## 핵심 파일
- `app/controllers/admin/users_controller.rb`
- `app/views/admin/users/index.html.erb`
- `app/views/admin/users/show.html.erb`
- 전화번호는 `user_profiles` 테이블에 저장됨
- 워크스페이스는 `workspace_members` 통해 연결 -
팀팀리드 티켓 클레임 완료07:15 커스텀 결제 메뉴
-
팀팀리드 티켓 클레임 완료07:14 통계 관리
-
팀팀리드 티켓 클레임 완료07:14 사용자 관리
-
팀팀리드 결제 관리 기능 분석 시작07:14 결제 관리
상세 보기
## 분석 범위
- 기존 결제 모델/테이블 구조 파악
- 관리자 페이지 구조 파악
- 서브 티켓 분해 및 팀 구성 계획 -
팀팀리드 티켓 클레임 완료07:14 결제 관리
-
팀팀리드 이메일 초대 티켓 분석 시작07:14 이메일 초대
상세 보기
## 작업 범위
- 이메일 초대 시 실제 이메일 발송
- 벌크 이메일 등록/발송
- 멤버 승인 상태 표시코드베이스 분석 후 서브 티켓 분해 예정
-
팀팀리드 티켓 클레임 완료07:14 이메일 초대
-
팀팀리드 배포 완료 - 관리자 메뉴 기능 프로덕션 반영06:50 관리자 메뉴
상세 보기
## 배포 정보
- 커밋: a58c601
- 서버: 143.198.211.253 (9way.org)
- 소요 시간: 64초
- 상태: 성공 (healthy)## 배포된 변경사항
- 사이드바에 관리자 메뉴 링크 추가 (admin 사용자만)
- 4개 언어 번역 추가 (ko/en/zh/vi)
- 통합 테스트 2건 추가 -
팀팀리드 워크스페이스 메뉴 권한 기능 구현 완료02:08 워크스페이스 메뉴 권한
상세 보기
## 완료 내역
### 구현 (sidebar-dev)
- `app/views/shared/_sidebar.html.erb`: 표시 조건 `staff?`로 변경
- `app/views/shared/_sidebar_workspace_section.html.erb`: "+ 워크스페이스 생성" 링크 추가, 빈 상태 처리### 테스트 (test-dev)
- `test/integration/sidebar_workspace_menu_test.rb`: 5개 통합 테스트 작성
- `test/fixtures/users.yml`: coach_basic, org_admin_basic 픽스처 추가
- 전체 테스트: 427 runs, 1134 assertions, 0 failures -
팀팀리드 상태 변경: 진행 중 → 완료02:08 워크스페이스 메뉴 권한
-
팀팀리드 상태 변경: 리뷰 → 완료02:08 워크스페이스 메뉴 권한 테스트 작성
-
팀팀리드 상태 변경: 리뷰 → 완료
-
Ttest-dev 테스트 작성 완료 - 모든 권한별 시나리오 통과02:07 워크스페이스 메뉴 권한 테스트 작성
상세 보기
## 변경 사항
### 새 파일
- `test/integration/sidebar_workspace_menu_test.rb` - 사이드바 워크스페이스 메뉴 권한 통합 테스트 (5개 시나리오)### 수정 파일
- `test/fixtures/users.yml` - coach_basic_user, org_admin_basic_user 픽스쳐 추가## 테스트 시나리오
1. regular 사용자 → 워크스페이스 섹션 미표시
2. coach_basic (워크스페이스 없음) → 섹션 표시 + 생성 링크
3. coach_pro (워크스페이스 있음) → 목록 표시 + 생성 링크
4. org_admin_basic → 섹션 표시 + 생성 링크
5. admin → 목록 + 생성 링크## 테스트 결과
- 신규 테스트: 5 runs, 30 assertions, 0 failures
- 전체 테스트: 427 runs, 1134 assertions, 0 failures, 0 errors -
Ttest-dev 상태 변경: 할 일 → 리뷰02:07 워크스페이스 메뉴 권한 테스트 작성
-
Ssidebar-dev 상태 변경: 할 일 → 리뷰
-
Ssidebar-dev 구현 완료 - 사이드바 워크스페이스 권한 조건 변경 및 생성 링크 추가
상세 보기
## 변경 사항
### 1. `app/views/shared/_sidebar.html.erb`
- 워크스페이스 섹션 표시 조건: `@sidebar_workspaces&.any?` → `Current.user&.staff?`
- staff? 사용자(admin, coach, org_admin)만 워크스페이스 섹션 표시
- workspaces 변수를 `@sidebar_workspaces || []`로 전달하여 nil 안전 처리### 2. `app/views/shared/_sidebar_workspace_section.html.erb`
- `return if workspaces.blank?` 가드 절 제거 → 빈 상태에서도 렌더링
- `selected_ws.id` → `selected_ws&.id`로 nil 안전 처리
- 하단에 "+ 워크스페이스 생성" 링크 추가 (Heroicon plus 아이콘, 기존 스타일 패턴 유지)
- 워크스페이스가 0개일 때도 헤더 + 생성 링크 표시### 테스트 결과
- 422 runs, 1104 assertions, 0 failures, 0 errors, 0 skips -
팀팀리드 위임: test-dev에게 '워크스페이스 메뉴 권한 테스트 작성' 작업 배정02:01 워크스페이스 메뉴 권한
-
팀팀리드 위임: sidebar-dev에게 '사이드바 워크스페이스 섹션 권한 조건 변경 및 생성 링크 추가' 작업 배정02:01 워크스페이스 메뉴 권한
-
팀팀리드 워크스페이스 메뉴 권한 기능 분석 시작01:50 워크스페이스 메뉴 권한
상세 보기
## 분석 범위
- 사용자 권한 시스템 파악
- 현재 사이드바/메뉴 구조 확인
- 워크스페이스 모델 및 관계 분석
- 필요한 서브 티켓 도출 -
팀팀리드 티켓 클레임 완료01:50 워크스페이스 메뉴 권한
-
팀팀리드 관리자 메뉴 구현 완료01:21 관리자 메뉴
상세 보기
## 변경 사항
- `app/views/shared/_sidebar.html.erb`: admin 사용자 조건부 관리자 메뉴 추가
- `app/views/shared/_sidebar_nav_item.html.erb`: admin 톱니바퀴 아이콘 추가
- `config/locales/ko.yml`: `nav.sidebar.admin: "관리자"` 추가
- `config/locales/en.yml`: `nav.sidebar.admin: "Admin"` 추가
- `config/locales/zh.yml`: `nav.sidebar.admin: "管理员"` 추가
- `config/locales/vi.yml`: `nav.sidebar.admin: "Quản trị"` 추가
- `test/integration/sidebar_test.rb`: 통합 테스트 2건 작성## 테스트 결과
- 422개 전체 테스트 통과 (0 failures, 0 errors) -
팀팀리드 상태 변경: 리뷰 → 완료01:21 사이드바에 관리자 메뉴 링크 추가
-
Ddev-1 상태 변경: 진행 중 → 리뷰01:20 사이드바에 관리자 메뉴 링크 추가
-
Ddev-1 사이드바 관리자 메뉴 구현 완료01:20 사이드바에 관리자 메뉴 링크 추가
상세 보기
## 변경 파일
- `app/views/shared/_sidebar_nav_item.html.erb` - admin 톱니바퀴 아이콘 SVG path 추가
- `app/views/shared/_sidebar.html.erb` - `Current.user&.admin?` 조건부 관리자 메뉴 렌더링 추가
- `config/locales/ko.yml` - `nav.sidebar.admin: "관리자"` 추가
- `config/locales/en.yml` - `nav.sidebar.admin: "Admin"` 추가
- `config/locales/zh.yml` - `nav.sidebar.admin: "管理员"` 추가
- `config/locales/vi.yml` - `nav.sidebar.admin: "Quản trị"` 추가
- `test/integration/sidebar_test.rb` - 신규 생성 (admin 링크 표시/비표시 테스트)## 테스트 결과
- 152 integration tests 전체 통과 (0 failures, 0 errors) -
팀팀리드 상태 변경: 진행 중 → 완료01:20 관리자 메뉴
-
팀팀리드 관리자 메뉴 기능 확인 완료 - 이미 구현되어 있음01:20 관리자 메뉴
상세 보기
## 분석 결과
관리자 사이드 메뉴 기능이 이미 완전히 구현되어 있음을 확인했습니다.## 구현 내용
1. **사이드바 HTML** (`app/views/shared/_sidebar.html.erb` 32-38줄)
- `Current.user&.admin?` 조건부 표시
- `admin_root_path`로 링크
- `controller_path.start_with?("admin")`으로 active 상태 판별2. **아이콘** (`app/views/shared/_sidebar_nav_item.html.erb` 9줄)
- "admin" 키로 톱니바퀴 SVG 아이콘 정의3. **다국어 번역** (`nav.sidebar.admin`)
- ko: "관리자"
- en: "Admin"
- zh: "管理员"
- vi: "Quản trị"## 비고
- 기존 Admin::UsersTest에서 `phone_number` 메서드 누락 에러 1건 발견 (본 티켓과 무관) -
Ddev-1 티켓 클레임 완료01:17 사이드바에 관리자 메뉴 링크 추가
-
팀팀리드 코드베이스 분석 시작 - 사이드 메뉴 및 관리자 페이지 구조 파악01:16 관리자 메뉴
-
팀팀리드 위임: dev-1에게 '사이드바에 관리자 메뉴 링크 추가' 작업 배정01:16 관리자 메뉴
-
팀팀리드 관리자 메뉴 티켓 분석 시작01:14 관리자 메뉴
상세 보기
## 작업 시작
- 티켓 claim 완료
- 코드베이스 분석 중: 사이드 메뉴 구조, 관리자 페이지 현황 파악 -
팀팀리드 티켓 클레임 완료01:14 관리자 메뉴
-
2026년 02월 27일
-
팀팀리드 상태 변경: 진행 중 → 완료22:39 메인페이지(랜딩) 다국어 번역 오류 수정
-
팀팀리드 메인페이지 다국어 번역 수정 완료22:39 메인페이지(랜딩) 다국어 번역 오류 수정
상세 보기
## 변경 사항
- `config/locales/zh.yml` — `home` 섹션 전체 추가 (중국어 번역 ~100줄)
- `config/locales/vi.yml` — `home` 섹션 전체 추가 (베트남어 번역 ~100줄)
- `config/locales/ko.yml` — `home.social_proof.count_suffix` 키 추가
- `config/locales/en.yml` — `home.social_proof.count_suffix` 키 추가
- `app/views/pages/home.html.erb` — 하드코딩된 한국어 텍스트를 i18n 키로 교체 (line 466)## 검증
- 4개 YAML 파일 파싱 정상 확인
- ko/en/zh/vi 모든 locale의 home 섹션 키 일치 확인 -
팀팀리드 분석 완료: ZH/VI에 home 섹션 전체 누락 확인22:35 메인페이지(랜딩) 다국어 번역 오류 수정
상세 보기
## 분석 결과
- KO/EN: 완전
- ZH/VI: `home` 섹션 전체 누락 (약 50개 키)
- 하드코딩된 한글 텍스트 1건 (467줄)
- navbar auth 키도 ZH/VI에서 누락## 작업 계획
1. ZH에 home 섹션 번역 추가
2. VI에 home 섹션 번역 추가
3. 하드코딩 텍스트 i18n화
4. auth 키 누락분 추가 -
팀팀리드 티켓 클레임 완료22:34 메인페이지(랜딩) 다국어 번역 오류 수정
-
팀팀리드 프로덕션 배포 완료 (9way.org)15:40 문항관리
-
팀팀리드 프로덕션 배포 완료 (9way.org)15:40 어드민_진단관리
-
팀팀리드 프로덕션 배포 완료 (9way.org)15:40 사용자 진단
상세 보기
## 배포 정보
- **커밋**: `da60c50` feat: Add admin management features, PDF improvements, and AI analysis locale support
- **커밋**: `62243db` fix: Increase Kamal deploy timeout to 90s for slow boot
- **서버**: 143.198.211.253 (DigitalOcean SGP1)
- **도메인**: https://9way.org
- **배포 소요**: 71.6초 (컨테이너 헬스체크 31.35초)## 배포된 기능
- 사용자 상세 페이지 진단 이력 확장 (DNA 5개, 결제상태 토글, 메모)
- 어드민 진단 세션 관리 목록 페이지
- 문항관리 리디자인 (유형/대상/언어 그룹 + 응답 통계)
- PDF 리포트 개선 및 AI 분석 다국어 지원 -
팀팀리드 어드민 3개 기능 구현 완료15:24 사용자 진단
상세 보기
## 완료 요약
### 1. 사용자 진단 이력 확장
- `admin/users_controller.rb` - includes 확장, toggle_payment 액션
- `admin/users/show.html.erb` - 테이블 형태로 전면 개편 (유형, DNA 5개, 결제상태, 메모, 완료일)
- 결제 상태 토글 (유료↔무료) 동작### 2. 진단 세션 관리 목록
- `admin/diagnosis_sessions_controller.rb` 신규 생성 - 검색, 필터, 페이지네이션
- `admin/diagnosis_sessions/index.html.erb` 신규 생성 - 전체 진단 세션 테이블
- 사이드바에 네비게이션 항목 추가
- 결제 상태 토글, 결과보기/PDF 링크, 워크스페이스명 표시### 3. 문항관리 리디자인
- `admin/survey_questions_controller.rb` - index 리디자인 + group_detail 액션
- `admin/survey_questions/index.html.erb` - 유형/대상별 카드 그리드
- `admin/survey_questions/group_detail.html.erb` 신규 - Part1 리커트 분포 + Part2 선택 비율
- 테스트 420건 전체 통과### routes.rb 통합 확인
- 충돌 없이 깔끔하게 3개 라우트 추가됨 -
팀팀리드 상태 변경: 진행 중 → 완료15:24 문항관리
-
팀팀리드 상태 변경: 진행 중 → 완료15:23 어드민_진단관리
-
팀팀리드 상태 변경: 진행 중 → 완료15:23 사용자 진단
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료15:23 어드민 진단 세션 관리 목록 페이지 구현
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 할 일 → 리뷰15:23 어드민 진단 세션 관리 목록 페이지 구현
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 위임: admin-survey-dev에게 '문항관리 리디자인 - 유형/대상/언어 그룹 + 응답 통계' 작업 배정15:16 문항관리
-
팀팀리드 위임: admin-diagnosis-dev에게 '어드민 진단 세션 관리 목록 페이지 구현' 작업 배정15:15 어드민_진단관리
-
팀팀리드 위임: admin-user-dev에게 '사용자 상세 - 진단 이력 확장 (DNA 5개, 결제상태 변경, 메모)' 작업 배정15:15 사용자 진단
-
팀팀리드 티켓 클레임 완료15:10 문항관리
-
팀팀리드 티켓 클레임 완료15:10 어드민_진단관리
-
팀팀리드 티켓 클레임 완료15:10 사용자 진단
-
팀팀리드 요약 탭 커스텀 브랜딩 표시 + 연필 아이콘 편집 진입 + PDF 표지 커스텀 브랜딩 분기 완료. 전체 테스트 통과.
-
팀팀리드 강점 브랜딩 수정 위자드 UI 완료. branding_wizard_controller.js (4단계: DNA→수식어→WAY+되고싶은모습→AI미리보기) + _tab_summary.html.erb 인라인 모달 통합. 전체 36개 테스트 통과.
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 완료08:49 강점 브랜딩: AI 브랜딩 문장 생성 서비스
-
팀팀리드 상태 변경: 진행 중 → 완료08:49 강점 브랜딩: 컨트롤러 API 엔드포인트
-
팀팀리드 티켓 클레임 완료08:39 강점 브랜딩: AI 브랜딩 문장 생성 서비스
-
팀팀리드 티켓 클레임 완료08:39 강점 브랜딩: 컨트롤러 API 엔드포인트
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료08:39 강점 브랜딩: DB 마이그레이션 + 모델
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료08:21 강점 브랜딩: DB 마이그레이션 + 모델
-
팀팀리드 상태 변경: 할 일 → 완료08:09 PDF 리포트 재설계 - AI 분석 (2p)
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료08:09 PDF 리포트 재설계 - 요약 (1p)
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료08:09 PDF 리포트 재설계 - 표지 (1p)
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료
-
팀팀리드 상태 변경: 리뷰 → 완료08:09 표지 + 해석가이드 + 요약 파트셜 리팩토링
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 상태 변경: 할 일 → 리뷰08:05 표지 + 해석가이드 + 요약 파트셜 리팩토링
-
팀팀리드 상태 변경: 할 일 → 리뷰
-
팀팀리드 위임: front-b에게 '강점 프로파일 + 탁월한 역할 + AI 분석 파트셜 신규 생성' 작업 배정
-
팀팀리드 위임: dna-dev에게 'DNA 차별성 Top5 파트셜 리디자인 (10p)' 작업 배정
-
팀팀리드 위임: front-a에게 '표지 + 해석가이드 + 요약 파트셜 리팩토링' 작업 배정
-
팀팀리드 PDF 리포트 전면 재설계 시작. 에이전트 3명 팀 구성하여 7개 섹션 병렬 작업 + 팀리드가 오케스트레이터/CSS 담당.
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 완료07:02 개인 PDF - 유료 콘텐츠 페이지 구현
-
Ppremium-dev 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
Ddomain-dev 상태 변경: 진행 중 → 완료
-
팀팀리드 이전 세션 에이전트 종료됨. 새 팀 구성하여 Premium Content 구현 재개.06:58 개인 PDF - 유료 콘텐츠 페이지 구현
-
팀팀리드 이전 세션 에이전트 종료됨. 새 팀 구성하여 Domain Detail 마무리 + Premium Content 구현 재개.
-
Ppremium-dev 상태 변경: 할 일 → 진행 중
-
Ddomain-dev 상태 변경: 할 일 → 진행 중
-
팀팀리드 위임: premium-dev에게 '유료 콘텐츠 PDF 파트셜 + 오케스트레이터 연동' 작업 배정06:41 개인 PDF - 유료 콘텐츠 페이지 구현
-
팀팀리드 위임: domain-dev에게 'Domain 상세 페이지 - 1위 중심 레이아웃 + 비율 바차트' 작업 배정
-
팀팀리드 두 PDF 티켓 동시 진행 시작. 코드베이스 분석 후 서브 티켓 생성 예정.
-
팀팀리드 티켓 클레임 완료06:35 개인 PDF - 유료 콘텐츠 페이지 구현
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 WAY 타입별 8개 섹션 구현 완료. _way_sections.html.erb 신규 생성, _way_detail.html.erb에서 WAY 하이라이트 분리, pdf.html.erb 페이지 순서 조정. Adult(701KB), Leader(730KB) PDF 생성 검증 완료. 모든 타입(adult/student/leader)에서 8개 섹션 정상 렌더링 확인.
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 멤버 결과 보기 기능 3개 티켓 모두 완료. 전체 394개 테스트 통과. 변경: DiagnosesController 권한 로직(workspace admin 허용), 멤버 카드/목록 뷰 보기 버튼 추가, 권한 통합 테스트 6개 작성.
-
팀팀리드 상태 변경: 할 일 → 완료06:15 멤버 결과 보기 권한 통합 테스트 작성
-
팀팀리드 상태 변경: 할 일 → 완료06:15 멤버 목록/카드 뷰에 결과 보기 버튼 추가
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 상태 변경: 할 일 → 완료
-
팀팀리드 위임: guide-dev에게 '가이드 텍스트 i18n + PDF 파트셜 + 오케스트레이터 수정' 작업 배정
-
팀팀리드 위임: chart-dev에게 'SVG 원형 차트 헬퍼 + PDF 파트셜 생성' 작업 배정
-
팀팀리드 차트+가이드 2개 티켓 일괄 작업 시작. chart-dev, guide-dev 2인 팀 구성 예정.
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 상태 변경: 진행 중 → 완료05:42 기존 팀 상위 DNA 섹션 정리
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 상태 변경: 진행 중 → 완료
-
팀팀리드 멤버 결과 보기 기능 3개 티켓 일괄 처리 시작. 팀 구성: backend-dev(권한 로직+테스트), frontend-dev(뷰 수정)
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 3개 티켓 일괄 작업 시작. backend-dev, frontend-dev 2인 팀 구성 예정.
-
팀팀리드 티켓 클레임 완료05:28 기존 팀 상위 DNA 섹션 정리
-
팀팀리드 티켓 클레임 완료
-
팀팀리드 티켓 클레임 완료