Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e944770
feat: ์ฑ„ํŒ…๋ฐฉ ๋ฉค๋ฒ„ ๋ชฉ๋ก ์กฐํšŒ API ์ถ”๊ฐ€ (#549)
dh2906 Apr 15, 2026
4441d1e
test: ChatRoomMembershipService ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ๋ณด๊ฐ• (#551)
dh2906 Apr 15, 2026
1d03fba
chore: ๋กค๋ง ๋กœ๊ทธ gzip ์••์ถ• ์ ์šฉ (#552)
dh2906 Apr 16, 2026
1e289f1
fix: ClaudeClient ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ study_time ํ…Œ์ด๋ธ” ํžŒํŠธ ๊ตฌ์ฒดํ™”
JanooGwan Apr 16, 2026
5da8880
fix: show tables ์„ ํ–‰ ์กฐํšŒ ์›์น™ ์ถ”๊ฐ€ ๋ฐ ์ค„ ๊ธธ์ด 120์ž ์ œํ•œ ์ค€์ˆ˜
JanooGwan Apr 16, 2026
845049c
fix: JaCoCo ์ œ์™ธ ๋ชฉ๋ก์— claude, mcp ์ธํ”„๋ผ ํด๋ผ์ด์–ธํŠธ ์ถ”๊ฐ€
JanooGwan Apr 16, 2026
f1c0dab
fix: ๋ฉ”์‹œ์ง€ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— unreadCount, isMuted ํ•„๋“œ ์ถ”๊ฐ€ (#555)
Soundbar91 Apr 16, 2026
1029a93
fix: ์™„๋ฃŒ๋œ SSE emitter ์ „์†ก ์˜ˆ์™ธ๋ฅผ ์ •๋ฆฌํ•˜๋„๋ก ์ฒ˜๋ฆฌ (#556)
dh2906 Apr 16, 2026
a9f5e01
chore: ๋ชจ๋‹ˆํ„ฐ๋ง ์Šคํƒ ์ œ๊ฑฐ (#557)
dh2906 Apr 16, 2026
83ff829
[codex] ๋กœ๊ทธ ์ถ”์  ์ƒ๊ด€๊ด€๊ณ„๋ฅผ ์ •๋ฆฌํ•˜๊ณ  OTel ํ”์ ์„ ์ œ๊ฑฐ (#558)
dh2906 Apr 20, 2026
64df724
fix: ์ฑ„ํŒ…๋ฐฉ ๋งˆ์ง€๋ง‰ ๋ฉ”์‹œ์ง€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋™๊ธฐํ™” (#559)
dh2906 Apr 21, 2026
d915d84
chore: .gitignore ํ•ญ๋ชฉ ์ถ”๊ฐ€
dh2906 Apr 21, 2026
a6879e6
docs: ์ฑ„ํŒ… ๋„๋ฉ”์ธ ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ ๋ฐ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ ๋ณด๊ฐ• (#562)
dh2906 Apr 22, 2026
cdc858f
docs: ๋™์•„๋ฆฌ ๋„๋ฉ”์ธ ๊ฐ€์ด๋“œ ๋ฌธ์„œ ์ž‘์„ฑ (#563)
dh2906 Apr 22, 2026
0e2e4a8
fix: ์šด์˜ ํ™˜๊ฒฝ์—์„œ Swagger๋ฅผ ๋น„ํ™œ์„ฑํ™” (#565)
dh2906 Apr 24, 2026
ad8eef5
hotfix: DB ํ…Œ์ด๋ธ”์— comment ์ถ”๊ฐ€ ๋ฐ ClaudeClient ํ”„๋กฌํ”„ํŠธ ๊ฐœ์„ 
JanooGwan Apr 24, 2026
81ba8ab
docs: ์œ ์ € ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#568)
dh2906 Apr 24, 2026
d71e808
docs: ์ˆœ๊ณต ์‹œ๊ฐ„ ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#570)
dh2906 Apr 25, 2026
b7da0ab
docs: ์•Œ๋ฆผ ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#571)
dh2906 Apr 25, 2026
65ae8f7
docs: ๊ณต์ง€ ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#572)
dh2906 Apr 25, 2026
bc98f3a
refactor: ์Šค์ผ€์ค„๋Ÿฌ ์ •๋ฆฌ
JanooGwan Apr 26, 2026
e6f4317
docs: ๋ฌธ์˜ ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#576)
dh2906 Apr 27, 2026
991454e
docs: ์ผ์ • ๋„๋ฉ”์ธ ์ •์ฑ… ๊ฐ€์ด๋“œ ์ถ”๊ฐ€ (#575)
dh2906 Apr 27, 2026
f4c8028
chore: Copilot ๋ฆฌ๋ทฐ ์ง€์นจ์„ KONECT ๊ธฐ์ค€์œผ๋กœ ๊ตฌ์ฒดํ™” (#578)
dh2906 Apr 27, 2026
69c5de4
test: ๋ฌธ์˜๋ฐฉ ๊ฒ€์ƒ‰ ๊ธฐ์ค€์„  ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ (#585)
dh2906 Apr 27, 2026
4550eb4
refactor: ๋ฉ”์‹œ์ง€ ๊ฒ€์ƒ‰ ์กฐํšŒ๋ฅผ QueryRepository๋กœ ๋ถ„๋ฆฌ (#586)
dh2906 Apr 27, 2026
21b5c62
refactor: ๊ด€๋ฆฌ์ž ๋ฌธ์˜๋ฐฉ ๋ชฉ๋ก ์กฐํšŒ๋ฅผ QueryRepository๋กœ ๋ถ„๋ฆฌ (#587)
dh2906 Apr 27, 2026
097fd5d
refactor: ์ฑ„ํŒ…๋ฐฉ ์„ค์ • ํ•ฉ์„ฑ ์ฑ…์ž„ ๋ถ„๋ฆฌ (#588)
dh2906 Apr 27, 2026
3bc3f4e
refactor: ๋ชฉ๋ก ์กฐํšŒ ๋งˆ์ง€๋ง‰ ๋ฉ”์‹œ์ง€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ™œ์šฉ (#591)
dh2906 Apr 27, 2026
abbc6ff
refactor: ์™ธ๋ถ€ ํ˜ธ์ถœ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ์ถ•์†Œ
JanooGwan Apr 27, 2026
12fc544
refactor: ๋ฉ”์‹œ์ง€ ์กฐํšŒ ํŽ˜์ด์ง€ ๊ณ„์‚ฐ ์ฑ…์ž„ ๋ถ„๋ฆฌ (#593)
dh2906 Apr 27, 2026
38eebb3
refactor: direct room ์ ‘๊ทผ ๋ณต์› ์ฑ…์ž„ ๋ถ„๋ฆฌ (#595)
dh2906 Apr 28, 2026
09e60b1
chore: DB ๋ฐฑ์—…์„ SSM ๋ช…๋ น ์‹คํ–‰ ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ
JanooGwan Apr 28, 2026
aef886c
refactor: ์ดˆ๋Œ€ ํ›„๋ณด ์กฐํšŒ ์ฑ…์ž„ ๋ถ„๋ฆฌ (#602)
dh2906 Apr 28, 2026
f663bc7
refactor: ๋ฉ”์‹œ์ง€ ์ „์†ก ์ฑ…์ž„ ๋ถ„๋ฆฌ (#604)
dh2906 Apr 28, 2026
dba0ed5
refactor: ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ ์žฌ์‚ฌ์šฉ ์ฑ…์ž„ ๋ถ„๋ฆฌ (#605)
dh2906 Apr 28, 2026
fc51a1a
refactor: ์ฑ„ํŒ…๋ฐฉ ๋ฉค๋ฒ„ ๋ช…๋ น ์ฑ…์ž„ ๋ถ„๋ฆฌ (#609)
dh2906 Apr 28, 2026
bdc749b
refactor: ๋ฉ”์‹œ์ง€ ์กฐํšŒ ์‘๋‹ต ์กฐ๋ฆฝ ์ฑ…์ž„ ๋ถ„๋ฆฌ (#607)
dh2906 Apr 28, 2026
d33d0a2
refactor: ์ฑ„ํŒ…๋ฐฉ ์ ‘๊ทผ ๊ฒ€์ฆ ์ฑ…์ž„ ์ •๋ฆฌ (#608)
dh2906 Apr 28, 2026
6b4a3c5
chore: develop ๋ฐฐํฌ ๋นŒ๋“œ์—์„œ Java ์—์ด์ „ํŠธ ์˜ต์…˜ ์ œ๊ฑฐ
JanooGwan Apr 28, 2026
8a7ab35
chore: develop ๋ฐฐํฌ ๋นŒ๋“œ์—์„œ Java ์—์ด์ „ํŠธ ์˜ต์…˜ ์ œ๊ฑฐ
JanooGwan Apr 28, 2026
f2240c1
perf: ์š”์ฒญ ๋กœ๊น…์˜ ๋ถˆํ•„์š”ํ•œ ์บ์‹ฑ ๋น„์šฉ ์ œ๊ฑฐ
dh2906 Apr 28, 2026
626a0a2
feat: GROUP ์ฑ„ํŒ…๋ฐฉ ๋ฉค๋ฒ„ ์ดˆ๋Œ€ API ์ถ”๊ฐ€ (#619)
dh2906 Apr 29, 2026
c6b6dcc
fix: ์˜ˆ์ƒ ๋ชปํ•œ ์˜ˆ์™ธ์˜ ์š”์ฒญ ๋””๋ฒ„๊ทธ ๋กœ๊ทธ ์ •๋ ฌ (#617)
dh2906 Apr 29, 2026
91c8547
fix: ์–ด๋“œ๋ฏผ ๋ฌธ์˜๋ฐฉ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ ๋ฐฉํ–ฅ ์ˆ˜์ •
JanooGwan Apr 30, 2026
3903a53
docs: ์–ด๋“œ๋ฏผ ๋ฌธ์˜๋ฐฉ isMine ์‘๋‹ต ๊ณ„์•ฝ ๋ฌธ์„œํ™”
JanooGwan Apr 30, 2026
1b41743
fix: ์–ด๋“œ๋ฏผ ์ฑ„ํŒ…๋ฐฉ ๋‚ด ๋ฉ”์‹œ์ง€ ๋ฐฉํ–ฅ ๋ฒ„๊ทธ ์ˆ˜์ •
JanooGwan Apr 30, 2026
208e6e0
fix: ์š”์ฒญ ๋กœ๊ทธ ๋งค์นญ์„ ์œ„ํ•ด requestId๋ฅผ ๋ช…์‹œ (#621)
dh2906 May 4, 2026
c73509f
feat: ์›น์‚ฌ์ดํŠธ ๊ณต๊ฐœ ์ •๋ณด API ์ถ”๊ฐ€ (#623)
dh2906 May 14, 2026
c44a053
fix: ๊ณต๊ฐœ API ๊ฒฝ๋กœ๋ฅผ konect๋กœ ๋ณ€๊ฒฝ (#624)
dh2906 May 14, 2026
a378ea4
feat: ์›น์‚ฌ์ดํŠธ ๋Œ€ํ•™ ์‘๋‹ต์— ๋กœ๊ณ  URL ํฌํ•จ (#625)
dh2906 May 18, 2026
0ee35e4
feat: ๋Œ€ํ•™๊ต ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ target ์ถ”๊ฐ€ (#626)
dh2906 May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
!build/
!build/libs/
!build/libs/KONECT_API.jar
!opentelemetry-javaagent.jar
9 changes: 0 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,3 @@ CLAUDE_MODEL=claude-sonnet-4-20250514

# MCP Bridge Configuration
MCP_BRIDGE_URL=http://localhost:3100

# Tracing Configuration (OTel Java Agent -> Tempo)
JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar
OTEL_SERVICE_NAME=your-service-name
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=none
OTEL_LOGS_EXPORTER=none
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://your-monitoring-host:4318/v1/traces
62 changes: 61 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
Always respond in Korean.
# Copilot ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ง€์นจ

๋ชจ๋“  ๋ฆฌ๋ทฐ ์ฝ”๋ฉ˜ํŠธ๋Š” ํ•œ๊ตญ์–ด๋กœ ์ž‘์„ฑํ•œ๋‹ค.

## ๋ฆฌ๋ทฐ ์šฐ์„ ์ˆœ์œ„

- ์ •ํ™•์„ฑ, ๋ณด์•ˆ, ๊ถŒํ•œ ๊ฒ€์ฆ, ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ, ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„, API ์‘๋‹ต ๊ณ„์•ฝ, ๋™์‹œ์„ฑ ๋ฌธ์ œ, ํ…Œ์ŠคํŠธ ๋ˆ„๋ฝ์„ ์šฐ์„  ํ™•์ธํ•œ๋‹ค.
- ๋ณ€๊ฒฝ๋œ ์ฝ”๋“œ์—์„œ ์‹ค์ œ๋กœ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ๋ฌธ์ œ๋งŒ ์ง€์ ํ•œ๋‹ค. ๋‹จ์ˆœ ์ทจํ–ฅ, ์Šคํƒ€์ผ ์„ ํ˜ธ, ๊ด‘๋ฒ”์œ„ํ•œ ๋ฆฌํŒฉํ„ฐ๋ง, ๊ทผ๊ฑฐ๊ฐ€ ์•ฝํ•œ ์ถ”์ธก์€ ๋ฆฌ๋ทฐ ์ฝ”๋ฉ˜ํŠธ๋กœ ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
- ๋ณด์•ˆ ๊ด€๋ จ ๋ณ€๊ฒฝ์—์„œ๋Š” ์ธ์ฆ/์ธ๊ฐ€ ์šฐํšŒ, ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฒ€์ฆ ๋ˆ„๋ฝ, ๋ฏผ๊ฐ์ •๋ณด ๋…ธ์ถœ, ์šด์˜ ํ™˜๊ฒฝ ์„ค์ • ๋…ธ์ถœ ๊ฐ€๋Šฅ์„ฑ์„ ์šฐ์„  ํ™•์ธํ•œ๋‹ค.
- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณ€๊ฒฝ์—์„œ๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆœ์„œ, ๊ธฐ์กด ๋ฐ์ดํ„ฐ ํ˜ธํ™˜์„ฑ, nullable/default ์ฒ˜๋ฆฌ, ๋กค๋ฐฑ ๋‚œ์ด๋„, ์ธ๋ฑ์Šค ํ•„์š”์„ฑ์„ ํ™•์ธํ•œ๋‹ค.
- ์™ธ๋ถ€ API, OAuth, Slack, Claude, MCP, ํŒŒ์ผ ์ €์žฅ์†Œ์ฒ˜๋Ÿผ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๊ฒฐ๋˜๋Š” ์ฝ”๋“œ๋Š” ์žฅ์•  ์ „ํŒŒ, timeout, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ์„ค์ •๊ฐ’ ๋ˆ„๋ฝ ์‹œ ๋™์ž‘์„ ํ™•์ธํ•œ๋‹ค.

## ์‹ฌ๊ฐ๋„ ํŒ๋‹จ

- P0: ๋ฐ์ดํ„ฐ ์†์‹ค, ๋ณด์•ˆ ์ทจ์•ฝ์ , ์ธ์ฆ/์ธ๊ฐ€ ์šฐํšŒ, ์šด์˜ ์žฅ์• ์ฒ˜๋Ÿผ ๋ฐ˜๋“œ์‹œ ๋ณ‘ํ•ฉ ์ „์— ๊ณ ์ณ์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋งŒ ํ•ด๋‹นํ•œ๋‹ค.
- P1: ์ •์ƒ ์‚ฌ์šฉ ํ๋ฆ„์—์„œ ๊ธฐ๋Šฅ์ด ๊นจ์ง€๊ฑฐ๋‚˜ API ๊ณ„์•ฝ์ด ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ๊ธฐ์กด ๋ฐ์ดํ„ฐ์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๋‹ค.
- P2: ํŠน์ • ์กฐ๊ฑด์—์„œ ์žฌํ˜„๋˜๋Š” ๋ฒ„๊ทธ, ์„ฑ๋Šฅ ์ €ํ•˜, ์œ ์ง€๋ณด์ˆ˜ ์œ„ํ—˜, ํ…Œ์ŠคํŠธ ๊ณต๋ฐฑ์ฒ˜๋Ÿผ ์ˆ˜์ • ๊ฐ€์น˜๊ฐ€ ๋ถ„๋ช…ํ•œ ๋ฌธ์ œ๋‹ค.
- P3: ์˜ํ–ฅ์ด ์ž‘๊ณ  ์„ ํƒ์ ์ธ ๊ฐœ์„ ์ด๋‹ค. ๋‹จ์ˆœ ์ทจํ–ฅ์ด๋ฉด ์ฝ”๋ฉ˜ํŠธํ•˜์ง€ ์•Š๋Š”๋‹ค.
- nitpick์„ P0/P1์ฒ˜๋Ÿผ ๊ณผ์žฅํ•˜์ง€ ๋ง๊ณ , ๋ฌธ์ œ์˜ ์‹ค์ œ ์˜ํ–ฅ๊ณผ ์žฌํ˜„ ๊ฐ€๋Šฅ์„ฑ์— ๋งž์ถฐ ํŒ๋‹จํ•œ๋‹ค.

## ํ”„๋กœ์ ํŠธ ๊ด€๋ก€

- ์ด ์ €์žฅ์†Œ์˜ ๊ธฐ์กด Spring Boot, JPA, QueryDSL, Bean Validation, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ํ…Œ์ŠคํŠธ ํŒจํ„ด์„ ์šฐ์„  ๋”ฐ๋ฅธ๋‹ค.
- ์š”์ฒญ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์ถ”์ƒํ™”, ํ™•์žฅ ํฌ์ธํŠธ, ๋ฐฉ์–ด ์ฝ”๋“œ, unrelated cleanup์„ ์ œ์•ˆํ•˜์ง€ ์•Š๋Š”๋‹ค.
- Java ์ฝ”๋“œ์—์„œ import๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ FQCN(Full Qualified Class Name)์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ์ง€์ ํ•œ๋‹ค.
- ๊ธฐ์กด ์Šคํƒ€์ผ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ๊ฐ€ ์‹ค์ œ ์œ ์ง€๋ณด์ˆ˜ ์œ„ํ—˜์„ ๋งŒ๋“ค ๋•Œ๋งŒ ์ง€์ ํ•œ๋‹ค. ๋‹จ์ˆœํžˆ ๋‹ค๋ฅธ ์Šคํƒ€์ผ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ด์œ ๋กœ ์ฝ”๋ฉ˜ํŠธ๋ฅผ ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
- ๋„๋ฉ”์ธ๋ณ„ `AGENTS.md`๊ฐ€ ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” PR์—์„œ๋Š” ํ•ด๋‹น ๋ฌธ์„œ์˜ ์ •์ฑ…, ์—ญํ• , ์ƒ๋ช…์ฃผ๊ธฐ, ๋ถˆ๋ณ€์‹๊ณผ ๊ตฌํ˜„์ด ์–ด๊ธ‹๋‚˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- ๋ณ€๊ฒฝ ๋ฒ”์œ„ ๋ฐ–์˜ ์˜ค๋ž˜๋œ ์ฃฝ์€ ์ฝ”๋“œ, ์ด๋ฆ„ ๋ณ€๊ฒฝ, ํฌ๋งท ์ •๋ฆฌ๋Š” ํ˜„์žฌ PR์˜ ๋ฒ„๊ทธ๋‚˜ ํšŒ๊ท€์™€ ์ง์ ‘ ์—ฐ๊ฒฐ๋  ๋•Œ๋งŒ ์–ธ๊ธ‰ํ•œ๋‹ค.

## ์ฃผ์„ ๊ธฐ์ค€

- ์กฐ๊ฑด์ด 2๊ฐœ ์ด์ƒ ๊ฒฐํ•ฉ๋œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™, ๊ถŒํ•œ ์กฐ๊ฑด, soft delete ์ œ์™ธ, ์ค‘๋ณต ์ œ๊ฑฐ, fallback ์šฐ์„ ์ˆœ์œ„, ๋Œ€ํ‘œ๊ฐ’ ์„ ํƒ, DTO ๋ณ€ํ™˜, count ์ฟผ๋ฆฌ ๋ถ„๋ฆฌ, fetch join ์„ ํƒ ์ด์œ ์ฒ˜๋Ÿผ ์ฝ”๋“œ๋งŒ์œผ๋กœ ์˜๋„๊ฐ€ ์ˆจ๊ฒจ์ง€๋Š” ์ง€์ ์—๋Š” ์ฃผ์„์„ ๊ถŒ์žฅํ•œ๋‹ค.
- ์ฃผ์„์€ ์ฝ”๋“œ๊ฐ€ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€๋ณด๋‹ค ์™œ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ด์•ผ ํ•œ๋‹ค.
- ๋‹จ์ˆœ ์ƒ์„ฑ์ž ํ˜ธ์ถœ, ํ•„๋“œ ๋งคํ•‘, ์ปฌ๋ ‰์…˜ ๋ฐ˜ํ™˜, ์ด๋ฆ„๋งŒ์œผ๋กœ ๋ช…ํ™•ํ•œ ๋ถ„๊ธฐ์—๋Š” ์ฃผ์„์„ ์š”๊ตฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

## ํ…Œ์ŠคํŠธ ๊ธฐ์ค€

- ๋ฒ„๊ทธ ์ˆ˜์ •, ๊ฒ€์ฆ ๋กœ์ง, ๊ถŒํ•œ ์ •์ฑ…, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, API ์‘๋‹ต ๋ณ€๊ฒฝ, ํšŒ๊ท€ ์œ„ํ—˜์ด ์žˆ๋Š” ๋ณ€๊ฒฝ์€ ์‹คํŒจ๋ฅผ ์žฌํ˜„ํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋˜๋Š” ์ •์ฑ…์„ ๊ณ ์ •ํ•˜๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- ๋ฆฌํŒฉํ„ฐ๋ง PR์—์„œ๋Š” ์ƒˆ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ๋ณด๋‹ค ๊ธฐ์กด ๋™์ž‘์ด ์œ ์ง€๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- ํ…Œ์ŠคํŠธ๋Š” ๋™์ž‘๊ณผ ์ •์ฑ…์„ ๊ฒ€์ฆํ•ด์•ผ ํ•œ๋‹ค. private ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์—ฌ๋ถ€, ๋‚ด๋ถ€ ๊ตฌํ˜„ ์ˆœ์„œ, ๊ณผ๋„ํ•œ mock ํ˜ธ์ถœ ํšŸ์ˆ˜์ฒ˜๋Ÿผ brittleํ•œ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์„ ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š”๋‹ค.
- ์ด๋ฏธ ์ปจํŠธ๋กค๋Ÿฌ/์„œ๋น„์Šค/๋ ˆํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ํŒจํ„ด์ด ์žˆ๋Š” ์˜์—ญ์—์„œ๋Š” ๊ฐ™์€ ๊ณ„์ธต์˜ ๊ธฐ์กด ํ…Œ์ŠคํŠธ ์Šคํƒ€์ผ์„ ๋”ฐ๋ฅด๋„๋ก ์ œ์•ˆํ•œ๋‹ค.
- mock ํ˜ธ์ถœ ํšŸ์ˆ˜ ๊ฒ€์ฆ์€ ํ•ด๋‹น ํ˜ธ์ถœ ์ž์ฒด๊ฐ€ ์™ธ๋ถ€ ๋ถ€์ž‘์šฉ, ์ด๋ฒคํŠธ ๋ฐœํ–‰, ์ €์žฅ, ์•Œ๋ฆผ ์ „์†ก ๊ฐ™์€ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฒฐ๊ณผ์ผ ๋•Œ๋งŒ ์š”๊ตฌํ•œ๋‹ค.
- ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณต ๊ฒฝ๋กœ๋งŒ ํ™•์ธํ•˜๊ณ  ์‹คํŒจ/๊ถŒํ•œ/๊ฒฝ๊ณ„๊ฐ’์„ ๋†“์นœ ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ค ์ž…๋ ฅ์ด ๋น ์กŒ๋Š”์ง€ ๊ตฌ์ฒด์ ์œผ๋กœ ์ œ์•ˆํ•œ๋‹ค.

## KONECT ํŠนํ™” ์ฒดํฌํฌ์ธํŠธ

- ๊ถŒํ•œ ๋กœ์ง์€ ๊ด€๋ฆฌ์ž ์šฐํšŒ, ์š”์ฒญ์ž์™€ ๋Œ€์ƒ์ž ๊ด€๊ณ„, ํด๋Ÿฝ/์ฑ„ํŒ…๋ฐฉ/๊ณต์ง€/์ผ์ •์˜ ์†Œ์† ๊ฒ€์ฆ์ด ๋น ์ง€์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- soft delete, ํƒˆํ‡ด ์‚ฌ์šฉ์ž, ์ฐจ๋‹จ/์ œ์™ธ ์กฐ๊ฑด, ์ค‘๋ณต ์ œ๊ฑฐ๊ฐ€ ํ•„์š”ํ•œ ์กฐํšŒ์—์„œ๋Š” ์‘๋‹ต์— ๋…ธ์ถœ๋˜๋ฉด ์•ˆ ๋˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- DTO ์‘๋‹ต ๋ณ€๊ฒฝ์€ ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ํ•„๋“œ๋ช…, nullability, enum/string ๊ฐ’, ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ๊นจ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
- JPA/QueryDSL ์กฐํšŒ ๋ณ€๊ฒฝ์€ N+1, ์ž˜๋ชป๋œ fetch join, count ์ฟผ๋ฆฌ ์™œ๊ณก, pagination ๊นจ์ง, distinct ๋ˆ„๋ฝ์„ ํ™•์ธํ•œ๋‹ค.
- Flyway ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ํŒŒ์ผ๋ช… ๋ฒ„์ „ ์ˆœ์„œ, ๊ธฐ์กด ์šด์˜ ๋ฐ์ดํ„ฐ backfill, NOT NULL ์ถ”๊ฐ€ ์ˆœ์„œ, ๊ธฐ๋ณธ๊ฐ’ ์ฒ˜๋ฆฌ๊นŒ์ง€ ํ™•์ธํ•œ๋‹ค.
- ์šด์˜ ์„ค์ • ๋ณ€๊ฒฝ์€ prod/stage/local ํ”„๋กœํŒŒ์ผ ์ฐจ์ด, Swagger/OpenAPI ๋…ธ์ถœ, secret/env ๋ˆ„๋ฝ ์‹œ ์‹คํŒจ ๋ฐฉ์‹์„ ํ™•์ธํ•œ๋‹ค.

## ๋ฆฌ๋ทฐ ์ฝ”๋ฉ˜ํŠธ ์ž‘์„ฑ ๋ฐฉ์‹

- ๊ฐ€์žฅ ์ž‘์€ ๊ด€๋ จ ๋ผ์ธ ๋ฒ”์œ„์— ์ฝ”๋ฉ˜ํŠธ๋ฅผ ๋‹จ๋‹ค.
- ์ฒซ ๋ฌธ์žฅ์— ๋ฌธ์ œ์™€ ์˜ํ–ฅ์„ ๋ฐ”๋กœ ์“ฐ๊ณ , ๊ฐ€๋Šฅํ•˜๋ฉด `์ด ์ž…๋ ฅ/์ƒํƒœ์—์„œ ์ด๋Ÿฐ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚œ๋‹ค` ํ˜•ํƒœ๋กœ ์‹คํŒจ ๋ชจ๋“œ๋ฅผ ์„ค๋ช…ํ•œ๋‹ค.
- ์ˆ˜์ • ์ œ์•ˆ์€ ๊ฐ€์žฅ ์ž‘์€ ๋ณ€๊ฒฝ ๋‹จ์œ„๋กœ ์ œ์‹œํ•œ๋‹ค.
- ๋ฌธ์ œ๊ฐ€ ์—†์œผ๋ฉด ๊ตฌํ˜„์„ ๋‹ค์‹œ ์„ค๋ช…ํ•˜๋Š” ์ฝ”๋ฉ˜ํŠธ๋ฅผ ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
- ํ™•์‹ ์ด ๋‚ฎ์€ ๊ฒฝ์šฐ ๋‹จ์ •ํ•˜์ง€ ๋ง๊ณ  ์–ด๋–ค ์ „์ œ๊ฐ€ ๋งž์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š”์ง€ ๋ช…์‹œํ•œ๋‹ค.
- ๋ฆฌ๋ทฐ์–ด ์ œ์•ˆ์ด ๊ธฐ์กด ๋™์ž‘, ํ˜ธํ™˜์„ฑ, ์‚ฌ์šฉ์ž ๊ฒฐ์ •, YAGNI ์›์น™๊ณผ ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋ฌด์กฐ๊ฑด ์ˆ˜์ •ํ•˜๋ผ๊ณ  ํ•˜์ง€ ๋ง๊ณ  ํ™•์ธ ์งˆ๋ฌธ์ด๋‚˜ ๊ทผ๊ฑฐ ํ™•์ธ์œผ๋กœ ํ‘œํ˜„ํ•œ๋‹ค.
56 changes: 0 additions & 56 deletions .github/workflows/deploy-monitoring.yml

This file was deleted.

103 changes: 56 additions & 47 deletions .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branches:
- main

permissions:
contents: read
id-token: write

jobs:
deploy:
runs-on: ubuntu-latest
Expand All @@ -29,23 +33,6 @@ jobs:
restore-keys: |
gradle-${{ runner.os }}-

- name: Cache OpenTelemetry Java Agent
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/otel-java-agent
key: otel-agent-${{ runner.os }}-${{ vars.OTEL_JAVA_AGENT_VERSION }}-${{ vars.OTEL_JAVA_AGENT_SHA256 }}

- name: Prepare OpenTelemetry Agent
run: |
mkdir -p ~/.cache/otel-java-agent
if [ ! -f ~/.cache/otel-java-agent/opentelemetry-javaagent.jar ]; then
wget -O ~/.cache/otel-java-agent/opentelemetry-javaagent.jar \
"https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${{ vars.OTEL_JAVA_AGENT_VERSION }}/opentelemetry-javaagent.jar"
fi
# Verify checksum
echo "${{ vars.OTEL_JAVA_AGENT_SHA256 }} $HOME/.cache/otel-java-agent/opentelemetry-javaagent.jar" | sha256sum -c -
cp ~/.cache/otel-java-agent/opentelemetry-javaagent.jar .

- name: Grant execute permission for gradlew
run: chmod +x gradlew

Expand Down Expand Up @@ -85,38 +72,60 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
OTEL_JAVA_AGENT_VERSION=${{ vars.OTEL_JAVA_AGENT_VERSION }}

- name: Backup prod MySQL before deploy
uses: appleboy/ssh-action@v1.2.0
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@ff717079ee2060e4bcee96c4779b553acc87447c # v4
with:
host: ${{ secrets.DB_SERVER_IP }}
username: ${{ secrets.DB_SERVER_USER }}
key: ${{ secrets.DB_SERVER_SSH_KEY }}
port: ${{ secrets.DB_SERVER_PORT }}
script: |
set -euo pipefail
START_TIME=$(date +%s)

WORK_DIR="/home/ubuntu/konect/prod-db-compose"
MYSQL_CONTAINER="mysql-prod"

set -a
source "$WORK_DIR/.env"
set +a

BACKUP_DIR="$WORK_DIR/db-backups/"
mkdir -p "$BACKUP_DIR"

DUMP_FILE="$BACKUP_DIR/$(date '+%Y%m%d_%H%M%S').sql"
docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" "$MYSQL_CONTAINER" \
mysqldump --no-tablespaces -u"$MYSQL_USERNAME" "$MYSQL_DATABASE" > "$DUMP_FILE"

find "$BACKUP_DIR" -type f -name '*.sql' -mtime +5 -delete

END_TIME=$(date +%s)
echo "Prod MySQL backup completed in $((END_TIME - START_TIME))s"
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Backup prod MySQL before deploy
env:
DB_INSTANCE_ID: ${{ secrets.DB_INSTANCE_ID }}
run: |
set -euo pipefail

COMMAND_ID=$(aws ssm send-command \
--instance-ids "$DB_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--comment "KONECT prod MySQL backup before deploy" \
--parameters commands='[
"bash -lc '\''START_TIME=$(date +%s); bash /home/ubuntu/konect/prod-db-compose/backup-db.sh; END_TIME=$(date +%s); echo \"Prod MySQL backup completed in $((END_TIME - START_TIME))s\"'\''"
]' \
--query "Command.CommandId" \
--output text)

set +e
aws ssm wait command-executed \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID"
WAITER_EXIT=$?
set -e

BACKUP_STATUS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "Status" \
--output text)

BACKUP_STATUS_DETAILS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "StatusDetails" \
--output text)

BACKUP_RESPONSE_CODE=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "ResponseCode" \
--output text)

echo "Prod MySQL backup status: $BACKUP_STATUS (details: $BACKUP_STATUS_DETAILS, response-code: $BACKUP_RESPONSE_CODE)"

if [ "$WAITER_EXIT" -ne 0 ] || [ "$BACKUP_STATUS" != "Success" ] || [ "$BACKUP_RESPONSE_CODE" != "0" ]; then
echo "Prod MySQL backup failed. Remote stdout/stderr is intentionally not printed to avoid leaking sensitive information."
exit 1
fi

- name: Deploy to prod server
uses: appleboy/ssh-action@v1.2.0
Expand Down
103 changes: 56 additions & 47 deletions .github/workflows/deploy-stage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branches:
- develop

permissions:
contents: read
id-token: write

jobs:
deploy:
runs-on: ubuntu-latest
Expand All @@ -29,23 +33,6 @@ jobs:
restore-keys: |
gradle-${{ runner.os }}-

- name: Cache OpenTelemetry Java Agent
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/otel-java-agent
key: otel-agent-${{ runner.os }}-${{ vars.OTEL_JAVA_AGENT_VERSION }}-${{ vars.OTEL_JAVA_AGENT_SHA256 }}

- name: Prepare OpenTelemetry Agent
run: |
mkdir -p ~/.cache/otel-java-agent
if [ ! -f ~/.cache/otel-java-agent/opentelemetry-javaagent.jar ]; then
wget -O ~/.cache/otel-java-agent/opentelemetry-javaagent.jar \
"https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${{ vars.OTEL_JAVA_AGENT_VERSION }}/opentelemetry-javaagent.jar"
fi
# Verify checksum
echo "${{ vars.OTEL_JAVA_AGENT_SHA256 }} $HOME/.cache/otel-java-agent/opentelemetry-javaagent.jar" | sha256sum -c -
cp ~/.cache/otel-java-agent/opentelemetry-javaagent.jar .

- name: Grant execute permission for gradlew
run: chmod +x gradlew

Expand Down Expand Up @@ -85,38 +72,60 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
OTEL_JAVA_AGENT_VERSION=${{ vars.OTEL_JAVA_AGENT_VERSION }}

- name: Backup stage MySQL before deploy
uses: appleboy/ssh-action@v1.2.0
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@ff717079ee2060e4bcee96c4779b553acc87447c # v4
with:
host: ${{ secrets.DB_SERVER_IP }}
username: ${{ secrets.DB_SERVER_USER }}
key: ${{ secrets.DB_SERVER_SSH_KEY }}
port: ${{ secrets.DB_SERVER_PORT }}
script: |
set -euo pipefail
START_TIME=$(date +%s)

WORK_DIR="/home/ubuntu/konect/stage-db-compose"
MYSQL_CONTAINER="mysql-stage"

set -a
source "$WORK_DIR/.env"
set +a

BACKUP_DIR="$WORK_DIR/db-backups/"
mkdir -p "$BACKUP_DIR"

DUMP_FILE="$BACKUP_DIR/$(date '+%Y%m%d_%H%M%S').sql"
docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" "$MYSQL_CONTAINER" \
mysqldump --no-tablespaces -u"$MYSQL_USERNAME" "$MYSQL_DATABASE" > "$DUMP_FILE"

find "$BACKUP_DIR" -type f -name '*.sql' -mtime +5 -delete

END_TIME=$(date +%s)
echo "Stage MySQL backup completed in $((END_TIME - START_TIME))s"
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Backup stage MySQL before deploy
env:
DB_INSTANCE_ID: ${{ secrets.DB_INSTANCE_ID }}
run: |
set -euo pipefail

COMMAND_ID=$(aws ssm send-command \
--instance-ids "$DB_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--comment "KONECT stage MySQL backup before deploy" \
--parameters commands='[
"bash -lc '\''START_TIME=$(date +%s); bash /home/ubuntu/konect/stage-db-compose/backup-db.sh; END_TIME=$(date +%s); echo \"Stage MySQL backup completed in $((END_TIME - START_TIME))s\"'\''"
]' \
--query "Command.CommandId" \
--output text)

set +e
aws ssm wait command-executed \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID"
WAITER_EXIT=$?
set -e

BACKUP_STATUS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "Status" \
--output text)

BACKUP_STATUS_DETAILS=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "StatusDetails" \
--output text)

BACKUP_RESPONSE_CODE=$(aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$DB_INSTANCE_ID" \
--query "ResponseCode" \
--output text)

echo "Stage MySQL backup status: $BACKUP_STATUS (details: $BACKUP_STATUS_DETAILS, response-code: $BACKUP_RESPONSE_CODE)"

if [ "$WAITER_EXIT" -ne 0 ] || [ "$BACKUP_STATUS" != "Success" ] || [ "$BACKUP_RESPONSE_CODE" != "0" ]; then
echo "Stage MySQL backup failed. Remote stdout/stderr is intentionally not printed to avoid leaking sensitive information."
exit 1
fi

- name: Deploy to stage server
uses: appleboy/ssh-action@v1.2.0
Expand Down
Loading
Loading