목표
원주 대상 계곡을 정하고, 계곡별로 쓸 강수·수위 관측소를 찾아 API로 데이터를 받을 수 있는지 확인한다. 이후 서버가 주기적으로 수집해 DB에 쌓는다.
A. 데이터 API 호출 확인
- 쓰는 데이터 API 전체
| 기관 | 용도 | 주소 | 형식 | 상태 |
|---|---|---|---|---|
| 한강홍수통제소 | 수위·유량 | waterlevel/list/10M·1H |
JSON | 10/31 확인 |
| 한강홍수통제소 | 강수량 | rainfall/list/10M·1H |
JSON | 10/31 확인 |
| 한강홍수통제소 | 관측소 제원 (기준 수위 4단계) | waterlevel/info.json |
JSON | 10/29 확인, 전체 목록은 잘림 |
| 기상청 API허브 | 관측 강수 (1분, RN_1HR 1시간 누적) | nph-flood_sfc_sts_pkg |
텍스트, disp=1이면 CSV | 10/29 확인 |
| 기상청 API허브 | 수치모델 강수 예보 | nph_flood_nwp_txt |
세로줄 구분 표 | 10/29 확인 |
- 기상청 확인한 것 (10/29)
- 키 하나로 활용신청한 API 전부 사용 (관측-통계 묶음형, 수치모델, 일통계)
- 관측은 약 4분 지연 → 수집은 '현재−5분' 기준
- 결측값
-99.9→ 0이 아니라 판정 불가로 처리 - 수치모델
tm·tmef는 UTC, 6시간 간격 - 원주 관측소
stn=114
- 한강홍수통제소 관측소 제원에 4단계 기준 수위가 있음:
attwl(관심) /wrnwl(주의) /almwl(경보) /srswl(심각). 위경도는 도-분-초 문자열 - 보류: 기상청 레이더 추정강수(신청 페이지 없음), 산림청 산악기상(계곡 정한 뒤 필요하면)
- VM
yeoulmok에서 한강홍수통제소 API를 직접 호출해 강수량·수위 데이터가 오는지 확인- 키 불러오기:
set -a; source ~/secrets/yeoulmok.env; set +a
- 키 불러오기:
- 강수량 관측소 목록 (같은
HRFCO_KEY로 열림 → 강수량 API도 사용 가능 확인)
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/info.json" | head -c 600
- 관측소 번호
rfobscd, 이름obsnm, 주소addr·etcaddr, 위경도lon·lat(도-분-초 문자열) - 수위 최신값 (10분 단위)
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/waterlevel/list/10M.json" | head -c 600
{ "wlobscd" : "1001603", "ymdhm" : "202610311150", "wl" : "0.16", "fw" : "0.05" }
wl: 수위(m),fw: 유량(m³/s). 유량은 빈칸(" ")인 관측소가 있음 → 0이 아니라 '없음'으로 처리- 11:59에 조회했는데 시각이 11:50 → 약 10분 늦게 들어옴. 시각은 한국시간
- 강수량 최신값 (10분 단위)
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/list/10M.json" | head -c 400
rf: 10분 강수량(mm)- 관측소 하나만 지정해서 부르기
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/waterlevel/list/10M/1006664.json"
- 응답이 작아서 잘리지 않음 → 서버 수집은 이 방식으로 함 (트러블슈팅 1번 참고)
- 과거 자료 조회:
list/{단위}/{번호}/{시작}/{끝}.json- 10분(
10M)은 12자리yyyymmddhhmm, 1시간(1H)은 10자리yyyymmddhh(트러블슈팅 2번 참고) - 결과를 시각·값만 보기 좋게 출력
- 10분(
P='import sys,json;[print(x["ymdhm"],x.get("wl",x.get("rf"))) for x in reversed(json.load(sys.stdin)["content"])]'
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/list/1H/10064070/2025071900/2025071923.json" | python3 -c "$P"
B. 원주 관측소 찾기
- 관측소 전체 목록을 파일로 받아 주소에 '원주'가 들어간 것만 골라내려 했으나 응답이 중간에 잘림 (트러블슈팅 1번 참고)
- 강수량: 잘린 파일 안에 원주 관측소가 들어 있어서
grep으로 찾음
curl -s -o rf_info.json "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/info.json"
grep -B2 -A4 "obsnm.*원주" rf_info.json
| 번호 | 이름 | 위치 |
|---|---|---|
| 10024240 | 원주시(황둔리) | 신림면 황둔리 |
| 10054010 | 원주시(법천교) | 부론면 법천교 |
| 10064010 | 원주 | 원주시 |
| 10064050 | 원주시(지정면사무소) | 지정면 |
| 10064060 | 원주시(문막교) | 문막읍 |
| 10064070 | 원주시(서곡초교) | 판부면 용수골길 서곡초등학교 |
| 10064075 | 원주시(신촌리) | 판부면 신촌리 |
| 10064090 | 원주시(흥양초교) | 소초면 |
- 수위: 잘린 파일엔 부론면 남한강 본류 2곳(법천교, 남한강대교)뿐이라 계곡 경보엔 못 씀
- 본류: 강의 가장 큰 줄기. 계곡 물은 작은 지류를 거쳐 들어옴
- 한강홍수통제소 홈페이지 → 수문 → 실시간 수문자료 → 수위 자료에서 원주 수위 관측소 11곳 확인
- 가현교, 남한강대교, 동부교, 문막교, 법천교, 봉미교, 옥산교, 원주교, 장현교, 지정대교, 판됀2교
- 관측소 팝업의 엑셀 다운로드로 주소, 팝업 주소창의
obscd로 번호 확인- 예:
wlpopup.do?obscd=1006664→ 동부교
- 예:
| 번호 | 이름 | 주소 | 해발 | 10/31 12:00 수위 |
|---|---|---|---|---|
| 1006664 | 원주시(동부교) | 반곡동(단구동) 동부교 | 151m | 0.08m, 유량 없음 |
| 1006665 | 원주시(원주교) | 봉산동 원주교 | 120m | 0.27m, 유량 0.43 |
- 두 번호 모두 API로 호출해 홈페이지 값과 같은 것 확인
C. 대상 계곡과 사고일 데이터
- 네이버 지도로 계곡 물이 어느 수위 관측소를 지나는지 확인
- 동부교로 오는 원주천은 금대리 → 판부면 → 동부교 방향(중앙고속도로를 따라)으로 내려옴
- 서곡리 개울은 서곡초 서쪽을 지나 북쪽으로 가지만 동부교 줄기가 아님
- 서곡리 물(서곡천)은 섬강 수계로, 흥업면 사제리 사제교를 지나 호저면 만종리 쪽으로 흐름 (강원일보 기사 기준). 원주 시내 원주천 위 동부교·원주교는 안 지남
- 수계: 물이 모여 같은 큰 강으로 흘러가는 하천 묶음
- 대상 계곡 2곳으로 정함 (신청서의 '계곡 2~3곳'과 맞음)
| 계곡 | 상류 강수 | 하류 수위 | 비고 |
|---|---|---|---|
| 금대리 계곡 | 원주시(신촌리) 10064075 |
원주시(동부교) 1006664 |
물이 동부교로 바로 내려옴 |
| 서곡리 계곡 | 원주시(서곡초교) 10064070 |
없음 | 2025-07-19 고립 사고 지점. 상류 강수 사전 경보만 |
- 서곡리 하류 수위 후보 3곳 주소 확인 (홈페이지 팝업 엑셀)
| 번호 | 이름 | 주소 | 판단 |
|---|---|---|---|
| 1006677 | 원주시(판대2교) | 지정면 판대리 | 섬강 본류 쪽, 서곡천 아님 |
| 1006672 | 원주시(장현교) | 호저면 신현리 | 방향은 맞지만 15km 이상 하류, 유량 5.42로 큰 물이 합쳐진 지점 |
| 1006670 | 원주시(옥산교) | 호저면 옥산리 | 방향은 맞지만 너무 멀어서 경보에 의미 없음 |
- 결정 방향: 서곡리는 상류 강수 사전 경보만, 하류 수위 즉시 경보는 금대리만 (회의에서 확정)
- 사고일(2025-07-19) 1시간 자료 조회
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/list/1H/10064070/2025071900/2025071923.json" | python3 -c "$P"
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/list/1H/10064075/2025071900/2025071923.json" | python3 -c "$P"
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/waterlevel/list/1H/1006664/2025071900/2025071923.json" | python3 -c "$P"
- 서곡초교 강수 (mm/시간)
03시 1 04시 12 05시 11 06시 1 07시 8 08시 11
10시 2 12시 1 19시 4 21시 4 23시 1 (나머지 0)
하루 약 56mm, 새벽~아침에 몰림
- 신촌리 강수, 동부교 수위: 그날 24시간 전부 결측
- 결측: 관측소가 그 시각 값을 못 보내서 비어 있는 것
- 동부교는 어제(10/30)와 올해 7월 자료는 정상 → 사고일만 기록이 없거나 설치가 그 뒤일 가능성. 언제부터 있는지는 미확인
- 기준값 정리
- 상류 강수 기준(X): 서곡초교 사고일 값으로 1차 설정 가능
- 하류 수위 기준(Y): 사고일 자료가 없어서 다른 강우일 기록이나 관측소 공식 기준 수위로 정해야 함 → 컨설팅 1회차 질문
D. 위치정보 법적 절차
- 기준은 서버가 개인위치정보를 받느냐
- 개인위치정보: 특정 사람이 어디 있는지 알 수 있는 위치 정보
- 개인위치정보를 다루는 위치기반서비스는 신고 필요 (담당: 방송미디어통신위원회, 예전 방송통신위원회)
- 개인위치정보를 다루지 않으면 신고 의무 폐지. 보호조치·누설 금지 등 일부 규정은 그대로 적용
- 여울목 기능별 판단
| 기능 | 서버가 사람 위치를 받나 | 판단 |
|---|---|---|
| 앱 근처 계곡(GPS) | 폰 안에서만 계산하면 안 받음 | 부담 적음 |
| 앱 계곡 구독 알림 | 계곡 이름만 받음 | 부담 적음 |
| 웹 실시간 사용자 수 | 받음 | 신고·약관·동의 필요 가능성 높음 |
| 웹 공무원 직접 알림 | 받음 | 신고·약관·동의 필요 가능성 높음 |
- 결정 방향: GPS는 폰 안에서만 쓰고 서버로 보내지 않음. 웹의 실시간 사용자 수·공무원 알림은 후순위
- 근거 기사가 2015년이라 이후 개정 여부는 컨설팅 때 확인
- 참고: 비즈한국 기사
트러블슈팅
1. 관측소 전체 목록 API 응답이 중간에 잘림
- 증상 :
waterlevel/info.json,rainfall/info.json을 받아 파이썬으로 읽으면 JSONDecodeError - 확인한 것 : 받은 파일 끝이 문장 중간에서 끊김. 헤더는 200,
Transfer-Encoding: chunked. 압축·HTTP/1.0으로 다시 받아도 해결 안 됨 - 원인 : 서버가 큰 목록을 끝까지 보내지 않음 (우리 쪽 문제 아님)
- 해결 : 원주 관측소는 홈페이지 실시간 수문자료에서 찾고, 팝업 주소의
obscd로 번호 확인. 운영은 번호를 지정해서 부르므로 응답이 작아 영향 없음 - 재발 방지 : 관측소 목록은 전체 API에 의존하지 않고, 쓸 관측소 번호를 DB에 고정해 둔다
2. 1시간 자료 조회에서 값이 전부 비어 나옴
- 증상 : 동부교 1시간 자료를 여러 날짜로 조회했는데 값이 전부 빈칸이거나 에러
- 확인한 것 : 날짜를 12자리(분 포함)로 넣었음. 10자리로 다시 조회하니 최근 값은 정상
- 원인 : 1시간 자료는 날짜를 10자리(
yyyymmddhh)로 넣어야 함 - 해결 : 10자리로 다시 조회. 그래도 2025-07-19는 결측이라 실제로 기록이 없는 것으로 확인
- 재발 방지 : 10분은 12자리, 1시간은 10자리. 빈 결과가 나오면 형식부터 확인
남은 작업
- 한강홍수통제소 강수량·수위 API 호출 확인
- 원주 대상 계곡 2곳과 관측소 매칭
- 사고일(2025-07-19) 과거 데이터 확인
- 동부교 수위 기록이 언제부터 있는지 확인
- 하류 수위 기준(Y) 정할 다른 강우일 찾기
- 서곡리 하류 수위 관측소 찾기 → 쓸 만한 곳 없음, 강수 경보만 (회의에서 확정)
- 위치정보 관련 법적 절차 1차 확인 (이후 개정 여부는 컨설팅 때)
- DB 설계와 수집 코드
배운 점
직접 작성A. 데이터 API 호출 확인
set -a; source ~/secrets/yeoulmok.env; set +a # API 키를 환경변수로 불러옴
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/waterlevel/list/10M/1006664.json" # 동부교 최신 수위 (10분 단위)
curl -s "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/list/1H/10064070/2025071900/2025071923.json" # 서곡초교 사고일 강수 (1시간 단위)
{ "wlobscd": "1006664", "ymdhm": "202610311200", "wl": "0.08", "fw": " " }
- 목적 : 코드 짜기 전 정부 API가 진짜 데이터를 주는지 확인
- 설명
- 사용하는 API
- 한강홍수통제소 —> 수위 (물높이) + 강수 (2개의 API)
- 기상청 —> 관측 강수랑 강수 예보
- 주소 읽는 법 —> 틀리면 404 에러
- waterlevel (수위)
- list : 값 목록
- 10M : 10분 단위
- 1006664 : 관측 번호
- 날짜 자릿수가 다름 —> 틀리면 빈칸으로 나옴
- 10분 : 12자리 (202610311200) : 분까지
- 1시간 : 10자리 (2025071923) : 시까지
- 값이 약간 늦게 들어옴
- 한강홍수통제소 : 약 10분
- 기상청 : 약 4분
- 그래서 수집할 때 지금시간에서 10분 여유를 둬야 함
- 빈칸이 0이 아님
- "fw": "" 처럼 빈칸이거나 기상청 -99.9는 관측 못함의 의미
- 0으로 처리하면 비 안 오는 거로 착각해서 위험한데도 안전하다고 판단할 수 있음 → 판정 불가로 처리
- 관측소마다 공식 기준 수위가 존재
- 관심 → 주의 → 경보 → 심각
- curl : 터미널에서 주소에 접속해 응답 받아오는 명령어
- wl / fw / rf : 수위 (m) , 유량 (m³/s , 1초에 흐르는 물의 양) , 강수량 (mm)
- 결측 : 관측소가 그 시각 값을 못 보내 비어 있는 것
- 사용하는 API
B. 원주 관측소 찾기
curl -s -o rf_info.json "http://api.hrfco.go.kr/$HRFCO_KEY/rainfall/info.json" # 강수 관측소 전체 목록을 파일로 저장
grep -B2 -A4 "obsnm.*원주" rf_info.json # 이름에 '원주'가 들어간 것만 앞뒤 줄과 함께 출력
- 목적 : 원주 안에서 우리가 쓸 강수, 수위 관측소 번호 찾기
- 설명
- 전체 목록에서 원주만 골라내지 못 함. 중간에 짤라냄
- 정부 서버에서 큰 목록을 끝까지 보내지 않음
- 강수 관측소는 운 좋게 잘린 앞부분 원주 8곳 존재
- grep으로 골라냈고 , 그 중 서곡초교랑 신촌리 유의
- grep : 파일에서 특정 글자가 들어간 줄만 찾는 명령
- -B2 -A4 : 앞 2줄 뒤 4줄 같이
- grep : 파일에서 특정 글자가 들어간 줄만 찾는 명령
- grep으로 골라냈고 , 그 중 서곡초교랑 신촌리 유의
- 수위 관측소는 잘린 부분에 있어서 홈페이지에서 직접 찾음
- 실시간 수문 자료 → 수위에서 원주 11곳 찾음
- obscd = 1006664 같은 숫자로 번호를 알아냄
- obscd : 관측소 번호
- 번호 하나만 찍어서 부르면 잘리지 않음
- 응답이 작아서 잘리지 않음
- 실제 서버는 우리 관측소 몇 개만 번호로 부르니 운영에 문제 X
- 전체 목록에서 원주만 골라내지 못 함. 중간에 짤라냄
C. 대상 계곡과 사고일 데이터
| 계곡 | 상류 강수 | 하류 수위 |
|---|---|---|
| 금대리 | 신촌리 (10064075) | 동부교 (1006664) |
| 서곡리 | 서곡초교 (10064070) | X |
- 목적 : 경보를 낼 계곡 정하고 각 계곡에 어느 관측소 값 쓸지 짝 지음
- 설명
- 경보는 두 가지 데이터로 낸다.
- 상류에 비가 많이 몰려오면 곧 물이 불어나니깐 미리 알림 (강수)
- 하류 물이 실제로 빨리 차오르면 바로 알리기 (수위)
- 그래서 계곡마다 위쪽 강수 관측소 + 아래쪽 수위 관측소 짝이 필요
- 금대리는 짝이 맞지만 서곡리는 수위 짝이 없음
- 서곡리 물 (서곡천) 은 원주 시내를 지나지 않고 서쪽 (흥업→호저)로 빠짐
- 그래도 넣은 이유 : 실제 사고가 (2025.07.19)에 난 곳
- 강수기록도 남아있음
- 그래서 서곡리는 강수 경보만 하자고 제안
- 그래도 넣은 이유 : 실제 사고가 (2025.07.19)에 난 곳
- 서곡리 물 (서곡천) 은 원주 시내를 지나지 않고 서쪽 (흥업→호저)로 빠짐
- 사고일 기록 : 서곡초교 강수는 새벽 4~5시에 시간당 12,11mm (하루 약 56mm)
- 근데 신촌리 강수량이랑 동부교 수위는 그 날 기록이 통째로 비어있음
- 그래서 기준값은 반만 정할 수 있음
- 강수기준 X 는 사고일 값으로 1차로 잡을 수 있다
- 기준값 X : 상류 1시간 강수 기준
- 수위 기준 Y는 다른 비 온 날 기록이나 관측소 공식 기준으로 정해야
- 기준값 Y : 하류 30분 수위 상승폭 기준
- 강수기준 X 는 사고일 값으로 1차로 잡을 수 있다
- 그래서 기준값은 반만 정할 수 있음
- 근데 신촌리 강수량이랑 동부교 수위는 그 날 기록이 통째로 비어있음
- 경보는 두 가지 데이터로 낸다.
D. 위치정보 법적 절차
| 기능 | 서버가 사람 위치를 받나 | 부담 |
|---|---|---|
| 앱 근처 계곡 | 안 받음 (폰에서 계산) | 적음 |
| 앱 구독 알림 | 계곡 이름만 받음 | 적음 |
| 웹 실시간 사용자 수 | 받음 | 신고·동의 필요 |
| 웹 공무원 직접 알림 | 받음 | 신고·동의 필요 |
- 목적 : 위치를 다루는 기능 중 법적 절차 필요한 걸 미리 확인
- 설명
- 기준은 하나임
- 이 사람이 지금 어디에 있는지
- 받으면 위치기반 서비스 신고 (방송미디어통신위원회)랑 약관, 동의 필요
- 이 사람이 지금 어디에 있는지
- 근처 계곡은 폰에서 계산해서 피함
- 서버에서 계곡 위치만 주고 폰이 자기 위치랑 비교
- 기능은 같은데 위치가 서버로 안 가니 신고 대상이 아님
- 서버에서 계곡 위치만 주고 폰이 자기 위치랑 비교
- 웹 두 기능은 위치로 받아야 함
- 지금 계곡에 몇 명 있나를 알리려면 사람들 위치를 모아야함
- 근거 : 2015년 기사라 추후 법 바뀌었는지 확인 필요
- 기준은 하나임