add standalone port-forwarding tool (마인크래프트 간편 포트포워딩)

포트포워딩만 단독으로 수행하는 세 번째 Electron 앱 추가.
- 포트 입력(기본 25565) → UPnP 개방 시도 → 외부에서 닿는지 점검(ifconfig.co
  + 임시 리스너) → 외부 접속 주소/성공·실패·확인불가 안내. '포트 닫기'로 매핑 제거.
- 점검 로직은 메인 설치기의 v0.3.14 오탐 수정(ifconfig 실패→확인불가)을 반영해
  자체 포함. sharp 미사용이라 빌드에서 제외(exe 약 73MB).
- 신규: src/installer-pf/{main,preload}.ts, installer-pf/{index.html,renderer.js},
  locales/installer-pf/ko-kr.json, tsconfig.installer-pf.json, electron-builder-pf.yml.
- package.json 에 installer:pf / dist:win:pf 스크립트, i18n 컴포넌트 유니온에
  'installer-pf' 추가. v0.3.15.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 21:43:06 +09:00
parent f554559be9
commit 86883f56e4
9 changed files with 686 additions and 3 deletions

View File

@@ -0,0 +1,64 @@
{
"app": {
"title": "마인크래프트 간편 포트포워딩"
},
"logViewer": {
"heading": "로그",
"collapse": "접기",
"expand": "펼치기"
},
"verdict": {
"success": "성공",
"fail": "실패",
"unknown": "확인 불가"
},
"main": {
"heading": "포트 열기",
"intro": "UPnP 로 라우터에 포트를 열고, 외부에서 실제로 닿는지 확인합니다. 마인크래프트 자바 서버는 TCP 25565 를 사용합니다.",
"portLabel": "포트",
"openBtn": "포트 열기 / 확인",
"closeBtn": "포트 닫기",
"quitBtn": "종료",
"working": "포트를 여는 중입니다… (외부 점검까지 최대 1분 정도 걸릴 수 있어요)",
"ipUnknown": "외부IP-확인불가",
"successMsg": "외부에서 접속 가능합니다. 접속 주소: {{addr}}",
"alreadyOpen": "(이미 열려 있던 상태입니다)",
"failMsg": "외부에서 포트에 닿지 않습니다. 라우터 UPnP 설정, 이중 NAT(CGNAT), Windows 방화벽, 또는 포워딩 대상 IP 를 확인하세요.",
"unknownMsg": "외부 도달 여부를 확정하지 못했습니다(외부 점검 서비스 응답 없음). 포트 매핑은 등록되었을 수 있습니다. 잠시 후 다시 시도하거나, 실제 접속으로 확인하세요.",
"detailLabel": "점검 상세: {{detail}}",
"error": "오류: {{message}}",
"closed": "포트 {{port}} 매핑을 제거했습니다."
},
"log": {
"start": "포트포워딩 시작: TCP {{port}}",
"cleanup": "이전 UPnP 매핑 정리 중…",
"externalIpHttp": "외부 IP(HTTP): {{ip}}",
"externalIpHttpFail": "외부 IP HTTP 조회 실패 → UPnP 게이트웨이로 폴백",
"externalIpUpnp": "외부 IP(UPnP): {{ip}}",
"externalIpFail": "외부 IP 확인 실패",
"probeStart": "외부 포트 점검 시작…",
"probeResult": "점검 결과: {{verdict}} ({{detail}})",
"preForwarded": "이미 외부에서 접속 가능한 상태입니다.",
"upnpTry": "UPnP 포트 개방 시도: TCP {{port}}",
"upnpReqOk": "UPnP 매핑 요청 성공.",
"upnpTryFail": "UPnP 개방 실패: {{message}}",
"recheck": "UPnP 반영 재점검 {{attempt}}/3…",
"upnpDone": "UPnP 개방 확인 완료: TCP {{port}}",
"upnpUnconfirmed": "UPnP 매핑은 등록됐지만 외부 도달은 확정되지 않았습니다.",
"closeTry": "UPnP 매핑 제거 시도: TCP {{port}}",
"upnpRemoveAttempt": "UPnP 매핑 제거 시도: {{message}}",
"upnpRemoveDone": "UPnP 매핑 제거 완료: TCP {{port}}",
"upnpClientFail": "UPnP 클라이언트 생성 실패: {{message}}",
"portInUse": "포트 {{port}}이(가) 이미 사용 중 → 임시 리스너 없이 외부 서비스 응답만으로 판정.",
"listenerBindFail": "임시 리스너 바인딩 실패: {{message}}",
"detailListenerHit": "임시 리스너 도달={{value}}",
"detailListenerSkip": "임시 리스너=skip(포트 사용중)",
"detailIfconfig": "ifconfig.co reachable={{reachable}} ip={{ip}}",
"detailIfconfigFail": "ifconfig.co 실패={{error}}",
"detailNone": "결과 없음"
},
"errors": {
"requestTimeout": "요청 시간 초과",
"upnpTimeout": "UPnP 요청 시간 초과"
}
}