config.local.toml 설정 단일화 .

This commit is contained in:
hbyang 2026-06-17 11:26:20 +09:00
parent 951d6eab84
commit e583cd6311
13 changed files with 207 additions and 0 deletions

View File

@ -54,6 +54,13 @@ class DBSessionManager(Singleton):
db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}" db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}"
LOG.i(f"Write DB create engine url : {db_url}") LOG.i(f"Write DB create engine url : {db_url}")
# SSL/TLS: 관리형 DB(RDS/Aurora/Azure)는 보통 TLS 필수. sslmode 가 설정되면 asyncpg 에 전달.
# ""/"disable" → 미적용(로컬). "require"/"verify-ca"/"verify-full" → asyncpg ssl 사용.
connect_args = {}
sslmode = (getattr(db_config, "sslmode", "") or "").lower()
if sslmode and sslmode != "disable":
connect_args["ssl"] = sslmode
engine = create_async_engine( engine = create_async_engine(
db_url, db_url,
echo=db_config.show_log, echo=db_config.show_log,
@ -61,6 +68,7 @@ class DBSessionManager(Singleton):
max_overflow=db_config.max_overflow, max_overflow=db_config.max_overflow,
pool_pre_ping=True, pool_pre_ping=True,
pool_recycle=600, pool_recycle=600,
connect_args=connect_args,
) )
self.__engines.append(engine) self.__engines.append(engine)
scoped_session = async_scoped_session( scoped_session = async_scoped_session(

View File

@ -0,0 +1,46 @@
# 복사해서 사용: cp config.local.toml.example config.local.toml
# 실제 config.local.toml 은 시크릿(DB 비번·OpenAI 키) 포함이라 커밋하지 않는다(.gitignore: *.toml).
# 모든 서버는 APP_ENV=local 로 띄우며 이 파일(config.local.toml)을 읽는다.
[WebServerConfig]
server_name = "NegosiumAgentServer"
port = 9500
process_count = 1
is_ssl = false
is_test = true
[LogConfig]
print_console = true
log_level = "debug"
# negosium_db 를 backend 와 공유. agent 는 learning 스키마에 RL 자산을 둔다.
# 도커 실행 시 host 는 docker-compose 가 DB_HOST 환경변수로 override 한다(컨테이너→호스트 DB).
# 관리형 DB(RDS/Aurora/Azure)는 host 에 엔드포인트, sslmode="require" 로 설정한다.
[MainDBConfig]
db_type = "postgresql"
name = "negosium_db"
write_host = "127.0.0.1"
write_port = 5432
write_id = "<DB_USER>"
write_pw = "<DB_PASSWORD>"
read_host = "127.0.0.1"
read_port = 5432
read_id = "<DB_USER>"
read_pw = "<DB_PASSWORD>"
show_log = false
pool_size = 10
max_overflow = 20
sslmode = "" # 로컬: "" 또는 "disable" / 관리형 DB: "require"|"verify-ca"|"verify-full"
[AgentConfig]
tenants_dir = "tenants"
config_cache_ttl_seconds = 300
allow_default_tenant = false
auto_seed_base = true
base_action_space = 9
base_seed_episodes = 300
# LLM(OpenAI). api_key 는 시크릿 — 실제 키를 채우고 커밋 금지.
[OpenAIConfig]
provider = "openai"
api_key = "<OPENAI_API_KEY>"
model = "gpt-4o-mini"

View File

@ -29,6 +29,8 @@ class MainDBConfig(ConfigModel):
show_log: bool = False show_log: bool = False
pool_size: int = 10 pool_size: int = 10
max_overflow: int = 20 max_overflow: int = 20
# SSL/TLS 모드: ""/"disable"=미사용(로컬), "require"/"verify-ca"/"verify-full"=관리형 DB(RDS/Aurora/Azure).
sslmode: str = ""
class OpenAIConfig(ConfigModel): class OpenAIConfig(ConfigModel):

View File

@ -20,3 +20,23 @@ log_config: LogConfig = configs.get(LogConfig)
main_db_config: MainDBConfig = configs.get(MainDBConfig) main_db_config: MainDBConfig = configs.get(MainDBConfig)
agent_config: AgentConfig = configs.get(AgentConfig) agent_config: AgentConfig = configs.get(AgentConfig)
openai_config: OpenAIConfig = configs.get(OpenAIConfig) or OpenAIConfig() openai_config: OpenAIConfig = configs.get(OpenAIConfig) or OpenAIConfig()
# DB 접속 env override (config.local.toml 은 그대로 두고, 도커 등에서 host 만 바꾸기 위함).
# 컨테이너 안에서는 127.0.0.1 이 자기 자신이라 호스트 DB 를 못 찾으므로,
# docker-compose 가 DB_HOST=host.docker.internal 을 주입한다. 로컬 실행은 env 미설정 → toml 그대로.
def _apply_db_env_override(cfg: MainDBConfig):
h = os.environ.get("DB_HOST")
if h:
cfg.write_host = cfg.read_host = h
if os.environ.get("DB_PORT"):
cfg.write_port = cfg.read_port = int(os.environ["DB_PORT"])
if os.environ.get("DB_USER"):
cfg.write_id = cfg.read_id = os.environ["DB_USER"]
if os.environ.get("DB_PASSWORD"):
cfg.write_pw = cfg.read_pw = os.environ["DB_PASSWORD"]
if os.environ.get("DB_NAME"):
cfg.name = os.environ["DB_NAME"]
_apply_db_env_override(main_db_config)

View File

@ -61,6 +61,12 @@ class DBSessionManager(Singleton):
db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}" db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}"
LOG.i(f"Write DB create engine url : {db_url}") LOG.i(f"Write DB create engine url : {db_url}")
# SSL/TLS: 관리형 DB(RDS/Aurora/Azure)는 보통 TLS 필수. sslmode 가 설정되면 asyncpg 에 전달.
connect_args = {}
sslmode = (getattr(db_config, "sslmode", "") or "").lower()
if sslmode and sslmode != "disable":
connect_args["ssl"] = sslmode
engine = create_async_engine( engine = create_async_engine(
db_url, db_url,
echo=db_config.show_log, echo=db_config.show_log,
@ -68,6 +74,7 @@ class DBSessionManager(Singleton):
max_overflow=db_config.max_overflow, max_overflow=db_config.max_overflow,
pool_pre_ping=True, pool_pre_ping=True,
pool_recycle=600, pool_recycle=600,
connect_args=connect_args,
) )
self.__engines.append(engine) self.__engines.append(engine)
scoped_session = async_scoped_session( scoped_session = async_scoped_session(

View File

@ -0,0 +1,37 @@
# 복사해서 사용: cp config.local.toml.example config.local.toml
# 실제 config.local.toml 은 시크릿 포함이라 커밋하지 않는다(.gitignore: *.toml).
# 모든 서버는 APP_ENV=local 로 띄우며 이 파일을 읽는다.
[WebServerConfig]
server_name = "NegosiumServer"
port = 9300
process_count = 1
is_ssl = false
is_test = true
[LogConfig]
print_console = true
log_level = "debug"
# DB Read/Write 분리. 도커 실행 시 host 는 docker-compose 의 DB_HOST 로 override.
# 관리형 DB(RDS/Aurora/Azure)는 host 에 엔드포인트, sslmode="require".
[MainDBConfig]
db_type = "postgresql"
name = "negosium_db"
write_host = "127.0.0.1"
write_port = 5432
write_id = "<DB_USER>"
write_pw = "<DB_PASSWORD>"
read_host = "127.0.0.1"
read_port = 5432
read_id = "<DB_USER>"
read_pw = "<DB_PASSWORD>"
show_log = false
pool_size = 10
max_overflow = 20
sslmode = "" # 로컬: "" / 관리형 DB: "require"|"verify-ca"|"verify-full"
[JwtToken]
access_key = "<JWT_ACCESS_SECRET>"
refresh_key = "<JWT_REFRESH_SECRET>"
access_expire_min = 30
refresh_expire_day = 7

View File

@ -32,6 +32,8 @@ class MainDBConfig(ConfigModel):
# PostgreSQL max_connections 를 넘지 않도록 설정해야 한다. (예: 10+20=30 x 2 x 5워커 = 300) # PostgreSQL max_connections 를 넘지 않도록 설정해야 한다. (예: 10+20=30 x 2 x 5워커 = 300)
pool_size: int = 10 pool_size: int = 10
max_overflow: int = 20 max_overflow: int = 20
# SSL/TLS 모드: ""/"disable"=미사용(로컬), "require"/"verify-ca"/"verify-full"=관리형 DB(RDS/Aurora/Azure).
sslmode: str = ""
class JwtToken(ConfigModel): class JwtToken(ConfigModel):

View File

@ -19,3 +19,21 @@ web_server_config: WebServerConfig = configs.get(WebServerConfig)
log_config: LogConfig = configs.get(LogConfig) log_config: LogConfig = configs.get(LogConfig)
main_db_config: MainDBConfig = configs.get(MainDBConfig) main_db_config: MainDBConfig = configs.get(MainDBConfig)
jwt_token_config: JwtToken = configs.get(JwtToken) jwt_token_config: JwtToken = configs.get(JwtToken)
# DB 접속 env override (config.local.toml 유지, 도커에서 host 만 교체). 로컬은 env 미설정 → toml 그대로.
def _apply_db_env_override(cfg: MainDBConfig):
h = os.environ.get("DB_HOST")
if h:
cfg.write_host = cfg.read_host = h
if os.environ.get("DB_PORT"):
cfg.write_port = cfg.read_port = int(os.environ["DB_PORT"])
if os.environ.get("DB_USER"):
cfg.write_id = cfg.read_id = os.environ["DB_USER"]
if os.environ.get("DB_PASSWORD"):
cfg.write_pw = cfg.read_pw = os.environ["DB_PASSWORD"]
if os.environ.get("DB_NAME"):
cfg.name = os.environ["DB_NAME"]
_apply_db_env_override(main_db_config)

View File

@ -18,6 +18,7 @@ services:
container_name: negosium-backend container_name: negosium-backend
environment: environment:
APP_ENV: local APP_ENV: local
DB_HOST: host.docker.internal # 컨테이너→호스트 DB (config.local.toml의 127.0.0.1 override)
ports: ports:
- "9300:9300" - "9300:9300"
# 컨테이너에서 호스트의 DB 로 접근 (config.docker.toml 의 host.docker.internal) # 컨테이너에서 호스트의 DB 로 접근 (config.docker.toml 의 host.docker.internal)
@ -30,6 +31,7 @@ services:
container_name: negodata-backend container_name: negodata-backend
environment: environment:
APP_ENV: local APP_ENV: local
DB_HOST: host.docker.internal # 컨테이너→호스트 DB (config.local.toml의 127.0.0.1 override)
ports: ports:
- "9400:9400" - "9400:9400"
extra_hosts: extra_hosts:
@ -42,6 +44,7 @@ services:
container_name: negosium-agent container_name: negosium-agent
environment: environment:
APP_ENV: local APP_ENV: local
DB_HOST: host.docker.internal # 컨테이너→호스트 DB (config.local.toml의 127.0.0.1 override)
ports: ports:
- "9500:9500" - "9500:9500"
extra_hosts: extra_hosts:

View File

@ -61,6 +61,12 @@ class DBSessionManager(Singleton):
db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}" db_url = f"{self.__DB_URL_MAP[db_config.db_type]}://{db_config.write_id}{pw}@{db_config.write_host}:{db_config.write_port}/{db_config.name}"
LOG.i(f"Write DB create engine url : {db_url}") LOG.i(f"Write DB create engine url : {db_url}")
# SSL/TLS: 관리형 DB(RDS/Aurora/Azure)는 보통 TLS 필수. sslmode 가 설정되면 asyncpg 에 전달.
connect_args = {}
sslmode = (getattr(db_config, "sslmode", "") or "").lower()
if sslmode and sslmode != "disable":
connect_args["ssl"] = sslmode
engine = create_async_engine( engine = create_async_engine(
db_url, db_url,
echo=db_config.show_log, echo=db_config.show_log,
@ -68,6 +74,7 @@ class DBSessionManager(Singleton):
max_overflow=db_config.max_overflow, max_overflow=db_config.max_overflow,
pool_pre_ping=True, pool_pre_ping=True,
pool_recycle=600, pool_recycle=600,
connect_args=connect_args,
) )
self.__engines.append(engine) self.__engines.append(engine)
scoped_session = async_scoped_session( scoped_session = async_scoped_session(

View File

@ -0,0 +1,37 @@
# 복사해서 사용: cp config.local.toml.example config.local.toml
# 실제 config.local.toml 은 시크릿 포함이라 커밋하지 않는다(.gitignore: *.toml).
# 모든 서버는 APP_ENV=local 로 띄우며 이 파일을 읽는다.
[WebServerConfig]
server_name = "NegodataServer"
port = 9400
process_count = 1
is_ssl = false
is_test = true
[LogConfig]
print_console = true
log_level = "debug"
# DB Read/Write 분리. 도커 실행 시 host 는 docker-compose 의 DB_HOST 로 override.
# 관리형 DB(RDS/Aurora/Azure)는 host 에 엔드포인트, sslmode="require".
[MainDBConfig]
db_type = "postgresql"
name = "negodata_db"
write_host = "127.0.0.1"
write_port = 5432
write_id = "<DB_USER>"
write_pw = "<DB_PASSWORD>"
read_host = "127.0.0.1"
read_port = 5432
read_id = "<DB_USER>"
read_pw = "<DB_PASSWORD>"
show_log = false
pool_size = 10
max_overflow = 20
sslmode = "" # 로컬: "" / 관리형 DB: "require"|"verify-ca"|"verify-full"
[JwtToken]
access_key = "<JWT_ACCESS_SECRET>"
refresh_key = "<JWT_REFRESH_SECRET>"
access_expire_min = 30
refresh_expire_day = 7

View File

@ -32,6 +32,8 @@ class MainDBConfig(ConfigModel):
# PostgreSQL max_connections 를 넘지 않도록 설정해야 한다. (예: 10+20=30 x 2 x 5워커 = 300) # PostgreSQL max_connections 를 넘지 않도록 설정해야 한다. (예: 10+20=30 x 2 x 5워커 = 300)
pool_size: int = 10 pool_size: int = 10
max_overflow: int = 20 max_overflow: int = 20
# SSL/TLS 모드: ""/"disable"=미사용(로컬), "require"/"verify-ca"/"verify-full"=관리형 DB(RDS/Aurora/Azure).
sslmode: str = ""
class JwtToken(ConfigModel): class JwtToken(ConfigModel):

View File

@ -19,3 +19,21 @@ web_server_config: WebServerConfig = configs.get(WebServerConfig)
log_config: LogConfig = configs.get(LogConfig) log_config: LogConfig = configs.get(LogConfig)
main_db_config: MainDBConfig = configs.get(MainDBConfig) main_db_config: MainDBConfig = configs.get(MainDBConfig)
jwt_token_config: JwtToken = configs.get(JwtToken) jwt_token_config: JwtToken = configs.get(JwtToken)
# DB 접속 env override (config.local.toml 유지, 도커에서 host 만 교체). 로컬은 env 미설정 → toml 그대로.
def _apply_db_env_override(cfg: MainDBConfig):
h = os.environ.get("DB_HOST")
if h:
cfg.write_host = cfg.read_host = h
if os.environ.get("DB_PORT"):
cfg.write_port = cfg.read_port = int(os.environ["DB_PORT"])
if os.environ.get("DB_USER"):
cfg.write_id = cfg.read_id = os.environ["DB_USER"]
if os.environ.get("DB_PASSWORD"):
cfg.write_pw = cfg.read_pw = os.environ["DB_PASSWORD"]
if os.environ.get("DB_NAME"):
cfg.name = os.environ["DB_NAME"]
_apply_db_env_override(main_db_config)