학과·강의 검색
학과 목록과 개설강좌를 JSON으로 내려주는 작은 서버입니다. 프런트엔드는 이 두 주소만 부르면 됩니다.
요청 파라미터
섹션 제목: “요청 파라미터”예시 서버의 HTTP 요청(모두 GET)과, 그 안에서 부르는 라이브러리 메서드입니다. 필드 이름은 Python snake_case 기준이고, Node.js는 camelCase 객체 인자, Java는 위치 인자입니다. 로그인은 필요 없습니다.
예시 서버
| 주소 | 파라미터 | 필수 | 설명 |
|---|---|---|---|
/departments |
파라미터 없음 | ||
/lectures |
department |
아니오 | 학과 코드 |
name |
아니오 | 과목명 (부분 일치). 둘 중 하나는 필수인 것은 이 예시 서버가 정한 규칙 |
라이브러리 메서드
| 메서드 | 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|---|
departments |
category_code |
문자열 | 예 | 소속 분류 (20 학부) |
|
year |
문자열 | 예 | 연도 | ||
semester_code |
문자열 | 예 | 학기 코드 (10 1학기, 20 2학기, 11·21 계절학기) |
||
lectures |
category_code, year, semester_code |
문자열 | 예 | 위와 같음 | |
department_code |
문자열 | 아니오 | 빈 문자열 | 학과 코드 | |
course_name |
문자열 | 아니오 | 빈 문자열 | 과목명 | |
instructor_name |
문자열 | 아니오 | 빈 문자열 | 교수명. 세 조건을 모두 비우면 그 학기 전체 |
예시 코드는 학부("20")이고 연도와 학기("20" = 2학기)는 코드 상단의 상수입니다. 코드 값은 모두 학교 값이며 목록은 organization_categories(), terms(...)로 받습니다 (학과·학기 코드).
응답 데이터 구조
섹션 제목: “응답 데이터 구조”예시 서버가 내려주는 JSON입니다. 위쪽이 GET /departments, 아래쪽이 GET /lectures?...의 응답이며, 값은 형태를 보여 주기 위한 예시입니다. 키 이름은 Python 예시 기준이고 Node.js 예시는 course_number가 courseNumber입니다. Java 컨트롤러는 라이브러리 모델(Department, Lecture)을 그대로 돌려주므로 필드가 더 많고 이름은 camelCase입니다.
[ { "code": "3517", "college": "인공지능융합대학", "name": "AI로봇학과" }, { "code": "3331", "college": "연계전공", "name": "스마트투어리즘매니지먼트소프트웨어" }][ { "course": "알고리즘및실습", "department": "컴퓨터공학과", "schedule": "화13:00-15:00", "credits": "3.0", "course_number": "009954" }]| 필드 | 의미 |
|---|---|
code |
학과 코드. /lectures?department=에 그대로 넘김 |
college / name |
단과대 / 학과(또는 전공) 이름 |
course / department |
과목명 / 개설 학과 이름 |
schedule |
요일과 시간 (학교 원문, 예: 화13:00-15:00) |
credits |
학점 (문자열) |
course_number |
교과목 번호. 교육과정 조회에 이어서 쓸 수 있음 |
라이브러리가 돌려주는 전체 필드(extra 포함)는 개설강좌와 학과·학기 코드를 보세요.
실패 시: 학교 서버가 실패하면 예외 없이 마지막 캐시 또는 빈 목록입니다. 예시 서버는 이를 빈 배열([])로 내려줍니다.
알아둘 점
섹션 제목: “알아둘 점”lectures의 학과 코드, 과목명, 교수명은 모두 선택입니다. 모두 비우면 그 학기 전체를 받는데 응답이 수 MB로 크므로(개설강좌), 예시 서버는 조건을 필수로 했습니다. 전체가 필요하면 학과 단위로 나눠 조회하세요.- 강의 결과에는 교수 이름(
instructor)도 들어 있습니다. 예시는 필요한 필드만 골라서 내려주고, 외부에 공개할 때는 어떤 필드를 낼지 직접 정하세요. - 과목명 검색은 부분 일치입니다. 결과가 0건인 이름도 있으므로 빈 결과 안내가 필요합니다.
- 강의의
course_number와department_code로 학과 교육과정의 학년·학기·교과목 개요(curriculum_courses)를 이어서 조회할 수 있습니다. 교육과정
예시 코드
섹션 제목: “예시 코드”import java.util.List;import kr.suhsaechan.sejongpeia.publicdata.SejongPublicData;import kr.suhsaechan.sejongpeia.publicdata.model.Department;import kr.suhsaechan.sejongpeia.publicdata.model.Lecture;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;
@RestControllerclass LectureSearchController {
private static final String UNDERGRADUATE_CATEGORY = "20"; private static final String YEAR = "2026"; private static final String SEMESTER = "20";
private final SejongPublicData publicData;
LectureSearchController(SejongPublicData publicData) { this.publicData = publicData; }
@GetMapping("/departments") List<Department> departments() { return publicData.departments(UNDERGRADUATE_CATEGORY, YEAR, SEMESTER); }
@GetMapping("/lectures") List<Lecture> lectures(@RequestParam(defaultValue = "") String department, @RequestParam(defaultValue = "") String name) { if (department.isBlank() && name.isBlank()) { // 조건이 없으면 그 학기 전체(수 MB)라서 이 서버는 조건을 필수로 함 return List.of(); } return publicData.lectures(UNDERGRADUATE_CATEGORY, YEAR, SEMESTER, department, name, ""); }}표준 라이브러리 서버입니다.
import jsonfrom http.server import BaseHTTPRequestHandler, HTTPServerfrom urllib.parse import parse_qs, urlparse
from sejongpeia import SejongPublicData
public_data = SejongPublicData() # 프로세스당 하나만 만들어 캐시를 공유UNDERGRADUATE_CATEGORY = "20" # 학교의 소속 분류 코드 (organization_categories()로 확인)YEAR, SEMESTER = "2026", "20" # 학기 목록은 terms(UNDERGRADUATE_CATEGORY)
def search_lectures(department_code: str, course_name: str) -> list: lectures = public_data.lectures(UNDERGRADUATE_CATEGORY, YEAR, SEMESTER, department_code=department_code, course_name=course_name) return [ {"course": lecture.name, "department": lecture.department_name, "schedule": lecture.schedule, "credits": lecture.credits, "course_number": lecture.course_number} for lecture in lectures ]
class LectureSearchHandler(BaseHTTPRequestHandler): def do_GET(self): url = urlparse(self.path) if url.path == "/departments": departments = public_data.departments(UNDERGRADUATE_CATEGORY, YEAR, SEMESTER) body = [{"code": department.code, "college": department.college_name, "name": department.major_name or department.unit_name} for department in departments] elif url.path == "/lectures": query = parse_qs(url.query) department_code = query.get("department", [""])[0].strip() course_name = query.get("name", [""])[0].strip() if not department_code and not course_name: # 조건이 없으면 그 학기 전체(수 MB)라서 이 서버는 조건을 필수로 함 self.send_error(400, "department or name is required") return body = search_lectures(department_code, course_name) else: self.send_error(404) return payload = json.dumps(body, ensure_ascii=False).encode("utf-8") self.send_response(200) self.send_header("Content-Type", "application/json; charset=utf-8") self.end_headers() self.wfile.write(payload)
if __name__ == "__main__": HTTPServer(("127.0.0.1", 8000), LectureSearchHandler).serve_forever()import { createServer } from 'node:http';import { SejongPublicData } from 'pro-sejongpeia';
const publicData = new SejongPublicData(); // 프로세스당 하나만 만들어 캐시를 공유const UNDERGRADUATE_CATEGORY = '20'; // 학교의 소속 분류 코드 (organizationCategories()로 확인)const YEAR = '2026';const SEMESTER = '20'; // 학기 목록은 terms(UNDERGRADUATE_CATEGORY)
async function searchLectures(departmentCode, courseName) { const lectures = await publicData.lectures({ categoryCode: UNDERGRADUATE_CATEGORY, year: YEAR, semesterCode: SEMESTER, departmentCode, courseName, }); return lectures.map((lecture) => ({ course: lecture.name, department: lecture.departmentName, schedule: lecture.schedule, credits: lecture.credits, courseNumber: lecture.courseNumber, }));}
createServer(async (request, response) => { const url = new URL(request.url, 'http://localhost'); let body; if (url.pathname === '/departments') { const departments = await publicData.departments({ categoryCode: UNDERGRADUATE_CATEGORY, year: YEAR, semesterCode: SEMESTER }); body = departments.map((department) => ({ code: department.code, college: department.collegeName, name: department.majorName || department.unitName })); } else if (url.pathname === '/lectures') { const departmentCode = (url.searchParams.get('department') ?? '').trim(); const courseName = (url.searchParams.get('name') ?? '').trim(); if (!departmentCode && !courseName) { // 조건이 없으면 그 학기 전체(수 MB)라서 이 서버는 조건을 필수로 함 response.writeHead(400).end('department or name is required'); return; } body = await searchLectures(departmentCode, courseName); } else { response.writeHead(404).end(); return; } response.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }).end(JSON.stringify(body));}).listen(8000, '127.0.0.1');