본문 바로가기
🗜 MCP

[국가법령 MCP 서버 만들기] - 2. 판례 목록, 판례 본문 조회하기

by Majestyblue 2025. 8. 29.

이전시간에 간단하게 판례 목록을 아래의 코드로 조회했었다. (gemini 땡큐!)

import requests
import json

# API 요청에 필요한 파라미터 설정
# OC 값은 사용자 ID로, 제공해주신 '<your_OC>'를 사용합니다.
# 검색어(query)는 '하자 보수'로 설정합니다.

params = {
    'OC': '<your_OC>',
    'target': 'prec',
    'type': 'JSON',
    'search': '1',
    'query': '하자 보수'
}

# API 요청을 보낼 URL
url = 'http://www.law.go.kr/DRF/lawSearch.do'

try:
    # GET 방식으로 API 요청 보내기
    response = requests.get(url, params=params)

    # 응답 상태 코드가 200 (성공)일 경우
    if response.status_code == 200:
        # 응답 받은 데이터를 JSON 형식으로 변환
        data = response.json()

        # JSON 데이터를 예쁘게 출력 (들여쓰기 4칸, 한글 깨짐 방지)
        print(json.dumps(data, indent=4, ensure_ascii=False))

    else:
        print(f"API 요청에 실패했습니다. 상태 코드: {response.status_code}")
        print(f"응답 내용: {response.text}")

except requests.exceptions.RequestException as e:
    print(f"오류가 발생했습니다: {e}")

 

                "id": "2",
                "사건번호": "2023다219417",
                "데이터출처명": "대법원",
                "사건종류코드": "400101",
                "사건종류명": "민사",
                "선고": "선고",
                "선고일자": "2023.06.29",
                "판례일련번호": "240583",
                "판결유형": "판결",
                "법원종류코드": "",
                "법원명": "대법원",
                "판례상세링크": "/DRF/lawService.do?OC=inomeant&target=prec&ID=240583&type=HTML&mobileYn=",
                "사건명": "하자보수보증금등청구의소"

 

 

이제 위에서 출력된 "판례일련번호"를 이용하여 본문을 조회해 보자. 먼저 국세청 자료는 HTML로만 조회된다고 하여 무조건 출력양식은 HTML로 해야 한다. 그런데 이걸 API 문서를 보고 접근하면 큰 낭패를 당하고 만다. (아휴 고생 좀 했다.)

 

iframe 안에 웹 주소가 있고 본문 내용이 없다. 웹 주소로 직접 들어가 접속해도 requests 라이브러리로는 내용을 파싱할 수 없다. 

<iframe style="position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; width: 100%; height: 100%;"

scrolling="auto" frameborder="0"

width="100%" height="100%"

marginheight="0" marginwidth="0" tabIndex="-1"

src = "http://www.law.go.kr/LSW/precInfoP.do?precSeq=240583&mode=0"></iframe>

 

알고보니 '동적 로딩' 이라고 하여 브라우저가 페이지를 연 후에, 자바스크립트가 추가로 서버와 통신하여 본문 내용을 나중에 채워 넣는 방식이었던 것이다. 따라서 Selenium을 이용하여 실제 웹 브라우저를 자동화하고 자바스크립트 로딩이 모두 끝난 후 최종 화면을 가져와야 한다.

 

import time
import re
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from urllib.parse import urljoin

# --- 설정 ---
PRECEDENT_ID = '240583'

# 웹 브라우저처럼 보이기 위한 헤더
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}

# --- 1단계: iframe의 src 주소 가져오기 (이전과 동일) ---
# 이 단계는 requests로도 충분히 빠릅니다.
import requests
print(f"--- 1단계: 판례일련번호 '{PRECEDENT_ID}'의 실제 컨텐츠 주소 얻기 ---")
wrapper_url = 'http://www.law.go.kr/DRF/lawService.do'
params = {
    'OC': '<your_OC>',
    'target': 'prec',
    'ID': PRECEDENT_ID,
    'type': 'HTML'
}
try:
    response_wrapper = requests.get(wrapper_url, params=params, headers=headers)
    response_wrapper.raise_for_status()
    soup_wrapper = BeautifulSoup(response_wrapper.text, 'lxml')
    iframe = soup_wrapper.find('iframe')
    if not iframe or not iframe.has_attr('src'):
        raise ValueError("껍데기 페이지에서 컨텐츠 iframe을 찾을 수 없습니다.")
    
    content_path = iframe['src']
    base_url = "http://www.law.go.kr"
    content_url = urljoin(base_url, content_path)
    
    print(f">> 성공! 실제 컨텐츠 주소: {content_url}")

    # --- 2단계: Selenium으로 자바스크립트가 로딩된 최종 페이지 소스 가져오기 ---
    print("\n--- 2단계: Selenium으로 최종 페이지 로딩 및 본문 가져오기 ---")
    
    # 웹 드라이버 자동 설정 및 실행
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')  # 브라우저 창을 화면에 띄우지 않음
    options.add_argument('--log-level=3') # 콘솔 로그 최소화
    options.add_argument(f"user-agent={headers['User-Agent']}") # User-Agent 설정
    
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=options)

    print(">> 가상 브라우저 실행 및 페이지 접속...")
    driver.get(content_url)

    # **핵심**: <div id="contentBody">가 나타날 때까지 최대 10초간 기다림
    wait = WebDriverWait(driver, 10)
    wait.until(EC.presence_of_element_located((By.ID, "contentBody")))
    print(">> 'contentBody' 로딩 확인 완료!")

    # 최종 페이지의 HTML 소스를 가져옴
    final_html = driver.page_source
    
    # 브라우저 종료
    driver.quit()

    # --- 3단계: 최종 HTML 소스를 BeautifulSoup으로 파싱 ---
    print("\n--- 3단계: 최종 HTML 분석 및 텍스트 추출 ---")
    
    soup_content = BeautifulSoup(final_html, 'lxml')
    
    content_body = soup_content.find('div', id='contentBody')
    
    if not content_body:
        raise ValueError("최종 HTML에서도 'contentBody'를 찾지 못했습니다.")

    raw_text = content_body.get_text(separator='\n', strip=True)
    cleaned_text = re.sub(r'\n\s*\n+', '\n', raw_text)

    print("\n--- [최종 판례 본문 텍스트] ---")
    print(cleaned_text)
    print("---------------------------------")

except Exception as e:
    print(f"\n처리 중 오류가 발생했습니다: {e}")
    if 'driver' in locals() and driver:
        driver.quit()

 

 

<최종 출력>

하자보수보증금등청구의소
[대법원 2023. 6. 29. 선고 2023다219417 판결]
【판시사항】
[1] 확정된 ‘조정을 갈음하는 결정’의 효력
[2] 확정된 ‘조정을 갈음하는 결정’에 인정되는 확정판결과 동일한 효력이 미치는 범위 및 소송절차 진행 중에 조정을 갈음하는 결정이 확정된 경우, 소송물 외의 권리관계에도  
효력이 미치기 위한 요건
[3] 당사자가 표시한 문언에 의하여 객관적인 의미가 명확하게 드러나지 않는 경우, 법률행위의 해석 방법 및 이러한 법리가 소송당사자 사이에 조정을 갈음하는 결정이 확정된  
후 결정사항의 해석에 관하여 다툼이 있는 경우에도 마찬가지로 적용되는지 여부
(적극)
【참조조문】
[1]
민사조정법 제30조
,
제34조
,
민사소송법 제220조
[2]
민사조정법 제30조
,
제34조
,
민사소송법 제216조
,
제220조
[3]
민법 제105조
,
민사조정법 제30조
,
제34조
【참조판례】
[1][2][3]
대법원 2017. 4. 26. 선고 2017다200771 판결
(공2017상, 1093) / [1]
대법원 2006. 6. 29. 선고 2005다32814, 32821 판결
(공2006하, 1404) / [2]
대법원 2007. 4. 26. 선고 2006다78732 판결
(공2007상, 770), 대법원 2015. 2. 26. 선고 2014다78225 판결 / [3]
대법원 1996. 10. 25. 선고 96다16049 판결
(공1996하, 3422),
대법원 2009. 9. 10. 선고 2009다31550 판결
【전문】
【원고, 상고인】
○○○입주자대표회의 (소송대리인 법무법인 영우 담당변호사 임광훈 외 2인)
【피고, 피상고인】
아이디에스 주식회사 (소송대리인 법무법인 백송 담당변호사 강영수 외 1인)
【원심판결】
부산고법 2023. 2. 2. 선고 2022나54521 판결
【주 문】
원심판결을 파기하고, 사건을 부산고등법원에 환송한다.
【이 유】
상고이유를 판단한다.
1.  사안의 개요
원심판결 이유 및 기록에 따르면 아래 사실을 알 수 있다.
가.  피고는 이 사건 아파트 265세대와 근린생활시설 33채로 구성된 이 사건 집합건물을 분양한 분양자이고, 이 사건 집합건물 중 근린생활시설 전부와 이 사건 아파트 중 25세대
를 소유하고 있는 구분소유자이기도 하다. 원고는 이 사건 집합건물을 관리하기 위하여 구성된 입주자대표회의이다.
나.  원고는 이 사건 아파트 일부 구분소유자들(239세대)로부터 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손해배상청구권을 양도받아 2019. 3. 27. 이 사건 소송을 제기
하였다.
다.  한편 원고가 지하 1층부터 지하 4층에 설치된 지하주차장의 사용 및 관리와 관련하여 그 영역을 구분하여 지하 1층 부분은 근린생활시설 측에서, 나머지 부분은 이 사건 아 
파트 측에서 사용하기로 하고 지하 1층과 지하 2층 사이에 주차차단기를 설치하는 공사를 시작하자, 피고는 이에 반대하면서 2019. 10. 2. 원고를 상대로 위 설치공사의 중지 등 
을 구하는 소송(이하 ‘공사중지의 소’라고 한다)을 별도로 제기하였다. 위 사건은 조정에 회부되어 그 절차(이하 ‘이 사건 조정절차’라고 한다)에서 2020. 7. 30. "원고와 피고는
 별지 기재와 같이 합의하였고 향후 위 내용을 성실히 지킬 것을 약속한다. 피고는 이 사건 소를 전부 취하하고 원고는 이에 동의한다."라는 내용의 조정을 갈음하는 결정(이하 ‘이 사건 결정’이라고 한다)이 내려져 2020. 8. 19. 그대로 확정되었다. 이 사건 결정에 첨부된 별지 합의서(이하 ‘이 사건 합의서’라고 한다)에는 "12. 소송 취하에 대하여"라는 
제목으로 "당해 사건 외의 원고와 피고 사이의 모든 소송은 취하하기로 한다."(이하 ‘이 사건 문구’라고 한다)라고 기재되어 있다.
라.  이 사건 결정 당시 원고와 피고 사이에는 이 사건 소송과 공사중지의 소 이외에 피고가 원고를 상대로 제기한 관리규약 개정 무효확인 소송(이하 ‘관리규약 개정 무효확인  
소송’이라고 한다), 피고가 원고의 대표자 등을 상대로 제기한 재정신청사건(이하 ‘재정신청사건’이라고 한다)이 법원에 계속 중이었다.
2.  원심의 판단
원심은, 이 사건 문구가 소 취하 합의의 대상을 공사중지의 소 이외에 원고와 피고 사이의 ‘모든 소송’이라고 명시하고 있는데, 이 사건 결정 당시 원고와 피고 사이에는 공사중 
지의 소 이외에 관리규약 개정 무효확인 소송, 재정신청사건, 이 사건 소송이 계속 중이었다는 등의 이유로, 원고와 피고는 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합
의하였다고 판단하여 피고에 대한 이 사건 소는 권리보호의 이익이 없어 부적법하다고 보았다.
3.  대법원의 판단
가.
조정을 갈음하는 결정에 대하여 이의신청 기간 내에 이의신청이 없으면 그 결정은 재판상의 화해와 같이 확정판결과 동일한 효력이 있고(민사조정법 제30조, 제34조 참조) 이는  
창설적 효력을 가지므로, 당사자 사이에 종전의 다툼 있는 법률관계를 바탕으로 한 권리의무관계는 소멸하고 결정된 내용에 따른 새로운 권리의무관계가 성립한다
(
대법원 2006. 6. 29. 선고 2005다32814, 32821 판결
등 참조).
한편
확정된 조정을 갈음하는 결정에 인정되는 확정판결과 동일한 효력은 소송물인 권리관계의 존부에 관한 판단에만 미치므로, 소송절차 진행 중에 조정을 갈음하는 결정이 확정된 경
우에 소송물 외의 권리관계에도 효력이 미치려면 특별한 사정이 없는 한 그 권리관계가 결정사항에 특정되거나 결정 중 청구의 표시 다음에 부가적으로 기재됨으로써 그 결정의  
기재 내용에 의하여 소송물인 권리관계가 되었다고 인정할 수 있어야 한다
(
대법원 2007. 4. 26. 선고 2006다78732 판결
, 대법원 2015. 2. 26. 선고 2014다78225 판결 등 참조).
특히 조정을 갈음하는 결정은 당사자 사이에 합의가 성립되지 아니한 경우에 조정담당판사나 수소법원이 직권으로 당사자의 이익이나 그 밖의 모든 사정을 고려하여 신청취지 내 
지 청구취지에 반하지 않는 한도에서 사건의 공평한 해결을 위하여 하는 결정이므로(민사조정법 제30조 참조), 그 효력이 소송물 외의 권리 관계에 미치는지 여부는 더욱 엄격하 
게 보아야 한다
(
대법원 2017. 4. 26. 선고 2017다200771 판결
참조).
또한
당사자가 표시한 문언에 의하여 법률행위의 객관적인 의미가 명확하게 드러나지 않는 경우에는 문언의 내용과 그 법률행위가 이루어진 동기 및 경위, 당사자가 그 법률행위에 의 
하여 달성하려는 목적과 진정한 의사, 거래의 관행 등을 종합적으로 고려하여 사회정의와 형평의 이념에 맞도록 논리와 경험의 법칙, 그리고 사회일반의 상식과 거래의 통념에 따
라 합리적으로 해석하여야 한다
(
대법원 1996. 10. 25. 선고 96다16049 판결
등 참조).
이러한 법리는 소송의 당사자 사이에서 조정을 갈음하는 결정이 확정된 후 그 결정사항의 해석에 관하여 다툼이 있는 경우에도 마찬가지로 적용된다
(
대법원 2009. 9. 10. 선고 2009다31550 판결
등 참조).
나.  원심판결 이유 및 기록에 따르면 다음과 같은 사정을 알 수 있다.
1) 이 사건 결정이 확정된 공사중지의 소는 피고가 이 사건 집합건물의 근린생활시설 전부 등을 소유한 구분소유자의 지위에서 공용부분인 지하주차장의 이용과 관련한 다툼을 해
결하기 위하여 그 입주자대표회의인 원고를 상대로 주차차단기 설치공사의 중지 등을 구한 소송이다. 반면에 이 사건 소송은 원고가 이 사건 아파트 일부 구분소유자들이「집합건
물의 소유 및 관리에 관한 법률」에 따라 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손해배상을 구한 것으로서 청구의 권원, 소송물 및 다툼의 대상이 서로 다르다. 그런
데 이 사건 결정의 결정사항이나 이 사건 합의서에 이 사건 소송이나 그 소송물이 특정되어 있지 않고, 이 사건 결정의 청구의 표시 다음에 이 사건 소송물의 권리관계가 부가적 
으로 기재되어 있지도 않으며, 이 사건 합의서에는 공사중지의 소의 소송물과 관련된 것으로서 지하주차장을 비롯한 이 사건 집합건물 공용부분의 사용, 관리에 관한 사항을 정하
는 내용과 함께 이 사건 문구가 적혀 있을 뿐인데, 여기에는 소 취하의 대상으로 ‘모든 소송’이라고만 기재되어 있다.
2) 이 사건 결정 당시 법원에 계속 중이던 관리규약 개정 무효확인 소송은 피고가 원고 등을 상대로 지하 1층을 상가주차장으로, 지하 2층부터 지하 4층을 이 사건 아파트 입주민
 전용주차장으로 구분하여 지정하는 내용 등을 담은 이 사건 집합건물 관리규약 개정의 무효 확인을 구한 소송이고, 재정신청사건은 원고가 위와 같이 주차차단기 설치공사를 하 
자 피고가 원고 대표자 등의 업무추진비 사용 등을 업무상횡령 등으로 문제 삼으며 고소한 사건에 관한 것으로서 모두 이 사건 집합건물의 구분소유자들 내부에서 지하주차장의  
사용을 두고 발생한 분쟁과 관련된 것인 반면에, 이 사건 소송은 그러한 관련성이 없다.
3) 원고는 이 사건 소송에서 2019. 7. 9. 하자감정을 신청하여 감정료로 2019. 9. 4. 33,000,000원, 2020. 2. 3. 16,500,000원 합계 49,500,000원을 납부하였고, 그 하자감정서가
 2020. 5. 7. 도착하였는데, 그 감정의견에 따르면 하자보수비가 10억 원이 넘는 금액이었다. 원고는 이 사건 결정이 확정되고 나서 얼마 지나지 않은 2020. 8. 24. 위 하자감정 
서를 반영하여 피고에게 하자보수에 갈음하는 손해배상으로 958,729,188원 및 이에 대한 지연손해금을 구하는 것으로 청구취지 및 청구원인 변경신청서를 제출하였다.
4) 이 사건 조정절차에서 피고는 2020. 5. 8. 조정의견서를 법원에 제출하였는데 여기에는 이 사건 문구도 포함되어 있었다. 원고는 소송대리인을 별도로 선임하지 않은 채 원고 
대표자 본인이 참석하여 2020. 5. 13. 1차 조정기일을 거친 후 2020. 5. 16. 입주자대표회의에서 ‘이 사건 소송 제1심판결이 조만간 있을 것으로 보이는데 그 손해배상금을 수령 
하여 하자보수공사를 진행하기로 하되 추후 필요시 장기수선계획을 검토하여 조정하고, 위 조정의견서를 검토하여 빠른 시일 내에 상가 측 대표와 만나 다음 조정기일(2020. 6. 19.) 이전까지 조율하는 것’으로 정하였다. 이후 2020. 6. 19. 2차 조정기일이, 2020. 7. 6. 3차 조정기일이 진행된 다음 앞서 본 바와 같이 이 사건 결정이 내려져 그대로 확정되
었다. 이 사건 결정에 첨부된 이 사건 합의서는 위 조정의견서 내용 중 상가 선수금, 장기수선충당금, 선거관리위원 선정에 관한 사항이 일부 수정되었을 뿐 이 사건 문구를 포함
한 나머지 사항은 그대로 남아 이 사건 결정에 포함되었다.
5) 이 사건 합의서에서 이 사건 문구를 제외한 나머지 항목들은 지하주차장 이용 및 요금징수를 포함한 이 사건 집합건물 공용부분의 관리에 관한 사항을 정하고 있을 뿐이고, 이
 사건 소송의 소송물인 이 사건 집합건물의 하자보수나 그에 갈음한 손해배상과 관련된 내용은 전혀 포함되어 있지 않다. 이 사건 조정절차에서 원고와 피고 사이에 지하주차장  
등 이 사건 집합건물 공용부분의 사용, 관리 문제 외에 하자보수에 갈음한 손해배상 문제를 어떻게 처리할 것인지에 관하여 논의한 것으로 보이지도 않는다.
6) 원고는 이 사건 집합건물을 관리하기 위하여 구성된 입주자대표회의로서 이 사건 아파트의 239세대 구분소유자들로부터 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손 
해배상청구권을 양도받아 이 사건 소송에 이르렀는바, 이미 49,500,000원의 비용을 지불하여 하자보수비 감정을 마쳤고 감정결과 10억 원이 넘는 하자보수비에 대한 감정의견을  
받은 상태에서 그에 상응하는 금전적 보상이 없이 손해배상청구권을 양도한 239세대 구분소유자들의 동의나 양해도 받지 않은 채 이 사건 소송의 소송물인 손해배상청구권을 포기
할 만한 동기가 있다고 보이지 않는다. 따라서 원고가 이 사건 조정절차에서 이 사건 결정에 이의를 제기하지 않음으로써 지하주차장 등 이 사건 집합건물 공용부분의 사용, 관리
와 관련된 분쟁을 해결하는 것에서 나아가 하자보수에 갈음한 손해배상청구에 관한 보상이나 대가를 받지 않은 채 이를 포기하려고 하였다거나 피고와 조율하는 과정에서 이를 조
정의 대상으로 삼았다고 보기 어렵다.
다.  위와 같은 사정을 앞서 본 법리에 비추어 살펴보면, 원고와 피고가 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합의하였다고 단정하기는 어렵다.
라.  그런데도 원심은 판시와 같은 사정만으로 원고와 피고가 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합의하였다고 보아 피고에 대한 이 사건 소를 권리보호의 이익이
 없다는 이유로 부적법하다고 판단하였다. 이러한 원심의 판단에는 필요한 심리를 다하지 아니한 채 논리와 경험의 법칙을 위반하여 자유심증주의의 한계를 벗어나 조정을 갈음하
는 결정 조항의 해석에 관한 법리를 오해하여 판결에 영향을 미친 잘못이 있다.
4.  결론
그러므로 원심판결을 파기하고 사건을 다시 심리·판단하도록 원심법원에 환송하기로 하여, 관여 대법관의 일치된 의견으로 주문과 같이 판결한다.
대법관 김선수(재판장) 박정화 노태악 오경미(주심)

 

 

이 두 코드를 합쳐보자!

1. PRECEDENT_ID = os.environ.get('<your_OC>') 형태로 수정 (dotenv 사용하지 않음)

2. 판례 목록 조회와 판례 본문 조회를 하나로 합쳐 비동기(async) 함수로 만든다.

3. 키워드인 query, 본문 검색 개수인 num을 입력받는다. (부하를 피해가 위해 num값은 최대 5로 설정한다.)

4. fastapi로 구현한다.

 

import os
import re
import asyncio
import json
import argparse
from typing import List, Dict, Optional

# --- 외부 라이브러리 ---
import httpx
from fastapi import FastAPI, Query, HTTPException
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from urllib.parse import urljoin

# --- FastAPI 앱 초기화 ---
app = FastAPI()

# --- 환경 변수에서 OC 값 로드 및 유효성 검사 ---
# 코드 보안을 위해 API 인증 정보는 환경 변수로 관리합니다.
LAW_API_OC = os.getenv("LAW_API_OC")
if not LAW_API_OC:
    raise ValueError("환경 변수 'LAW_API_OC'가 설정되지 않았습니다.")

# --- 1단계: 판례 목록의 ID를 가져오는 함수 ---
async def fetch_precedent_list(query: str, num: int, oc: str, client: httpx.AsyncClient) -> List[str]:
    """주어진 쿼리로 판례를 검색하여 판례일련번호(ID) 목록을 반환합니다."""
    search_url = "http://www.law.go.kr/DRF/lawSearch.do"
    params = {'target': 'prec', 'type': 'HTML', 'query': query, 'OC': oc}
    
    try:
        response = await client.get(search_url, params=params)
        response.raise_for_status()
        
        soup = BeautifulSoup(response.text, 'lxml')
        
        # --- ★★★ 최종 수정된 CSS 선택자 ★★★ ---
        # 제공해주신 HTML을 보니, 결과는 <table class="tbl8"> 안에 있었습니다.
        # 이 테이블 안의 <td> 태그 아래에 있는 <a> 태그를 모두 찾습니다.
        items = soup.select("table.tbl8 td a")
        
        if not items:
            # 이 메시지가 보인다면 웹사이트 구조가 또 바뀐 것입니다.
            print(">> HTML에서 판례 목록 링크를 찾지 못했습니다.")
        
        ids = []
        for item in items:
            href = item.get('href', '')
            # 링크(href)에서 판례일련번호(ID=숫자)를 정규식으로 추출합니다.
            match = re.search(r"ID=(\d+)", href)
            if match:
                ids.append(match.group(1))
        
        # 요청된 개수(num)만큼만 잘라서 반환합니다.
        return ids[:num]
    except httpx.HTTPStatusError as e:
        print(f"Error fetching precedent list: {e}")
        return []

# --- 2-1단계(동기): Selenium을 실행하여 최종 HTML을 가져오는 함수 ---
def run_selenium_and_get_html(url: str) -> str:
    """Selenium을 실행하여 JS 로딩이 완료된 최종 페이지의 HTML을 반환합니다."""
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')  # 브라우저 창을 띄우지 않음
    options.add_argument('--log-level=3')
    options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36')

    service = Service(ChromeDriverManager().install())
    driver = None
    try:
        driver = webdriver.Chrome(service=service, options=options)
        driver.get(url)
        # 본문 내용이 담긴 <div id="contentBody">가 로드될 때까지 최대 10초 대기
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.ID, "contentBody"))
        )
        return driver.page_source
    finally:
        # 오류 발생 여부와 관계없이 브라우저 종료
        if driver:
            driver.quit()

# --- 2단계: 단일 판례의 상세 본문을 가져오는 함수 ---
async def fetch_single_precedent_detail(precedent_id: str, oc: str, client: httpx.AsyncClient) -> Optional[Dict]:
    """판례 ID를 받아 상세 본문 내용을 스크래핑하여 JSON(Dict) 형태로 반환합니다."""
    base_url = "http://www.law.go.kr"
    wrapper_url = f"{base_url}/DRF/lawService.do"
    params = {'target': 'prec', 'ID': precedent_id, 'type': 'HTML', 'OC': oc}
    
    try:
        # 1. <iframe> 주소를 담은 껍데기 페이지 요청 (httpx 사용)
        response_wrapper = await client.get(wrapper_url, params=params)
        response_wrapper.raise_for_status()
        soup_wrapper = BeautifulSoup(response_wrapper.text, 'lxml')
        iframe = soup_wrapper.find('iframe')
        if not iframe or not iframe.has_attr('src'):
            return None
        
        content_url = urljoin(base_url, iframe['src'])

        # 2. Selenium 동기 함수를 별도 스레드에서 비동기적으로 실행
        # 이것이 동기 코드(Selenium)를 비동기(FastAPI) 환경에 통합하는 핵심입니다.
        loop = asyncio.get_running_loop()
        final_html = await loop.run_in_executor(
            None,  # 기본 스레드 풀 사용
            run_selenium_and_get_html, 
            content_url
        )

        # 3. 최종 HTML에서 본문 내용 파싱 (BeautifulSoup 사용)
        soup_content = BeautifulSoup(final_html, 'lxml')
        content_body = soup_content.find('div', id='contentBody')
        if not content_body:
            return None

        title = content_body.find('h2').get_text(strip=True) if content_body.find('h2') else "제목 없음"
        raw_text = content_body.get_text(separator='\n', strip=True)
        cleaned_text = re.sub(r'\n\s*\n+', '\n', raw_text)

        return {
            "precedent_id": precedent_id,
            "title": title,
            "source_url": content_url,
            "full_text": cleaned_text
        }
    except Exception as e:
        print(f"Error fetching detail for ID {precedent_id}: {e}")
        # 단일 작업 실패 시 None을 반환하여 다른 작업에 영향을 주지 않음
        return None

# --- 메인 로직: 전체 프로세스를 orchestrate하는 함수 ---
async def get_precedents(query: str, num: int, oc: str) -> List[Dict]:
    async with httpx.AsyncClient() as client:
        # 1. 판례 ID 목록 가져오기
        precedent_ids = await fetch_precedent_list(query, num, oc, client)
        if not precedent_ids:
            return []
        
        # 2. 각 ID에 대한 본문 조회 작업을 비동기 태스크로 생성
        tasks = [fetch_single_precedent_detail(pid, oc, client) for pid in precedent_ids]
        
        # 3. asyncio.gather를 사용하여 모든 태스크를 동시에 실행
        results = await asyncio.gather(*tasks)
        
        # 4. 실패한 작업(None)을 제외하고 성공한 결과만 필터링하여 반환
        return [res for res in results if res]

# --- FastAPI 엔드포인트 정의 ---
@app.get("/search-precedents/")
async def search_precedents_endpoint(
    query: str,
    # num의 기본값은 3, ge=1 (1 이상), le=5 (5 이하)로 입력값 검증
    num: int = Query(default=3, ge=1, le=5)
):
    """
    판례 키워드와 개수를 받아 상세 본문이 포함된 판례 목록을 반환합니다.
    - **query**: 검색할 키워드 (예: 하자보수)
    - **num**: 가져올 판례 개수 (기본값: 3, 최소: 1, 최대: 5)
    """
    if not query.strip():
        raise HTTPException(status_code=400, detail="'query'는 비어 있을 수 없습니다.")

    results = await get_precedents(query, num, LAW_API_OC)
    
    return {"query": query, "count": len(results), "results": results}

async def main_test(query: str, num: int):
    """
    매개변수로 받은 query와 num을 사용하여 핵심 함수를 테스트합니다.
    """
    print("--- 판례 조회 함수 테스트 시작 ---")
    
    test_oc = os.getenv("LAW_API_OC")
    if not test_oc:
        print("!!! 오류: LAW_API_OC 환경 변수가 설정되지 않았습니다.")
        return

    print(f"사용자 OC: {test_oc}")
    print(f"검색어: '{query}', 요청 개수: {num}\n")
    print("... 판례 목록 조회 및 본문 스크래핑 중 ...\n")
    
    results = await get_precedents(query=query, num=num, oc=test_oc)
    
    print("--- 테스트 결과 ---")
    if results:
        print(json.dumps(results, indent=4, ensure_ascii=False))
        
        # --- ★★★ 수정된 부분 ★★★ ---
        # 실제 성공한 개수와 요청한 개수를 비교하여 안내 메시지를 추가합니다.
        successful_count = len(results)
        print(f"\n총 {successful_count}개의 판례를 성공적으로 조회했습니다.")
        
        if successful_count < num:
            print(f"\n[안내] 요청하신 {num}개 중 {num - successful_count}개는 조회에 실패했습니다.")
            print("      (일부 판례는 페이지 구조가 특수하여 조회가 불가능할 수 있습니다.)")
        # --- ★★★ 수정 끝 ★★★ ---
            
    else:
        print("조회된 판례가 없습니다.")
    
    print("--- 테스트 종료 ---")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="국가법령정보센터 판례 조회 테스트 스크립트")
    parser.add_argument("query", type=str, help="검색할 판례 키워드 (예: \"하자 보수\")")
    parser.add_argument("--num", type=int, default=3, help="검색할 판례 개수 (기본값: 3, 최대: 5)")
    args = parser.parse_args()

    if not 1 <= args.num <= 5:
        print("오류: num 값은 1에서 5 사이여야 합니다.")
    else:
        asyncio.run(main_test(query=args.query, num=args.num))

 

 

 

출력결과

(mylaw_info) PS D:\my_mcp\mylaw_info> python test3.py "하자보수"
--- 판례 조회 함수 테스트 시작 ---
사용자 OC: inomeant
검색어: '하자보수', 요청 개수: 3

... 판례 목록 조회 및 본문 스크래핑 중 ...


DevTools listening on ws://127.0.0.1:56198/devtools/browser/bce586c7-bbc4-4f48-aad3-069ec571ad8e

DevTools listening on ws://127.0.0.1:56199/devtools/browser/34037be8-782f-4cc6-996d-19abb7bcf1a6

DevTools listening on ws://127.0.0.1:56200/devtools/browser/f780a53d-3c46-42d2-a585-78ebd5b75545
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1756453748.878205   10676 voice_transcription.cc:58] Registering VoiceTranscriptionCapability
Error fetching detail for ID 418792: Message: 
Stacktrace:
        GetHandleVerifier [0x0x110a8a3+63283]
        GetHandleVerifier [0x0x110a8e4+63348]
        (No symbol) [0x0xf43e43]
        (No symbol) [0x0xf8c8de]
        (No symbol) [0x0xf8cc7b]
        (No symbol) [0x0xfd4ef2]
        (No symbol) [0x0xfb1464]
        (No symbol) [0x0xfd271a]
        (No symbol) [0x0xfb1216]
        (No symbol) [0x0xf80855]
        (No symbol) [0x0xf816f4]
        GetHandleVerifier [0x0x137bb43+2623955]
        GetHandleVerifier [0x0x1376daa+2604090]
        GetHandleVerifier [0x0x113069a+218410]
        GetHandleVerifier [0x0x1120ed8+154984]
        GetHandleVerifier [0x0x112742d+180925]
        GetHandleVerifier [0x0x11122b8+94536]
        GetHandleVerifier [0x0x1112442+94930]
        GetHandleVerifier [0x0x10fd5ea+9338]
        BaseThreadInitThunk [0x0x75e0fcc9+25]
        RtlGetAppContainerNamedObjectPath [0x0x77b582ae+286]
        RtlGetAppContainerNamedObjectPath [0x0x77b5827e+238]

--- 테스트 결과 ---
[
    {
        "precedent_id": "240583",
        "title": "하자보수보증금등청구의소",
        "source_url": "http://www.law.go.kr/LSW/precInfoP.do?precSeq=240583&mode=0",
        "full_text": "하자보수보증금등청구의소\n[대법원 2023. 6. 29. 선고 2023다219417 판결]\n【판시사항】\n[1] 확정된 ‘조정을 갈음하는 결정’의 효력\n[2] 확정된 ‘조정을 갈음하는 결정’에 인정되는 확정판결과 동 
일한 효력이 미치는 범위 및 소송절차 진행 중에 조정을 갈음하는 결정이 확정된 경우, 소송물 외의 권리관계에도 효력이 미치기 위한 요건\n[3] 당사자가 표시한 문언에 의하여 객관적인 의미가 명확하게 드러나지 않는 경우
, 법률행위의 해석 방법 및 이러한 법리가 소송당사자 사이에 조정을 갈음하는 결정이 확정된 후 결정사항의 해석에 관하여 다툼이 있는 경우에도 마찬가지로 적용되는지 여부\n(적극)\n【참조조문】\n[1]\n민사조정법 제30조
\n,\n제34조\n,\n민사소송법 제220조\n[2]\n민사조정법 제30조\n,\n제34조\n,\n민사소송법 제216조\n,\n제220조\n[3]\n민법 제105조\n,\n민사조정법 제30조\n,\n제34조\n【참조판례】\n[1][2][3]\n대법원 2017. 4. 26. 선고 2017다200771 판결\n(공2017상, 1093) / [1]\n대법원 2006. 6. 29. 선고 2005다32814, 32821 판결\n(공2006하, 1404) / [2]\n대법원 2007. 4. 26. 선고 2006다78732 판결\n(공2007상, 770), 대법원 2015. 2. 26. 선고 2014다78225 판결 / [3]\n대법원 1996. 10. 25. 선고 96다16049 판결\n(공1996하, 3422),\n대법원 2009. 9. 10. 선고 2009다31550 판결\n【전문】\n【원고, 상고인】\n○○○입주자대표회의 (소송대리인 법무법인 영우 담당변호사 임광훈
 외 2인)\n【피고, 피상고인】\n아이디에스 주식회사 (소송대리인 법무법인 백송 담당변호사 강영수 외 1인)\n【원심판결】\n부산고법 2023. 2. 2. 선고 2022나54521 판결\n【주 문】\n원심판결을 파기하고, 사건을 부산고등 
법원에 환송한다.\n【이 유】\n상고이유를 판단한다.\n1.  사안의 개요\n원심판결 이유 및 기록에 따르면 아래 사실을 알 수 있다.\n가.  피고는 이 사건 아파트 265세대와 근린생활시설 33채로 구성된 이 사건 집합건물을 분
양한 분양자이고, 이 사건 집합건물 중 근린생활시설 전부와 이 사건 아파트 중 25세대를 소유하고 있는 구분소유자이기도 하다. 원고는 이 사건 집합건물을 관리하기 위하여 구성된 입주자대표회의이다.\n나.  원고는 이 사 
건 아파트 일부 구분소유자들(239세대)로부터 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손해배상청구권을 양도받아 2019. 3. 27. 이 사건 소송을 제기하였다.\n다.  한편 원고가 지하 1층부터 지하 4층에 설치된 지 
하주차장의 사용 및 관리와 관련하여 그 영역을 구분하여 지하 1층 부분은 근린생활시설 측에서, 나머지 부분은 이 사건 아파트 측에서 사용하기로 하고 지하 1층과 지하 2층 사이에 주차차단기를 설치하는 공사를 시작하자, 
피고는 이에 반대하면서 2019. 10. 2. 원고를 상대로 위 설치공사의 중지 등을 구하는 소송(이하 ‘공사중지의 소’라고 한다)을 별도로 제기하였다. 위 사건은 조정에 회부되어 그 절차(이하 ‘이 사건 조정절차’라고 한다)에서
 2020. 7. 30. \"원고와 피고는 별지 기재와 같이 합의하였고 향후 위 내용을 성실히 지킬 것을 약속한다. 피고는 이 사건 소를 전부 취하하고 원고는 이에 동의한다.\"라는 내용의 조정을 갈음하는 결정(이하 ‘이 사건 결정’이라고 한다)이 내려져 2020. 8. 19. 그대로 확정되었다. 이 사건 결정에 첨부된 별지 합의서(이하 ‘이 사건 합의서’라고 한다)에는 \"12. 소송 취하에 대하여\"라는 제목으로 \"당해 사건 외의 원고와 피고 사이의 모든 소송
은 취하하기로 한다.\"(이하 ‘이 사건 문구’라고 한다)라고 기재되어 있다.\n라.  이 사건 결정 당시 원고와 피고 사이에는 이 사건 소송과 공사중지의 소 이외에 피고가 원고를 상대로 제기한 관리규약 개정 무효확인 소송( 
이하 ‘관리규약 개정 무효확인 소송’이라고 한다), 피고가 원고의 대표자 등을 상대로 제기한 재정신청사건(이하 ‘재정신청사건’이라고 한다)이 법원에 계속 중이었다.\n2.  원심의 판단\n원심은, 이 사건 문구가 소 취하 합 
의의 대상을 공사중지의 소 이외에 원고와 피고 사이의 ‘모든 소송’이라고 명시하고 있는데, 이 사건 결정 당시 원고와 피고 사이에는 공사중지의 소 이외에 관리규약 개정 무효확인 소송, 재정신청사건, 이 사건 소송이 계속
 중이었다는 등의 이유로, 원고와 피고는 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합의하였다고 판단하여 피고에 대한 이 사건 소는 권리보호의 이익이 없어 부적법하다고 보았다.\n3.  대법원의 판단\n가.\n조정을
 갈음하는 결정에 대하여 이의신청 기간 내에 이의신청이 없으면 그 결정은 재판상의 화해와 같이 확정판결과 동일한 효력이 있고(민사조정법 제30조, 제34조 참조) 이는 창설적 효력을 가지므로, 당사자 사이에 종전의 다툼 
있는 법률관계를 바탕으로 한 권리의무관계는 소멸하고 결정된 내용에 따른 새로운 권리의무관계가 성립한다\n(\n대법원 2006. 6. 29. 선고 2005다32814, 32821 판결\n등 참조).\n한편\n확정된 조정을 갈음하는 결정에 인정되
는 확정판결과 동일한 효력은 소송물인 권리관계의 존부에 관한 판단에만 미치므로, 소송절차 진행 중에 조정을 갈음하는 결정이 확정된 경우에 소송물 외의 권리관계에도 효력이 미치려면 특별한 사정이 없는 한 그 권리관계
가 결정사항에 특정되거나 결정 중 청구의 표시 다음에 부가적으로 기재됨으로써 그 결정의 기재 내용에 의하여 소송물인 권리관계가 되었다고 인정할 수 있어야 한다\n(\n대법원 2007. 4. 26. 선고 2006다78732 판결\n, 대법
원 2015. 2. 26. 선고 2014다78225 판결 등 참조).\n특히 조정을 갈음하는 결정은 당사자 사이에 합의가 성립되지 아니한 경우에 조정담당판사나 수소법원이 직권으로 당사자의 이익이나 그 밖의 모든 사정을 고려하여 신청취
지 내지 청구취지에 반하지 않는 한도에서 사건의 공평한 해결을 위하여 하는 결정이므로(민사조정법 제30조 참조), 그 효력이 소송물 외의 권리 관계에 미치는지 여부는 더욱 엄격하게 보아야 한다\n(\n대법원 2017. 4. 26. 
선고 2017다200771 판결\n참조).\n또한\n당사자가 표시한 문언에 의하여 법률행위의 객관적인 의미가 명확하게 드러나지 않는 경우에는 문언의 내용과 그 법률행위가 이루어진 동기 및 경위, 당사자가 그 법률행위에 의하여  
달성하려는 목적과 진정한 의사, 거래의 관행 등을 종합적으로 고려하여 사회정의와 형평의 이념에 맞도록 논리와 경험의 법칙, 그리고 사회일반의 상식과 거래의 통념에 따라 합리적으로 해석하여야 한다\n(\n대법원 1996. 10. 25. 선고 96다16049 판결\n등 참조).\n이러한 법리는 소송의 당사자 사이에서 조정을 갈음하는 결정이 확정된 후 그 결정사항의 해석에 관하여 다툼이 있는 경우에도 마찬가지로 적용된다\n(\n대법원 2009. 9. 10. 선고 2009다31550 판결\n등 참조).\n나.  원심판결 이유 및 기록에 따르면 다음과 같은 사정을 알 수 있다.\n1) 이 사건 결정이 확정된 공사중지의 소는 피고가 이 사건 집합건물의 근린생활시설 전부 등을 소유한 구분소유자의 지위
에서 공용부분인 지하주차장의 이용과 관련한 다툼을 해결하기 위하여 그 입주자대표회의인 원고를 상대로 주차차단기 설치공사의 중지 등을 구한 소송이다. 반면에 이 사건 소송은 원고가 이 사건 아파트 일부 구분소유자들 
이「집합건물의 소유 및 관리에 관한 법률」에 따라 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손해배상을 구한 것으로서 청구의 권원, 소송물 및 다툼의 대상이 서로 다르다. 그런데 이 사건 결정의 결정사항이나 이
 사건 합의서에 이 사건 소송이나 그 소송물이 특정되어 있지 않고, 이 사건 결정의 청구의 표시 다음에 이 사건 소송물의 권리관계가 부가적으로 기재되어 있지도 않으며, 이 사건 합의서에는 공사중지의 소의 소송물과 관련
된 것으로서 지하주차장을 비롯한 이 사건 집합건물 공용부분의 사용, 관리에 관한 사항을 정하는 내용과 함께 이 사건 문구가 적혀 있을 뿐인데, 여기에는 소 취하의 대상으로 ‘모든 소송’이라고만 기재되어 있다.\n2) 이 사
건 결정 당시 법원에 계속 중이던 관리규약 개정 무효확인 소송은 피고가 원고 등을 상대로 지하 1층을 상가주차장으로, 지하 2층부터 지하 4층을 이 사건 아파트 입주민 전용주차장으로 구분하여 지정하는 내용 등을 담은 이
 사건 집합건물 관리규약 개정의 무효 확인을 구한 소송이고, 재정신청사건은 원고가 위와 같이 주차차단기 설치공사를 하자 피고가 원고 대표자 등의 업무추진비 사용 등을 업무상횡령 등으로 문제 삼으며 고소한 사건에 관 
한 것으로서 모두 이 사건 집합건물의 구분소유자들 내부에서 지하주차장의 사용을 두고 발생한 분쟁과 관련된 것인 반면에, 이 사건 소송은 그러한 관련성이 없다.\n3) 원고는 이 사건 소송에서 2019. 7. 9. 하자감정을 신청
하여 감정료로 2019. 9. 4. 33,000,000원, 2020. 2. 3. 16,500,000원 합계 49,500,000원을 납부하였고, 그 하자감정서가 2020. 5. 7. 도착하였는데, 그 감정의견에 따르면 하자보수비가 10억 원이 넘는 금액이었다. 원고는 이
 사건 결정이 확정되고 나서 얼마 지나지 않은 2020. 8. 24. 위 하자감정서를 반영하여 피고에게 하자보수에 갈음하는 손해배상으로 958,729,188원 및 이에 대한 지연손해금을 구하는 것으로 청구취지 및 청구원인 변경신청서
를 제출하였다.\n4) 이 사건 조정절차에서 피고는 2020. 5. 8. 조정의견서를 법원에 제출하였는데 여기에는 이 사건 문구도 포함되어 있었다. 원고는 소송대리인을 별도로 선임하지 않은 채 원고 대표자 본인이 참석하여 2020. 5. 13. 1차 조정기일을 거친 후 2020. 5. 16. 입주자대표회의에서 ‘이 사건 소송 제1심판결이 조만간 있을 것으로 보이는데 그 손해배상금을 수령하여 하자보수공사를 진행하기로 하되 추후 필요시 장기수선계획을 검토하여
 조정하고, 위 조정의견서를 검토하여 빠른 시일 내에 상가 측 대표와 만나 다음 조정기일(2020. 6. 19.) 이전까지 조율하는 것’으로 정하였다. 이후 2020. 6. 19. 2차 조정기일이, 2020. 7. 6. 3차 조정기일이 진행된 다음  
앞서 본 바와 같이 이 사건 결정이 내려져 그대로 확정되었다. 이 사건 결정에 첨부된 이 사건 합의서는 위 조정의견서 내용 중 상가 선수금, 장기수선충당금, 선거관리위원 선정에 관한 사항이 일부 수정되었을 뿐 이 사건  
문구를 포함한 나머지 사항은 그대로 남아 이 사건 결정에 포함되었다.\n5) 이 사건 합의서에서 이 사건 문구를 제외한 나머지 항목들은 지하주차장 이용 및 요금징수를 포함한 이 사건 집합건물 공용부분의 관리에 관한 사항
을 정하고 있을 뿐이고, 이 사건 소송의 소송물인 이 사건 집합건물의 하자보수나 그에 갈음한 손해배상과 관련된 내용은 전혀 포함되어 있지 않다. 이 사건 조정절차에서 원고와 피고 사이에 지하주차장 등 이 사건 집합건물
 공용부분의 사용, 관리 문제 외에 하자보수에 갈음한 손해배상 문제를 어떻게 처리할 것인지에 관하여 논의한 것으로 보이지도 않는다.\n6) 원고는 이 사건 집합건물을 관리하기 위하여 구성된 입주자대표회의로서 이 사건  
아파트의 239세대 구분소유자들로부터 분양자인 피고에 대하여 가지는 하자보수에 갈음한 손해배상청구권을 양도받아 이 사건 소송에 이르렀는바, 이미 49,500,000원의 비용을 지불하여 하자보수비 감정을 마쳤고 감정결과 10억 원이 넘는 하자보수비에 대한 감정의견을 받은 상태에서 그에 상응하는 금전적 보상이 없이 손해배상청구권을 양도한 239세대 구분소유자들의 동의나 양해도 받지 않은 채 이 사건 소송의 소송물인 손해배상청구권을 포기 
할 만한 동기가 있다고 보이지 않는다. 따라서 원고가 이 사건 조정절차에서 이 사건 결정에 이의를 제기하지 않음으로써 지하주차장 등 이 사건 집합건물 공용부분의 사용, 관리와 관련된 분쟁을 해결하는 것에서 나아가 하 
자보수에 갈음한 손해배상청구에 관한 보상이나 대가를 받지 않은 채 이를 포기하려고 하였다거나 피고와 조율하는 과정에서 이를 조정의 대상으로 삼았다고 보기 어렵다.\n다.  위와 같은 사정을 앞서 본 법리에 비추어 살펴
보면, 원고와 피고가 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합의하였다고 단정하기는 어렵다.\n라.  그런데도 원심은 판시와 같은 사정만으로 원고와 피고가 이 사건 결정을 통하여 이 사건 소송을 취하하기로 합
의하였다고 보아 피고에 대한 이 사건 소를 권리보호의 이익이 없다는 이유로 부적법하다고 판단하였다. 이러한 원심의 판단에는 필요한 심리를 다하지 아니한 채 논리와 경험의 법칙을 위반하여 자유심증주의의 한계를 벗어 
나 조정을 갈음하는 결정 조항의 해석에 관한 법리를 오해하여 판결에 영향을 미친 잘못이 있다.\n4.  결론\n그러므로 원심판결을 파기하고 사건을 다시 심리·판단하도록 원심법원에 환송하기로 하여, 관여 대법관의 일치된  
의견으로 주문과 같이 판결한다.\n대법관 김선수(재판장) 박정화 노태악 오경미(주심)"
    },
    {
        "precedent_id": "233013",
        "title": "하자보수보증금청구·하자보수보증금청구",
        "source_url": "http://www.law.go.kr/LSW/precInfoP.do?precSeq=233013&mode=0",
        "full_text": "하자보수보증금청구·하자보수보증금청구\n[대법원 2022. 3. 31. 선고 2021다294902, 294919 판결]\n【판시사항】\n하자보수보증계약의 보증기간을 주계약의 하자담보책임기간과 동일하게 정하였는데,  
하자담보책임기간 내에 발생한 하자에 대하여 보증기간이 종료된 후 보증사고가 발생한 경우, 보증금청구권의 소멸시효 기산점(=보증사고가 발생한 때)\n【참조조문】\n상법 제662조\n,\n제665조\n,\n제666조 제5호\n,\n제726조의5\n,\n민법 제105조\n,\n제166조 제1항\n,\n제428조\n【참조판례】\n대법원 2001. 5. 29. 선고 2000다3897 판결\n(공2001하, 1455),\n대법원 2006. 4. 28. 선고 2004다16976 판결\n(공2006상, 908), 대법원 2012. 8. 23. 
선고 2012다18748 판결, 대법원 2014. 6. 26. 선고 2012다44808 판결,\n대법원 2015. 11. 26. 선고 2013다62490 판결\n,\n대법원 2021. 2. 25. 선고 2020다248698 판결\n(공2021상, 710)\n【전문】\n【원고, 상고인】\n○○○○○○○ 입주자대표회의 외 2인 (소송대리인 변호사 김남식 외 3인)\n【피고, 피상고인】\n주택도시보증공사 (소송대리인 법무법인 태영 담당변호사 강현성 외 3인)\n【피고 보조참가인】\n대성산업 주식회사 (소송대리인 법무법인 
태영 담당변호사 강현성 외 3인)\n【원심판결】\n서울고법 2021. 10. 20. 선고 2020나2032884, 2032891 판결\n【주 문】\n원심판결 중 원고들 패소 부분을 파기하고, 이 부분 사건을 서울고등법원에 환송한다.\n【이 유】\n상
고이유를 판단한다.\n1.  관련 법리\n가.\n보험금청구권의 소멸시효 기산점은 특별한 사정이 없는 한 보험사고가 발생한 때이고\n(대법원 2012. 8. 23. 선고 2012다18748 판결 등 참조),\n보험사고란 보험계약에서 보험자의  
보험금 지급책임을 구체화하는 불확정한 사고를 의미하는 것이다. 보증보험에서 보험사고가 구체적으로 무엇인지는 당사자 사이의 약정으로 계약 내용에 편입된 보험약관과 보험약관이 인용하고 있는 보험증권 및 주계약의 구
체적인 내용 등을 종합하여 결정하여야 한다\n(\n대법원 2006. 4. 28. 선고 2004다16976 판결\n, 대법원 2014. 6. 26. 선고 2012다44808 판결 등 참조).\n그리고 보증보험증권에 보험기간이 정해져 있는 경우에는 보험사고가 
그 기간 내에 발생한 때에 한하여 보험자가 보험계약상의 책임을 지는 것이 원칙이지만, 보증보험계약의 목적이 주계약의 하자담보책임기간 내에 발생한 하자에 대하여 보험계약자의 하자보수의무 불이행으로 인한 손해를 보 
상하기 위한 것임에도 불구하고 보험기간을 주계약의 하자담보책임기간과 동일하게 정한 경우 특별한 사정이 없으면 위 보증보험계약은 그 계약의 보험기간, 즉 하자담보책임기간 내에 발생한 하자에 대하여는 비록 보험기간 
이 종료된 후 보험사고가 발생하였다고 하더라도 보험자로서 책임을 지기로 하는 내용의 계약이라고 해석함이 상당하다\n(\n대법원 2001. 5. 29. 선고 2000다3897 판결\n,\n대법원 2015. 11. 26. 선고 2013다62490 판결\n등  
참조).\n나.\n이와 같은 법리는 보증기간을 주계약의 하자담보책임기간과 동일하게 정한 하자보수보증계약에서도 마찬가지로 적용되어야 하므로, 특별한 사정이 없는 한 그 계약의 보증기간, 즉 하자담보책임기간 내에 발생한
 하자에 대하여 보증기간이 종료된 후 보증사고가 발생하였다면 그 보증사고가 발생한 때로부터 보증금청구권의 소멸시효가 진행한다\n.\n2.  사실관계 및 대법원의 판단\n가.  원심판결 이유와 기록에 의하면 다음과 같은 사
실 또는 사정을 알 수 있다.\n1) 이 사건 보증계약은 각 보증기간을 각 공정별 하자보수책임기간과 동일하게 정하였다.\n2) 이 사건 보증계약 약관은 ‘보증사고라 함은 하자보수대상시설공사에 발생한 하자로서 각 공정별 하 
보완청구를 받고도 이를 이행하지 아니한 것을 의미하므로, 이 경우 보험금청구권의 소멸시효는 늦어도 보험기간의 종기부터 진행한다고 전제한 다음, 1년 차 하자에 대한 보증기간의 종기는 2011. 6. 30.이고, 2년 차 하자에
 대한 보증기간의 종기는 2012. 6. 30.이며, 이 사건 소는 위 각 보증기간의 종기로부터 5년의 소멸시효 기간이 지난 2018. 6. 28. 제기되었으므로, 원고들의 피고에 대한 1, 2년 차 하자 항목에 관한 보증금청구권은 소멸시 
효 완성으로 모두 소멸하였다고 판단하였다. 이러한 원심의 판단에는 보증금청구권의 소멸시효 기산점에 관한 법리를 오해하고 필요한 심리를 다하지 아니하여 판결에 영향을 미친 잘못이 있다(원심이 들고 있는 대법원 판례 
는 하자담보책임기간과 보험기간이 서로 동일하지 않은 사안에 관한 것으로서 이 사건에서 원용하기에 적절하지 않다). 이를 지적하는 상고이유 주장은 이유 있다.\n3.  결론\n그러므로 원심판결 중 원고들 패소 부분을 파기 
하고, 이 부분 사건을 다시 심리·판단하도록 하기 위하여 원심법원에 환송하기로 하여, 관여 대법관의 일치된 의견으로 주문과 같이 판결한다.\n대법관 김재형(재판장) 안철상 노정희(주심) 이흥구"
    }
]

총 2개의 판례를 성공적으로 조회했습니다.

[안내] 요청하신 3개 중 1개는 조회에 실패했습니다.
      (일부 판례는 페이지 구조가 특수하여 조회가 불가능할 수 있습니다.)
--- 테스트 종료 ---

 

 

한 개의 자료가 조회 실패하였는데 잘 안될 수 있다고 한다. 일단 여기까지