Skip to content

Commit d9a1f02

Browse files
authored
docs: Symphony 테스트 워크플로 정리 (#240)
* docs: Symphony 테스트 워크플로 정리 * docs: 아키텍처 문서 및 시퀀스 다이어그램 보완
1 parent 44d40cd commit d9a1f02

7 files changed

Lines changed: 220 additions & 32 deletions

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
- [x] Label을 지정했나요?
2121

2222
## 🔗 관련 이슈
23-
23+
-
2424

2525
## 💬 기타 참고 사항

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,77 @@ Redis는 목적에 따라 Core Redis와 MQ Redis로 분리해 사용합니다.
179179
| `redis-core` | 6379 | 재고, 중복 신청, 대기열, 분산 락 |
180180
| `redis-mq` | 6380 | Redis Stream, 신청 처리 상태 |
181181

182+
## 시퀀스 다이어그램
183+
184+
### 선착순 신청 흐름
185+
186+
```mermaid
187+
---
188+
config:
189+
theme: redux-color
190+
themeCSS: |
191+
text.actor {
192+
font-size: 17px !important;
193+
}
194+
.messageText {
195+
font-size: 19px !important;
196+
}
197+
.note {
198+
fill: #f1f5f9 !important;
199+
stroke: #cbd5e1 !important;
200+
}
201+
.noteText {
202+
font-size: 17px !important;
203+
}
204+
.labelText {
205+
font-size: 17px !important;
206+
}
207+
.loopText {
208+
font-size: 17px !important;
209+
}
210+
---
211+
sequenceDiagram
212+
autonumber
213+
actor User
214+
participant API as API Server
215+
participant Core as Redis Core<br/>(Sorted Set)
216+
participant Consumer as Consumer Server
217+
participant Stream as Redis Stream
218+
participant DB as PostgreSQL / PostGIS
219+
220+
activate API
221+
User->>API: POST /lesson/apply
222+
API->>Core: 재고 선점 / 중복 확인 / 대기열 등록
223+
Note over API,Core: requestId는 Sorted Set Waiting Room에서 대기
224+
API-->>User: requestId 반환
225+
deactivate API
226+
227+
activate Consumer
228+
rect rgb(255, 242, 242)
229+
Note over Core,Stream: Admission 단계
230+
Consumer->>Core: 대기열 requestId dequeue
231+
Consumer->>Core: 상태변경: PROCESSING
232+
Consumer->>Stream: XADD 신청 메시지
233+
end
234+
Note over Consumer,Stream: 신청 메시지는 Redis Stream에 적재
235+
rect rgb(239, 246, 255)
236+
Note over Core,DB: Consumer 처리 단계
237+
Stream-->>Consumer: XREADGROUP
238+
Consumer->>DB: DB 반영
239+
Consumer->>Core: 상태변경: SUCCESS / FAIL
240+
end
241+
deactivate Consumer
242+
243+
loop requestId polling
244+
activate API
245+
User->>API: GET /lesson/apply/{requestId}
246+
API->>Core: 상태 조회
247+
Core-->>API: WAITING / PROCESSING / SUCCESS / FAIL
248+
API-->>User: 현재 상태 응답
249+
deactivate API
250+
end
251+
```
252+
182253
## 배포 자동화
183254

184255
배포는 GitHub Actions, S3, CodeDeploy를 사용합니다.

WORKFLOW.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
tracker:
3+
kind: linear
4+
api_key: $LINEAR_API_KEY
5+
project_slug: "ai-test-workflow-94d799fcd978"
6+
required_labels:
7+
- ai-test-workflow
8+
active_states:
9+
- Backlog
10+
- Todo
11+
- Research
12+
- Planning
13+
- Approved
14+
- In Progress
15+
- In Review
16+
- Rework
17+
terminal_states:
18+
- Done
19+
- Closed
20+
- Cancelled
21+
- Canceled
22+
- Duplicate
23+
polling:
24+
interval_ms: 5000
25+
workspace:
26+
root: ~/code/symphony-workspaces/trainus
27+
hooks:
28+
after_create: |
29+
git clone --branch develop https://github.com/prgrms-web-devcourse-final-project/WEB5_7_3star_BE.git .
30+
agent:
31+
max_concurrent_agents: 1
32+
max_turns: 8
33+
codex:
34+
command: codex --model gpt-5.4-mini --config model_reasoning_effort="high" --config shell_environment_policy.inherit=all app-server
35+
approval_policy: never
36+
thread_sandbox: workspace-write
37+
turn_sandbox_policy:
38+
type: workspaceWrite
39+
networkAccess: true
40+
---
41+
42+
너는 Linear 이슈 `{{ issue.identifier }}`를 작업하고 있다.
43+
44+
이 파일은 실행 설정과 공통 지시만 담는다. 세부 역할, 승인 기준, 테스트 경계는 이슈 본문과 `docs/ai-test-workflow/rules/*.md`에서 정한다.
45+
46+
산출물 경로:
47+
- Researcher: `docs/ai-test-workflow/reports/research-report.md`
48+
- Planner: `docs/ai-test-workflow/reports/test-plan.md`
49+
- Reviewer: `docs/ai-test-workflow/reports/review-report.md`
50+
- 공통 로그: `docs/ai-test-workflow/logs/prompt-and-tool-log.md`
51+
52+
이슈 정보:
53+
- 식별자: {{ issue.identifier }}
54+
- 제목: {{ issue.title }}
55+
- 현재 상태: {{ issue.state }}
56+
- 라벨: {{ issue.labels }}
57+
- URL: {{ issue.url }}
58+
59+
설명:
60+
{% if issue.description %}
61+
{{ issue.description }}
62+
{% else %}
63+
설명이 없습니다.
64+
{% endif %}
65+
66+
참조 문서:
67+
- `docs/ai-test-workflow/rules/agent-roles.md`가 있으면 읽는다.
68+
- `docs/ai-test-workflow/rules/human-approval-policy.md`가 있으면 읽는다.
69+
- `docs/ai-test-workflow/rules/test-boundary.md`가 있으면 읽는다.
70+
- 근거가 부족할 때는 임의로 만들지 말고, 부족한 근거를 기록한 뒤 가능한 범위의 분석만 계속한다.
71+
72+
출력 규칙:
73+
- 이슈 결과, 리포트 파일, 로그 항목, Linear 코멘트, 최종 응답은 모두 한국어로 작성한다.
74+
- 코드 식별자, 파일 경로, 클래스명, 메서드명, 명령어, 예외명은 원문 그대로 유지한다.
75+
76+
작업 원칙:
77+
1. Linear 이슈를 작업의 단일 기준으로 삼는다.
78+
2. 이슈 본문에 적힌 역할과 범위를 따른다.
79+
3. 이슈 범위를 벗어나지 않는다.
80+
4. 이슈에 사람 승인이 필요하면, 요청된 리포트 또는 계획만 만든 뒤 멈춘다.
81+
5. Implementer 역할이 명시되고 승인이 완료되지 않으면 운영 코드를 수정하지 않는다.
82+
6. 이슈가 워크플로 증거를 요구하면 `docs/ai-test-workflow/logs/prompt-and-tool-log.md`에 프롬프트/도구 사용 내역을 기록한다.
83+
7. 최종 응답에는 완료한 작업, 수정한 파일, 실행한 검증, 남은 블로커를 요약한다.
84+
8. 리포트를 작성할 때는 `목적, 확인한 근거, 발견 사항, 한계/블로커, 다음 단계`처럼 간결한 한국어 섹션을 우선 사용한다.
85+
86+
상태 전이:
87+
- `Backlog`: 아직 착수하지 않은 이슈다.
88+
- `Todo`: 작업 대기 상태다.
89+
- `Research`: 저장소 근거를 조사하는 단계다.
90+
- `Planning`: 계획을 정리했고 사람 승인을 기다리는 단계다. 이 상태에서는 구현을 시작하지 않는다.
91+
- `Approved`: 사람이 승인했고 구현을 시작할 수 있는 단계다. 이 상태에서만 Implementer가 동작한다.
92+
- `In Progress`: 승인된 범위 안에서 구현 중인 단계다.
93+
- `In Review`: 구현이 끝났고 결과를 검토하는 단계다. 이 상태에서는 Reviewer만 검토를 수행한다.
94+
- `Rework`: 검토 결과 수정이 필요한 단계다. 이 상태에서는 같은 범위만 다시 수정한다.
95+
- `Done`: 최종 수용이 끝난 상태다.
96+
97+
워크플로 메모:
98+
- PR, 커밋, 리포트, 로그 같은 산출물은 상태가 아니라 작업 결과로 다룬다.
99+
- Linear 상태는 작업의 진행 단계만 표현하고, 세부 산출물은 리포트/로그 문서로 남긴다.
100+
- PR 본문이 필요하면 `.github/PULL_REQUEST_TEMPLATE.md`의 항목 순서와 제목을 그대로 따라 작성한다.
101+
- PR 본문은 자유 서술로 대체하지 말고, 작업 개요 / 작업 내용 / PR 유형 / Check List / 관련 이슈 / 기타 참고 사항 항목을 빠짐없이 채운다.
102+
- PR의 `관련 이슈`에는 GitHub 이슈 목록을 확인한 뒤 실제 이슈 번호를 `#123` 형식으로 적는다.
30.3 KB
Loading

docs/architecture/trainus-architecture-async-processing.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@
1313
"ranksep": "1.3",
1414
}
1515

16+
node_attr = {
17+
"fontsize": "19",
18+
"margin": "0.20",
19+
}
20+
21+
edge_attr = {
22+
"fontsize": "20",
23+
}
24+
25+
cluster_attr = {
26+
"fontsize": "22",
27+
}
28+
1629

1730
with Diagram(
1831
"TrainUs Architecture - Async Processing",
@@ -21,29 +34,31 @@
2134
outformat="png",
2235
direction="LR",
2336
graph_attr=graph_attr,
37+
node_attr=node_attr,
38+
edge_attr=edge_attr,
2439
):
2540
client = ALB("Client / ALB")
2641

27-
with Cluster("API Server"):
42+
with Cluster("API Server", graph_attr=cluster_attr):
2843
api = EC2("API Server\n(api profile)")
2944

30-
with Cluster("Redis Core"):
45+
with Cluster("Redis Core", graph_attr=cluster_attr):
3146
core = Redis("Redis Core\nstock / duplicate")
3247

33-
with Cluster("Consumer Server - Admission"):
48+
with Cluster("Consumer Server - Admission", graph_attr=cluster_attr):
3449
admission = EC2("Consumer Server\n(admission dequeue)")
3550
stream = Redis("Redis Stream\nlesson:apply:stream")
3651

37-
with Cluster("Consumer Server"):
52+
with Cluster("Consumer Server", graph_attr=cluster_attr):
3853
consumer = EC2("Consumer Server\n(batch insert)")
3954

40-
with Cluster("Database"):
55+
with Cluster("Database", graph_attr=cluster_attr):
4156
db = PostgreSQL("PostgreSQL / PostGIS")
4257

43-
client >> Edge(label="apply request") >> api
44-
api >> Edge(label="duplicate / stock check") >> core
45-
core >> Edge(label="dequeue requestIds") >> admission
46-
admission >> Edge(label="SET PROCESSING + XADD") >> stream
47-
stream >> Edge(label="XREADGROUP batch") >> consumer
48-
consumer >> Edge(label="batch insert") >> db
49-
consumer >> Edge(label="XACK / XDEL", dir="back") >> stream
58+
client >> Edge(label="apply request", fontsize="20") >> api
59+
api >> Edge(label="duplicate / stock check", fontsize="20") >> core
60+
core >> Edge(label="dequeue requestIds", fontsize="20") >> admission
61+
admission >> Edge(label="SET PROCESSING + XADD", fontsize="20") >> stream
62+
stream >> Edge(label="XREADGROUP batch", fontsize="20") >> consumer
63+
consumer >> Edge(label="batch insert", fontsize="20") >> db
64+
consumer >> Edge(label="XACK / XDEL", dir="back", fontsize="20") >> stream
67.9 KB
Loading

docs/architecture/trainus-architecture.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,27 @@
2222
}
2323

2424
node_attr = {
25-
"fontsize": "18",
26-
"margin": "0.14",
25+
"fontsize": "19",
26+
"margin": "0.20",
2727
}
2828

2929
edge_attr = {
30-
"fontsize": "15",
30+
"fontsize": "20",
3131
}
3232

3333
cluster_attr = {
3434
"margin": "20",
35-
"fontsize": "18",
35+
"fontsize": "22",
3636
}
3737

3838
instance_cluster_attr = {
3939
"margin": "8",
40-
"fontsize": "15",
40+
"fontsize": "22",
4141
}
4242

4343
asg_cluster_attr = {
4444
"margin": "15",
45-
"fontsize": "18",
45+
"fontsize": "24",
4646
}
4747

4848
with Diagram(
@@ -79,7 +79,7 @@
7979
width="1.42",
8080
height="0.28",
8181
fixedsize="true",
82-
fontsize="15",
82+
fontsize="19",
8383
)
8484
api_app_n = Node(
8585
"Spring Boot",
@@ -88,7 +88,7 @@
8888
width="1.42",
8989
height="0.28",
9090
fixedsize="true",
91-
fontsize="15",
91+
fontsize="19",
9292
)
9393
api_ec2_n - api_app_n
9494

@@ -113,7 +113,7 @@
113113
width="1.42",
114114
height="0.28",
115115
fixedsize="true",
116-
fontsize="15",
116+
fontsize="19",
117117
)
118118
consumer_app_n = Node(
119119
"Spring Boot",
@@ -122,7 +122,7 @@
122122
width="1.42",
123123
height="0.28",
124124
fixedsize="true",
125-
fontsize="15",
125+
fontsize="19",
126126
)
127127
consumer_ec2_n - consumer_app_n
128128

@@ -135,15 +135,15 @@
135135
alb >> Edge(minlen="2") >> api_ec2_1
136136
alb >> Edge(minlen="2") >> api_ec2_n
137137

138-
api_app_1 >> Edge(label="apply request") >> redis_core
139-
api_app_1 >> Edge(label="poll status") >> redis_mq
140-
api_app_1 >> Edge(label="read/write", color="darkgreen") >> postgres
138+
api_app_1 >> Edge(label="apply request", fontsize="20") >> redis_core
139+
api_app_1 >> Edge(label="poll status", fontsize="20") >> redis_mq
140+
api_app_1 >> Edge(label="read/write", color="darkgreen", fontsize="20") >> postgres
141141

142-
redis_core >> Edge(label="admit") >> consumer_app_1
143-
consumer_app_1 >> Edge(label="XREAD / ACK") >> redis_mq
144-
consumer_app_1 >> Edge(label="batch insert") >> postgres
142+
redis_core >> Edge(label="admit", fontsize="20") >> consumer_app_1
143+
consumer_app_1 >> Edge(label="XREAD / ACK", fontsize="20") >> redis_mq
144+
consumer_app_1 >> Edge(label="batch insert", fontsize="20") >> postgres
145145

146-
prometheus << Edge(label="metrics", style="dashed") << [api_app_1, consumer_app_1]
146+
prometheus << Edge(label="metrics", style="dashed", fontsize="20") << [api_app_1, consumer_app_1]
147147

148-
codedeploy >> Edge(label="deploy api", color="blue", style="dashed", constraint="false") >> api_ec2_1
149-
codedeploy >> Edge(label="deploy consumer", color="blue", style="dashed", constraint="false") >> consumer_ec2_1
148+
codedeploy >> Edge(label="deploy api", color="blue", style="dashed", constraint="false", fontsize="20") >> api_ec2_1
149+
codedeploy >> Edge(label="deploy consumer", color="blue", style="dashed", constraint="false", fontsize="20") >> consumer_ec2_1

0 commit comments

Comments
 (0)