Oh MyUtils

.env 편집기 - 환경 변수 파일 파싱, 검증, 비교 & 변환 온라인

.env 파일을 파싱, 검증, 비교, 변환합니다. 구문 검사, 나란히 비교, .env/JSON/YAML/Docker Compose 형식 변환 — 100% 클라이언트 사이드, 비밀 정보가 브라우저를 벗어나지 않습니다.

.env 내용

자주 묻는 질문

.env 파일 편집기란 무엇인가요?

.env 파일 편집기는 개발자가 .env(dotenv) 파일을 파싱, 검증, 편집, 정렬, 비교, 변환할 수 있는 온라인 도구입니다. .env 파일은 데이터베이스 연결, API 키, 기능 플래그 등의 설정을 KEY=value 쌍으로 저장합니다. 이 도구는 구문 검증, 알파벳 정렬, 두 .env 파일의 나란히 비교, .env/JSON/YAML/Docker Compose 간 형식 변환을 지원하며, 100% 브라우저에서 실행됩니다.

이 .env 편집기를 어떻게 사용하나요?

1. 편집 탭: .env 파일 내용을 입력 영역에 붙여넣습니다. 도구가 즉시 검증하여 오류와 경고를 표시합니다. 정렬 버튼으로 변수를 알파벳순으로 정렬하고, 포맷 버튼으로 출력을 정리합니다. 2. 비교 탭: 두 개의 .env 파일을 나란히 배치된 패널에 붙여넣습니다. 누락, 추가, 다른 값을 가진 변수를 강조 표시합니다. 3. 변환 탭: 지원되는 형식의 내용을 붙여넣고 출력 형식을 선택하면 즉시 변환됩니다.

데이터가 안전한가요? 서버로 전송되나요?

데이터는 100% 안전하며 브라우저를 벗어나지 않습니다. 모든 파싱, 검증, 비교, 변환은 전적으로 클라이언트 사이드 JavaScript에서 처리됩니다. 환경 변수, 비밀번호, API 키 등 어떤 설정 데이터도 서버로 전송되지 않습니다.

어떤 검증 검사를 수행하나요?

검증기는 다음을 확인합니다: (1) 잘못된 변수 이름 — 문자 또는 밑줄로 시작해야 하며 문자, 숫자, 밑줄만 포함해야 합니다. (2) 구분자 누락 — 각 비주석 줄에 = 기호가 필요합니다. (3) 중복 키. (4) 빈 값. (5) 닫히지 않은 따옴표. 각 문제에는 줄 번호가 포함됩니다.

.env 파일 비교는 어떻게 작동하나요?

비교 도구는 두 .env 파일을 분석하여 모든 변수를 네 그룹으로 분류합니다: (1) 파일 A에만 있음 — 빨간색으로 표시. (2) 파일 B에만 있음 — 초록색으로 표시. (3) 다른 값 — 노란색으로 표시. (4) 동일 — 같은 키와 값을 가진 변수. 각 카테고리의 수를 보여주는 요약을 제공합니다.

어떤 형식 간에 변환할 수 있나요?

네 가지 형식 간 양방향 변환을 지원합니다: (1) .env 형식 — 표준 KEY=value 쌍. (2) JSON — 플랫 JSON 객체. (3) YAML — YAML 키-값 매핑. (4) Docker Compose 환경 — docker-compose.yml에서 사용하는 environment: 목록 형식. 자동 형식 감지를 지원합니다.

.env 파일을 알파벳순으로 정렬할 수 있나요?

네, 정렬 기능은 모든 변수를 키 이름으로 알파벳순(A-Z 또는 Z-A)으로 정렬합니다. 주석은 보존되어 뒤따르는 변수에 연결되므로 문서가 정리된 상태를 유지합니다.

코드 예제

// .env File Parser, Validator, and Converter

function parseEnv(content) {
  const lines = content.split('\n');
  const entries = [];
  const errors = [];
  const warnings = [];
  const seen = new Map();

  for (let i = 0; i < lines.length; i++) {
    const lineNum = i + 1;
    const raw = lines[i];
    const trimmed = raw.trim();

    if (!trimmed || trimmed.startsWith('#')) continue;

    const eqIdx = trimmed.indexOf('=');
    if (eqIdx === -1) {
      errors.push({ line: lineNum, message: "Missing '=' separator" });
      continue;
    }

    const key = trimmed.slice(0, eqIdx).trim();
    let value = trimmed.slice(eqIdx + 1);

    if (!key) {
      errors.push({ line: lineNum, message: 'Empty key name' });
      continue;
    }
    if (!/^[A-Za-z_]\w*$/.test(key)) {
      errors.push({ line: lineNum, message: `Invalid name "${key}"` });
      continue;
    }

    // Handle quoted values
    if (value.startsWith('"') && value.endsWith('"')) {
      value = value.slice(1, -1).replace(/\\n/g, '\n');
    } else if (value.startsWith("'") && value.endsWith("'")) {
      value = value.slice(1, -1);
    } else {
      const commentIdx = value.indexOf(' #');
      if (commentIdx !== -1) value = value.slice(0, commentIdx);
      value = value.trim();
    }

    if (seen.has(key)) {
      warnings.push({ line: lineNum, message: `Duplicate key "${key}"` });
    }
    seen.set(key, lineNum);
    entries.push({ key, value, line: lineNum });
  }

  return { entries, errors, warnings };
}

function envToJson(entries, indent = 2) {
  const obj = {};
  for (const { key, value } of entries) obj[key] = value;
  return JSON.stringify(obj, null, indent);
}

function diffEnv(entriesA, entriesB) {
  const mapA = new Map(entriesA.map(e => [e.key, e.value]));
  const mapB = new Map(entriesB.map(e => [e.key, e.value]));
  const onlyInA = [], onlyInB = [], different = [], identical = [];

  for (const [key, valA] of mapA) {
    if (!mapB.has(key)) onlyInA.push(key);
    else if (mapB.get(key) !== valA) different.push({ key, valueA: valA, valueB: mapB.get(key) });
    else identical.push(key);
  }
  for (const key of mapB.keys()) {
    if (!mapA.has(key)) onlyInB.push(key);
  }
  return { onlyInA, onlyInB, different, identical };
}

// Usage
const result = parseEnv('DB_HOST=localhost\nDB_PORT=5432\nAPI_KEY=sk_live_abc');
console.log('Entries:', result.entries.length);
console.log('JSON:', envToJson(result.entries));

관련 도구