Skip to content

TR 응답 블록 파싱 예외로 데이터가 조용히 유실되던 문제 수정 - #2

Open
qudgus3822 wants to merge 2 commits into
odumag99:mainfrom
qudgus3822:main
Open

TR 응답 블록 파싱 예외로 데이터가 조용히 유실되던 문제 수정#2
qudgus3822 wants to merge 2 commits into
odumag99:mainfrom
qudgus3822:main

Conversation

@qudgus3822

@qudgus3822 qudgus3822 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📝 요약

  • TR 응답 파싱 중 예외가 나면 그 블록이 큐에 들어가지 못하고 통째로 사라지던 문제를 고쳤습니다. 조회 결과가 경고 한 줄 없이 일부만 도착하는 실패 모드였습니다.
  • 반복(배열) 블록에서 한 행이 깨져도 나머지 행은 살리도록 행 단위로 예외를 격리했습니다.
  • 서버가 준 데이터 길이가 구조체 정의와 안 맞을 때(nLen % struct_size != 0) ERROR 로그를 남깁니다.

실계좌에서 주문/체결 조회(s8180) 결과가 일부만 들어오는 것을 추적하다 발견했습니다.


⚠️ 문제 상황

1. 파싱 예외 = 블록 증발 (가장 심각)

Received._auto_parse()에서 난 예외는 위로 올라가다 WMCAAgent._wnd_proc()except Exception에서 삼켜집니다. 윈도우 프로시저는 예외를 밖으로 내보내면 안 되니 삼키는 것 자체는 맞는데, 문제는 삼킨 뒤에 벌어지는 일입니다.

_handle_wmca_event()
  └ parse_outdatablock()  ← 여기서 예외
  └ self.message_queue.put(...)  ← 실행되지 않음

message_queue.put()이 실행되지 않으므로 receive_events()를 도는 호출부는 그 블록을 영영 보지 못합니다. 호출부 입장에선 "데이터가 원래 없었다"와 구분할 방법이 없습니다. 로그는 메시지 처리 오류 한 줄뿐이라, 조회가 반쪽만 성공한 건지 정말 결과가 없는 건지 알 수 없었습니다.

2. 레코드 경계가 어긋나면 조용히 잘리고, 남은 행은 밀려 읽힘

_parse_array_internal()은 행 수를 occurs_count = nLen // struct_size로 구합니다. 구조체 정의가 서버가 보내는 레코드 길이와 1바이트라도 다르면:

  • 나눗셈이 내림이라 뒤쪽 행이 조용히 잘려나가고
  • 남은 행들도 한 칸씩 밀려 읽혀 전부 쓰레기 값이 됩니다

쓰레기 행은 상위 필터(종목코드 없음 / 수량 0 등)에 걸려 자연스럽게 사라지므로, 겉으로는 그냥 "일부만 조회됐다"로만 보입니다. 원인을 짚을 단서가 전혀 없습니다.

3. 한 행이 깨지면 블록 전체가 날아감

배열 파싱 루프에 방어가 없어, 한 행에서 예외가 나면 그 블록 전체(TR에 따라 반복 최대 15~20건)가 함께 사라졌습니다.


💡 해결 방안 및 근거

structures/common.py

  • _auto_parse(): 파싱을 try/except로 감싸고, 실패하면 szData원본 bytes 그대로 반환합니다.
    • 이미 "파서 미등록" 경우에 bytes를 반환하는 기존 동작이 있고, 호출부들도 isinstance(block.szData, bytes)로 방어하고 있습니다. 그 경로를 재사용하므로 인터페이스 변화 없이 "조용한 증발"만 "눈에 보이는 경고"로 바뀝니다.
    • 예외를 그대로 두면 블록이 사라지지만, bytes로 내려주면 최소한 블록 자체는 호출부까지 도착합니다.
  • _parse_array_internal(): 행 단위 try/except로 부분 성공을 허용합니다. 한 행이 깨졌다고 멀쩡한 나머지 행까지 버릴 이유가 없습니다.
  • _parse_array_internal(): nLen % struct_size != 0이면 ERROR 로그를 남깁니다. 구조체 정의와 서버 스펙이 어긋났다는 유일한 단서라서 반드시 남겨야 합니다.

wmca_agent.py

  • _wnd_proc()의 예외 로그에 "이 이벤트는 큐에 들어가지 못하고 유실됨"과 wparam을 함께 남깁니다. 이 줄이 찍혔다는 건 응답 일부가 유실됐다는 뜻인데, 기존 메시지로는 그 사실이 드러나지 않았습니다.

호환성

정상 경로의 동작은 그대로입니다. 예외가 나던 경로만 "증발" 대신 "bytes 반환 + 로그"로 바뀝니다. 공개 API 시그니처 변경 없음.


✅ 리뷰 체크리스트

  • 빌드 가능 여부 확인했나요?
  • 기존 기능에 영향이 없는지 확인했나요?

qudgus3822 and others added 2 commits July 31, 2026 11:33
- 파싱 실패 해결 : 체결가가 float(소수)로 넘어오는걸 파싱하지 못함 (분할 매수의 경우)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant