TJEdu 교육용 서버 · ctrlcv.kr · API v2.2 (API 키)

Git REST API 사용 설명서

포털로 돌아가기

이 문서는 교육용 서버에서 본인 호스팅 공간의 Git 저장소(repo.git)를 HTTPS REST API로 조작하고 커스텀 버전관리 웹 애플리케이션을 개발하는 방법을 설명합니다. 교육생·강사·관리자 로그인 세션을 기반으로 본인 디렉터리만 안전하게 조작할 수 있습니다.

변경 요약 (v2.2)

  • 모든 Git 명령에 TZ=Asia/Seoul → 커밋 시각 한국 시간(+0900)
  • historydate KST 정규화 + date_raw
  • 환경설정: 폴더 단위 대상(targets) · 예외(excludes)
  • commit은 설정 범위만 Git 스테이징 후 커밋
  • rollback 시 범위 내 변경이 있을 때만 자동 백업 커밋
  • 인증: Git API 키 (tjgit_…) — 포털 「새 API 키 발급」
  • 헤더 Authorization: Bearer <key> 또는 X-Git-Api-Key / body api_key
  • 포털 세션은 키 발급·폐기용 (폴백으로 git_api 호출도 가능)
  • 저장소: 공식 repo.git (Git 커밋)

엔드포인트 https://ctrlcv.kr/api.php?action=git_api

메서드 POST · Content-Type: application/json

인증 Git API 키 (권장) · 키 형식 tjgit_ + hex

키 발급 포털 로그인 → 마이페이지 → 새 API 키 발급

워크트리 /home/아이디/public_html

저장소 /home/아이디/repo.git

설정 파일 /home/아이디/git_api_settings.json

타임존 Asia/Seoul (KST)

1. 인증 (Git API 키)

// 권장: Authorization 헤더
Authorization: Bearer tjgit_xxxxxxxx...

// 또는
X-Git-Api-Key: tjgit_xxxxxxxx...

// 또는 JSON body
{
  "git_action": "history",
  "api_key": "tjgit_xxxxxxxx..."
}
curl -s https://ctrlcv.kr/api.php?action=git_api \
  -H "Authorization: Bearer tjgit_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"git_action":"history"}'

3. 환경설정 (폴더 대상 / 예외)

commit은 설정에 맞는 파일만 repo.git에 커밋합니다. 기본값은 targets: ["*"] (public_html 전체, 강제 예외 제외)입니다.

targets 값 의미
*public_html 전체 (권장 기본)
.루트 파일만 (하위 폴더 제외)
01, api, …해당 폴더(재귀) 또는 파일

강제 제외(항상): .env, .env.example, .git

// 설정 조회
{ "git_action": "get_settings" }

// 설정 저장
{
  "git_action": "save_settings",
  "targets": [".", "01", "api"],
  "excludes": ["node_modules", "*.log", "package-lock.json"]
}

// 저장 전 미리보기
{
  "git_action": "preview_targets",
  "targets": ["01"],
  "excludes": ["01/images"]
}
// get_settings 응답 일부
{
  "success": true,
  "settings": { "targets": ["*"], "excludes": [], "updated_at": "..." },
  "folders": [ { "path": "*", "label": "(전체 public_html)" }, ... ],
  "forced_excludes": [".env", ".env.example", ".git"],
  "preview_count": 42,
  "preview_files": ["index.php", "01/about.php", "..."],
  "storage": "repo.git"
}

2. 한국 시간(KST) 정책

서버 OS·PHP·Git 환경이 달라도, Git API는 항상 Asia/Seoul을 사용합니다.

구간 동작
commit / clone 쉘 환경 TZ=Asia/Seoul로 Git 실행 → Author/Committer 시각 +0900 기록
history / log date = KST 정규화 문자열 · date_raw = Git 원본 ISO-8601 · 응답 루트 timezone: "Asia/Seoul"
commit 응답 committed_at (예: 2026-07-29 14:30:00), timezone
기본 커밋 메시지 commit_msg 생략 시 버전 저장 - Y-m-d H:i:s (KST)

UI에 시간을 표시할 때는 date(이미 KST)를 그대로 쓰면 됩니다. 절대 시각 재계산이 필요하면 date_raw를 파싱하세요.

4. 주요 API 동작 기능 (git_action)

요청 body는 JSON 객체입니다. git_action이 필수이며, 생략 시 기본값은 status입니다. 저장소가 없을 때 주요 동작 호출 시 repo.git이 자동 초기화됩니다.

4.1 init — 저장소 자동/수동 초기화

{
  "git_action": "init"
}

repo.git을 만듭니다. 포털 UI의 기본 진입점은 새 API 키 발급이며, 키 발급 시 저장소가 없으면 자동 초기화됩니다. 커밋/히스토리 호출 시에도 없으면 자동 생성됩니다.

4.2 status — 변경 파일 상태 검사

{
  "git_action": "status"
}

수정·미추적 파일 목록을 반환합니다.

// 응답 예시
{
  "success": true,
  "initialized": true,
  "short_output": " M index.html\n?? app.js",
  "output": "On branch master\n..."
}

4.3 commit — 버전 커밋 저장

{
  "git_action": "commit",
  "commit_msg": "메인 디자인 및 반응형 UI 작성 완료"
}
  • 변경 파일은 repo.git에 Git 커밋으로 저장됩니다.
  • 환경설정의 targets / excludes에 해당하는 파일만 스테이징 후 커밋합니다.
  • user.name / user.email 자동 설정 · 타임스탬프 KST(+0900).
  • 변경이 없으면 success: false와 “커밋할 변경사항이 없습니다” 메시지.
// 응답 예시
{
  "success": true,
  "message": "Git 커밋이 저장되었습니다. (12개 파일)",
  "output": "...",
  "file_count": 12,
  "files": ["index.php", "01/about.php"],
  "committed_at": "2026-07-29 14:30:00",
  "timezone": "Asia/Seoul",
  "storage": "repo.git"
}

4.4 history / log — 커밋 타임라인 조회

{
  "git_action": "history"
}

최근 최대 20개 커밋을 배열로 반환합니다. log는 동일 동작입니다.

// 응답 예시
{
  "success": true,
  "timezone": "Asia/Seoul",
  "commits": [
    {
      "hash": "a1b2c3d",
      "author": "test",
      "date": "2026-07-29 14:30:00",
      "date_raw": "2026-07-29T14:30:00+09:00",
      "message": "메인 디자인 및 반응형 UI 작성 완료"
    }
  ],
  "raw_output": "a1b2c3d|test|2026-07-29T14:30:00+09:00|메인 디자인..."
}
필드 설명
hash짧은 커밋 해시
author작성자 이름
dateKST 정규화 시각 (Y-m-d H:i:s) — UI 표시용 권장
date_rawGit 원본 ISO-8601 (오프셋 포함)
message커밋 메시지
timezone응답 루트: 항상 Asia/Seoul

4.5 rollback / checkout — 지정 커밋으로 라이브 복구

{
  "git_action": "rollback",
  "commit_hash": "a1b2c3d"
}

지정 해시 상태로 public_html을 체크아웃합니다. 버전관리 대상 범위에 변경이 있을 때만 롤백 전 자동 백업 커밋을 생성합니다.

4.6 diff — 변경 내용 비교

{
  "git_action": "diff"
}

// 특정 커밋 기준
{
  "git_action": "diff",
  "commit_hash": "a1b2c3d"
}

commit_hash 생략 시 HEAD 기준 working tree diff를 반환합니다.

4.7 clone / pull — GitHub 원격 연동

// Clone (HTTPS GitHub URL)
{
  "git_action": "clone",
  "repo_url": "https://github.com/username/repository"
}

// Pull
{
  "git_action": "pull"
}

clone은 --separate-git-dir=repo.git 방식으로 워크트리와 저장소를 분리합니다. GitHub HTTPS URL 형식만 허용됩니다.

5. 공통 응답 규칙

6. JavaScript fetch() 연동 예제

포털 로그인 후 학생 서브도메인 페이지에서도 동일하게 호출할 수 있습니다. (반드시 credentials: 'include')

const GIT_API = 'https://ctrlcv.kr/api.php?action=git_api';
// 포털에서 발급한 키 (서버 사이드에 두는 것을 권장)
const GIT_API_KEY = 'tjgit_YOUR_KEY';

async function gitApi(git_action, payload = {}) {
    const res = await fetch(GIT_API, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + GIT_API_KEY
        },
        body: JSON.stringify({ git_action, ...payload })
    });
    return res.json();
}

// 1) 커밋 타임라인 (KST date 사용)
async function loadGitHistory() {
    const data = await gitApi('history');
    if (!data.success) {
        console.error(data.message);
        return;
    }
    console.log('timezone:', data.timezone); // "Asia/Seoul"
    data.commits.forEach(c => {
        // c.date → "2026-07-29 14:30:00" (이미 한국 시간)
        console.log(`[${c.date}] ${c.hash} ${c.message}`);
    });
}

// 2) 버전 커밋
async function saveVersion(msg) {
    const data = await gitApi('commit', { commit_msg: msg });
    if (data.success) {
        console.log('저장 시각(KST):', data.committed_at);
    }
}

// 3) 과거 버전으로 복구
async function restoreVersion(hash) {
    const data = await gitApi('rollback', { commit_hash: hash });
    console.log(data.message);
}

// 4) 화면에 리스트 렌더링 예시
async function renderHistory(listEl) {
    const data = await gitApi('history');
    if (!data.success) {
        listEl.textContent = data.message || '조회 실패';
        return;
    }
    listEl.innerHTML = data.commits.map(c => `
      <li>
        <strong>${c.message}</strong>
        <span>${c.date}</span>
        <code>${c.hash}</code>
      </li>
    `).join('');
}

7. 오류 메시지

message 원인
Git API 키가 필요합니다… 키/세션 없음 · 포털에서 키 발급 후 Bearer 헤더 사용
유효하지 않은 Git API 키입니다. 키 오타·폐기됨·다른 계정 키
로그인이 필요합니다. 키 발급/목록 API 호출 시 포털 세션 필요
권한이 없습니다. 타인 username 지정 (강사·관리자 외)
올바르지 않은 사용자명입니다. username 형식 불일치
웹 호스팅 디렉터리를 찾을 수 없습니다. public_html 없음
복원할 커밋 해시(Hash)가 필요합니다. rollback 시 commit_hash 누락
올바른 GitHub HTTPS 저장소 URL… clone 시 repo_url 형식 오류
올바르지 않은 Git 동작입니다. 지원하지 않는 git_action

8. 주의사항

문서 버전: 2026-07-29 · v2.2 Git API 키 인증 · 엔드포인트 api.php?action=git_api