From 2cd05ccf8c889ea27e2060f50f62db119f2152da Mon Sep 17 00:00:00 2001 From: happybell80 Date: Mon, 16 Mar 2026 00:44:32 +0900 Subject: [PATCH] docs: clarify llm model ssot transition --- ...ace_config_로컬이식_통합리서치.md | 151 +++++++++++++++++- ...SOT와_하드코딩_분산_문제오픈.md | 76 ++++++++- 2 files changed, 222 insertions(+), 5 deletions(-) diff --git a/journey/research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md b/journey/research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md index 2dce282..55fdf45 100644 --- a/journey/research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md +++ b/journey/research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md @@ -4,6 +4,14 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] # 260315 모델 SSOT 하드코딩 분산과 workspace-config 로컬 이식 통합 리서치 +## 상위 원칙 + +- [0_VALUE Writing Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/writing-principles.md) +- [0_VALUE Infrastructure SSOT Principle](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/infrastructure-ssot-principle.md) +- [0_VALUE Coding Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/coding-principles.md) +- [로빙 문서 작성 원칙](../../book/300_architecture/312_writing-principles.md) +- [로빙 인프라 설정 SSOT 원칙](../../book/300_architecture/314_infrastructure-ssot-principle.md) + ## 이 리서치가 받는 문제 문서 - 현재 문제 정의와 영향 범위는 [workspace-config 루트기준 SSOT와 하드코딩 분산 문제 오픈](../troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md)에서 엽니다. @@ -14,6 +22,33 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - 그 결과 모델명만 바꿔도 전체가 따라 바뀌지 않고, 서비스별 fallback과 직접 SDK 호출이 다시 살아나는 구조입니다. - 같은 유형의 문제가 인프라 문서에서는 주소, 포트, 경로, secret의 하드코딩과 runtime SSOT 불일치 문제로 반복 기록돼 있습니다. - 따라서 이번 이슈는 단순 모델 선택 문제가 아니라, `운영값을 한 곳에서 선언하고 실제 런타임이 그 계약만 따르게 만드는 구조`를 아직 닫지 못한 문제입니다. +- 이 구조는 로컬 전용이 아니라 서버와 로컬이 함께 공유해야 하는 공통 구조입니다. +- 지금의 핵심은 새 구조를 발명하는 것이 아니라, 이미 있는 `workspace-config` 2파일 주입 구조 위에서 남은 로컬 `.env`와 코드 우회 경로를 제거하는 것입니다. +- 또한 사용자 관점에서는 "주 모델을 `--`로 바꾸자"라고 했을 때 수정 지점이 즉시 답돼야 합니다. +- 이 리서치의 작업 목표는 주 모델 선언을 `workspace-config/runtime.env`로 올리고, 과도기에는 최소 `rb8001/.env`까지만 수정하거나 API 호출 입력에서 모델명을 명시하면 그 값으로 실제 호출 모델이 바뀌도록 만드는 것입니다. + +## Facts + +### 1. 상위 SSOT는 절대경로가 아니라 루트 기준값 + 상대 구조를 요구한다 + +- `0_VALUE/02_Governance/infrastructure-ssot-principle.md`는 환경마다 절대경로가 달라도, 루트 기준값 하나만 바꾸면 같은 디렉터리 구조와 같은 설정 해석 규칙을 따라가게 유지하라고 명시합니다. +- `0_VALUE/02_Governance/workspace-config/README.md`는 `workspace-config`의 SSOT가 특정 절대경로가 아니라, 워크스페이스 루트 기준값 아래에서 같은 상대 구조를 해석하는 방식이라고 명시합니다. + +### 2. 상위 코드 원칙은 하드코딩·광범위 예외·상시 폴백으로 문제를 덮지 말라고 요구한다 + +- `0_VALUE/02_Governance/coding-principles.md`는 운영 IP, 포트, 시크릿, 공통 URL을 코드에 하드코딩하지 말라고 명시합니다. +- 같은 문서는 catch-all fallback, 광범위 예외 처리, 기본값 주입으로 구조적 결함을 가리지 말라고 명시합니다. + +### 3. 로빙의 실제 모델/런타임 경로에는 하드코딩과 분산 참조가 남아 있다 + +- `DEFAULT_LLM_MODEL` 같은 선언은 존재하지만, 실제 경로에는 `GeminiHandler` 직접 생성, Gemini SDK 직접 호출, `gemini-*` fallback 문자열 배열이 섞여 있습니다. +- `workspace-config`도 상위 원칙상 상대 구조로 해석돼야 하지만, 일부 compose와 문서는 여전히 서버 절대경로와 서비스별 설정을 함께 전제합니다. + +### 4. 서버도 공용 주입 구조는 이미 있으나, 모델 SSOT는 아직 완전히 올라가지 않았다 + +- 서버 기준 `rb8001`, `skill-slack`은 이미 공용 `runtime.env`, `secrets.env`를 읽는 구조를 사용합니다. +- 하지만 `DEFAULT_LLM_MODEL`의 실제 원천은 공용 `runtime.env`가 아니라 서비스 로컬 `.env`에 남아 있는 구간이 있습니다. +- 따라서 현재 문제는 `workspace-config` 구조 부재가 아니라, `DEFAULT_LLM_MODEL`과 호출 경로가 아직 그 구조에 끝까지 종속되지 못한 상태입니다. ## 직접 연결되는 로빙 문서 @@ -21,6 +56,8 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - [LLM 모델 비교 분석](./LLM_모델_비교_분석.md) - [로빙 LLM API, Agent API, 모델 선정, 비용 비교 리서치](./orchestration_tools/260312_로빙_LLM_API_Agent_API_모델선정_비용비교_리서치.md) +- [23서버 인프라점검 응답실패 원인확정 리서치](./260307_23서버_인프라점검_응답실패_원인확정_리서치.md) +- [콜드메일 skill-rag-file 500 및 실패은닉 원인확정 리서치](./260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md) ### Gemini 단일 모델 고정과 fallback 기록 @@ -31,11 +68,50 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] ### SSOT 분산과 하드코딩 잔존 - [아침 뉴스 슬랙 포맷 SSOT 분산 및 표시 혼선](../troubleshooting/260310_아침뉴스슬랙포맷_SSOT_분산_및_표시혼선.md) +- [프롬프트 DB 응답생성 폐루프 미연결](../troubleshooting/260310_프롬프트DB_응답생성_폐루프_미연결.md) - [프롬프트 DB 부분 도입 상태와 하드코딩 프롬프트 잔존](../troubleshooting/260311_prompt_db_partial_adoption_and_hardcoded_prompts.md) - [하드코딩 URL 제거 작업](../troubleshooting/250915_hardcoded_url_removal.md) +- [rb8001: 하드코딩 URL/DB 기본값 환경변수화 정리](../troubleshooting/251023_admin_rb8001_URL_환경변수화_정리.md) +- [코드와 규칙 정렬 점검](../troubleshooting/251023_code_alignment_with_rules.md) - [로빙 인프라 설정 SSOT 원칙](../../book/300_architecture/314_infrastructure-ssot-principle.md) -## 상위 SSOT와 workspace-config 기준 문서 +## 이 리서치와 함께 닫아야 할 문서 묶음 + +### 0. 닫힌 문서 재오픈 금지 원칙 + +- `완전 닫힘`, `종결`, `완료`로 표시된 문서는 다시 열지 않습니다. +- 새 회귀나 새 사실은 기존 종결 문서를 재오픈하지 않고 새 troubleshooting/research 문서로 분리합니다. +- 따라서 아래 묶음은 현재 문제와 함께 닫아야 하는 열린 문서 또는 미종결 문서만 유지합니다. + +### 1. 리서치 + +- [LLM 모델 비교 분석](./LLM_모델_비교_분석.md) +- [로빙 LLM API, Agent API, 모델 선정, 비용 비교 리서치](./orchestration_tools/260312_로빙_LLM_API_Agent_API_모델선정_비용비교_리서치.md) +- [23서버 인프라점검 응답실패 원인확정 리서치](./260307_23서버_인프라점검_응답실패_원인확정_리서치.md) +- [콜드메일 skill-rag-file 500 및 실패은닉 원인확정 리서치](./260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md) +- [23서버 워크스페이스 SSOT 구조전환 리서치](https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/research/260309_23서버_워크스페이스_SSOT_구조전환_리서치.md) + +### 2. 트러블슈팅 + +- [workspace-config 루트기준 SSOT와 하드코딩 분산 문제 오픈](../troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md) +- [아침 뉴스 슬랙 포맷 SSOT 분산 및 표시 혼선](../troubleshooting/260310_아침뉴스슬랙포맷_SSOT_분산_및_표시혼선.md) +- [프롬프트 DB 응답생성 폐루프 미연결](../troubleshooting/260310_프롬프트DB_응답생성_폐루프_미연결.md) +- [프롬프트 DB 부분 도입 상태와 하드코딩 프롬프트 잔존](../troubleshooting/260311_prompt_db_partial_adoption_and_hardcoded_prompts.md) +- [Gemini 모델 최적화: gemini-2.5-flash-lite 전환](../troubleshooting/250906_gemini_model_optimization.md) +- [admin gemini single model and ethics visibility](../troubleshooting/251021_admin_gemini_single_model_and_ethics_visibility.md) +- [IR deck Gemini fallback 빈응답 처리](../troubleshooting/251202_ir_deck_gemini_fallback_빈응답_처리.md) +- [하드코딩 URL 제거 작업](../troubleshooting/250915_hardcoded_url_removal.md) +- [rb8001: 하드코딩 URL/DB 기본값 환경변수화 정리](../troubleshooting/251023_admin_rb8001_URL_환경변수화_정리.md) +- [코드와 규칙 정렬 점검](../troubleshooting/251023_code_alignment_with_rules.md) +- [gateway SSOT runtime/secrets 분리 적용 및 검증](../troubleshooting/260307_gateway_SSOT_runtime_secrets_분리_적용_및_검증.md) + +### 3. 닫힘 원칙 + +- 이 리서치를 닫을 때는 모델 교체 가능성만 보지 않고, `workspace-config`, 프롬프트 경로, URL/엔드포인트, fallback 정책이 같은 방식으로 SSOT를 따르도록 함께 닫아야 합니다. +- 따라서 한 문서만 완료로 두고 주변 문서를 미확정으로 남기지 않습니다. `모델 원천`, `호출 경로`, `프롬프트 원천`, `운영 URL 원천`이 모두 공용 계약으로 수렴했는지 기준으로 함께 판정합니다. +- 닫힘 이후 동일 계열 문제가 다시 나타나면 이 리서치를 재오픈하지 않고 새 문서를 엽니다. + +## 관련 기준 문서 - [0_VALUE Infrastructure SSOT Principle](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/infrastructure-ssot-principle.md) - [0_VALUE workspace-config README](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/workspace-config/README.md) @@ -45,7 +121,51 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - [23제어면 gateway workspace-config 단일화](https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/worklog/260309_23제어면_gateway_workspace_config_단일화.md) - [24서버 robeing runtime workspace-config 단일화](https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/worklog/260310_24서버_robeing_runtime_workspace_config_단일화.md) -## 통합 해석 +## 외부 사례 비교 + +### 1. OpenAI와 Gemini는 모두 요청 입력에서 모델명을 받는다 + +- OpenAI Responses API는 요청 본문에서 `model`을 직접 받습니다. + - 예: `responses.create({ model: "gpt-5.4", input: ... })` + - 출처: +- Gemini API도 `generateContent` 호출에서 `model`을 직접 받습니다. + - 예: `models.generateContent({ model: "gemini-2.5-flash", ... })` + - 출처: +- Anthropic Messages API도 요청 본문에서 `model`을 필수로 받습니다. + - 예: `messages.create({ model: "claude-sonnet-4-20250514", ... })` + - 출처: +- 즉 외부 주요 API들은 "요청 단위로 모델명을 지정할 수 있다"는 점에서는 공통입니다. + +### 2. 하지만 애플리케이션 레벨에서는 단일 추상화로 감싸는 패턴이 널리 쓰인다 + +- LangChain은 `init_chat_model` 또는 `initChatModel`로 모델 초기화를 단일 진입점에서 처리합니다. + - Python 예시: `init_chat_model("gpt-5.2")`, `init_chat_model("google_genai:gemini-2.5-flash-lite")` + - JavaScript 예시: `initChatModel("gpt-5.2")`, `initChatModel("google-genai:gemini-2.5-flash-lite")` + - 출처: , +- LangChain은 `provider:model` 형식도 허용하므로, 호출부는 공통 인터페이스를 쓰고 provider 차이는 초기화 계층에서 해석합니다. +- LiteLLM은 더 나아가 "100+ LLMs"를 하나의 인터페이스와 게이트웨이로 통합하고, provider별 endpoint 차이를 내부에서 번역한다고 설명합니다. + - 출처: + +### 3. 우리가 참고할 핵심 포인트 + +- 요청 단위 모델 지정 자체는 이상한 설계가 아닙니다. OpenAI/Gemini/Anthropic 모두 그렇게 합니다. +- 다만 서비스 코드가 provider SDK를 직접 고르는 것은 별개 문제입니다. +- 외부 사례에서 참고할 부분은 다음입니다. + - API 입력에서는 `model` override를 허용한다. + - 내부 구현에서는 단일 factory/gateway/initializer가 provider 차이를 해석한다. + - 호출부는 `GeminiHandler`, `OpenAIHandler`를 직접 만들지 않고 공통 인터페이스만 사용한다. + +### 4. 로빙에 적용할 권고안 + +- 기본 경로는 `workspace-config/runtime.env -> settings.DEFAULT_LLM_MODEL -> 단일 LLM factory/service -> handler`로 고정합니다. +- 예외적으로 API 요청에 `model`이 명시되면 그 입력값을 우선 적용할 수 있습니다. +- 이 경우에도 handler 선택은 호출부가 아니라 factory/service가 담당해야 합니다. +- 권장 해석 방식은 아래 둘 중 하나입니다. + - `model` 문자열만 보고 factory가 provider를 판별 + - `provider` + `model`을 명시적으로 받고 factory가 둘을 함께 검증 +- 현재 로빙처럼 서비스 코드 곳곳에서 Gemini SDK 직접 호출, OpenAI handler 직접 생성, fallback 배열 직접 선언이 섞여 있는 구조는 외부 사례의 "요청 입력은 유연하게, 내부 선택은 단일화" 패턴과 다릅니다. + +## Interpretation ### 1. workspace-config는 값 저장 폴더가 아니라 런타임 계약입니다 @@ -58,6 +178,7 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - `DEFAULT_LLM_MODEL`은 선언돼 있지만, 실제 경로는 `GeminiHandler` 직접 생성, Gemini SDK 직접 호출, `gemini-*` fallback 리스트, 서비스별 개별 모델 하드코딩이 섞여 있습니다. - 그래서 `주 모델 변경`이 `SSOT 1개 값 변경`으로 닫히지 않고, 여러 서비스의 코드 경로를 다시 건드려야 하는 구조가 됩니다. - 즉 지금의 직접 원인은 `gpt-5-mini` 전환 작업이고, 근본 원인은 `모델 호출 계약의 SSOT`와 `실제 호출 구현`이 분리되지 않은 점입니다. +- 이 해석은 서버와 로컬 모두 동일합니다. 서버별 모델 차이가 필요해도 그것은 코드 차이가 아니라 `runtime.env` 값 차이로만 표현돼야 합니다. ### 3. 구조적으로 닫아야 할 기준 @@ -65,6 +186,20 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - 서비스는 `어떤 모델을 쓸지`가 아니라 `어떤 작업을 요청할지`만 말해야 합니다. - fallback도 각 서비스가 개별 문자열 배열을 들고 있지 말고, 공용 정책 계층에서만 관리돼야 합니다. - 이 기준이 닫혀야 `DEFAULT_LLM_MODEL` 같은 값이 실제 SSOT가 됩니다. +- 닫혀야 할 최종 경로는 `runtime.env -> settings.DEFAULT_LLM_MODEL -> 단일 LLM factory/service -> handler`입니다. +- `GEMINI_MODEL`, 코드 기본값 문자열, 요청별 모델 직접 주입, 서비스별 fallback 배열은 모두 이 경로의 우회로로 봐야 합니다. +- 사용자 작업 기준으로는 목표 수정 지점과 과도기 최소 수정 지점을 함께 고정해야 합니다. +- 목표 수정 지점: `workspace-config/runtime.env` +- 과도기 최소 수정 지점: `workspace-config/runtime.env`와 `rb8001/.env` +- 예외 허용 입력 경로: API 호출에서 모델명을 명시하면 그 입력값만으로 실제 호출 모델이 바뀌는 것 + +## Unresolved + +- 각 하위 프로젝트 compose가 로컬에서 어떤 방식으로 루트 기준값을 해석하게 맞출지 +- 각 하위 프로젝트 compose가 서버에서 어떤 방식으로 공용 runtime env만 기준으로 읽게 맞출지 +- 서비스별 `.env`와 코드 fallback 중 무엇이 아직 실제 런타임 경로에 남아 있는지 전체 인벤토리 +- 로컬 기준 공용 파일만 읽도록 바꿀 때, 프로젝트별 예외가 필요한 서비스가 있는지 여부 +- 서버 기준 공용 파일만 읽도록 바꿀 때, 운영상 예외가 필요한 서비스가 있는지 여부 ## workspace-config 로컬 이식 기준 @@ -115,6 +250,8 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] - 코드 기본값이나 compose `environment:`에 운영값을 하드코딩하지 않아야 합니다. - 서비스별 `.env`는 정말 필요한 로컬 실험 오버라이드에만 써야 합니다. - 주소, 포트, 시크릿이 바뀌면 `workspace-config`의 두 파일만 수정한 뒤 재기동해서 반영 여부를 검증해야 합니다. +- 같은 기준을 서버에도 그대로 적용합니다. 서버별 차이는 파일 위치가 아니라 값만 달라야 합니다. +- 특히 주 LLM 모델은 서비스 로컬 `.env`가 아니라 공용 `runtime.env`에서만 선언되고, 코드는 `settings.DEFAULT_LLM_MODEL`만 소비해야 합니다. 로컬 SSOT의 닫힘 조건은 아래 3가지입니다. @@ -122,8 +259,16 @@ tags: [research, llm, ssot, workspace-config, hardcoding, robeing] 2. 모든 서비스가 그 파일만 바라보는가 3. 실제 실행 결과가 그 값으로 해석되는가 -## 이번 문서의 결론 +서버와 로컬을 함께 보는 닫힘 조건은 아래 3가지입니다. + +1. 서버와 로컬 모두 주 모델 원천이 각자 `runtime.env` 1곳인가 +2. 서버와 로컬 모두 코드가 `settings.DEFAULT_LLM_MODEL`만 소비하는가 +3. 서버와 로컬 모두 실제 호출이 단일 factory/service 경로만 타는가 + +## 결론 - 로빙의 현재 LLM 주모델 교체 난이도는 `모델 선정` 자체보다 `모델 호출 구조가 SSOT를 강제하지 못하는 설계`에서 발생합니다. - 인프라 쪽 `workspace-config`가 해결한 방식은 값 자체가 아니라 `계약과 주입 지점`을 단일화한 것입니다. - 로빙도 같은 방식으로 `모델명`, `제공자`, `fallback`, `SDK 선택`을 공용 유틸리티 또는 팩토리 한 곳으로 승격해야, 이후 모델 교체가 SSOT 변경 1회로 닫힙니다. +- 따라서 이 작업은 로컬만 정리해서 끝나는 문제가 아니라, 서버와 로컬이 함께 같은 계약을 쓰도록 맞추는 공통 정리 작업입니다. +- 더 정확히 말하면, 현재 단계의 본질은 `workspace-config` 구조 도입이 아니라 `남아 있는 .env 원천과 코드 우회 경로 청산`입니다. diff --git a/journey/troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md b/journey/troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md index 568a4ac..2326550 100644 --- a/journey/troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md +++ b/journey/troubleshooting/260316_workspace_config_루트기준_SSOT와_하드코딩_분산_문제오픈.md @@ -2,16 +2,66 @@ tags: [troubleshooting, workspace-config, ssot, hardcoding, runtime] # workspace-config 루트기준 SSOT와 하드코딩 분산 문제 오픈 +## 상위 원칙 + +- [0_VALUE Writing Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/writing-principles.md) +- [0_VALUE Infrastructure SSOT Principle](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/infrastructure-ssot-principle.md) +- [0_VALUE Coding Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/coding-principles.md) +- [로빙 문서 작성 원칙](../../book/300_architecture/312_writing-principles.md) +- [로빙 인프라 설정 SSOT 원칙](../../book/300_architecture/314_infrastructure-ssot-principle.md) + ## 문제 정의 - `workspace-config`와 모델/런타임 설정은 SSOT라고 선언돼 있지만, 실제 코드·compose·문서에는 절대경로와 하드코딩, 분산 참조가 함께 남아 있습니다. - 그 결과 값 변경이 `WORKSPACE_ROOT + workspace-config/runtime.env|secrets.env` 한 곳에서 닫히지 않고, 프로젝트별 수정과 해석 혼선이 반복됩니다. +- 이 문제는 로컬만의 문제가 아니라 서버도 같은 목표 구조로 닫혀야 하는 공통 문제입니다. +- 현재 서버와 로컬 모두 `runtime.env -> settings.DEFAULT_LLM_MODEL -> 단일 factory/service -> handler`로 완전히 닫혀 있지 않고, 서비스 로컬 `.env`와 코드 우회 경로가 함께 남아 있습니다. +- 사용자가 "주 모델을 `--`로 바꾸자"라고 했을 때 수정 지점이 즉시 답돼야 하는데, 지금은 그 기준도 충분히 고정돼 있지 않습니다. +- 현재 문서 기준의 목표는 주 모델 선언을 `workspace-config/runtime.env`에 두고, 과도기에는 최소 `rb8001/.env`까지만 수정하거나 API 호출에서 모델명을 명시하면 그 입력값을 따라 실제 호출 모델이 바뀌도록 만드는 것입니다. ## 관련 문서 - [모델 SSOT 하드코딩 분산과 workspace-config 로컬이식 통합 리서치](../research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md) -- [0_VALUE Infrastructure SSOT Principle](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/infrastructure-ssot-principle.md) - [0_VALUE Workspace Config](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/workspace-config/README.md) +- [하드코딩 URL 제거 작업](./250915_hardcoded_url_removal.md) +- [아침 뉴스 슬랙 포맷 SSOT 분산 및 표시 혼선](./260310_아침뉴스슬랙포맷_SSOT_분산_및_표시혼선.md) +- [프롬프트 DB 부분 도입 상태와 하드코딩 프롬프트 잔존](./260311_prompt_db_partial_adoption_and_hardcoded_prompts.md) + +## 이 문제를 닫을 때 함께 닫아야 할 문서 묶음 + +### 0. 닫힌 문서 재오픈 금지 원칙 + +- `완전 닫힘`, `종결`, `완료`로 표시된 문서는 다시 열지 않습니다. +- 닫힌 문서에서 새 회귀나 새 사실이 발견되면, 기존 문서를 재오픈하지 않고 새 troubleshooting/research 문서에서 후속 이슈를 엽니다. +- 따라서 이 묶음에는 현재 문제를 닫는 데 함께 봐야 하는 `열린 문서` 또는 `아직 닫힘이 확정되지 않은 문서`만 남깁니다. + +### 1. 직접 리서치 묶음 + +- [모델 SSOT 하드코딩 분산과 workspace-config 로컬이식 통합 리서치](../research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md) +- [LLM 모델 비교 분석](../research/LLM_모델_비교_분석.md) +- [로빙 LLM API, Agent API, 모델 선정, 비용 비교 리서치](../research/orchestration_tools/260312_로빙_LLM_API_Agent_API_모델선정_비용비교_리서치.md) +- [23서버 인프라점검 응답실패 원인확정 리서치](../research/260307_23서버_인프라점검_응답실패_원인확정_리서치.md) +- [콜드메일 skill-rag-file 500 및 실패은닉 원인확정 리서치](../research/260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md) +- [23서버 워크스페이스 SSOT 구조전환 리서치](https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/research/260309_23서버_워크스페이스_SSOT_구조전환_리서치.md) + +### 2. 직접 트러블슈팅 묶음 + +- [아침 뉴스 슬랙 포맷 SSOT 분산 및 표시 혼선](./260310_아침뉴스슬랙포맷_SSOT_분산_및_표시혼선.md) +- [프롬프트 DB 응답생성 폐루프 미연결](./260310_프롬프트DB_응답생성_폐루프_미연결.md) +- [프롬프트 DB 부분 도입 상태와 하드코딩 프롬프트 잔존](./260311_prompt_db_partial_adoption_and_hardcoded_prompts.md) +- [Gemini 모델 최적화: gemini-2.5-flash-lite 전환](./250906_gemini_model_optimization.md) +- [admin gemini single model and ethics visibility](./251021_admin_gemini_single_model_and_ethics_visibility.md) +- [IR deck Gemini fallback 빈응답 처리](./251202_ir_deck_gemini_fallback_빈응답_처리.md) +- [rb8001: 하드코딩 URL/DB 기본값 환경변수화 정리](./251023_admin_rb8001_URL_환경변수화_정리.md) +- [코드와 규칙 정렬 점검](./251023_code_alignment_with_rules.md) +- [gateway SSOT runtime/secrets 분리 적용 및 검증](./260307_gateway_SSOT_runtime_secrets_분리_적용_및_검증.md) + +### 3. 닫힘 판정 규칙 + +- 현재 문제를 닫을 때는 위 문서들을 별개 이슈로 남기지 않고, `주 LLM 모델 SSOT`, `workspace-config 런타임 계약`, `하드코딩 프롬프트/URL/모델 우회 경로`가 실제로 함께 줄어들었는지 확인합니다. +- 특히 `DEFAULT_LLM_MODEL` 원천이 공용 `runtime.env` 1곳으로 올라갔는지, 서비스 로컬 `.env`와 코드 fallback이 제거됐는지, 단일 factory/service 경로만 남았는지를 공통 닫힘 조건으로 봅니다. +- 사용자 모델 변경 요청 기준으로는 최소 `workspace-config/runtime.env`와 `rb8001/.env`까지만 수정하거나, API 입력 모델명만으로 실제 호출 모델이 바뀌어야 합니다. +- 닫힘 이후 회귀가 생기면 이 문서를 재오픈하지 않고 새 문서를 엽니다. ## 이 문서가 여는 리서치 @@ -20,6 +70,7 @@ tags: [troubleshooting, workspace-config, ssot, hardcoding, runtime] ## 재현 조건 - 로컬 워크스페이스에서 `workspace-config/runtime.env`, `workspace-config/secrets.env`를 기준으로 설정을 맞추려 할 때 +- 서버 워크스페이스에서 `/home/admin/workspace-config/runtime.env`, `/home/admin/workspace-config/secrets.env`를 기준으로 설정을 맞추려 할 때 - 하위 프로젝트의 compose, 코드, 문서가 여전히 절대경로 `/home/admin/...` 또는 서비스별 개별 설정을 전제할 때 - 모델·엔드포인트·모니터·DB 설정 변경을 한 곳에서 끝내려 할 때 @@ -30,6 +81,12 @@ tags: [troubleshooting, workspace-config, ssot, hardcoding, runtime] - `0_VALUE/02_Governance/infrastructure-ssot-principle.md`는 환경마다 절대경로가 달라도, 루트 기준값 하나만 바꾸면 같은 디렉터리 구조와 같은 설정 해석 규칙을 따라가게 유지하라고 명시합니다. - `0_VALUE/02_Governance/workspace-config/README.md`는 `workspace-config`의 SSOT가 특정 절대경로가 아니라, 워크스페이스 루트 기준값 아래에서 같은 상대 구조를 해석하는 방식이라고 명시합니다. +### 1-1. 상위 코드 원칙은 하드코딩·광범위 예외·상시 폴백으로 문제를 덮지 말라고 요구한다 + +- `0_VALUE/02_Governance/coding-principles.md`는 운영 IP, 포트, 시크릿, 공통 URL을 코드에 하드코딩하지 말라고 명시합니다. +- 같은 문서는 catch-all fallback, 광범위 예외 처리, 기본값 주입으로 구조적 결함을 가리지 말라고 명시합니다. +- 따라서 현재 이슈는 단순 경로 정리 문제가 아니라, 상위 코드 원칙과 런타임 SSOT 원칙이 실제 적용 경로에서 어긋난 상태로 해석해야 합니다. + ### 2. 현재 로컬에는 공용 런타임 파일 두 개가 존재한다 - 로컬 경로 `/home/happybell/projects/workspace-config/runtime.env`가 존재합니다. @@ -47,9 +104,17 @@ tags: [troubleshooting, workspace-config, ssot, hardcoding, runtime] - 일부 서비스는 여전히 서비스별 `.env`, 코드 기본값, 하드코딩 fallback을 같이 들고 있습니다. - 따라서 현재는 상위 원칙과 로컬 실행 구조가 완전히 일치한다고 볼 수 없습니다. +### 5. 서버도 구조 일부는 같지만, DEFAULT_LLM_MODEL SSOT는 아직 분산돼 있다 + +- 서버 기준 `rb8001`와 `skill-slack`은 이미 `/home/admin/workspace-config/runtime.env`, `/home/admin/workspace-config/secrets.env`를 `env_file`로 읽는 구조를 사용합니다. +- 하지만 `DEFAULT_LLM_MODEL`의 실제 원천은 아직 공용 `workspace-config/runtime.env`가 아니라 서비스 로컬 `.env`에 남아 있습니다. +- 따라서 서버는 `runtime.env/secrets.env` 2파일 구조를 이미 갖고 있지만, 주 LLM 모델 SSOT만 공용 런타임 계층으로 완전히 승격되지 않은 상태입니다. +- 이 문제는 서버 구조가 틀린 것이 아니라, 마지막 우회 경로가 남아 있는 상태로 해석해야 합니다. + ## 영향 범위 - 로컬 개발자가 `WORKSPACE_ROOT`와 `workspace-config` 두 파일만 바꾸면 된다고 믿고 작업해도, 실제 하위 프로젝트에서는 추가 수정이 발생할 수 있습니다. +- 서버 운영자도 공용 `workspace-config`만 바꾸면 된다고 믿고 작업해도, 실제로는 서비스 로컬 `.env`와 코드 우회 경로 때문에 추가 수정이 발생할 수 있습니다. - 모델, 모니터, DB, URL, 포트 같은 공용 운영값이 여러 군데에서 따로 관리되면 회귀와 오판 위험이 커집니다. - 문제를 `troubleshooting -> research -> plans -> worklog` 흐름으로 닫아야 하는데, 시작점이 불명확해져 같은 논쟁이 반복됩니다. @@ -58,15 +123,22 @@ tags: [troubleshooting, workspace-config, ssot, hardcoding, runtime] - `WORKSPACE_ROOT`만 다르면 서버와 로컬이 같은 상대 구조 `workspace-config/runtime.env`, `workspace-config/secrets.env`를 동일하게 해석합니다. - 공용 운영값 변경 시 수정 지점은 `runtime.env`, `secrets.env` 두 파일로 닫힙니다. - 하위 프로젝트는 서비스별 `.env`나 코드 하드코딩이 아니라, 공용 런타임 파일만 기준으로 읽습니다. +- 특히 주 LLM 모델은 `runtime.env -> settings.DEFAULT_LLM_MODEL -> 단일 LLM factory/service -> handler` 한 줄 경로로만 해석됩니다. +- 서버별 모델 차이는 코드 분기가 아니라 `runtime.env` 값 차이로만 표현됩니다. +- 목표 상태에서는 사용자가 주 모델 변경을 요청하면 `workspace-config/runtime.env` 1곳만 수정합니다. +- 과도기 기준에서도 최소 `workspace-config/runtime.env`와 `rb8001/.env`까지만 수정하거나, API 입력에서 모델명을 명시하면 그 값만으로 실제 호출 모델이 바뀌어야 합니다. ## 미확정 항목 - 각 하위 프로젝트 compose가 로컬에서 어떤 방식으로 루트 기준값을 해석하게 맞출지 +- 각 하위 프로젝트 compose가 서버에서 어떤 방식으로 공용 runtime env만 기준으로 읽게 맞출지 - 서비스별 `.env`와 코드 fallback 중 무엇이 아직 실제 런타임 경로에 남아 있는지 전체 인벤토리 - 로컬 기준 공용 파일만 읽도록 바꿀 때, 프로젝트별 예외가 필요한 서비스가 있는지 여부 +- 서버 기준 공용 파일만 읽도록 바꿀 때, 운영상 예외가 필요한 서비스가 있는지 여부 ## 다음 단계 -- 원인과 잔존 경로 수집은 `research`에서 더 좁힙니다. +- 원인과 잔존 경로 수집은 [모델 SSOT 하드코딩 분산과 workspace-config 로컬이식 통합 리서치](../research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md)에서 더 좁힙니다. +- 리서치에서는 로컬과 서버를 분리된 문제로 보지 않고, 같은 목표 구조를 향한 공통 전환으로 해석합니다. - 어떤 저장소를 어떤 순서로 고칠지는 `plans`에서 고정합니다. - 닫힘 선언은 `worklog`에서만 합니다.