225 lines
21 KiB
Markdown
225 lines
21 KiB
Markdown
# C++ 모듈화와 공개 API 정리
|
|
|
|
기존 B33/MITC4 솔버의 모델·local 계산·assembly·procedure·backend·I/O 책임을 분리하고 공개 header의 vendor 의존을 격리한 리팩터링이다. 새 물리·입력·해법·결과 schema 또는 tolerance를 도입하는 기능이 아니다. 현재 재사용할 구조·CLI·I/O·수치 비교 계약은 [solver-core](../solver-core/README.md)에 모았다.
|
|
|
|
## 설계와 실제 데이터 흐름
|
|
|
|
[Domain](../../include/fesa/model/domain.h)은 의미 모델을 소유하고 [AnalysisModel](../../include/fesa/analysis/analysis_model.h)은 더 짧게 사는 non-owning view다. [DofManager](../../include/fesa/fem/dof_manager.h)는 equation·partition·pattern을 소유한다. [Element](../../include/fesa/elements/element.h)의 typed local contribution은 [SparseAssembler](../../src/fesa/assembly/sparse_assembler.cpp)에서 결정적 순서로 조립된다. [LinearStaticProcedureExecutor](../../include/fesa/analysis/linear_static_procedure.h)는 caller-owned 실행/선형해법 adapter를 참조하고 실행에 필요한 state만 만든다. [ResultRecovery](../../include/fesa/results/result_recovery.h)는 위치·단위·부호를 가진 결과를 복구하고 [HDF5 writer](../../src/fesa/io/hdf5/hdf5_results_writer.cpp)는 직렬화한다.
|
|
|
|
[FesaApplication](../../src/fesa/app/fesa_application.cpp)이 객체·lexical output path·lease·실행 수명을 조합한다. 공개 API는 `include/fesa/`, 구현은 대응 `src/fesa/`에 두며 vendor handle과 오류 번호는 private 수치/I/O adapter 뒤에 둔다. 공개 API 이름을 예전 `.hpp` 시절 표기로 복원하거나 parser에서 concrete numerical storage를 직접 소유하지 않는다. Polymorphic base의 public virtual destructor, 단독 소유의 unique_ptr·RAII, self-contained include guard와 source identity를 유지한다.
|
|
|
|
이 경계는 현재 eigen·dynamic·thermal·solid가 확장한 구조의 기반이다. 당시 static 리팩터링 성공을 나중에 추가된 모든 절차의 재검증으로 해석하지 않는다. 특히 trial/commit과 파일 final replacement는 다른 실패 경계다. 내부 accepted frame이 있어도 전체 해석이 실패하면 미완성 정상 final을 공개하지 않는다.
|
|
|
|
## 보존한 입력·출력과 비교 의미
|
|
|
|
CLI는 입력 `.inp` 하나, lexical sibling HDF5·log, warning/오류 진단과 exit 의미를 유지했다. B33는 node·element endpoint·section point를, MITC4는 instance/node·element/point identity를 보존한다. 같은 node에 모인 endpoint action을 평균하거나 physical shell strain에 numerical drilling 값을 섞지 않는다. 정적 schema0·canonical frame0의 mandatory dataset·dtype·shape는 리팩터링 편의를 위해 바꾸지 않는다.
|
|
|
|
현재 수치 비교는 common family의 row5%·RMS1% 및 identity/finite 사전검사를 따른다. 과거 리팩터링 보고서에는 B33 `absolute_floor+1e-6*reference_scale`와 S4 fixed absolute1e-5로 수행한 당시 비교가 있다. B33176/176행, S4294/294행 통과 기록은 그 옛 기준·revision의 evidence이며 현재 common policy로 다시 판정한 결과가 아니다. Beam stress는 당시 Abaqus 외부 비교 N/A였고 analytical/unit·HDF5 schema evidence와 구분한다.
|
|
|
|
## 교훈과 검증 한계
|
|
|
|
- Naming·format·header guard·Doxygen와 dependency 경계를 정리해도 displacement만으로 stress/reaction·수명·실패 보존이 증명되지는 않는다. Header 변경은 대응 src consumer까지 함께 확인한다.
|
|
- Dense 크기 곱 overflow는 할당 전에 확인한다. Public API의 Status/Result와 backend exception 변환은 원래 실패 의미를 보존해야 한다.
|
|
- 상속된 환경 변수가 검사 실패의 원인이었던 사례가 있다. 환경 오류와 solver 결함을 구분한다. Formatter의 변경 유무와 native exit, link 성공과 runtime DLL 준비를 따로 판단한다.
|
|
- 과거 실행 절차를 현재 실행 계획으로 복원하지 않는다. CTest와 별도 Python suite의 성공을 합치지 않는다.
|
|
|
|
이 문서 작업에서는 build/test를 실행하지 않았다. 당시 모듈화와 reference의 bounded 검증은 남기되 최신 전체 회귀·외부 배포 준비 완료를 선언하지 않는다. 현재 물리적 미해결 사항은 각 기능 README가 소유한다.
|
|
|
|
## Refactor 코드 채택 후 구조
|
|
|
|
2026-10-18 통합은 FESADev `7438c827` 이력에 Refactor `11f09eeb`의 제품 `.h/.cpp`
|
|
274개와 직접 MSVC 빌드를 선별 도입한다. 옛 구현을 섞는 호환 계층이나 새 정식화는 추가하지 않는다.
|
|
[파일 manifest](merge-manifest.json)는 원본 Git blob과 working bytes, 보존·도입 방침을 구분하고,
|
|
[테스트 이관표](test-migration.tsv)는 양쪽 기존 identity·assertion·oracle와 최종 위치를 연결한다.
|
|
|
|
- [AnalysisProcedure](../../include/fesa/analysis/analysis_procedure.h)와
|
|
[factory](../../src/fesa/analysis/prepared_analysis.cpp)는 shell linear/nonlinear static,
|
|
eigen, HHT, thermal과 solid static/frequency/HHT를 선택한다. 실행 수명은 호출자 adapter보다 짧다.
|
|
[PreparedAnalysisOutcome](../../include/fesa/analysis/prepared_analysis_outcome.h)은 family별
|
|
typed completed payload를 유지하고, [결과 dispatch](../../src/fesa/results/prepared_results_writer.cpp)는
|
|
검증된 payload를 해당 writer로 보낸다. 기존 schema·atomic finalize 의미는 유지한다.
|
|
- [Element capabilities](../../include/fesa/elements/element_capabilities.h)는 ShellTrialElement,
|
|
SolidTrialElement, ShellInertiaElement, ThermalElement, ShellReferenceElement를 분리한다.
|
|
Adapter는 immutable kernel을 빌리므로 kernel의 수명과 주소가 안정적이어야 한다.
|
|
Equation·accepted history는 요소에 두지 않는다. Local layout과 full response를 typed로 보존한다.
|
|
- [EquilibriumAlgorithm/EquilibriumStep](../../src/fesa/analysis/equilibrium_algorithm.h)는
|
|
iteration 순서와 procedure-local typed pending candidate를 분리한다. Algorithm은 candidate를
|
|
소유하거나 type-erase하지 않는다. Static은1, mechanical HHT는0에서 시작하는 inclusive 순서를 유지하고,
|
|
procedure의 검증·commit 경계가 accepted state를 바꾼다.
|
|
- [ShellHhtIntegrator](../../src/fesa/analysis/hht_reduced_integrator.h)는 predictor·rate 계산·
|
|
physical-rate 복원을 분리한다. Chart/root/solver와 callback은 동기 borrowed view이며
|
|
rate 출력 buffer는 호출자 소유로 입력·서로와 alias하지 않는다. `RunReducedHhtStep`은
|
|
predictor→pending endpoint→commit 순서만 조정하고 accepted history를 소유하지 않는다.
|
|
- [PARDISO Session](../../src/fesa/solvers/linear/pardiso_session.h)은 private factor/solve/release
|
|
수명을 공통화한다. 기존1×1 TLS 회피의 범위를 vendor 전체 해결로 확대하지 않는다.
|
|
[SparsePattern](../../include/fesa/math/sparse_pattern.h)은 CSR 값 구조이며 지속 backend cache가 아니다.
|
|
[SpMV](../../src/fesa/math/sparse_matrix.cpp)는 여전히 호출마다 변환 배열·값 복사·handle을 소유한다.
|
|
|
|
수식·적분·reduction 순서·cache 수명에 영향이 있는 도입 차이는 manifest에 따로 분류했다.
|
|
출처 일치·compile·테스트 통과만으로 수치 동등성을 선언하지 않으며 독립 수치 검토와
|
|
영향받은 analytical/invariant·물리·reference 검증을 별도로 수행한다.
|
|
|
|
## 이번 병합의 현재 검증 상태
|
|
|
|
T2/T3 단계에서 직접 MSVC와 CMake/Ninja의 Debug solver/CLI 및 세 테스트 target build가 완료됐다.
|
|
제품274개는 Refactor working bytes와 일치한다. 양쪽 실제 discovery는 unit849,
|
|
integration72, reference43으로 총964개이며 canonical identity가 일치한다.
|
|
당시 선별 실행은 CMake176개, Native15개, 합성 reference comparator28개,
|
|
Python145개가 failure/error/skip 없이 통과했다. 이는 전체964개 실행·실제 모델 비교 완료가 아니다.
|
|
근거는 작업 공간의 `.build/merge-verification/t2-20261018-01/`와
|
|
`t3-20261018-01/`에 있다. 원래 dev와 Refactor 저장소 및 기준자료는 보존했다.
|
|
|
|
2026-10-18 사용자 지시로 `reference/temp`는 검증에 사용하지 않는다. 정식 경로에 없는
|
|
`shellNL-meshfine`, `shellNL-meshfine_02`, `shellNL-meshfine-pressure` 자료는 복사·복원하지 않는다.
|
|
해당 실제 비교는 자료 미확보로 미완료이며 테스트를 skip 처리하거나 통과로 바꾸지 않는다.
|
|
전체 Debug 검증·독립 수치 검토·정식 자료 비교의 현재 진행은 아래 T5 중간 기록과 구분한다.
|
|
정리 전 필수 검증을 충족하지 못하면 테스트 삭제와 최종 병합 완료 판정을 진행하지 않는다.
|
|
T4 문서 갱신 자체로 build/test를 추가 실행하지 않았다.
|
|
|
|
### T5 최초 중간 snapshot — 2026-10-18 03:00 UTC, 이후 범위 변경 전 이력
|
|
|
|
2026-10-18에 전체 Native Debug 솔루션, CMake Debug configure/build와 Ninja dependency
|
|
검사를 새로 실행해 모두 exit0을 확인했다. 제품102 compile unit의 dependency가 유효하고,
|
|
양쪽 세 테스트 executable의 실제 identity는 unit849·integration72·reference43,
|
|
CTest964개로 일치한다. Public header111개는 각각 독립 TU로 private/vendor include 경로 없이
|
|
MSVC C++17 `/EHsc /W4 /WX /MDd /Zs` 검사를 통과했다. CLI·test의 네 runtime 디렉터리에서
|
|
DLL7개의 SHA256이 같다. 제품274개와 정식 reference32개 bytes도 중간 기록 전에 재확인했다.
|
|
`reference/temp`의12개 경로는 byte 검증 대상에서 제외했고 입력·CSV·결과를 사용하지 않았다.
|
|
|
|
Native unit 전체는 필터 없이 계속 실행 중이며 **전체 종료 코드와 XML은 아직 없다**.
|
|
중간 stdout에서 완료57개 identity를 관측했으며 다음 개별 검사는 새로 PASS 종료했다.
|
|
|
|
- `ReducedManufacturedControllerKeepsExactInitialOrbit`: 396862ms.
|
|
- `C08aRigidManufacturedOrbitReducedCoordinateTimeConvergence`: 7-grid, 7153515ms.
|
|
- `C08bInitialPhysicalSpectrumProbe`: 716ms.
|
|
- `PredictorStartCompletesPreviouslyFailingLumpedFreePlateGrid`: 539678ms.
|
|
|
|
현재 `C08bFreeFiniteRotationPlateSelfConvergenceAndPhysicalInvariants`의8-grid를 수행한다.
|
|
h=1/64·1/128·1/256·1/512·1/1024의 계산 요약이 생성됐으나 남은8192·16384·32768증분
|
|
fine-grid와 최종 시간수렴·물리 gate는 미완료다. 모든 grid의 총 증분수는57840이다.
|
|
CPU/RSS 상승이나 부분 로그를 전체 통과 근거로 삼지 않는다. Native 나머지 executable,
|
|
전체 CTest와 Python suite는 같은 직렬 큐에서 대기하며 임의 timeout·skip·필터를 추가하지 않았다.
|
|
|
|
Refactor 원본 밖 별도 source snapshot304개에서 Native Debug 기준 solver/CLI를 새로
|
|
빌드해 exit0과 DLL7개 일치를 확인했다. 정적5모델을 포함한 정식 입력11개에 대해 기준·Native·
|
|
CMake 실행물을 같은 scratch 입력 경로와 bytes에서 직렬 실행하고 schema·identity·각 field를
|
|
대조하는 후속 큐를 준비했다. **새 실제 모델 실행·비교는 아직 시작하지 않았다.** 보고서 JSON의
|
|
case·policy·quantity와 실제 exit를 확인하며, parity의 빈 결과·자료 부재·dtype 차이·불일치는
|
|
nonzero로 남긴다. Exact field assertion의 불일치를 새 물리 허용치 위반으로 승격하지 않고
|
|
출처·dtype·identity·rounding 차이를 분류한 뒤 기존 승인 기준과 대조한다. 임시 도구의 합성
|
|
증거 하한 검사9건은 솔버나 물리 검증 통과가 아니다. 빈 결과·자료 누락의 옛 false-green을
|
|
각각 exit0으로 재현하고 수정 후 exit1·exit2가 되는 것을 확인했다.
|
|
|
|
독립 수치 검토는 명백한 식 오류나 승인 기준 변경을 발견하지 못했으나 `CONCERNS`다.
|
|
inverse→factor solve·Jet·eigen whitening·paired 산술과 spatial RM 변환은 rounding graph에
|
|
영향이 있어 비트 보존을 가정하지 않는다. 특히 `hdf5_primitives.cpp`, dynamic/nonlinear HDF5
|
|
writer의 `J^T m=g` LU action은 T2 영향 routing 누락을 T5 manifest에 보충하고 finite-rotation
|
|
virtual-work·완전 inverse action·HDF5 reaction readback 검사 identity에 연결했다.
|
|
이 정적 검토를 실제 전체 실행·reference closure의 승인으로 해석하지 않는다.
|
|
|
|
정식 `shellNL-meshfine`·`shellNL-meshfine-pressure`는 자료 미확보로 미실행이고,
|
|
`shellNL-meshfine_02`는 자료 부재와 현재 comparator 연결 부재를 함께 남긴다.
|
|
Thermal 새 필수 reference 부재와 기존 NT11 diagnostic/nonblocking 불일치도 유지한다.
|
|
필수 gate를 충족하지 않았으므로 테스트 삭제·T6 진입·최종 병합 완료 판정을 진행하지 않는다.
|
|
|
|
중간 근거는 `.build/merge-verification/t5-20261018-01/before-prune/`에 있으며
|
|
`running-checkpoint.json`과 `progress.jsonl`이 실행 큐·PID·현재 관측을 보존한다.
|
|
파일 manifest의 `t5_before_prune_verification`은 이 중간 snapshot을 기록하며 T1/T2/T3 원필드는 보존했다.
|
|
|
|
|
|
### T5 사용자 승인 정적 범위 — 검증 완료, 제한 유지
|
|
|
|
사용자는 장시간 HHT 동해석 검증을 중단하고 정적 해석 검증 후 다음 단계로 진행하도록
|
|
범위를 변경했다. 위 최초 snapshot의 전체 큐·미완료 gate 설명은 당시 이력이다. 현재는
|
|
HHT·solid dynamic·eigen/frequency·transient thermal 실제 수치 실행을 유예하고 해당 테스트를
|
|
보존한다. 기존 전체 큐와 후속 watcher는 `user_cancelled_static_only`로 종료했으며,
|
|
부분 stdout·미생성 XML·취소 근거를 보존했다. 이를 수치 실패나 통과로 계산하지 않는다.
|
|
|
|
현재964개 identity를 source body·경로·행·SHA256에 대응시켜 정적·공통631개(unit555,
|
|
integration35, reference41)를 선택하고333개를 유예했다. 과거 정적553개는 분류 근거로만
|
|
읽었으며 그중11개를 유예하고 현재 추가 공통89개를 포함했다. 순수 SO3 미분·좌표변환,
|
|
mock 수명·dispatch, parser/mapping 및 합성 comparator 정책 검사는 포함하고 실제 비정적
|
|
procedure를 호출하는 검사는 제외했다. 선택표는 `before-prune/static-only/selection.json`에 있다.
|
|
|
|
새 직렬 실행은 Native·CMake의 선택631개, 명시적 목록 CTest631개 및 Python 합성·정책
|
|
검사다. 고유 C++ 검사 수는631개이며 실행 경로별 수를 합쳐 고유 검사 수로 보고하지 않는다.
|
|
Native·CMake 각631개 및 CTest631개가 실제 exit0·skip0으로 확인됐다. Native/CMake의
|
|
unit555·reference41은 처음 실행에서 통과했고 integration35는 아래 환경 대조 후 전부 통과했다.
|
|
CTest JUnit의 실제 이름을 canonical identity로 역매핑해 선택631개와 누락·중복0을 확인했다.
|
|
Python 합성·정책145개도 exit0·failure/error/skip0이며 실제 비정적 물리 검증으로 세지 않는다.
|
|
정식 정적5모델도 fresh Refactor 기준·통합 Native·통합 CMake에서 같은 scratch 입력 bytes/경로로
|
|
총15번 실행했고 등록 비교15개·보고서 검증15개·schema/identity/field parity5개가 모두 exit0이다.
|
|
추가 정식 shellNL 자료의 부재와 `_02` comparator 연결 부재는 미완료로 유지하며, 확보된
|
|
정적 범위의 gate가 충족되면 다음 단계로 진행할 수 있다는 사용자 지시를 따른다.
|
|
|
|
임시 parity 도구의0길이 dataset만 있는 파일 false-green도 실제 exit0으로 재현했다.
|
|
필수 inventory와 파일 전체의 비어있지 않은 data 검사를 추가한 도구는 같은 경우 exit1,
|
|
의미있는 합성 동일값 exit0·불일치 exit1을 보였다. 개별0길이 dataset은 허용한다.
|
|
이는 임시 도구 검증이며 제품 물리·reference 통과를 대신하지 않는다. 현재 근거 경로는
|
|
`.build/merge-verification/t5-20261018-01/before-prune/static-only/run-20261018-01/`이다.
|
|
|
|
|
|
정적 모델의 beam은 U/UR·RF/RM·section actions6가족212행, shell은 U blocking·UR warning-only
|
|
2가족294행을 기존 기준으로 비교했다. ShellNL은 translation blocking·rotation warning-only와
|
|
내부 force/moment balance·accepted free residual을 통과했다. RF/RM3가족의 수치 비교는
|
|
**false/review-only**로 보존하며 stress mapping은 여전히 미판정이다. Hex8 선형·비선형 정적은
|
|
각 Step-1/increment10의 U(length)·RF(force)·S(force/length²)를 원본 CSV·source identity와
|
|
기존5%/1% 기준으로 비교했다. 개별 quantity/frame/policy·원본/실행물/결과 hash 및 literal
|
|
argv/cwd/env는 manifest와 raw `final-static-summary.json`·각 closed execution record에 있다.
|
|
|
|
초기 Native/CMake integration에서는 같은 application 검사1개가 각각 output-busy로 실패했다.
|
|
Native 실패 lock 경로261자, CMake260자였으며 동일 Native exe·동일 identity에서 TMP/TEMP만
|
|
바꾼 대조가 긴 경로 exit1→짧은 task-owned 경로 exit0을 보였다. 짧은 고유 TMP에서 양쪽
|
|
integration35개 전체를 다시 실행해 identity35·exit0·failure/error/skip0을 확인했다. 원래
|
|
실패 XML/log와 최초 큐 aggregate exit1은 환경/경로 한계로 보존했다. 제품·테스트·허용치는
|
|
바꾸지 않았다. 모델 input/result/lock 길이도 사전 확인했으며 최대193자다.
|
|
|
|
독립 정적 수치 보충 검토는 `CONCERNS / required_static_missing=false`다. 선택631개의
|
|
정적 수치 필수 coverage 누락은 발견하지 못했으며, 이를 RF/RM·stress mapping 또는 유예
|
|
기능의 물리 승인으로 확대하지 않는다. 사용자 수정 범위의 정리 전 정적 gate는 충족했으므로
|
|
다음 단계로 진행할 수 있다. 비정적333개·누락 정식 fine/_02/pressure 비교·열해석 새 reference
|
|
부재와 기존 NT11 diagnostic 제한은 미완료로 유지한다. 테스트 정리·최종 병합은 아직 수행하지 않았다.
|
|
|
|
### T6 정적 범위 검사 정리 — 삭제 0개
|
|
|
|
[최종 정리 검토](test-cleanup-review.md)에 따라 검사·helper를 모두 보존했다.
|
|
실제 본문에서 public/private owner, 실패 뒤 출력·factor 보존, TLS·FP flags·비트 및
|
|
독립 frozen oracle의 경계가 달라 동등 대체를 입증하지 못했다. 폐기 구조만 검사한다고
|
|
확정할 근거도 없었다. 비정적333개와 자료 없는 fine/_02/pressure 관련 검사는 보존한다.
|
|
이관표2,876행의 원래12열은 그대로 두고 최종 판정·근거 연결3열만 추가했다.
|
|
|
|
검사 source·helper·양쪽 등록 변경이0이므로 문서 전용 정적 검토만 수행했다.
|
|
T6 raw `.build/merge-verification/t6-20261018/`는 원셀 보존, 현재964개 body와 선택631개,
|
|
Native/CMake 등록·제품274개·T5 실행물/hash 보존을 확인한다. T5 당시 실행 결과를
|
|
새 실행으로 보고하지 않으며 전체964개 PASS도 주장하지 않는다. 최종 정적 검증과
|
|
병합 완료 판정은 T7에 남긴다.
|
|
|
|
|
|
### T7 최종 정적 검증과 근거 보존 — 통합 승인 전
|
|
|
|
이 절이 위의 최초 전체 실행 snapshot·T5/T6 진행 상태보다 최신이다. T6/T7에서 코드·검사·
|
|
helper·비교 도구·빌드 등록을 바꾸지 않았으므로 문서 전용 변경에 대한 지침에 따라 build/test와
|
|
모델을 반복 실행하지 않았다. 대신 T5 검증 commit `4841f122`와 최종 코드 상태 `4846206e`의
|
|
해당 입력 집합이 같음을 확인하고 실제 실행물·DLL·입력·결과의 hash를 대조했다. 이 확인을
|
|
통과한 **T5 실제 실행 근거를 재사용**하며 T7의 새 실행으로 세지 않는다.
|
|
|
|
새 정적 검토는 제품274개 Refactor bytes,964개 검사 body·631개 선택/333개 보존, 이관표
|
|
원셀·정리 판정, 양쪽 등록과 실행물, 성공 XML8개와 정적5모델×3실행물의 closed record15개·
|
|
전체50단계 exit0을 확인했다. Formulation23개와 상대 링크397개, 루트 AGENTS/CLAUDE 동일성,
|
|
원래 두 저장소 pin과 정식 reference32개를 확인했다. 최초 보호 목록55개 중 temp12개를
|
|
읽기·hash 대상에서 제외하고 나머지43개 원본·로그·설정·과거 계획을 대조했다.
|
|
삭제한 검사·helper는0개이며 전체964개 또는 유예333개를 통과로 보고하지 않는다.
|
|
|
|
원시 근거는 작업 worktree 정리 뒤에도 유지하도록 원래 FESADev root의
|
|
`.build/merge-verification/refactor-integration-final-20261018-01/`에 복사했다.
|
|
`archive-inventory.json`은 원래 절대 경로→보존 위치·SHA256·크기를 연결한다. Worker raw,
|
|
base의 문서/독립 수치 검토 raw, 실제 실행물9개·runtime DLL35개(5디렉터리×7개), 새로 빌드한
|
|
Refactor 기준 source304개 등1,379개 파일의 복사 hash를 확인했다. 기존 실패·중단·옛 임시 도구
|
|
기록도 포함하며 원본을 이동·삭제하거나 과거 argv/cwd를 다시 쓰지 않았다. 현재 근거는
|
|
`worker-raw/t7-20261018/final-static-state.json`과 `archive-integrity.json`에서 찾을 수 있다.
|
|
|
|
HHT 등 비정적 검증과 미확보 fine/_02/pressure 비교, ShellNL RF/RM false/review-only·응력
|
|
mapping 미판정, 열해석 reference/NT11 제한은 그대로 남는다. 승인된 정적 범위의 최종 상태를
|
|
확인했으며 독립 최종 검토와 사용자 통합 승인 후 원래 dev에 반영한다. 아직 원래 dev 병합·
|
|
원격 push를 수행하지 않았다.
|