krx-js-client
v1.0.1
Published
KRX Javascript Client and Trigger Batch
Readme
krx-js-client
krx-js-client는 Node.js용 KRX(한국거래소) 데이터 클라이언트와 오전 조건 스캔 배치 도구를 함께 제공하는 ESM 패키지입니다.
이 패키지로 할 수 있는 일:
- 종목별 OHLCV, 시가총액, 기본적 지표 조회
- 날짜 기준 전 종목 스냅샷 조회
- 종목코드 ↔ 종목명 매핑 조회
- 오전 배치 트리거 실행 및 JSON 결과 저장
- KRX 직접 로그인 또는 Kakao 로그인 기반 세션 자동 관리
주의할 점:
- 패키지 루트(
krx-js-client)는 데이터 클라이언트 관련 export만 다시 내보냅니다. - 배치 API(
runBatch,triggerMorning...)는krx-js-client/trigger_batch.js로 직접 import해야 합니다. - 현재 CLI 모드는
morning만 구현되어 있습니다.afternoon은 구현되어 있지 않습니다. - 패키지에
playwright의존성은 포함되어 있지만, Chromium 브라우저 바이너리는 별도 설치가 필요할 수 있습니다.
1. 설치
이 패키지는 ESM("type": "module") 기준입니다.
프로젝트 로컬 설치
npm install krx-js-client처음 로그인/인증을 실행하는 환경이라면 Chromium 설치도 확인하세요.
npx playwright install chromium다음 상황에서는 위 명령이 특히 필요합니다.
browserType.launch: Executable doesn't exist같은 오류가 날 때- CI / 서버 / 새 개발 머신에서 처음 실행할 때
playwright패키지는 설치되어 있는데 실제 브라우저가 없는 경우
CLI를 전역으로 설치하고 싶다면
npm install -g krx-js-client
npx playwright install chromium전역 설치 후에는 krx-trigger 명령을 바로 사용할 수 있습니다.
2. 환경 변수와 인증 방식
기본 로그인 방식은 KRX 직접 로그인입니다.
KRX_LOGIN_METHOD기본값:krxKRX_LOGIN_METHOD=krx이면KRX_ID,KRX_PW필요- 그 외 값이면 Kakao 로그인으로 간주되며
KAKAO_ID,KAKAO_PW필요
환경 변수 목록
| 변수 | 기본값 | 용도 |
| --- | --- | --- |
| KRX_LOGIN_METHOD | krx | 로그인 방식 선택. krx면 KRX 직접 로그인, 그 외는 Kakao 로그인 |
| KRX_ID | 없음 | KRX 직접 로그인 ID |
| KRX_PW | 없음 | KRX 직접 로그인 비밀번호 |
| KAKAO_ID | 없음 | Kakao 로그인 ID |
| KAKAO_PW | 없음 | Kakao 로그인 비밀번호 |
.env 예시: KRX 직접 로그인
KRX_LOGIN_METHOD=krx
KRX_ID=your_krx_id
KRX_PW=your_krx_password.env 예시: Kakao 로그인
KRX_LOGIN_METHOD=kakao
KAKAO_ID=your_kakao_id
KAKAO_PW=your_kakao_password중요한 차이: 라이브러리 vs CLI
- CLI(
krx-trigger)는dotenv/config를 자동 로드합니다. - 라이브러리 사용 시에는
.env를 자동 로드하지 않습니다.
즉, 라이브러리에서 환경 변수를 쓰려면 직접 로드해야 합니다.
import 'dotenv/config';
import { get_market_ohlcv_by_ticker } from 'krx-js-client';
const rows = await get_market_ohlcv_by_ticker('20240102');
console.log(rows.slice(0, 3));3. 인증 관리자와 세션/캐시 파일
내장 인증은 KRXAuthManager가 담당합니다.
기본 파일 경로:
- 세션 파일:
~/.krx_session.json - 로그인 락 파일:
~/.krx_session.lock - ISIN 캐시 파일:
~/.krx_isin_cache.json
세션 파일(~/.krx_session.json)
로그인 성공 후 대략 아래와 같은 구조로 저장됩니다.
{
"cookies": {
"JSESSIONID": "...",
"mdc.client_session": "..."
},
"krx_cookies": [
{
"name": "mdc.client_session",
"value": "...",
"domain": "data.krx.co.kr",
"path": "/"
}
],
"last_login": "2026-04-09T07:00:00.000Z",
"last_validated": "2026-04-09T07:00:00.000Z"
}동작 특성:
- 세션 만료 기준: 4시간
- 최근 검증 freshness: 5분 이내면 재검증을 건너뜀
- 세션이 만료되면 요청 시 자동 재로그인을 최대 3회까지 시도
락 파일(~/.krx_session.lock)
동시에 여러 프로세스가 로그인할 때 충돌을 줄이기 위한 파일입니다.
- 락 획득 대기 타임아웃: 120초
- 오래된 락 파일은 자동 정리 시도
- 권한 문제나 비정상 종료가 있으면 수동 삭제가 필요할 수 있음
ISIN 캐시 파일(~/.krx_isin_cache.json)
종목코드 → ISIN 매핑을 캐시합니다.
{
"date": "20240102",
"cached_at": "2026-04-09T07:00:00.000Z",
"cache": {
"005930": "KR7005930003"
}
}동작 특성:
- 개별 종목 조회 시 내부적으로 ISIN 조회에 사용됩니다.
- 거래일 기준 캐시를 새로 구성합니다.
- 현재 공개 API에서 ISIN 캐시 경로를 바꾸는 옵션은 없습니다.
4. 빠른 시작
가장 간단한 라이브러리 사용
import 'dotenv/config';
import {
get_market_ohlcv_by_date,
get_market_ticker_name,
get_market_ticker_name_map,
} from 'krx-js-client';
const samsung = await get_market_ticker_name('005930');
console.log(samsung); // 삼성전자 같은 단일 문자열
const map = await get_market_ticker_name_map(null, 'KOSPI');
console.log(map['005930']);
const ohlcv = await get_market_ohlcv_by_date('20240102', '20240112', '005930');
console.log(ohlcv[0]);권장 방식: KRXAuthManager를 명시적으로 주입
주의: KRXDataClient 생성자 자체는 krxId, krxPw 같은 값을 직접 받지 않습니다. 환경 변수 또는 authManager를 사용해야 합니다.
import 'dotenv/config';
import { KRXAuthManager, KRXDataClient } from 'krx-js-client';
const authManager = new KRXAuthManager({
loginMethod: 'krx',
krxId: process.env.KRX_ID,
krxPw: process.env.KRX_PW,
headless: true,
});
const client = new KRXDataClient({ authManager });
const rows = await client.get_market_ohlcv_by_ticker('20240102', 'KOSPI');
console.log(rows.slice(0, 5));Kakao 로그인 예시
import 'dotenv/config';
import { KRXAuthManager, KRXDataClient } from 'krx-js-client';
const authManager = new KRXAuthManager({
loginMethod: 'kakao',
kakaoId: process.env.KAKAO_ID,
kakaoPw: process.env.KAKAO_PW,
headless: true,
});
const client = new KRXDataClient({ authManager });
const rows = await client.get_market_cap_by_ticker('20240102');
console.log(rows.slice(0, 3));테스트/모킹용 requestImpl 사용
requestImpl을 주면 내장 HTTP 요청과 자동 로그인 흐름을 우회합니다.
import { KRXDataClient } from 'krx-js-client';
const client = new KRXDataClient({
requestImpl: async (bld, params) => {
console.log('mock request', bld, params);
return [];
},
});
const rows = await client.get_market_ohlcv_by_ticker('20240102');
console.log(rows); // []5. 패키지 루트 export (import ... from 'krx-js-client')
패키지 루트는 index.js를 통해 krx_data_client.js의 export를 다시 내보냅니다.
5.1 오류 클래스
| export | 설명 |
| --- | --- |
| KRXAuthError | 인증/로그인 관련 기본 오류 |
| KRX2FARequiredError | 2차 인증이 필요한 상황을 표현하는 오류 클래스 |
| KRXSessionExpiredError | 세션 만료, 로그인 페이지 HTML 응답, 빈 응답 등 세션 유효성 문제 |
| KRXDataError | 데이터 조회/입력값 문제. 예: 종목을 찾을 수 없음, fetch 미설정 |
예시:
import 'dotenv/config';
import {
get_market_ohlcv_by_date,
KRXAuthError,
KRXSessionExpiredError,
KRXDataError,
} from 'krx-js-client';
try {
const rows = await get_market_ohlcv_by_date('20240102', '20240105', '005930');
console.log(rows);
} catch (error) {
if (error instanceof KRXSessionExpiredError) {
console.error('세션이 만료되어 재로그인이 필요합니다.');
} else if (error instanceof KRXAuthError) {
console.error('로그인 실패:', error.message);
} else if (error instanceof KRXDataError) {
console.error('데이터 오류:', error.message);
} else {
console.error(error);
}
}5.2 클래스
KRXAuthManager
생성자 옵션:
new KRXAuthManager({
kakaoId,
kakaoPw,
krxId,
krxPw,
loginMethod,
headless = true,
cookiePath,
lockPath,
loginProvider,
fetchImpl,
})주요 포인트:
- 기본 로그인 방식은
process.env.KRX_LOGIN_METHOD || 'krx' cookiePath기본값:~/.krx_session.jsonlockPath기본값:~/.krx_session.lockloginProvider를 주면 내장 Playwright 로그인 대신 사용자 정의 로그인 함수를 사용fetchImpl은 로그인 후 세션 검증용 API probe에 사용login({ force })메서드로 세션 로드/저장/재로그인 처리
loginProvider는 cookies 배열을 돌려주는 형태를 기대합니다.
import { KRXAuthManager } from 'krx-js-client';
const authManager = new KRXAuthManager({
loginMethod: 'krx',
krxId: 'id',
krxPw: 'pw',
loginProvider: async () => ({
cookies: [
{ name: 'mdc.client_session', value: 'dummy', domain: 'data.krx.co.kr', path: '/' },
],
}),
});
await authManager.login({ force: true });KRXDataClient
생성자 옵션:
new KRXDataClient({
autoLogin = true,
requestImpl = null,
fetchImpl = null,
authManager = null,
})주의할 점:
authManager를 주지 않고requestImpl도 없으면 내부에서new KRXAuthManager()를 생성합니다.- 이 경우 인스턴스 생성 시점에 환경 변수가 이미 준비되어 있어야 합니다.
autoLogin인자는 현재 구현에서 저장만 되고 실제 동작에는 사용되지 않습니다.fetchImpl을 주지 않으면globalThis.fetch를 사용합니다.- 런타임에
fetch가 없고fetchImpl도 주지 않으면KRXDataError('fetchImpl not configured')가 발생합니다.
5.3 함수 export
아래 함수들은 모두 패키지 루트에서 바로 import할 수 있습니다.
ensure_session_valid(): Promise<boolean>
기본 클라이언트의 세션이 유효한지 확인합니다.
- 최근 5분 이내에 확인했다면 네트워크 없이
true - 로그인 실패 시 예외를 던지지 않고
false
import 'dotenv/config';
import { ensure_session_valid } from 'krx-js-client';
const ok = await ensure_session_valid();
console.log('session ok?', ok);reset_session_freshness(): void
ensure_session_valid()의 freshness 캐시를 초기화합니다.
import { reset_session_freshness } from 'krx-js-client';
reset_session_freshness();get_market_ohlcv_by_date(fromdate, todate, ticker, adjusted = true)
개별 종목의 기간별 OHLCV를 반환합니다.
반환 shape:
[
{
date: Date,
Open: number | null,
High: number | null,
Low: number | null,
Close: number | null,
Volume: number | null,
Amount: number | null,
MarketCap: number | null,
},
]예시:
import 'dotenv/config';
import { get_market_ohlcv_by_date } from 'krx-js-client';
const rows = await get_market_ohlcv_by_date('20240102', '20240110', '005930');
console.log(rows[0]);get_market_ohlcv_by_ticker(date, market = 'ALL')
특정 거래일의 전 종목 OHLCV 스냅샷을 반환합니다.
내부적으로 지정 날짜가 휴장일이면 최근 거래일로 보정해서 조회합니다.
지원 시장 코드:
KOSPIKOSDAQKONEXALL
반환 shape:
[
{
ticker: string,
Open: number | null,
High: number | null,
Low: number | null,
Close: number | null,
Volume: number | null,
Amount: number | null,
},
]get_market_cap_by_ticker(date, market = 'ALL')
특정 거래일의 전 종목 시가총액 스냅샷을 반환합니다.
이 메서드도 내부적으로 최근 거래일 보정을 사용합니다.
반환 shape:
[
{
ticker: string,
MarketCap: number | null,
Volume: number | null,
Amount: number | null,
ListedShares: number | null,
},
]get_market_cap_by_date(fromdate, todate, ticker)
개별 종목의 기간별 시가총액/거래량/거래대금을 반환합니다.
[
{
date: Date,
MarketCap: number | null,
Volume: number | null,
Amount: number | null,
},
]get_market_fundamental_by_date(fromdate, todate, ticker)
개별 종목의 기본적 지표를 반환합니다.
[
{
date: Date,
BPS: number | null,
PER: number | null,
PBR: number | null,
EPS: number | null,
DIV: number | null,
DPS: number | null,
},
]get_market_trading_volume_by_date(fromdate, todate, ticker, detail = false)
투자자별 거래량을 반환합니다.
detail = false일 때:
[
{
date: Date,
기관합계: number | null,
기타법인: number | null,
개인: number | null,
외국인합계: number | null,
전체: number | null,
},
]detail = true일 때:
[
{
date: Date,
금융투자: number | null,
보험: number | null,
투신: number | null,
사모: number | null,
은행: number | null,
기타금융: number | null,
연기금: number | null,
기타법인: number | null,
개인: number | null,
외국인: number | null,
기타외국인: number | null,
전체: number | null,
},
]get_market_trading_value_by_date(fromdate, todate, ticker, on = '순매수')
투자자별 거래대금 계열 데이터를 반환합니다.
현재 구현 주의:
on인자는 실제로 사용되지 않습니다.- 내부적으로
get_market_trading_value_by_investor(fromdate, todate, ticker)를 그대로 호출합니다. - 즉, 현재 JS 구현에서는
on='순매수',on='매수',on='매도'같은 의미 구분이 없습니다.
반환 shape은 get_market_trading_value_by_investor(..., false)와 동일합니다.
get_market_trading_value_by_investor(fromdate, todate, ticker, detail = false)
투자자별 순매수 성격의 거래대금 데이터를 반환합니다. 구현상 buy - sell 계산으로 만들어집니다.
detail = false일 때:
[
{
date: Date,
기관합계: number,
기타법인: number,
개인: number,
외국인합계: number,
전체: number,
},
]detail = true일 때:
[
{
date: Date,
금융투자: number,
보험: number,
투신: number,
사모: number,
은행: number,
기타금융: number,
연기금: number,
기관합계: number,
기타법인: number,
개인: number,
외국인: number,
기타외국인: number,
},
]예시:
import 'dotenv/config';
import { get_market_trading_value_by_investor } from 'krx-js-client';
const rows = await get_market_trading_value_by_investor('20240102', '20240105', '005930', true);
console.log(rows[0]);get_market_ticker_list(date = null, market = 'KOSPI')
시장별 종목코드 배열을 반환합니다.
import 'dotenv/config';
import { get_market_ticker_list } from 'krx-js-client';
const kospiTickers = await get_market_ticker_list(null, 'KOSPI');
console.log(kospiTickers.slice(0, 10));get_market_ticker_name(ticker)
패키지 루트의 이 함수는 단일 종목코드에 대한 종목명 문자열을 반환합니다.
import 'dotenv/config';
import { get_market_ticker_name } from 'krx-js-client';
const name = await get_market_ticker_name('005930');
console.log(name); // 문자열get_market_ticker_name_map(date = null, market = 'ALL')
시장별 ticker -> name 맵 객체를 반환합니다.
import 'dotenv/config';
import { get_market_ticker_name_map } from 'krx-js-client';
const map = await get_market_ticker_name_map(null, 'ALL');
console.log(map['005930']);get_index_ohlcv_by_date(fromdate, todate, ticker, freq = 'd')
지수 OHLCV를 반환합니다.
[
{
date: Date,
Open: number | null,
High: number | null,
Low: number | null,
Close: number | null,
Volume: number | null,
Amount: number | null,
},
]주의:
- 구현상
ticker문자열의 첫 글자와 나머지를 분리해 API 파라미터로 사용합니다. freq인자는 현재 구현에서 실제로 사용되지 않습니다.
get_nearest_business_day_in_a_week(targetDate = null, prev = true)
가까운 거래일 문자열(YYYYMMDD)을 반환합니다.
주의:
- 현재 JS 구현에서는 사실상 "가장 가까운 최근 거래일" 헬퍼로 동작합니다.
prev인자는 의미 있게 사용되지 않습니다.
import { get_nearest_business_day_in_a_week } from 'krx-js-client';
const d = await get_nearest_business_day_in_a_week('20240106', true);
console.log(d); // 예: 202401055.4 추가 export: __test
소스에는 __test export도 존재합니다.
포함 항목:
parseNumberparseDateCookieJarextractOutputgetNearestBusinessDayFileLockensureClientSessionCookiereadSessionFilewriteSessionFilecreateTempSessionFile
테스트/내부 검증 성격으로 보이므로 애플리케이션 코드에서의 직접 의존은 권장하지 않습니다.
6. KRXDataClient 공개 메서드 정리
KRXDataClient는 아래 공개 메서드를 제공합니다.
| 메서드 | 설명 |
| --- | --- |
| get_market_ohlcv(fromdate, todate, ticker, adjusted = true) | 개별 종목 OHLCV |
| get_market_fundamental(fromdate, todate, ticker) | 개별 종목 기본적 지표 |
| get_market_trading_volume_by_date(fromdate, todate, ticker, detail = false) | 투자자별 거래량 |
| get_index_ohlcv(fromdate, todate, ticker, freq = 'd') | 지수 OHLCV |
| get_market_ohlcv_by_ticker(date, market = 'ALL') | 날짜 기준 전 종목 OHLCV |
| get_market_cap_by_ticker(date, market = 'ALL') | 날짜 기준 전 종목 시총 |
| get_market_ticker_name(date = null, market = 'ALL') | ticker -> name 맵 반환 |
| get_market_ticker_list(date = null, market = 'KOSPI') | 종목코드 배열 반환 |
| get_market_cap(fromdate, todate, ticker) | 개별 종목 시총 |
| get_nearest_business_day(targetDate = null) | 가장 가까운 최근 거래일 반환 |
| get_nearest_business_day_in_a_week(targetDate = null, prev = true) | 현재 구현상 위 메서드와 동일 |
| is_market_day(targetDate = null) | 거래일 여부 boolean |
| get_market_ohlcv_by_date(fromdate, todate, ticker, adjusted = true) | get_market_ohlcv 별칭 |
| get_market_cap_by_date(fromdate, todate, ticker) | get_market_cap 별칭 |
| get_market_fundamental_by_date(fromdate, todate, ticker) | get_market_fundamental 별칭 |
| get_index_ohlcv_by_date(fromdate, todate, ticker, freq = 'd') | get_index_ohlcv 별칭 |
| get_market_trading_value_by_date(fromdate, todate, ticker, on = '순매수') | 현재 구현상 investor 버전 위임 |
| get_market_trading_value_by_investor(fromdate, todate, ticker, detail = false) | 투자자별 거래대금 순값 |
로그인 관련 공개 메서드는 KRXDataClient가 아니라 KRXAuthManager.login({ force })에 있습니다.
중요 차이:
- 클래스 메서드
client.get_market_ticker_name(date, market)은 이름과 달리 종목명 문자열이 아니라 맵 객체를 반환합니다. - 패키지 루트 함수
get_market_ticker_name(ticker)만 단일 문자열을 반환합니다.
import 'dotenv/config';
import { KRXDataClient } from 'krx-js-client';
const client = new KRXDataClient();
const map = await client.get_market_ticker_name(null, 'ALL');
console.log(typeof map, map['005930']);7. 배치 API (import ... from 'krx-js-client/trigger_batch.js')
패키지 루트에서 재-export되지 않으므로 서브패스로 import하세요.
import { runBatch } from 'krx-js-client/trigger_batch.js';export 목록
| export | 설명 |
| --- | --- |
| runBatch(mode, logLevel = 'INFO', outputPath = null, injectedFunctions = {}) | 전체 배치 실행 |
| triggerMorningVolumeSurge(...) | 거래량 급증 상위주 계산 |
| triggerMorningGapUpMomentum(...) | 갭 상승 모멘텀 상위주 계산 |
| triggerMorningValueToCapRatio(...) | 시총 대비 집중 자금 유입 상위주 계산 |
| applyAbsoluteFilters(rows, minValue) | 배치 내부 절대 필터 유틸 |
| normalizeAndScore(...) | 정규화 + 점수화 유틸 |
| enhanceRows(rows, tickerMap) | 종목명 결합 유틸 |
| getSnapshot(tradeDate) | 일자 스냅샷 조회 |
| getPreviousSnapshot(tradeDate) | 직전 거래일 스냅샷 조회 |
| getMarketCapRows(tradeDate, market) | 시총 스냅샷 조회 |
runBatch 예시
import 'dotenv/config';
import { runBatch } from 'krx-js-client/trigger_batch.js';
const result = await runBatch('morning', 'INFO', './trigger-output.json');
console.log(result.metadata);outputPath를 생략하면 파일 저장 없이 결과 객체만 반환합니다.
morning 모드에서 생성되는 트리거 키
거래량 급증 상위주갭 상승 모멘텀 상위주시총 대비 집중 자금 유입 상위주
배치 결과 JSON shape
{
"거래량 급증 상위주": [
{
"code": "005930",
"name": "삼성전자",
"current_price": 70000,
"change_rate": 1.23,
"volume": 12345678,
"trade_value": 876543210000,
"volume_increase": 55.4
}
],
"갭 상승 모멘텀 상위주": [
{
"code": "035420",
"name": "NAVER",
"current_price": 200000,
"change_rate": 2.1,
"volume": 1000000,
"trade_value": 200000000000,
"gap_rate": 1.8
}
],
"시총 대비 집중 자금 유입 상위주": [
{
"code": "000660",
"name": "SK하이닉스",
"current_price": 180000,
"change_rate": 3.2,
"volume": 5000000,
"trade_value": 900000000000,
"trade_value_ratio": 0.45,
"market_cap": 130000000000000
}
],
"metadata": {
"run_time": "2026-04-09T08:00:00.000Z",
"trigger_mode": "morning",
"trade_date": "20260409",
"selection_mode": "direct",
"lookback_days": 10
}
}조건부 필드:
volume_increase: 거래량 급증 트리거일 때만 포함gap_rate: 갭 상승 모멘텀 트리거일 때만 포함trade_value_ratio,market_cap: 시총 대비 자금 유입 트리거일 때만 포함- 후보가 없으면 각 트리거 값은 빈 배열이 될 수 있음
8. CLI 사용법
실행 명령:
krx-trigger <mode> [LOG_LEVEL] [--output <path>]현재 허용값:
mode:morning만 가능LOG_LEVEL:DEBUG,INFO,WARNING
주의:
- 내부
runBatch()는ERROR레벨 숫자도 가지고 있지만, 실제 CLI 인자 파서는DEBUG,INFO,WARNING만 허용합니다. .env는 CLI가 자동 로드합니다.
예시
# 패키지를 로컬 설치한 프로젝트에서
npx krx-trigger morning INFO --output ./trigger-output.json# 로그를 더 자세히 보고 싶을 때
npx krx-trigger morning DEBUG# 전역 설치 후
krx-trigger morning WARNING --output /tmp/krx-morning.json도움말
krx-trigger --help9. 현재 구현 기준 제한사항 / 주의사항
이 항목들은 소스 기준 실제 구현 상태입니다.
afternoon모드는 구현되어 있지 않습니다.runBatch('afternoon', ...)와 CLIkrx-trigger afternoon은 실패합니다.
패키지 루트 함수
get_market_ticker_name(ticker)와 클래스 메서드client.get_market_ticker_name(date, market)의 의미가 다릅니다.- 루트 함수: 단일 종목명 문자열
- 클래스 메서드:
ticker -> name맵 객체
get_market_trading_value_by_date(..., on)의on파라미터는 현재 무시됩니다.- 내부적으로
get_market_trading_value_by_investor()에 그대로 위임됩니다.
- 내부적으로
get_nearest_business_day_in_a_week(targetDate, prev)의prev는 현재 구현에서 의미 있게 쓰이지 않습니다.- 사실상
get_nearest_business_day()와 동일하게 동작합니다.
- 사실상
거래일 계산 로직은 단순화되어 있습니다.
- 주말 제외
- 5월 1일, 12월 31일 제외
- 2025년 일부 휴장일만 하드코딩되어 있음
- 완전한 KRX 공식 휴장일 캘린더는 아닙니다.
get_index_ohlcv_by_date(..., freq)/get_index_ohlcv(..., freq)의freq인자는 현재 구현에서 사용되지 않습니다.get_market_ticker_name_map(date, market)/ 클래스의get_market_ticker_name(date, market)에서date인자는 현재 구현상 사용되지 않습니다.autoLogin생성자 옵션은 현재 구현에서 의미 있는 차이를 만들지 않습니다.requestImpl을 주면 내장 인증/세션 처리 흐름이 사실상 비활성화됩니다.- 테스트/모킹에는 좋지만 실제 KRX 통신에는 직접 책임져야 합니다.
Playwright 패키지는 의존성에 포함되어 있어도 브라우저 설치는 별도로 필요할 수 있습니다.
KRX 웹 페이지 구조나 로그인 셀렉터가 바뀌면 인증 흐름이 깨질 수 있습니다.
10. 문제 해결
10.1 KRX direct login requires KRX_ID and KRX_PW.
원인:
- 기본 로그인 방식이
krx인데 계정 정보가 없음
해결:
export KRX_LOGIN_METHOD=krx
export KRX_ID=your_id
export KRX_PW=your_password또는 .env를 설정하고, 라이브러리라면 import 'dotenv/config'를 직접 호출하세요.
10.2 Kakao login requires KAKAO_ID and KAKAO_PW.
원인:
KRX_LOGIN_METHOD가krx가 아닌 값인데 Kakao 계정 환경 변수가 없음
해결:
export KRX_LOGIN_METHOD=kakao
export KAKAO_ID=your_id
export KAKAO_PW=your_password10.3 playwright가 설치되지 않았습니다... 또는 Chromium 실행 파일 오류
원인:
- Playwright 패키지 또는 브라우저 바이너리가 준비되지 않음
해결:
npm install krx-js-client
npx playwright install chromium10.4 HTML response - session expired, Empty response - session expired, JSON parse failed - session expired
원인:
- 로그인 세션이 만료됨
- KRX가 JSON 대신 로그인 페이지/오류 페이지를 반환함
해결:
- 한 번 더 재시도
- 세션 파일 삭제 후 재로그인
- 브라우저 설치 상태 확인
rm -f ~/.krx_session.json ~/.krx_session.lock10.5 mdc.client_session 쿠키가 없습니다.
원인:
- 로그인은 진행됐지만 KRX 데이터 세션 쿠키 확보에 실패
해결:
npx playwright install chromium재실행- KRX 로그인 페이지 동작 변화 여부 확인
- headless 환경 문제라면
headless: false로 직접 점검
import 'dotenv/config';
import { KRXAuthManager } from 'krx-js-client';
const auth = new KRXAuthManager({
loginMethod: 'krx',
krxId: process.env.KRX_ID,
krxPw: process.env.KRX_PW,
headless: false,
});
await auth.login({ force: true });10.6 로그인 락 획득 타임아웃
원인:
- 다른 프로세스가 로그인 중이거나 stale lock이 남아 있음
해결:
rm -f ~/.krx_session.lock여러 프로세스가 동시에 뜨는 배치 환경이라면 시작 시점을 분산하세요.
10.7 종목을 찾을 수 없습니다: ...
원인:
- 잘못된 종목코드
- 비정상 캐시
- 거래일/티커 조합 문제
해결:
rm -f ~/.krx_isin_cache.json그 후 다시 조회하세요.
10.8 fetchImpl not configured
원인:
- 런타임에
globalThis.fetch가 없고fetchImpl도 주입하지 않음
해결:
import fetch from 'node-fetch';
import { KRXDataClient } from 'krx-js-client';
const client = new KRXDataClient({ fetchImpl: fetch });또는 fetch가 있는 Node 런타임을 사용하세요.
10.9 Invalid mode: afternoon 또는 CLI에서 morning 외 모드 실패
원인:
- 현재 구현은
morning전용
해결:
- CLI와
runBatch()모두morning만 사용하세요.
10.10 배치 결과가 빈 배열만 나온다
가능한 원인:
- 해당 거래일에 조건을 만족하는 종목이 없음
- 데이터 조회는 성공했지만 필터(거래대금/시총/상승 여부)에 모두 걸러짐
해결:
DEBUG로그로 실행- 출력 파일을 저장해서 메타데이터와 거래일 확인
npx krx-trigger morning DEBUG --output ./trigger-output.json10.11 CommonJS에서 require()가 바로 안 된다
원인:
- 패키지가 ESM(
"type": "module")임
해결:
import사용- 또는 동적 import 사용
const { get_market_ticker_name } = await import('krx-js-client');
console.log(await get_market_ticker_name('005930'));11. 참고 예제 모음
날짜 기준 전 종목 스냅샷 + 종목명 합치기
import 'dotenv/config';
import {
get_market_ohlcv_by_ticker,
get_market_ticker_name_map,
} from 'krx-js-client';
const tradeDate = '20240102';
const [rows, nameMap] = await Promise.all([
get_market_ohlcv_by_ticker(tradeDate, 'KOSPI'),
get_market_ticker_name_map(null, 'KOSPI'),
]);
const enriched = rows.slice(0, 10).map((row) => ({
...row,
name: nameMap[row.ticker] || '',
}));
console.log(enriched);세션을 미리 확인한 뒤 조회
import 'dotenv/config';
import {
ensure_session_valid,
get_market_cap_by_ticker,
reset_session_freshness,
} from 'krx-js-client';
const ok = await ensure_session_valid();
if (!ok) {
throw new Error('세션 준비 실패');
}
const rows = await get_market_cap_by_ticker('20240102');
console.log(rows.slice(0, 3));
reset_session_freshness();프로그램에서 배치 실행
import 'dotenv/config';
import { runBatch } from 'krx-js-client/trigger_batch.js';
const output = await runBatch('morning', 'INFO');
console.log(Object.keys(output));
console.log(output.metadata);12. 라이선스
LICENSE 파일을 참고하세요.
