add new meeting

This commit is contained in:
djeon 2025-10-23 17:26:28 +09:00
commit 5eeb251551
17 changed files with 2290 additions and 334 deletions

View File

@ -1,9 +0,0 @@
{
"permissions": {
"allow": [
"Bash(git commit:*)"
],
"deny": [],
"ask": []
}
}

View File

@ -1,2 +1,2 @@
#Thu Oct 23 16:04:00 KST 2025 #Thu Oct 23 16:03:15 KST 2025
gradle.version=8.14 gradle.version=8.14

View File

@ -12,4 +12,7 @@ dependencies {
// Feign (for external API calls) // Feign (for external API calls)
implementation "io.github.openfeign:feign-jackson:${feignJacksonVersion}" implementation "io.github.openfeign:feign-jackson:${feignJacksonVersion}"
implementation "io.github.openfeign:feign-okhttp:${feignJacksonVersion}" implementation "io.github.openfeign:feign-okhttp:${feignJacksonVersion}"
// H2 Database for local development
runtimeOnly 'com.h2database:h2'
} }

298
ai/logs/ai.log Normal file
View File

@ -0,0 +1,298 @@
2025-10-23 16:24:30 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 33322 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai)
2025-10-23 16:24:30 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8
2025-10-23 16:24:30 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "local"
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 4 ms. Found 0 JPA repository interfaces.
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-23 16:24:31 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces.
2025-10-23 16:24:31 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8084 (http)
2025-10-23 16:24:31 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
2025-10-23 16:24:31 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24]
2025-10-23 16:24:31 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2025-10-23 16:24:31 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 694 ms
2025-10-23 16:24:31 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default]
2025-10-23 16:24:31 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final
2025-10-23 16:24:31 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Boolean -> org.hibernate.type.BasicTypeReference@5c5f12e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration numeric_boolean -> org.hibernate.type.BasicTypeReference@23f8036d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.NumericBooleanConverter -> org.hibernate.type.BasicTypeReference@23f8036d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration true_false -> org.hibernate.type.BasicTypeReference@68f69ca3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.TrueFalseConverter -> org.hibernate.type.BasicTypeReference@68f69ca3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration yes_no -> org.hibernate.type.BasicTypeReference@1e3566e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration org.hibernate.type.YesNoConverter -> org.hibernate.type.BasicTypeReference@1e3566e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@2b058bfd
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte -> org.hibernate.type.BasicTypeReference@2b058bfd
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Byte -> org.hibernate.type.BasicTypeReference@2b058bfd
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary -> org.hibernate.type.BasicTypeReference@4805069b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration byte[] -> org.hibernate.type.BasicTypeReference@4805069b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [B -> org.hibernate.type.BasicTypeReference@4805069b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration binary_wrapper -> org.hibernate.type.BasicTypeReference@14ca88bc
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-binary -> org.hibernate.type.BasicTypeReference@14ca88bc
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration image -> org.hibernate.type.BasicTypeReference@f01fc6d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration blob -> org.hibernate.type.BasicTypeReference@85cd413
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Blob -> org.hibernate.type.BasicTypeReference@85cd413
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob -> org.hibernate.type.BasicTypeReference@688d2a5d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_blob_wrapper -> org.hibernate.type.BasicTypeReference@2842c098
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@2820b369
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration short -> org.hibernate.type.BasicTypeReference@2820b369
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Short -> org.hibernate.type.BasicTypeReference@2820b369
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration integer -> org.hibernate.type.BasicTypeReference@46b21632
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration int -> org.hibernate.type.BasicTypeReference@46b21632
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Integer -> org.hibernate.type.BasicTypeReference@46b21632
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@476c137b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration long -> org.hibernate.type.BasicTypeReference@476c137b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Long -> org.hibernate.type.BasicTypeReference@476c137b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@79144d0e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration float -> org.hibernate.type.BasicTypeReference@79144d0e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Float -> org.hibernate.type.BasicTypeReference@79144d0e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@540212be
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration double -> org.hibernate.type.BasicTypeReference@540212be
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Double -> org.hibernate.type.BasicTypeReference@540212be
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_integer -> org.hibernate.type.BasicTypeReference@2579d8a
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigInteger -> org.hibernate.type.BasicTypeReference@2579d8a
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration big_decimal -> org.hibernate.type.BasicTypeReference@2507a170
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.math.BigDecimal -> org.hibernate.type.BasicTypeReference@2507a170
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character -> org.hibernate.type.BasicTypeReference@7e20f4e3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char -> org.hibernate.type.BasicTypeReference@7e20f4e3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Character -> org.hibernate.type.BasicTypeReference@7e20f4e3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration character_nchar -> org.hibernate.type.BasicTypeReference@3af39e7b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration string -> org.hibernate.type.BasicTypeReference@4f6ff62
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.String -> org.hibernate.type.BasicTypeReference@4f6ff62
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nstring -> org.hibernate.type.BasicTypeReference@1c62d2ad
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration characters -> org.hibernate.type.BasicTypeReference@651caa2e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration char[] -> org.hibernate.type.BasicTypeReference@651caa2e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration [C -> org.hibernate.type.BasicTypeReference@651caa2e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration wrapper-characters -> org.hibernate.type.BasicTypeReference@433ae0b0
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration text -> org.hibernate.type.BasicTypeReference@70840a5a
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ntext -> org.hibernate.type.BasicTypeReference@7af9595d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration clob -> org.hibernate.type.BasicTypeReference@7a34c1f6
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Clob -> org.hibernate.type.BasicTypeReference@7a34c1f6
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration nclob -> org.hibernate.type.BasicTypeReference@6e9f8160
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.NClob -> org.hibernate.type.BasicTypeReference@6e9f8160
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob -> org.hibernate.type.BasicTypeReference@3e998033
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_char_array -> org.hibernate.type.BasicTypeReference@e1a150c
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_clob_character_array -> org.hibernate.type.BasicTypeReference@527d5e48
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob -> org.hibernate.type.BasicTypeReference@407b41e6
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_character_array -> org.hibernate.type.BasicTypeReference@3291d9c2
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration materialized_nclob_char_array -> org.hibernate.type.BasicTypeReference@6cfd08e9
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Duration -> org.hibernate.type.BasicTypeReference@54ca9420
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Duration -> org.hibernate.type.BasicTypeReference@54ca9420
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDateTime -> org.hibernate.type.BasicTypeReference@4ea48b2e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDateTime -> org.hibernate.type.BasicTypeReference@4ea48b2e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalDate -> org.hibernate.type.BasicTypeReference@72c704f1
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalDate -> org.hibernate.type.BasicTypeReference@72c704f1
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration LocalTime -> org.hibernate.type.BasicTypeReference@76f9e000
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.LocalTime -> org.hibernate.type.BasicTypeReference@76f9e000
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTime -> org.hibernate.type.BasicTypeReference@7612116b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetDateTime -> org.hibernate.type.BasicTypeReference@7612116b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@1c05097c
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@562f6681
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTime -> org.hibernate.type.BasicTypeReference@6f6f65a4
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.OffsetTime -> org.hibernate.type.BasicTypeReference@6f6f65a4
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeUtc -> org.hibernate.type.BasicTypeReference@990b86b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithTimezone -> org.hibernate.type.BasicTypeReference@3dea1ecc
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration OffsetTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@105c6c9e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTime -> org.hibernate.type.BasicTypeReference@40a7974
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZonedDateTime -> org.hibernate.type.BasicTypeReference@40a7974
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithTimezone -> org.hibernate.type.BasicTypeReference@8d5da7e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZonedDateTimeWithoutTimezone -> org.hibernate.type.BasicTypeReference@65a4b9d6
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration date -> org.hibernate.type.BasicTypeReference@16ef1160
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Date -> org.hibernate.type.BasicTypeReference@16ef1160
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration time -> org.hibernate.type.BasicTypeReference@41f90b10
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Time -> org.hibernate.type.BasicTypeReference@41f90b10
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timestamp -> org.hibernate.type.BasicTypeReference@67593f7b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.sql.Timestamp -> org.hibernate.type.BasicTypeReference@67593f7b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Date -> org.hibernate.type.BasicTypeReference@67593f7b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar -> org.hibernate.type.BasicTypeReference@2773504f
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Calendar -> org.hibernate.type.BasicTypeReference@2773504f
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.GregorianCalendar -> org.hibernate.type.BasicTypeReference@2773504f
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_date -> org.hibernate.type.BasicTypeReference@497921d0
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration calendar_time -> org.hibernate.type.BasicTypeReference@40d10264
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration instant -> org.hibernate.type.BasicTypeReference@6edd4fe2
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.Instant -> org.hibernate.type.BasicTypeReference@6edd4fe2
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid -> org.hibernate.type.BasicTypeReference@53918b5e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.UUID -> org.hibernate.type.BasicTypeReference@53918b5e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration pg-uuid -> org.hibernate.type.BasicTypeReference@53918b5e
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-binary -> org.hibernate.type.BasicTypeReference@5366575d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration uuid-char -> org.hibernate.type.BasicTypeReference@1b6cad77
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration class -> org.hibernate.type.BasicTypeReference@1fca53a7
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Class -> org.hibernate.type.BasicTypeReference@1fca53a7
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration currency -> org.hibernate.type.BasicTypeReference@40dee07b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration Currency -> org.hibernate.type.BasicTypeReference@40dee07b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Currency -> org.hibernate.type.BasicTypeReference@40dee07b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration locale -> org.hibernate.type.BasicTypeReference@21e39b82
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.Locale -> org.hibernate.type.BasicTypeReference@21e39b82
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration serializable -> org.hibernate.type.BasicTypeReference@5f9a8ddc
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.io.Serializable -> org.hibernate.type.BasicTypeReference@5f9a8ddc
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration timezone -> org.hibernate.type.BasicTypeReference@1280bae3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.util.TimeZone -> org.hibernate.type.BasicTypeReference@1280bae3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration ZoneOffset -> org.hibernate.type.BasicTypeReference@256a5df0
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.time.ZoneOffset -> org.hibernate.type.BasicTypeReference@256a5df0
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration url -> org.hibernate.type.BasicTypeReference@1868ed54
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.net.URL -> org.hibernate.type.BasicTypeReference@1868ed54
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration vector -> org.hibernate.type.BasicTypeReference@131777e8
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration row_version -> org.hibernate.type.BasicTypeReference@45790cb
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration object -> org.hibernate.type.JavaObjectType@2bc2e022
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration java.lang.Object -> org.hibernate.type.JavaObjectType@2bc2e022
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration null -> org.hibernate.type.NullType@1ff81b0d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_date -> org.hibernate.type.BasicTypeReference@1c610f
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_time -> org.hibernate.type.BasicTypeReference@5abc5854
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_timestamp -> org.hibernate.type.BasicTypeReference@5c3007d
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar -> org.hibernate.type.BasicTypeReference@66b40dd3
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_date -> org.hibernate.type.BasicTypeReference@7296fe0b
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_calendar_time -> org.hibernate.type.BasicTypeReference@4a5066f5
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_binary -> org.hibernate.type.BasicTypeReference@578d472a
2025-10-23 16:24:31 [main] DEBUG o.hibernate.type.BasicTypeRegistry - Adding type registration imm_serializable -> org.hibernate.type.BasicTypeReference@1191029d
2025-10-23 16:24:31 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer
2025-10-23 16:24:31 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2025-10-23 16:24:32 [main] WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata
java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
at org.hibernate.boot.model.relational.Database.<init>(Database.java:45)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20)
2025-10-23 16:24:32 [main] ERROR o.s.o.j.LocalContainerEntityManagerFactoryBean - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
2025-10-23 16:24:32 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
2025-10-23 16:24:32 [main] INFO o.a.catalina.core.StandardService - Stopping service [Tomcat]
2025-10-23 16:24:32 [main] INFO o.s.b.a.l.ConditionEvaluationReportLogger -
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-10-23 16:24:32 [main] ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
at com.unicorn.hgzero.ai.AiApplication.main(AiApplication.java:20)
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
at org.hibernate.boot.model.relational.Database.<init>(Database.java:45)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1835)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784)
... 15 common frames omitted
Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:191)
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentWithDefaults(JdbcEnvironmentInitiator.java:152)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:362)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 30 common frames omitted
2025-10-23 16:25:55 [main] INFO com.unicorn.hgzero.ai.AiApplication - Starting AiApplication using Java 23.0.2 with PID 33935 (/Users/jominseo/HGZero/ai/build/classes/java/main started by jominseo in /Users/jominseo/HGZero/ai)
2025-10-23 16:25:55 [main] DEBUG com.unicorn.hgzero.ai.AiApplication - Running with Spring Boot v3.3.0, Spring v6.1.8
2025-10-23 16:25:55 [main] INFO com.unicorn.hgzero.ai.AiApplication - The following 1 profile is active: "local"
2025-10-23 16:25:55 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-23 16:25:55 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces.
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2025-10-23 16:25:56 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 0 ms. Found 0 Redis repository interfaces.
2025-10-23 16:25:56 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8084 (http)
2025-10-23 16:25:56 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
2025-10-23 16:25:56 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.24]
2025-10-23 16:25:56 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2025-10-23 16:25:56 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 608 ms
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
2025-10-23 16:25:56 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
2025-10-23 16:25:56 [main] INFO o.s.b.a.h.H2ConsoleAutoConfiguration - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:testdb'
2025-10-23 16:25:56 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default]
2025-10-23 16:25:56 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.5.2.Final
2025-10-23 16:25:56 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled
2025-10-23 16:25:56 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer
2025-10-23 16:25:56 [main] WARN org.hibernate.orm.deprecation - HHH90000025: H2Dialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
2025-10-23 16:25:56 [main] INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2025-10-23 16:25:56 [main] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default'
2025-10-23 16:25:56 [main] WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2025-10-23 16:25:56 [main] ERROR i.n.r.d.DnsServerAddressStreamProviders - Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library
2025-10-23 16:25:57 [main] WARN o.s.b.a.s.s.UserDetailsServiceAutoConfiguration -
Using generated security password: 1665e64f-a0ac-49dc-806e-846f88237e7c
This generated password is for development use only. Your security configuration must be updated before running your application in production.
2025-10-23 16:25:57 [main] INFO o.s.s.c.a.a.c.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer - Global AuthenticationManager configured with UserDetailsService bean with name inMemoryUserDetailsManager
2025-10-23 16:25:57 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 3 endpoints beneath base path '/actuator'
2025-10-23 16:25:57 [main] INFO o.s.s.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@54ad9ff9, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3b6b9981, org.springframework.security.web.context.SecurityContextHolderFilter@3ce34b92, org.springframework.security.web.header.HeaderWriterFilter@4a89722e, org.springframework.web.filter.CorsFilter@2eb6e166, org.springframework.security.web.csrf.CsrfFilter@2c3762c7, org.springframework.security.web.authentication.logout.LogoutFilter@751e7d99, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@331b0bfd, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@20894afb, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@43b1fdb7, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@61d4e070, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@f511a8e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1b52f723, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7bdbf06f, org.springframework.security.web.access.ExceptionTranslationFilter@64c009b8, org.springframework.security.web.access.intercept.AuthorizationFilter@7dfbdcfe]
2025-10-23 16:25:57 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8084 (http) with context path '/'
2025-10-23 16:25:57 [main] INFO com.unicorn.hgzero.ai.AiApplication - Started AiApplication in 1.733 seconds (process running for 1.843)
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
2025-10-23 16:26:47 [http-nio-8084-exec-1] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 0 ms
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.security.web.FilterChainProxy - Securing GET /
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.s.HttpSessionRequestCache - Saved request http://localhost:8084/?continue to session
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@32da6cef, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@104972a0
2025-10-23 16:26:47 [http-nio-8084-exec-1] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login
2025-10-23 16:26:47 [http-nio-8084-exec-2] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.security.web.FilterChainProxy - Securing GET /favicon.ico
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@32da6cef, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@104972a0
2025-10-23 16:26:47 [http-nio-8084-exec-3] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to http://localhost:8084/login
2025-10-23 16:26:47 [http-nio-8084-exec-4] DEBUG o.s.security.web.FilterChainProxy - Securing GET /login
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
2025-10-23 16:27:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.

View File

@ -6,7 +6,7 @@ spring:
datasource: datasource:
url: jdbc:${DB_KIND:postgresql}://${DB_HOST:20.249.153.213}:${DB_PORT:5432}/${DB_NAME:aidb} url: jdbc:${DB_KIND:postgresql}://${DB_HOST:20.249.153.213}:${DB_PORT:5432}/${DB_NAME:aidb}
username: ${DB_USERNAME:hgzerouser} username: ${DB_USERNAME:hgzerouser}
password: ${DB_PASSWORD:} password: ${DB_PASSWORD:Hi5Jessica!}
driver-class-name: org.postgresql.Driver driver-class-name: org.postgresql.Driver
hikari: hikari:
maximum-pool-size: 20 maximum-pool-size: 20

File diff suppressed because one or more lines are too long

View File

@ -88,27 +88,57 @@
margin-bottom: var(--space-md); margin-bottom: var(--space-md);
} }
/* 통계 카드 - 모바일에서 컴팩트하게 */ /* 통계 카드 - 정보 표시용 (인터랙션 없음) */
.stat-box { .stat-box {
min-height: 80px; min-height: 80px;
padding: var(--space-sm); padding: var(--space-sm);
background: var(--gray-100); /* 플랫한 배경 */
border: 1px solid var(--gray-200); /* 얇은 경계선 */
border-radius: var(--radius-md); /* 부드러운 모서리 */
box-shadow: none; /* 그림자 제거 */
transition: none; /* 호버 효과 제거 */
} }
.stat-box.highlight { /* 상태별 컬러 코딩 */
background: var(--primary-light); .stat-box.stat-incomplete {
border: 2px solid var(--primary); background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%); /* 차분한 블루 그라데이션 */
border-color: #90CAF9;
}
.stat-box.stat-urgent {
background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%); /* 주의 오렌지 그라데이션 */
border-color: #FFB74D;
}
.stat-box.stat-overdue {
background: linear-gradient(135deg, #FFEBEE 0%, #FFCDD2 100%); /* 긴급 레드 그라데이션 */
border-color: #EF5350;
} }
.stat-number { .stat-number {
font-size: var(--font-h2); font-size: var(--font-h1); /* 더 크게 강조 */
font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold);
color: var(--primary); line-height: 1.2;
margin-bottom: 2px; margin-bottom: 4px;
}
.stat-box.stat-incomplete .stat-number {
color: #1976D2; /* 진한 블루 */
}
.stat-box.stat-urgent .stat-number {
color: #F57C00; /* 진한 오렌지 */
}
.stat-box.stat-overdue .stat-number {
color: #D32F2F; /* 진한 레드 */
} }
.stat-text { .stat-text {
font-size: var(--font-caption); font-size: var(--font-caption);
color: var(--gray-700); color: var(--gray-600); /* 더 연하게 */
font-weight: var(--font-weight-regular); /* 보통 굵기 */
opacity: 0.85;
} }
/* 원형 진행 바 - 모바일에서 축소 */ /* 원형 진행 바 - 모바일에서 축소 */
@ -131,17 +161,17 @@
/* 데스크톱에서 통계 카드 크기 복원 */ /* 데스크톱에서 통계 카드 크기 복원 */
@media (min-width: 768px) { @media (min-width: 768px) {
.stat-box { .stat-box {
min-height: 100px; min-height: 110px;
padding: var(--space-md); padding: var(--space-lg);
} }
.stat-number { .stat-number {
font-size: var(--font-h1); font-size: 2.5rem; /* 더 큰 숫자 */
margin-bottom: var(--space-xs); margin-bottom: var(--space-xs);
} }
.stat-text { .stat-text {
font-size: var(--font-small); font-size: var(--font-body);
} }
.circular-progress { .circular-progress {
@ -227,23 +257,26 @@
border-color: var(--primary); border-color: var(--primary);
} }
/* Todo 카드 */ /* Todo 카드 - 컴팩트 디자인 */
.todo-card { .todo-card {
position: relative; position: relative;
background: var(--white); background: var(--white);
padding: var(--space-md); padding: var(--space-md);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
box-shadow: var(--shadow-md); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
margin-bottom: var(--space-md); margin-bottom: var(--space-sm);
transition: all var(--transition-normal); transition: all var(--transition-normal);
border: 1px solid var(--gray-200);
} }
.todo-card:hover { .todo-card:hover {
box-shadow: var(--shadow-lg); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
border-color: var(--primary);
} }
.todo-card.completed { .todo-card.completed {
opacity: 0.6; opacity: 0.5;
background: var(--gray-50);
} }
.todo-card.completed .todo-title { .todo-card.completed .todo-title {
@ -251,20 +284,22 @@
color: var(--gray-500); color: var(--gray-500);
} }
/* 레이아웃: 체크박스 + 콘텐츠 */
.todo-top { .todo-top {
display: flex; display: flex;
gap: var(--space-md); gap: var(--space-md);
margin-bottom: var(--space-md); align-items: flex-start;
} }
.todo-checkbox-wrapper { .todo-checkbox-wrapper {
flex-shrink: 0; flex-shrink: 0;
padding-top: 2px;
} }
.todo-checkbox { .todo-checkbox {
width: 24px; width: 24px;
height: 24px; height: 24px;
border: 2px solid var(--gray-300); border: 2px solid var(--gray-400);
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
transition: all var(--transition-fast); transition: all var(--transition-fast);
@ -277,41 +312,41 @@
.todo-content-wrapper { .todo-content-wrapper {
flex: 1; flex: 1;
min-width: 0; /* 텍스트 오버플로우 방지 */
} }
.todo-title { /* 배지 영역 */
font-size: var(--font-body);
font-weight: var(--font-weight-medium);
color: var(--gray-900);
margin-bottom: var(--space-sm);
}
.todo-badges { .todo-badges {
display: flex; display: flex;
gap: var(--space-sm); gap: var(--space-xs);
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: var(--space-sm); margin-bottom: var(--space-xs);
} }
/* Todo 제목 */
.todo-title {
font-size: var(--font-body);
font-weight: var(--font-weight-regular);
color: var(--gray-900);
margin-bottom: var(--space-xs);
line-height: 1.5;
}
/* 하단 메타 정보 */
.todo-meta-row { .todo-meta-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-md); gap: var(--space-sm);
font-size: var(--font-small); font-size: var(--font-small);
color: var(--gray-500); color: var(--gray-500);
} flex-wrap: wrap;
.todo-assignee {
display: flex;
align-items: center;
gap: var(--space-sm);
} }
.todo-meeting-link { .todo-meeting-link {
display: flex; display: inline-flex;
align-items: center; align-items: center;
gap: var(--space-xs); gap: 4px;
color: var(--primary); color: #4CAF50; /* 연한 초록색 */
text-decoration: none; text-decoration: none;
font-size: var(--font-small); font-size: var(--font-small);
cursor: pointer; cursor: pointer;
@ -319,19 +354,47 @@
} }
.todo-meeting-link:hover { .todo-meeting-link:hover {
color: var(--primary-dark); color: #388E3C;
text-decoration: underline;
} }
.todo-progress-section { /* 담당자 정보 숨김 (간결한 디자인) */
margin-top: var(--space-md); .todo-assignee {
padding-top: var(--space-md); display: none;
border-top: 1px solid var(--gray-300);
} }
.todo-progress-label { /* 액션 버튼 영역 */
font-size: var(--font-small); .todo-actions {
color: var(--gray-700); margin-top: var(--space-xs);
margin-bottom: var(--space-sm); }
/* 아이콘 버튼 */
.icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 0;
background: none;
border: none;
border-radius: var(--radius-md);
color: var(--gray-600);
cursor: pointer;
transition: all var(--transition-fast);
}
.icon-btn:hover {
background: var(--gray-100);
color: var(--primary);
}
.icon-btn:active {
background: var(--gray-200);
}
.icon-btn .material-icons {
font-size: 20px;
} }
/* 빈 상태 */ /* 빈 상태 */
@ -463,44 +526,33 @@
<main class="main-content"> <main class="main-content">
<!-- 통계 개요 --> <!-- 통계 개요 -->
<div class="stats-overview"> <div class="stats-overview">
<div class="stat-box"> <div class="stat-box stat-incomplete">
<div class="stat-number" id="totalTodos">0</div> <div class="stat-number" id="totalTodos">0</div>
<div class="stat-text">전체</div> <div class="stat-text">미완료</div>
</div> </div>
<div class="stat-box highlight"> <div class="stat-box stat-urgent">
<div class="circular-progress"> <div class="stat-number" id="urgentTodos">0</div>
<svg viewBox="0 0 80 80">
<circle class="bg-circle" cx="40" cy="40" r="36"></circle>
<circle class="progress-circle" cx="40" cy="40" r="36"
stroke-dasharray="226" stroke-dashoffset="226" id="progressCircle"></circle>
</svg>
<div class="circular-progress-text" id="completionRate">0%</div>
</div>
<div class="stat-text">완료율</div>
</div>
<div class="stat-box">
<div class="stat-number" id="inProgressTodos">0</div>
<div class="stat-text">진행 중</div>
</div>
<div class="stat-box">
<div class="stat-number text-error" id="urgentTodos">0</div>
<div class="stat-text">마감 임박</div> <div class="stat-text">마감 임박</div>
</div> </div>
<div class="stat-box stat-overdue">
<div class="stat-number" id="overdueTodos">0</div>
<div class="stat-text">지연</div>
</div>
</div> </div>
<!-- 필터 탭 --> <!-- 필터 탭 -->
<div class="filter-tabs"> <div class="filter-tabs">
<button class="filter-tab active" data-filter="all" onclick="filterTodos('all')"> <button class="filter-tab active" data-filter="all" onclick="filterTodos('all')">
전체 전체 (<span id="filterAllCount">0</span>)
</button> </button>
<button class="filter-tab" data-filter="in_progress" onclick="filterTodos('in_progress')"> <button class="filter-tab" data-filter="overdue" onclick="filterTodos('overdue')">
진행 중 지연 (<span id="filterOverdueCount">0</span>)
</button>
<button class="filter-tab" data-filter="completed" onclick="filterTodos('completed')">
완료
</button> </button>
<button class="filter-tab" data-filter="urgent" onclick="filterTodos('urgent')"> <button class="filter-tab" data-filter="urgent" onclick="filterTodos('urgent')">
마감 임박 마감 임박 (<span id="filterUrgentCount">0</span>)
</button>
<button class="filter-tab" data-filter="completed" onclick="filterTodos('completed')">
완료 (<span id="filterCompletedCount">0</span>)
</button> </button>
</div> </div>
@ -623,28 +675,27 @@
// 통계 업데이트 // 통계 업데이트
function updateStats() { function updateStats() {
const total = allTodos.length; const total = allTodos.filter(t => t.status !== 'completed').length; // 미완료 전체
const completed = allTodos.filter(t => t.status === 'completed').length; const completed = allTodos.filter(t => t.status === 'completed').length;
const inProgress = allTodos.filter(t => t.status === 'in_progress').length;
const urgent = allTodos.filter(t => { const urgent = allTodos.filter(t => {
const dday = calculateDday(t.dueDate); const dday = calculateDday(t.dueDate);
return dday >= 0 && dday <= 3 && t.status !== 'completed'; return dday >= 0 && dday <= 3 && t.status !== 'completed';
}).length; }).length;
const overdue = allTodos.filter(t => {
const dday = calculateDday(t.dueDate);
return dday < 0 && t.status !== 'completed';
}).length;
// 카운터 애니메이션 // 상단 통계 블록 카운터 애니메이션
animateCounter('totalTodos', total); animateCounter('totalTodos', total);
animateCounter('inProgressTodos', inProgress);
animateCounter('urgentTodos', urgent); animateCounter('urgentTodos', urgent);
animateCounter('overdueTodos', overdue);
// 완료율 원형 진행 바 // 필터 탭 개수 업데이트
const completionRate = total > 0 ? Math.round((completed / total) * 100) : 0; $('#filterAllCount').textContent = allTodos.length;
const circumference = 226; $('#filterOverdueCount').textContent = overdue;
const offset = circumference - (completionRate / 100 * circumference); $('#filterUrgentCount').textContent = urgent;
$('#filterCompletedCount').textContent = completed;
setTimeout(() => {
$('#progressCircle').style.strokeDashoffset = offset;
$('#completionRate').textContent = `${completionRate}%`;
}, 100);
} }
// Todo 리스트 렌더링 // Todo 리스트 렌더링
@ -655,8 +706,11 @@
// 필터 적용 // 필터 적용
if (currentFilter === 'completed') { if (currentFilter === 'completed') {
filteredTodos = allTodos.filter(t => t.status === 'completed'); filteredTodos = allTodos.filter(t => t.status === 'completed');
} else if (currentFilter === 'in_progress') { } else if (currentFilter === 'overdue') {
filteredTodos = allTodos.filter(t => t.status === 'in_progress'); filteredTodos = allTodos.filter(t => {
const dday = calculateDday(t.dueDate);
return dday < 0 && t.status !== 'completed';
});
} else if (currentFilter === 'urgent') { } else if (currentFilter === 'urgent') {
filteredTodos = allTodos.filter(t => { filteredTodos = allTodos.filter(t => {
const dday = calculateDday(t.dueDate); const dday = calculateDday(t.dueDate);
@ -702,7 +756,6 @@
onchange="toggleTodoComplete('${todo.id}', this.checked)"> onchange="toggleTodoComplete('${todo.id}', this.checked)">
</div> </div>
<div class="todo-content-wrapper"> <div class="todo-content-wrapper">
<div class="todo-title">${todo.title}</div>
<div class="todo-badges"> <div class="todo-badges">
${createBadge(statusInfo.badgeText, statusInfo.badgeType)} ${createBadge(statusInfo.badgeText, statusInfo.badgeType)}
${createBadge( ${createBadge(
@ -711,28 +764,17 @@
todo.priority todo.priority
)} )}
</div> </div>
<div class="todo-title">${todo.title}</div>
<div class="todo-meta-row"> <div class="todo-meta-row">
<div class="todo-assignee"> <a class="todo-meeting-link" onclick="goToMeeting('${todo.meetingId}')">
${createAvatar(todo.assignee, 'sm')} 🔗 ${todo.meetingTitle}
<span>${todo.assignee.name}</span> </a>
</div>
<span></span>
<span>${formatDate(todo.dueDate)}</span> <span>${formatDate(todo.dueDate)}</span>
</div> </div>
<a class="todo-meeting-link" onclick="goToMeeting('${todo.meetingId}')">
🔗 ${todo.meetingTitle}
</a>
${!isCompleted && todo.progress > 0 ? `
<div class="todo-progress-section">
<div class="todo-progress-label">진행률: ${todo.progress}%</div>
${createProgressBar(todo.progress)}
</div>
` : ''}
${!isCompleted ? ` ${!isCompleted ? `
<div class="todo-actions"> <div class="todo-actions">
<button class="btn btn-ghost btn-sm" onclick="editTodo('${todo.id}')"> <button class="icon-btn" onclick="editTodo('${todo.id}')" title="편집">
<span class="material-icons" style="font-size: 16px;">edit</span> <span class="material-icons">edit</span>
편집
</button> </button>
</div> </div>
` : ''} ` : ''}
@ -760,11 +802,11 @@
// Todo 완료 토글 // Todo 완료 토글
function toggleTodoComplete(todoId, isChecked) { function toggleTodoComplete(todoId, isChecked) {
if (isChecked) { if (isChecked) {
if (confirm('이 Todo를 완료 처리하시겠습니까?')) { // 완료 처리
if (confirm('완료 처리하시겠습니까?')) {
const todo = allTodos.find(t => t.id === todoId); const todo = allTodos.find(t => t.id === todoId);
if (todo) { if (todo) {
todo.status = 'completed'; todo.status = 'completed';
todo.progress = 100;
showToast('Todo가 완료되었습니다', 'success'); showToast('Todo가 완료되었습니다', 'success');
updateStats(); updateStats();
renderTodoList(); renderTodoList();
@ -773,11 +815,17 @@
event.target.checked = false; event.target.checked = false;
} }
} else { } else {
const todo = allTodos.find(t => t.id === todoId); // 미완료로 되돌리기
if (todo) { if (confirm('미완료로 변경하시겠습니까?')) {
todo.status = 'in_progress'; const todo = allTodos.find(t => t.id === todoId);
updateStats(); if (todo) {
renderTodoList(); todo.status = 'incomplete';
showToast('미완료로 변경되었습니다', 'info');
updateStats();
renderTodoList();
}
} else {
event.target.checked = true;
} }
} }
} }

View File

@ -591,8 +591,8 @@
<!-- 탭 네비게이션 --> <!-- 탭 네비게이션 -->
<nav class="tab-nav"> <nav class="tab-nav">
<div class="tabs"> <div class="tabs">
<div class="tab active" data-tab="minutes">회의록</div> <div class="tab active" data-tab="dashboard">대시보드</div>
<div class="tab" data-tab="dashboard">대시보드</div> <div class="tab" data-tab="minutes">회의록</div>
</div> </div>
</nav> </nav>
@ -642,7 +642,7 @@
</div> </div>
<!-- 회의록 탭 --> <!-- 회의록 탭 -->
<div id="minutes-content" class="tab-content active"> <div id="minutes-content" class="tab-content">
<!-- 안건 1 --> <!-- 안건 1 -->
<div class="section"> <div class="section">
<div class="section-header"> <div class="section-header">
@ -826,7 +826,7 @@
</div> </div>
<!-- 대시보드 탭 --> <!-- 대시보드 탭 -->
<div id="dashboard-content" class="tab-content"> <div id="dashboard-content" class="tab-content active">
<!-- 핵심내용 --> <!-- 핵심내용 -->
<div class="section dashboard-section"> <div class="section dashboard-section">
<div class="section-header"> <div class="section-header">

View File

@ -234,41 +234,32 @@
color: var(--gray-700); color: var(--gray-700);
} }
/* 잠금 해제 요청 버튼 */ /* 읽기 전용 표시 */
.unlock-request-btn { .readonly-badge {
display: flex; display: inline-flex;
align-items: center; align-items: center;
gap: 4px; padding: 4px 8px;
padding: 6px 12px; background: var(--gray-100);
background: transparent; border-radius: var(--radius-sm);
border: 1px solid var(--primary); color: var(--gray-600);
border-radius: var(--radius-md);
color: var(--primary);
font-size: var(--font-caption); font-size: var(--font-caption);
font-weight: var(--font-weight-medium); font-weight: var(--font-weight-medium);
cursor: pointer; margin-left: 8px;
transition: all var(--transition-fast);
white-space: nowrap;
flex-shrink: 0;
}
.unlock-request-btn img {
width: 16px;
height: 16px;
flex-shrink: 0;
}
.unlock-request-btn:hover {
background: var(--primary-light);
border-color: var(--primary);
}
.unlock-request-btn:active {
transform: scale(0.98);
} }
</style> </style>
</head> </head>
<body> <body>
<!--
[진입 경로]
10-회의록상세조회.html → 하단 액션 바 "수정" 버튼 클릭
[권한 제어]
- 검증완료 전 (작성중/초안 상태): 모든 참석자가 수정 가능
- 검증완료 후: 회의 생성자만 수정 가능 (참석자는 "수정" 버튼 비활성화)
- 참석자 관리: 회의 생성자만 추가/삭제 가능
- 회의 일시/장소: 읽기 전용 (회의 예약 화면에서만 변경 가능)
-->
<!-- 헤더 --> <!-- 헤더 -->
<header class="header"> <header class="header">
<div class="header-left"> <div class="header-left">
@ -287,6 +278,7 @@
<main class="main-content"> <main class="main-content">
<!-- 기본 정보 --> <!-- 기본 정보 -->
<div class="info-card"> <div class="info-card">
<!-- 회의 제목 (편집 가능) -->
<input <input
type="text" type="text"
class="meeting-title-input" class="meeting-title-input"
@ -294,13 +286,17 @@
placeholder="회의 제목을 입력하세요" placeholder="회의 제목을 입력하세요"
oninput="markAsUnsaved()" oninput="markAsUnsaved()"
> >
<!-- 회의 일시 (읽기 전용 - 회의 예약 화면에서만 변경 가능) -->
<div class="info-row"> <div class="info-row">
<span class="info-icon">📅</span> <span class="info-icon">📅</span>
<span>2025년 10월 25일 14:00 (90분)</span> <span>2025년 10월 25일 14:00 (90분)</span>
<span class="text-caption text-muted" style="margin-left: 8px;">(읽기 전용)</span>
</div> </div>
<!-- 회의 장소 (읽기 전용 - 회의 예약 화면에서만 변경 가능) -->
<div class="info-row"> <div class="info-row">
<span class="info-icon">📍</span> <span class="info-icon">📍</span>
<span>본사 2층 대회의실</span> <span>본사 2층 대회의실</span>
<span class="text-caption text-muted" style="margin-left: 8px;">(읽기 전용)</span>
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="info-icon"></span> <span class="info-icon"></span>
@ -383,17 +379,14 @@
</div> </div>
</div> </div>
<!-- 검증 완료 --> <!-- 검증 완료 (읽기 전용) -->
<div class="verification-lock"> <div class="verification-lock">
<input type="checkbox" class="checkbox" id="verify-1" checked disabled> <input type="checkbox" class="checkbox" id="verify-1" checked disabled>
<label for="verify-1" style="flex: 1; min-width: 0;"> <label for="verify-1" style="flex: 1; min-width: 0;">
<span class="font-medium">검증 완료</span> <span class="font-medium">검증 완료</span>
<span class="text-caption text-muted"> (잠금됨)</span> <span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
</label> </label>
<button class="unlock-request-btn" onclick="unlockSection(1)"> <span class="readonly-badge">🔒 읽기 전용</span>
<img src="img/padlock.png" alt="">
<span>잠금해제요청</span>
</button>
</div> </div>
</div> </div>
@ -456,12 +449,9 @@
<input type="checkbox" class="checkbox" id="verify-2" checked disabled> <input type="checkbox" class="checkbox" id="verify-2" checked disabled>
<label for="verify-2" style="flex: 1; min-width: 0;"> <label for="verify-2" style="flex: 1; min-width: 0;">
<span class="font-medium">검증 완료</span> <span class="font-medium">검증 완료</span>
<span class="text-caption text-muted"> (잠금됨)</span> <span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
</label> </label>
<button class="unlock-request-btn" onclick="unlockSection(2)"> <span class="readonly-badge">🔒 읽기 전용</span>
<img src="img/padlock.png" alt="">
<span>잠금해제요청</span>
</button>
</div> </div>
</div> </div>
@ -519,12 +509,9 @@
<input type="checkbox" class="checkbox" id="verify-3" checked disabled> <input type="checkbox" class="checkbox" id="verify-3" checked disabled>
<label for="verify-3" style="flex: 1; min-width: 0;"> <label for="verify-3" style="flex: 1; min-width: 0;">
<span class="font-medium">검증 완료</span> <span class="font-medium">검증 완료</span>
<span class="text-caption text-muted"> (잠금됨)</span> <span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
</label> </label>
<button class="unlock-request-btn" onclick="unlockSection(3)"> <span class="readonly-badge">🔒 읽기 전용</span>
<img src="img/padlock.png" alt="">
<span>잠금해제요청</span>
</button>
</div> </div>
</div> </div>
</main> </main>
@ -643,11 +630,6 @@
}, 2000); }, 2000);
} }
// 섹션 잠금 해제 요청
function unlockSection(sectionId) {
showToast('검증 해제 승인을 요청했습니다', 'info');
}
// 관련회의록 제거 // 관련회의록 제거
function removeReference(btn) { function removeReference(btn) {
const item = btn.closest('.reference-item'); const item = btn.closest('.reference-item');

View File

@ -4,7 +4,7 @@
- **작성일**: 2025-10-21 - **작성일**: 2025-10-21
- **최종 수정일**: 2025-10-23 - **최종 수정일**: 2025-10-23
- **작성자**: 이미준 (서비스 기획자) - **작성자**: 이미준 (서비스 기획자)
- **버전**: 1.4.4 - **버전**: 1.4.7
- **설계 철학**: Mobile First Design - **설계 철학**: Mobile First Design
--- ---
@ -1099,106 +1099,116 @@ graph TD
### 09-Todo관리 ### 09-Todo관리
#### 개요 #### 개요
- **목적**: 할당된 Todo 목록 조회 및 진행 상황 관리 - **목적**: 나의 Todo(내가 담당자인 Todo) 조회 및 관리
- **관련 유저스토리**: UFR-TODO-010, UFR-TODO-030, **UFR-TODO-040 (Todo 수정)** - **관련 유저스토리**: UFR-TODO-040 (Todo 관리)
- **비즈니스 중요도**: 높음 - **비즈니스 중요도**: 높음
- **접근 경로**: 대시보드 → 하단 네비게이션 "Todo" 또는 대시보드 "내 Todo" 카드 → "전체 보기" - **접근 경로**: 대시보드 → 하단 네비게이션 "Todo" 또는 대시보드 "내 Todo" 카드 → "전체 보기"
- **대전제**:
- Todo의 상태는 완료/미완료만 존재
- 09-Todo관리 화면에서는 나의 Todo(내가 담당자인 Todo)만 표시
#### 주요 기능 #### 주요 기능
1. Todo 목록 표시 (상태별 필터링) 1. 나의 Todo 목록 표시 (필터링)
2. **Todo 수정 (UFR-TODO-040)** - 신규 추가 2. Todo 완료/미완료 상태 변경
3. Todo 완료 처리 3. Todo 편집 (모달)
4. 회의록 원문으로 이동 (양방향 연결) 4. 회의록 상세로 이동 (양방향 연결)
5. Todo 진행 상황 통계 5. Todo 통계 (전체, 마감임박, 지연)
6. 마감 임박 Todo 알림
#### UI 구성요소 #### UI 구성요소
**Mobile (320px~768px)** **Mobile (320px~768px)**
- **헤더** - **헤더**
- "Todo" 타이틀 - "Todo 관리" 타이틀
- 필터 버튼 (상태별) - 프로필 아이콘 (모바일)
- **통계 카드** - **상단 통계 블록** (4개 블록)
- 전체 Todo 개수 - **전체**: 미완료 전체 개수
- 완료율 (원형 진행 바) - **마감임박**: 기한 3일 이내 미완료 개수 (강조 스타일)
- 마감 임박 Todo 개수 (배지) - **지연**: 기한이 지난 미완료 개수
- **필터 탭** - **필터 탭**
- 전체, 진행 중, 완료, 마감 임박 - **전체 (개수)**: 완료/미완료 전체
- **지연 (개수)**: 기한이 지난 미완료
- **마감임박 (개수)**: 기한 3일 이내 미완료
- **완료 (개수)**: 완료된 Todo
- **Todo 리스트** - **Todo 리스트 블록**
- 각 Todo 카드: - **정렬**: 미완료 → 완료 순서, 기한일 오래된 순 (복합 정렬)
- 체크박스 (완료 처리) - **각 Todo 카드** (블록 형태):
- Todo 내용 - **체크박스** (완료/미완료 토글, 액션 가능 표시)
- 마감일 (색상 코딩: 초록-여유, 노랑-임박, 빨강-지연) - **Todo 제목**
- 우선순위 배지 (높음/보통/낮음) - **상태 뱃지**: D+n(지연) / D-day / D-n / 완료
- 관련 회의록 링크 아이콘 - **우선순위 뱃지**: 높음(빨강) / 보통(노랑) / 낮음(회색)
- **"편집" 버튼** (본인 담당 Todo만 표시) - 신규 - **기한**
- 스와이프 액션: 수정, 삭제 - **회의록 제목 + 링크** (클릭 시 10-회의록상세조회 대시보드 탭으로 이동)
- **편집 버튼** (권한 있는 경우에만 노출, 액션 가능 표시)
- **FAB** (Floating Action Button) - **페이징**: 최초 10건 노출, 10건 이상일 경우 하단에 "10개 더보기" 버튼
- "Todo 추가" (수동 추가)
**Tablet/Desktop (768px+)** **Tablet/Desktop (768px+)**
- 좌측: Todo 리스트 - 좌측 사이드바 + 메인 콘텐츠 영역
- 우측: 선택된 Todo 상세 정보 - 통계 블록 4개 가로 배치
- Todo 내용 - Todo 리스트 그리드 레이아웃 (2열)
- 담당자
- 마감일
- 우선순위
- 관련 회의록 섹션 (임베디드 뷰)
- 진행 메모 (추가 가능)
#### 인터랙션 #### 인터랙션
1. **Todo 수정 (UFR-TODO-040)** - 신규 추가 1. **Todo 완료/미완료 상태 변경**
- **편집 버튼 클릭**: - **체크박스 클릭**:
- 인라인 편집 모드로 전환 또는 수정 모달 표시 - 완료 처리 시: "완료 처리하시겠습니까?" 확인 모달
- **수정 가능 항목** (담당자 권한): - 미완료로 되돌릴 때: "미완료로 변경하시겠습니까?" 확인 모달
- ✏️ Todo 제목 (문구) - 확인 시: 상태 업데이트, 통계 갱신, 리스트 재정렬
- 📅 마감일 (날짜 선택기) - 취소 시: 이전 상태 유지
- 🎯 우선순위 (high/medium/low 드롭다운)
- ❌ 담당자 변경 불가 (본인 담당 Todo) 2. **Todo 편집 (UFR-TODO-040)**
- **저장 버튼**: 수정 완료 - **편집 버튼 클릭** (권한: 담당자 본인 OR 회의 생성자):
- **취소 버튼**: 편집 모드 취소 - 편집 모달 표시
- **수정 완료 시**: - **모바일**: 바텀시트 형식
- **데스크톱**: 중앙 모달
- **수정 가능 항목**:
- ✏️ Todo 제목 (input, 필수)
- 👤 담당자 (select, 회의록 참석자 중 선택) - **회의 생성자만 변경 가능**
- 📅 마감일 (날짜 선택기, 필수)
- 🎯 우선순위 (높음/보통/낮음 select, 필수)
- **권한 표시**:
- 담당자 본인: "본인에게 할당된 Todo만 수정할 수 있습니다. 담당자는 변경할 수 없습니다."
- 회의 생성자: "회의 생성자로서 모든 항목을 수정할 수 있습니다. 담당자 변경 시 알림이 전송됩니다."
- **저장 버튼 클릭**:
- 유효성 검사 (제목, 마감일 필수)
- "Todo가 수정되었습니다" 토스트 메시지 - "Todo가 수정되었습니다" 토스트 메시지
- 회의록에 수정 내용 실시간 반영 - 회의록에 수정 내용 실시간 반영
- 마감일 변경 시 캘린더 자동 업데이트 - 담당자 변경 시: 이전/새 담당자에게 알림 발송
- **권한 제어**: - 마감일 변경 시: 캘린더 자동 업데이트
- 본인에게 할당된 Todo만 편집 버튼 표시 - **취소 버튼**: 모달 닫기, 변경 사항 취소
- 다른 사람의 Todo는 조회만 가능 (편집 버튼 숨김)
2. **Todo 완료 처리** 3. **회의록 링크 클릭**
- 체크박스 클릭: - 10-회의록상세조회 화면으로 이동
- 확인 다이얼로그 ("완료 처리하시겠습니까?") - **대시보드 탭이 우선 노출**
- 완료 시: 체크 애니메이션, 회의록에 실시간 반영
- 완료 Todo는 리스트 하단으로 이동 (취소선)
3. **회의록 연결** 4. **필터 탭 클릭**
- 회의록 링크 아이콘 클릭: - 선택한 필터 기준으로 Todo 목록 갱신
- 회의록상세조회 화면으로 이동 - 활성 탭 강조 표시
- 해당 Todo가 언급된 섹션으로 자동 스크롤
- 하이라이트 효과
4. **필터링** 5. **10개 더보기 버튼**
- 필터 탭 클릭: 해당 상태의 Todo만 표시 - 클릭 시 하단에 10건씩 추가 로드
- 마감 임박: 3일 이내 마감 Todo - 페이지 새로고침 없이 무한 스크롤 방식
5. **수동 추가** #### 디자인 요구사항
- FAB 클릭: Todo 추가 모달 - **액션 블록 vs 정보 블록 차별화**:
- 내용, 마감일, 우선순위 입력 - 액션 가능 (체크박스, 편집 버튼): 호버 시 배경색 변경, 그림자 효과
- 정보 표시 (상태 뱃지, 우선순위, 기한): 정적 표시, 호버 효과 없음
- **모바일 최적화**:
- 바텀시트 편집 모달 (전체 화면 X)
- 터치 영역 최소 44px × 44px
#### 데이터 요구사항 #### 데이터 요구사항
- **입력**: 사용자 ID - **입력**: 사용자 ID (내가 담당자인 Todo만 조회)
- **출력**: - **출력**:
- Todo 목록 (상태, 내용, 담당자, 마감일, 우선순위, 회의록 링크) - Todo 목록 (제목, 상태, 담당자, 마감일, 우선순위, 회의록 제목, 회의록 ID)
- Todo 통계 (전체, 완료, 진행 중) - Todo 통계 (전체, 마감임박, 지연, 완료)
- **연동**: Todo 서비스, Meeting 서비스 - **연동**: Meeting 서비스 (Todo 관리 통합)
#### 에러 처리 #### 에러 처리
- **Todo 로딩 실패**: "Todo 목록을 불러올 수 없습니다" + 재시도 버튼 - **Todo 로딩 실패**: "Todo 목록을 불러올 수 없습니다" + 재시도 버튼
- **완료 처리 실패**: "완료 처리에 실패했습니다. 다시 시도해주세요" - **상태 변경 실패**: "상태 변경에 실패했습니다. 다시 시도해주세요"
- **편집 저장 실패**: "저장에 실패했습니다. 다시 시도해주세요"
- **빈 상태**: "할당된 Todo가 없습니다. 새 회의를 시작해보세요!" - **빈 상태**: "할당된 Todo가 없습니다. 새 회의를 시작해보세요!"
--- ---
@ -1236,8 +1246,8 @@ graph TD
- 작성자 및 최종 수정 시간 - 작성자 및 최종 수정 시간
- **탭 네비게이션** (상단, Fixed) - **탭 네비게이션** (상단, Fixed)
- "회의록" 탭 (기본 활성) - "대시보드" 탭 (기본 활성)
- "대시보드" 탭 - "회의록" 탭
- **회의록 탭 콘텐츠** (섹션별 구조) - **회의록 탭 콘텐츠** (섹션별 구조)
- 각 섹션: - 각 섹션:
@ -1300,8 +1310,8 @@ graph TD
**Tablet/Desktop (768px+)** **Tablet/Desktop (768px+)**
- **상단**: 탭 네비게이션 - **상단**: 탭 네비게이션
- 회의록 (기본) - 대시보드 (기본 활성)
- 대시보드 - 회의록
- **메인 영역**: - **메인 영역**:
- 회의록 탭: 전체 회의록 내용 (섹션별 구조) - 회의록 탭: 전체 회의록 내용 (섹션별 구조)
- 대시보드 탭: 핵심내용, 결정사항, Todo 진행상황, 참고자료 (11-회의록대시보드.html 구조 참조) - 대시보드 탭: 핵심내용, 결정사항, Todo 진행상황, 참고자료 (11-회의록대시보드.html 구조 참조)
@ -1389,42 +1399,45 @@ graph TD
- **목적**: 지난 회의록 조회 및 수정 - **목적**: 지난 회의록 조회 및 수정
- **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, **UFR-TODO-040 (Todo 수정)** - **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, **UFR-TODO-040 (Todo 수정)**
- **비즈니스 중요도**: 중간 - **비즈니스 중요도**: 중간
- **접근 경로**: 대시보드 → "내 회의록" → 회의록상세조회 → "수정" - **접근 경로**: 10-회의록상세조회 → 하단 액션 바 "수정" 버튼 클릭
- **권한 제어**:
- **검증완료 전**: 모든 참석자가 수정 가능
- **검증완료 후**: 회의 생성자만 수정 가능 (참석자는 "수정" 버튼 비활성화)
#### 주요 기능 #### 주요 기능
1. 회의록 목록 조회 (필터링, 정렬, 검색) 1. 회의 기본 정보 표시 및 수정
- 회의 제목: 수정 가능
- 회의 일시/장소: 읽기 전용 (회의 예약 화면에서만 변경 가능)
- 참석자 관리: 회의 생성자만 추가/삭제 가능
2. 회의록 내용 수정 (섹션별) 2. 회의록 내용 수정 (섹션별)
3. **AI 요약 수정** (섹션별) 3. **AI 요약 수정** (섹션별)
4. **참고자료 편집** (추가/제거) 4. **참고자료 편집** (추가/제거)
5. **Todo 수정 (UFR-TODO-040)** - 신규 추가 (회의 생성자만) 5. **Todo 수정 (UFR-TODO-040)** - 신규 추가 (회의 생성자만)
6. 자동 저장 (30초 간격) 6. 자동 저장 (30초 간격)
7. 수정 이력 관리 7. 수정 이력 관리
8. 상태 변경 (확정완료 → 작성중) 8. 상태 변경 (검증완료 → 작성중으로 자동 변경)
#### UI 구성요소 #### UI 구성요소
**Mobile (320px~768px)** **Mobile (320px~768px)**
- **헤더** - **헤더**
- 뒤로가기 버튼 - 뒤로가기 버튼 (10-회의록상세조회로 이동)
- "회의록 수정" 타이틀 - "회의록 수정" 타이틀
- "저장" 버튼 (Primary) - "저장" 버튼 (Primary)
- 자동 저장 인디케이터 - 자동 저장 인디케이터 ("저장됨", "저장 중...")
- **필터 및 검색** (상단) - **회의 기본 정보 영역**
- 상태 필터: 전체 / 작성중 / 확정완료 - 회의 제목: 편집 가능 (텍스트 필드)
- 정렬: 최신순 / 회의일시순 / 제목순 - 회의 일시: 읽기 전용 (📅 아이콘 + 날짜/시간 표시)
- 검색창: 제목, 참석자, 키워드 - 회의 장소: 읽기 전용 (📍 아이콘 + 장소명)
- 참석자 목록:
- 회의 생성자: 추가/삭제 가능 (05-회의진행 화면과 동일한 UI)
- 참석자: 읽기 전용 표시
- 각 참석자: 아바타 + 이름, 삭제(×) 버튼 (생성자는 삭제 불가)
- "참석자 추가" 버튼 (이메일 입력 + 초대)
- 회의록 상태 배지 (자동 관리)
- **회의록 리스트** (목록 모드) - **편집 화면**
- 각 회의록 카드:
- 회의 제목
- 회의 일시
- 상태 배지
- 마지막 수정 시간
- 검증 완료율 (작성중인 경우)
- 스와이프 액션: 수정, 삭제
- **수정 모드** (편집 화면)
- 섹션별 편집 영역 - 섹션별 편집 영역
- 각 섹션: - 각 섹션:
- 섹션 제목 - 섹션 제목
@ -1452,24 +1465,28 @@ graph TD
- 자동 저장 상태 표시 ("저장됨", "저장 중...") - 자동 저장 상태 표시 ("저장됨", "저장 중...")
**Tablet/Desktop (768px+)** **Tablet/Desktop (768px+)**
- 좌측: 회의록 리스트 - **헤더**: Mobile과 동일 (뒤로가기, 타이틀, 저장 버튼, 자동 저장 인디케이터)
- 중앙: 선택된 회의록 편집 영역 - **메인 영역**:
- 우측: 수정 이력 패널 - 회의 기본 정보 영역 (Mobile과 동일)
- 편집 화면 (섹션별 편집, AI 요약, 참고자료, Todo)
- **우측 패널** (선택사항):
- 수정 이력 (v2.0 고도화 예정)
- 미리보기
#### 인터랙션 #### 인터랙션
1. **회의록 선택** 1. **화면 진입**
- 리스트에서 회의록 클릭: 편집 모드로 전환 - 10-회의록상세조회 → "수정" 버튼 클릭
- 편집 모드에서 다른 회의록 선택: 저장 확인 다이얼로그 - 권한 확인: 검증완료 후에는 회의 생성자만 접근 가능
- 바로 편집 모드로 시작
2. **내용 수정** 2. **내용 수정**
- 텍스트 영역 클릭: 포커스 및 편집 가능 - 텍스트 영역 클릭: 포커스 및 편집 가능
- 자동 저장: 30초 간격, 인디케이터 표시 - 자동 저장: 30초 간격, 인디케이터 표시
- 수동 저장: "저장" 버튼 클릭 - 수동 저장: "저장" 버튼 클릭
3. **섹션 잠금 해제** 3. **검증완료 섹션 (권한별 차등 표시)**
- 잠긴 섹션: 회의 생성자에게 승인 요청 - **회의 생성자**: 06-검증완료 화면에서 잠금 해제 가능
- 승인 대기 중: "승인 대기 중" 배지 표시 - **참석자**: 읽기 전용 표시 ("🔒 읽기 전용" 배지)
- 승인 완료: 편집 가능
4. **AI 요약 편집** 4. **AI 요약 편집**
- 요약 텍스트 필드 클릭: 직접 수정 가능 - 요약 텍스트 필드 클릭: 직접 수정 가능
@ -2015,6 +2032,8 @@ graph TD
| 1.4.4 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- **유저스토리**: UFR-TODO-040 (Todo수정) 신규 추가<br> - 회의록 확정 전/후 Todo 수정 기능<br> - 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br> - 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- **09-Todo관리**: Todo 수정 기능 추가<br> - "편집" 버튼 추가 (완료되지 않은 본인 Todo만 표시)<br> - Todo 편집 모달: 제목, 마감일, 우선순위 수정 (담당자 변경 불가)<br> - 수정 완료 시 회의록에 실시간 반영, 마감일 변경 시 캘린더 자동 업데이트<br> - 권한 제어: 본인에게 할당된 Todo만 편집 버튼 표시<br>- **11-회의록수정**: Todo 섹션 편집 기능 추가 (회의 생성자만)<br> - Todo 목록 표시 및 인라인 편집 (제목, 담당자, 마감일, 우선순위)<br> - Todo 추가/삭제 기능<br> - 담당자 변경 시 이전/새 담당자에게 알림 발송<br>- **프로토타입**: design/uiux/prototype/09-Todo관리.html 수정 (편집 모달 및 기능 구현) | | 1.4.4 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- **유저스토리**: UFR-TODO-040 (Todo수정) 신규 추가<br> - 회의록 확정 전/후 Todo 수정 기능<br> - 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br> - 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- **09-Todo관리**: Todo 수정 기능 추가<br> - "편집" 버튼 추가 (완료되지 않은 본인 Todo만 표시)<br> - Todo 편집 모달: 제목, 마감일, 우선순위 수정 (담당자 변경 불가)<br> - 수정 완료 시 회의록에 실시간 반영, 마감일 변경 시 캘린더 자동 업데이트<br> - 권한 제어: 본인에게 할당된 Todo만 편집 버튼 표시<br>- **11-회의록수정**: Todo 섹션 편집 기능 추가 (회의 생성자만)<br> - Todo 목록 표시 및 인라인 편집 (제목, 담당자, 마감일, 우선순위)<br> - Todo 추가/삭제 기능<br> - 담당자 변경 시 이전/새 담당자에게 알림 발송<br>- **프로토타입**: design/uiux/prototype/09-Todo관리.html 수정 (편집 모달 및 기능 구현) |
| 1.4.4 | 2025-10-23 | 강지수 | Mobile 하단 네비게이션 프로토타입 구현 기준 반영<br>- **Mobile 하단 네비게이션**: 4개 메뉴 → 3개 메뉴로 수정 (홈/회의록/Todo)<br> - 프로필 메뉴 제거 (Desktop 사이드바의 사용자 정보 영역으로 통합)<br> - 프로토타입 실제 구현 상태 반영 (02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html)<br> - 사용 화면 번호 업데이트: 08→09, 11→12<br>- **참고 사항**: 프로필 메뉴가 필요한 경우 프로토타입에 추가 구현 필요<br>- **설계서-프로토타입 일관성**: 네비게이션 구조 완전 통일 달성 | | 1.4.4 | 2025-10-23 | 강지수 | Mobile 하단 네비게이션 프로토타입 구현 기준 반영<br>- **Mobile 하단 네비게이션**: 4개 메뉴 → 3개 메뉴로 수정 (홈/회의록/Todo)<br> - 프로필 메뉴 제거 (Desktop 사이드바의 사용자 정보 영역으로 통합)<br> - 프로토타입 실제 구현 상태 반영 (02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html)<br> - 사용 화면 번호 업데이트: 08→09, 11→12<br>- **참고 사항**: 프로필 메뉴가 필요한 경우 프로토타입에 추가 구현 필요<br>- **설계서-프로토타입 일관성**: 네비게이션 구조 완전 통일 달성 |
| 1.4.5 | 2025-10-23 | 강지수 | 로그아웃 기능 추가 (Desktop 사이드바 + Mobile 헤더)<br>- **Desktop 좌측 사이드바**: 하단에 사용자 정보 영역 추가<br> - 사용자 정보 (아바타 + 이름 + 이메일)<br> - 로그아웃 버튼 (btn-ghost btn-sm)<br>- **Mobile 상단 헤더**: 우측에 프로필 아이콘 버튼 추가 (👤)<br> - 클릭 시 드롭다운 메뉴 표시 (사용자 정보 + 로그아웃 버튼)<br> - 드롭다운 위치: 우측 상단 기준 아래로 펼침<br> - 오버레이 배경으로 UX 개선<br>- **프로토타입 파일**: 02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html<br>- **JavaScript 함수**: toggleProfileMenu(), logout() 추가<br>- **반응형 처리**: Desktop에서는 드롭다운 숨김, Mobile에서는 사이드바 사용자 영역 숨김<br>- **설계서-프로토타입 일관성**: 로그아웃 기능 완전 통일 | | 1.4.5 | 2025-10-23 | 강지수 | 로그아웃 기능 추가 (Desktop 사이드바 + Mobile 헤더)<br>- **Desktop 좌측 사이드바**: 하단에 사용자 정보 영역 추가<br> - 사용자 정보 (아바타 + 이름 + 이메일)<br> - 로그아웃 버튼 (btn-ghost btn-sm)<br>- **Mobile 상단 헤더**: 우측에 프로필 아이콘 버튼 추가 (👤)<br> - 클릭 시 드롭다운 메뉴 표시 (사용자 정보 + 로그아웃 버튼)<br> - 드롭다운 위치: 우측 상단 기준 아래로 펼침<br> - 오버레이 배경으로 UX 개선<br>- **프로토타입 파일**: 02-대시보드.html, 09-Todo관리.html, 12-회의록목록조회.html<br>- **JavaScript 함수**: toggleProfileMenu(), logout() 추가<br>- **반응형 처리**: Desktop에서는 드롭다운 숨김, Mobile에서는 사이드바 사용자 영역 숨김<br>- **설계서-프로토타입 일관성**: 로그아웃 기능 완전 통일 |
| 1.4.6 | 2025-10-23 | 강지수 | 검증완료 섹션 잠금해제 정책 단순화<br>- **정책 변경**: 검증완료 섹션은 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)<br>- **제거**: 참석자용 잠금해제 요청 기능 완전 제거 (공수 절감)<br>- **11-회의록수정**: 검증완료 섹션에 "🔒 읽기 전용" 배지 표시 (참석자 화면)<br> - 잠금해제요청 버튼 제거<br> - unlockSection() 함수 제거<br> - 읽기 전용 안내 텍스트 추가: "(잠금됨 · 회의 생성자만 수정 가능)"<br>- **06-검증완료**: 회의 생성자용 잠금해제 버튼 유지 (변경 없음)<br>- **인터랙션**: "3. 섹션 잠금 해제" → "3. 검증완료 섹션 (권한별 차등 표시)"로 수정<br>- **유저스토리**: UFR-MEET-055, UFR-COLLAB-030 권한 제어 명확화 |
| 1.4.7 | 2025-10-23 | 강지수, 도그냥 | Todo 및 회의록 관련 UI/UX 재정의<br>- **09-Todo관리**: "Todo수정" → "Todo관리" 기능 확장<br> - 통계 블록: 전체(미완료), 마감임박(3일 이내), 지연(기한 경과)<br> - 필터 탭 개수 표시: 전체(개수), 지연(개수), 마감임박(개수), 완료(개수)<br> - 편집 모달: 제목, 담당자, 마감일, 우선순위 수정<br> - 체크박스 확인 모달: 완료/미완료 전환 시 확인<br> - 프로토타입: 09-Todo관리.html (통계, 필터, 모달 구현)<br>- **10-회의록상세조회**: 탭 순서 및 기본 노출 변경<br> - 탭 순서: 대시보드 → 회의록 (기존: 회의록 → 대시보드)<br> - 기본 활성 탭: 대시보드 (Desktop/Mobile 공통)<br> - 프로토타입: 10-회의록상세조회.html (탭 순서 변경, active 클래스 이동)<br>- **11-회의록수정**: 진입 경로 및 권한 제어 명확화<br> - 진입 경로: 10-회의록상세조회 → "수정" 버튼 클릭<br> - 권한 제어: 검증완료 전(모든 참석자), 검증완료 후(회의 생성자만)<br> - 회의 일시/장소: 읽기 전용 표시 추가 "(읽기 전용)"<br> - UI 구성: 회의록 리스트 제거, 직접 편집 화면으로 시작<br> - 프로토타입: 11-회의록수정.html (권한 코멘트 추가, readonly 표시) |
--- ---

View File

@ -1,6 +1,6 @@
# AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.3) # AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.5)
- [AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.3)](#ai기반-회의록-작성-및-이력-관리-개선-서비스---유저스토리-v203) - [AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.0.5)](#ai기반-회의록-작성-및-이력-관리-개선-서비스---유저스토리-v205)
- [차별화 전략](#차별화-전략) - [차별화 전략](#차별화-전략)
- [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors) - [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors)
- [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators) - [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators)
@ -316,9 +316,22 @@ UFR-MEET-047: [회의록상세조회] 회의록 작성자로서 | 나는, 지난
- 각 회의록별 정보: 제목, 날짜, 관련도 %, 요약 내용 - 각 회의록별 정보: 제목, 날짜, 관련도 %, 요약 내용
- 클릭 시 해당 회의록으로 이동 - 클릭 시 해당 회의록으로 이동
[탭 네비게이션]
- **탭 구성**: 대시보드 / 회의록 (2개 탭)
- **기본 노출**: 대시보드 탭 우선 노출
- **탭 전환**: 클릭 시 콘텐츠 전환, URL 변경 없음
- **대시보드 탭 내용**:
- 핵심내용 (주요 포인트 요약)
- 결정사항
- Todo 진행상황
- 관련회의록
- **회의록 탭 내용**:
- 섹션별 상세 내용
- AI 요약
- 관련회의록
[부가 기능] [부가 기능]
- 회의록 수정 버튼 (수정 권한이 있는 경우만 활성화) - 회의록 수정 버튼 (수정 권한이 있는 경우만 활성화)
- 탭 네비게이션 (회의록/대시보드)
- 뒤로가기 버튼 (회의록 목록으로 복귀) - 뒤로가기 버튼 (회의록 목록으로 복귀)
- 더보기 메뉴 (다운로드, 삭제 등) - 더보기 메뉴 (다운로드, 삭제 등)
@ -336,10 +349,15 @@ UFR-MEET-047: [회의록상세조회] 회의록 작성자로서 | 나는, 지난
--- ---
UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이 완료되지 않았거나 수정이 필요한 | 지난 회의록을 수정하고 싶다. UFR-MEET-055: [회의록수정] 회의 참석자로서 | 나는, 검증이 완료되지 않았거나 수정이 필요한 | 지난 회의록을 수정하고 싶다.
- **화면번호**: 11-회의록수정
- 시나리오: 지난 회의록 수정 - 시나리오: 지난 회의록 수정
회의록 상세 화면에서 수정 버튼을 클릭하면 | 회의록 수정 화면으로 이동하고 | 내용을 수정할 수 있다. 회의록 상세 화면에서 수정 버튼을 클릭하면 | 회의록 수정 화면으로 이동하고 | 내용을 수정할 수 있다.
[진입 경로]
- 10-회의록상세조회 화면 → 하단 액션 바 "수정" 버튼 클릭
- 권한이 있는 경우에만 "수정" 버튼 활성화
[수정 가능 항목] [수정 가능 항목]
- ✅ **회의 제목**: 수정 가능 - ✅ **회의 제목**: 수정 가능
- ❌ **회의 일시**: 수정 불가 (readonly, 회의 예약 화면에서만 변경 가능) - ❌ **회의 일시**: 수정 불가 (readonly, 회의 예약 화면에서만 변경 가능)
@ -351,7 +369,7 @@ UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이
- ✅ **섹션별 AI 요약**: AI 재생성 버튼으로 수정 가능 - ✅ **섹션별 AI 요약**: AI 재생성 버튼으로 수정 가능
- ✅ **섹션별 내용**: 마크다운 에디터로 수정 가능 - ✅ **섹션별 내용**: 마크다운 에디터로 수정 가능
- ✅ **관련회의록**: 추가/삭제 가능 - ✅ **관련회의록**: 추가/삭제 가능
- ❌ **검증완료 섹션**: 잠금 해제 후 수정 가능 (회의록 생성자만 잠금 해제 가능) - ❌ **검증완료 섹션**: 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)
- 🔄 **회의록 상태**: 수정 시 자동으로 '작성중'으로 변경 (사용자 직접 변경 불가) - 🔄 **회의록 상태**: 수정 시 자동으로 '작성중'으로 변경 (사용자 직접 변경 불가)
[수정 기능] [수정 기능]
@ -366,9 +384,16 @@ UFR-MEET-055: [회의록수정] 회의록 작성자로서 | 나는, 검증이
- 취소 시 이전 상태로 복원 - 취소 시 이전 상태로 복원
[권한 제어] [권한 제어]
- 본인이 작성한 회의록만 수정 가능 **검증완료 전 (작성중/초안 상태)**
- 검증완료 섹션 잠금/해제는 회의록 생성자만 가능 - 모든 참석자가 회의록 수정 가능
- 조회 전용 권한인 경우 수정 버튼 비활성화 - 모든 섹션 편집 가능 (검증완료 섹션 없음)
- 참석자 관리: 회의 생성자만 가능
**검증완료 후**
- 회의 생성자만 회의록 수정 가능
- 참석자는 "수정" 버튼 비활성화 (조회만 가능)
- 검증완료 섹션: 회의 생성자만 잠금 해제 후 수정 가능
- 수정 시 회의록 상태는 '작성중'으로 자동 변경 (재검증 필요)
- M/13 - M/13
@ -773,10 +798,10 @@ UFR-COLLAB-030: [검증완료] 회의 참석자로서 | 나는, 회의록의 정
- 미검증 → 검증 중 → 검증 완료 - 미검증 → 검증 중 → 검증 완료
[섹션 잠금 기능] [섹션 잠금 기능]
- 회의 생성자만 가능 - 회의 생성자만 잠금/해제 가능
- 주요 섹션 검증 완료 시 잠금 가능 (선택) - 주요 섹션 검증 완료 시 잠금 가능 (선택)
- 잠긴 섹션은 추가 수정 불가 - 잠긴 섹션은 회의 생성자만 잠금 해제 후 수정 가능
- 회의 생성자가 잠그면 검증 완료로 표시 - 참석자는 검증완료된 섹션을 읽기 전용으로만 확인 가능
[처리 결과] [처리 결과]
- 검증이 완료됨 - 검증이 완료됨
@ -890,62 +915,87 @@ UFR-TODO-030: [Todo완료처리] Todo 담당자로서 | 나는, 완료된 Todo
--- ---
UFR-TODO-040: [Todo수정] Todo 담당자 또는 회의 생성자로서 | 나는, Todo 내용을 변경하기 위해 | 회의록 확정 전후에 Todo를 수정하고 싶다. UFR-TODO-040: [Todo관리] Todo 담당자로서 | 나는, 나의 Todo를 효율적으로 관리하기 위해 | Todo 목록을 조회하고 상태를 변경하고 편집하고 싶다.
- 시나리오: Todo 수정 - 시나리오: Todo 관리 화면 조회 및 관리
Todo 목록에서 수정이 필요한 상황에서 | 담당자 또는 회의 생성자가 Todo 수정 버튼을 클릭하면 | Todo 내용, 담당자, 마감일, 우선순위를 변경할 수 있다. 09-Todo관리 화면에 접근하면 | 나의 Todo(내가 담당자인 Todo) 목록이 표시되고 | 필터링, 상태 변경, 편집이 가능하다.
[화면 정보] [화면 정보]
- 화면번호: 09-Todo관리 - 화면번호: 09-Todo관리
- 프로토타입: design/uiux/prototype/09-Todo관리.html - 프로토타입: design/uiux/prototype/09-Todo관리.html
[수정 가능 항목] [대전제]
- Todo 제목 (문구) - Todo의 상태는 완료/미완료만 존재
- 담당자 (드롭다운 선택) - 09-Todo관리 화면에서는 나의 Todo(내가 담당자인 Todo)만 표시
- 마감일 (날짜 선택기)
- 우선순위 (high/medium/low)
[수정 시점] [화면 구성]
- **회의록 확정 전**: 회의 진행 중(05-회의진행) 또는 회의 종료 전(07-회의종료)에서 수정 가능 **1. 상단 통계 블록**
- **회의록 확정 후**: Todo 관리 화면(09-Todo관리) 또는 회의록 수정 화면(11-회의록수정)에서 수정 가능 - 전체: 미완료 전체 개수
- 마감임박: 기한 3일 이내 미완료 개수
- 지연: 기한이 지난 미완료 개수
**2. 필터링 기준**
- 전체(개수): 완료/미완료 전체
- 지연(개수): 기한이 지난 미완료
- 마감임박(개수): 기한 3일 이내 미완료
- 완료(개수): 완료된 Todo
**3. Todo 리스트 블록**
- 정렬: 미완료 → 완료 순서, 기한일 오래된 순 (복합 정렬)
- 표시 항목:
- 체크박스 (완료/미완료 토글)
- Todo 제목
- 상태 뱃지: D+n(지연) / D-day / D-n / 완료
- 우선순위 뱃지: 높음 / 보통 / 낮음
- 기한
- 회의록 제목 + 링크 (해당 Todo가 속한 회의록 상세로 이동)
- 편집 버튼 (권한 있는 경우에만 노출)
- 페이징: 최초 10건 노출, 10건 이상일 경우 하단에 "10개 더보기" 버튼 표시
**4. 편집 모달**
- 제목 (input)
- 담당자 (해당 회의록 참석자 중 select) - 회의 생성자만 변경 가능
- 마감일 (달력)
- 우선순위 (높음/보통/낮음 select)
[UI/UX 요구사항]
- **디자인 차별화**: 액션 가능한 블록(체크박스, 편집 버튼)과 정보 표시 블록은 시각적으로 구분
- **체크박스 동작**:
- 체크박스 클릭 시 "완료 처리하시겠습니까?" 확인 모달 표시
- 확인 시 완료 처리, 취소 시 이전 상태 유지
- 미완료로 되돌릴 때도 "미완료로 변경하시겠습니까?" 확인 모달 표시
- **편집 버튼**: 담당자 본인 OR 회의 생성자인 경우에만 노출
- **편집 모달**: 모바일에서는 바텀시트 형식으로 표시
- **회의록 링크**: 클릭 시 10-회의록상세조회 화면으로 이동 (대시보드 탭 우선 노출)
[권한 제어] [권한 제어]
- **Todo 담당자**: 본인에게 할당된 Todo만 수정 가능 (09-Todo관리) - **Todo 담당자**: 본인에게 할당된 Todo만 편집 가능
- 수정 가능 항목: 제목, 마감일, 우선순위 - 수정 가능 항목: 제목, 마감일, 우선순위
- 담당자 변경 불가 (본인 담당 Todo) - 담당자 변경 불가
- **회의 생성자**: 해당 회의의 모든 Todo 수정 가능 (11-회의록수정) - **회의 생성자**: 해당 회의의 모든 Todo 편집 가능 (11-회의록수정 화면에서)
- 수정 가능 항목: 제목, 담당자, 마감일, 우선순위 - 수정 가능 항목: 제목, 담당자, 마감일, 우선순위
- 담당자 변경 가능 - 담당자 변경 가능
[수정 인터페이스]
- 09-Todo관리: 각 Todo 항목에 "편집" 버튼 표시
- 클릭 시 인라인 편집 모드 또는 수정 모달 표시
- 수정 완료 후 "저장" 버튼 클릭
- 11-회의록수정: "액션 아이템(Todo)" 섹션에서 수정
- 회의록 수정 시 Todo 섹션도 편집 가능
- Todo 추가/삭제/수정 모두 가능
[처리 결과] [처리 결과]
- Todo 정보 업데이트 - Todo 상태 변경 시:
- 수정 시간 기록 - 완료/미완료 상태 즉시 업데이트
- 수정자 정보 저장 - 통계 블록 갱신
- 회의록에 수정 내용 실시간 반영 - 리스트 재정렬
- 담당자 변경 시 이전 담당자와 새 담당자에게 알림 발송 - Todo 편집 저장 시:
- 마감일 변경 시 캘린더 자동 업데이트 - Todo 정보 업데이트
- 수정 시간 기록
[알림 발송] - 회의록에 수정 내용 실시간 반영
- 담당자 변경 시: 이전 담당자 및 새 담당자에게 알림 - 담당자 변경 시 이전/새 담당자에게 알림 발송
- 마감일 변경 시: 담당자에게 알림 (캘린더 업데이트) - 마감일 변경 시 캘린더 자동 업데이트
- 제목/우선순위 변경 시: 담당자에게 알림 (변경 사항 안내)
[Policy/Rule] [Policy/Rule]
- 담당자는 본인 Todo만 수정 가능 (담당자 변경 불가) - 필터별 개수 표시로 사용자가 전체 보기 여부 판단 가능
- 회의 생성자는 모든 Todo 수정 가능 (담당자 변경 가능) - 체크박스 토글 시 확인 액션 필수 (실수 방지)
- 확정 전/후 모두 수정 가능 - 편집 권한 없는 Todo는 편집 버튼 미노출
- 수정 시 회의록에 즉시 반영
[비고] [비고]
- 회의록 확정 후에도 유연한 Todo 관리 가능 - 진행률 표시 제거 (상태는 완료/미완료만)
- 인사 이동, 우선순위 변경, 일정 조정 등 실무 요구사항 반영 - 날짜별 그룹핑은 v2.0 고도화 시 고려
- Todo 하이라이트 기능은 v2.0 고도화 시 고려
- M/13 - M/13
@ -1044,5 +1094,7 @@ UFR-TODO-040: [Todo수정] Todo 담당자 또는 회의 생성자로서 | 나는
| 2.0.1 | 2025-10-23 | 강지수 (Product Designer) | 공유 기능 제거 반영 <br>- AFR-USER-020: 대시보드 "공유받은 회의록" 섹션 제거<br>- UFR-MEET-046: 회의록 목록 카테고리 필터 "공유받은 회의" 제거 | | 2.0.1 | 2025-10-23 | 강지수 (Product Designer) | 공유 기능 제거 반영 <br>- AFR-USER-020: 대시보드 "공유받은 회의록" 섹션 제거<br>- UFR-MEET-046: 회의록 목록 카테고리 필터 "공유받은 회의" 제거 |
| 2.0.2 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- 회의록 확정 전/후 Todo 수정 기능 추가<br>- 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br>- 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- 09-Todo관리, 11-회의록수정 화면에서 수정 가능 | | 2.0.2 | 2025-10-23 | 강지수, 도그냥 | Todo 수정 기능 추가 (UFR-TODO-040)<br>- 회의록 확정 전/후 Todo 수정 기능 추가<br>- 권한별 수정 범위: 담당자(본인 Todo만), 회의 생성자(모든 Todo)<br>- 수정 항목: 제목, 담당자, 마감일, 우선순위<br>- 09-Todo관리, 11-회의록수정 화면에서 수정 가능 |
| 2.0.3 | 2025-10-23 | 강지수 (Product Designer) | 회의록 수정 항목 정책 명확화 (UFR-MEET-055)<br>- 회의 일시/장소: readonly 처리 (회의 예약 화면에서만 변경 가능)<br>- 참석자 관리: 회의 생성자만 추가/삭제 가능 (11-회의록수정 화면에서 직접 관리)<br>- 참석자 UI: 05-회의진행 화면과 동일한 방식으로 구현<br>- 프로토타입: 11-회의록수정.html에 참석자 관리 섹션 추가 | | 2.0.3 | 2025-10-23 | 강지수 (Product Designer) | 회의록 수정 항목 정책 명확화 (UFR-MEET-055)<br>- 회의 일시/장소: readonly 처리 (회의 예약 화면에서만 변경 가능)<br>- 참석자 관리: 회의 생성자만 추가/삭제 가능 (11-회의록수정 화면에서 직접 관리)<br>- 참석자 UI: 05-회의진행 화면과 동일한 방식으로 구현<br>- 프로토타입: 11-회의록수정.html에 참석자 관리 섹션 추가 |
| 2.0.4 | 2025-10-23 | 강지수 (Product Designer) | 검증완료 섹션 잠금해제 정책 단순화<br>- **정책 변경**: 검증완료 섹션은 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)<br>- **제거**: 참석자용 잠금해제 요청 기능 완전 제거 (공수 절감)<br>- UFR-MEET-055: 권한 제어 명확화 (생성자만 잠금 해제 가능)<br>- UFR-COLLAB-030: 섹션 잠금 기능 설명 업데이트<br>- 프로토타입 11-회의록수정.html: 잠금해제요청 버튼 제거, 검증완료 섹션 읽기 전용 표시 |
| 2.0.5 | 2025-10-23 | 강지수 (Product Designer), 도그냥 (Service Planner) | Todo 및 회의록 관련 요구사항 재정의<br>- **UFR-TODO-040 (09-Todo관리)**: "Todo수정" → "Todo관리" 기능 확장<br> - 통계 블록 재정의: 전체(미완료), 마감임박(3일 이내), 지연(기한 경과)<br> - 필터링: 전체, 지연, 마감임박, 완료 (각 필터에 개수 표시)<br> - 체크박스 확인 모달: 완료/미완료 전환 시 확인<br> - 권한: 담당자 본인 OR 회의록 작성자만 편집 가능<br>- **UFR-MEET-047 (10-회의록상세조회)**: 탭 순서 및 기본 노출 변경<br> - 탭 구성: 대시보드 / 회의록<br> - 기본 노출: 대시보드 탭 우선 노출 (기존: 회의록 우선)<br>- **UFR-MEET-055 (11-회의록수정)**: 진입 경로 및 권한 제어 명확화<br> - 진입 경로: 10-회의록상세조회 → "수정" 버튼 클릭<br> - 권한 제어: 검증완료 전(모든 참석자), 검증완료 후(회의 생성자만)<br> - 회의 일시/장소: 읽기 전용 표시 명시 |
--- ---

View File

@ -0,0 +1,123 @@
# 백엔드 서비스 실행 프로파일 가이드
## 개요
HGZero 프로젝트의 모든 백엔드 서비스를 IntelliJ IDEA에서 실행할 수 있는 실행 프로파일을 생성했습니다.
## 생성된 실행 프로파일
### 1. UserApplication
- **포트**: 8080
- **데이터베이스**: userdb (20.214.121.121:5432)
- **Redis 데이터베이스**: 0
- **메인 클래스**: `com.unicorn.hgzero.user.UserApplication`
- **모듈**: user
- **로그 파일**: logs/user.log
### 2. NotificationApplication
- **포트**: 8084
- **데이터베이스**: notificationdb (4.230.159.143:5432)
- **Redis 데이터베이스**: 4
- **메인 클래스**: `com.unicorn.hgzero.notification.NotificationApplication`
- **모듈**: notification
- **로그 파일**: logs/notification.log
### 3. AiApplication
- **포트**: 8083
- **데이터베이스**: aidb (20.249.153.213:5432)
- **Redis 데이터베이스**: 4
- **메인 클래스**: `com.unicorn.hgzero.ai.AiApplication`
- **모듈**: ai
- **로그 파일**: logs/ai.log
### 4. SttApplication
- **포트**: 8082
- **데이터베이스**: sttdb (4.230.65.89:5432)
- **Redis 데이터베이스**: 2
- **메인 클래스**: `com.unicorn.hgzero.stt.SttApplication`
- **모듈**: stt
- **로그 파일**: logs/stt.log
## 환경 변수 설정
각 서비스별로 다음 환경 변수들이 설정되어 있습니다:
### 공통 환경 변수
- `JWT_SECRET`: 각 서비스별 개발용 JWT 시크릿 키
- `CORS_ALLOWED_ORIGINS`: http://localhost:*
- `SHOW_SQL`: true (개발용)
- `DDL_AUTO`: update (개발용)
- `LOG_LEVEL_APP`: DEBUG
- 기타 로깅 레벨 설정
### 서비스별 특화 환경 변수
#### AI 서비스
- `AZURE_OPENAI_API_KEY`: OpenAI API 키가 설정됨
- `AZURE_OPENAI_ENDPOINT`: https://api.openai.com/v1
- `AZURE_OPENAI_DEPLOYMENT`: gpt-4o
- `AZURE_OPENAI_EMBEDDING_DEPLOYMENT`: text-embedding-3-large
#### Notification 서비스
- `MAIL_HOST`: smtp.gmail.com
- `MAIL_PORT`: 587
- `NOTIFICATION_FROM_EMAIL`: noreply@hgzero.com
- `NOTIFICATION_FROM_NAME`: HGZero
#### STT 서비스
- `AZURE_SPEECH_REGION`: eastus
- `AZURE_SPEECH_LANGUAGE`: ko-KR
- `AZURE_BLOB_CONTAINER_NAME`: recordings
#### User 서비스
- `LDAP_URLS`: ldaps://ldap.example.com:636
- `LDAP_BASE`: dc=example,dc=com
## 실행 방법
### IntelliJ IDEA에서 실행
1. IntelliJ IDEA에서 프로젝트 열기
2. Run/Debug Configurations 에서 원하는 서비스 선택
3. Run 또는 Debug 모드로 실행
### 서비스 실행 순서 권장사항
1. **UserApplication** (8080) - 사용자 인증 서비스
2. **SttApplication** (8082) - 음성 인식 서비스
3. **AiApplication** (8083) - AI 처리 서비스
4. **NotificationApplication** (8084) - 알림 서비스
## 주의사항
### 데이터베이스 연결 설정
**현재 설정된 데이터베이스 비밀번호**: `hgzero123!`
- 모든 서비스가 동일한 데이터베이스 비밀번호를 사용하도록 설정되었습니다
- **HIBERNATE_DIALECT**가 `org.hibernate.dialect.PostgreSQLDialect`로 명시적으로 설정되어 연결 오류를 방지합니다
### 필수 설정이 필요한 환경 변수
다음 환경 변수들은 실제 운영 시 설정이 필요합니다:
- `REDIS_PASSWORD`: Redis 비밀번호 (필요시)
- `AZURE_SPEECH_SUBSCRIPTION_KEY`: Azure Speech 서비스 키 (STT 서비스)
- `AZURE_EVENTHUB_CONNECTION_STRING`: Event Hub 연결 문자열
- `AZURE_STORAGE_CONNECTION_STRING`: Azure Storage 연결 문자열
- `MAIL_USERNAME`, `MAIL_PASSWORD`: 이메일 발송용 계정 정보
### 포트 충돌 방지
- User: 8080
- STT: 8082
- AI: 8083
- Notification: 8084
모든 서비스가 서로 다른 포트를 사용하므로 동시 실행이 가능합니다.
## 로그 파일 위치
- 모든 로그는 프로젝트 루트의 `logs/` 디렉토리에 저장됩니다
- 각 서비스별 로그 파일:
- `logs/user.log`
- `logs/notification.log`
- `logs/ai.log`
- `logs/stt.log`
## 개발 환경 설정
- 모든 프로파일은 `dev` 프로파일로 설정됨
- SQL 로깅이 활성화되어 개발 중 디버깅 용이
- DDL 자동 업데이트로 스키마 변경 자동 반영

1440
logs/ai.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,6 @@ import org.springframework.context.annotation.ComponentScan;
public class UserApplication { public class UserApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(UserApplication.java, args); SpringApplication.run(UserApplication.class, args);
} }
} }