Skip to content

FIX : 로깅 모듈 버그 2종 수정#70

Merged
Turtle-Hwan merged 3 commits into
Turtle-Hwan:mainfrom
ArticPenguin:fix/logger-dev-mode
Apr 28, 2026
Merged

FIX : 로깅 모듈 버그 2종 수정#70
Turtle-Hwan merged 3 commits into
Turtle-Hwan:mainfrom
ArticPenguin:fix/logger-dev-mode

Conversation

@ArticPenguin
Copy link
Copy Markdown
Contributor

#주요 변경점

  • 로컬 빌드 시 디버그 로그 미노출 버그 수정

  • Chrome 내부 객체 로깅 오류 수정

    1. 로컬 빌드 환경에서 디버그 로그가 출력되지 않던 버그

    문제
    로컬 테스트용으로 빌드(build:local)한 확장 프로그램에서 logger 모듈의 debugLog / infoLog가 전혀 출력되지 않아 디버깅이 사실상 불가능한 상태였습니다.

    원인
    로그 출력 여부를 결정하는 IS_DEV 값을 빌드 도구(Vite)가 제공하는 개발 모드 플래그로 판단하고 있었는데, 이 플래그는 로컬 빌드 시 항상 false로 처리되는 특성이 있었습니다. 즉, 아무리 로컬용 빌드 명령을 써도 프로덕션처럼 동작했습니다.

    결정
    빌드 도구 플래그 대신 빌드 스크립트에 명시된 mode 문자열을 직접 비교하도록 변경했습니다. build:local 스크립트에 --mode development가 붙어있는 한 IS_DEV가 정확히 true가 됩니다.


    2. Chrome 내부 객체가 [object Object]로 깨져 보이던 버그

    문제
    chrome.runtime.lastError 같은 Chrome 브라우저 내부 객체를 로그에 찍으면
    [object Object]로만 출력되어 어떤 에러인지 전혀 알 수 없었습니다.

    원인
    로거가 "일반 객체가 아닌 것"을 단순 문자열 변환(String())으로 처리했는데,
    Chrome 내부 객체는 프로퍼티(예: .message)가 숨겨진 방식으로 저장되어 있어
    일반적인 방법으로는 읽히지 않았습니다.

    결정
    숨겨진 프로퍼티까지 읽는 방식(Object.getOwnPropertyNames)으로 교체해
    Chrome 내부 객체도 의미있는 내용으로 출력되도록 수정했습니다.
    또한 클래스 인스턴스는 "[type]": "클래스명" 힌트를 함께 출력해 타입 파악을 쉽게 했습니다.


    앞으로의 협업 포인ㄴ트

    • 로컬 테스트 빌드: pnpm run build:local → debug/info 로그 정상 출력
    • 프로덕션 빌드: pnpm run build → 로그 자동 묵음 (기존과 동일)
    • 코드에서 로그를 찍을 때는 반드시 debugLog / infoLog / warnLog / errorLog 사용
      (console.log 직접 호출 금지 — 민감 정보가 배포 빌드에 노출될 위험)

    관리 포인트

    • build:local 스크립트에 반드시 --mode development가 유지되어야 합니다.
      이 플래그가 빠지면 로컬 빌드에서도 다시 로그가 묵음이 됩니다.

    변경 범위

    src/utils/logger.ts 단일 파일, 프로덕션 동작 변경 없음

LINKU 화이띵

ArticPenguin and others added 2 commits April 27, 2026 19:11
import.meta.env.DEV는 vite build 시 명령(command)을 기준으로 false로
치환되어 --mode development로 빌드해도 debugLog가 항상 묵음이 됨.
import.meta.env.MODE는 --mode 플래그 값을 그대로 반영하므로
build:local(--mode development)에서 debug/info 로그가 정상 출력됨.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

docs(logger): add comment explaining DEV vs MODE distinction

import.meta.env.DEV가 vite build 시 항상 false가 되는 이유와
MODE로 교체한 배경을 주석으로 명시함.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
기존에는 isPlainObject가 false인 객체(클래스 인스턴스, chrome API 객체 등)를
String()으로 변환해 "[object Object]"로 로깅되는 문제가 있었음.

Object.getOwnPropertyNames으로 교체해 non-enumerable 프로퍼티까지 추출하도록 수정.
이를 통해 chrome.runtime.lastError.message(non-enumerable)나 DOMException 등
Chrome 내부 객체도 의미있는 정보로 출력됨.
클래스 인스턴스에는 "[type]" 힌트를 추가해 타입 파악을 용이하게 함.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the IS_DEV flag to use import.meta.env.MODE for more reliable environment detection during local builds and enhances the sanitizeValue function to better handle non-plain objects and class instances by extracting properties and adding type hints. The review feedback suggests specifically handling RegExp objects to improve debug output and wrapping property access in a try-catch block to prevent potential crashes when encountering throwing getters or Proxy objects.

Comment thread src/utils/logger.ts Outdated
Comment on lines +147 to +149
const allKeys = isPlainObject(value)
? Object.keys(value)
: Object.getOwnPropertyNames(value as object);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

RegExp 객체는 일반 객체처럼 속성을 순회하는 것보다 toString()을 통해 정규식 패턴을 보여주는 것이 디버깅에 훨씬 유용합니다. 현재 로직에서는 RegExp가 non-plain 객체로 분류되어 lastIndex와 같은 내부 속성만 출력되는 문제가 있으므로, 순회 전에 별도로 처리하는 것을 권장합니다.

    if (value instanceof RegExp) {
      return sanitizeString(value.toString());
    }

    const allKeys = isPlainObject(value)
      ? Object.keys(value)
      : Object.getOwnPropertyNames(value as object);

Comment thread src/utils/logger.ts
Comment on lines +152 to 157
const sanitizedObject = keys.reduce<Record<string, unknown>>((acc, key) => {
acc[key] = SENSITIVE_KEY_PATTERN.test(key)
? REDACTED
: sanitizeValue(entryValue, depth + 1, seen);
: sanitizeValue((value as Record<string, unknown>)[key], depth + 1, seen);
return acc;
}, {});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

로깅 대상 객체가 Proxy이거나 특정 상황에서 예외를 던지는 getter를 가지고 있을 경우(예: 일부 브라우저 내부 객체), 속성 접근 시 로거 자체가 중단될 수 있습니다. 안전한 로깅을 위해 속성 값을 읽어올 때 try-catch로 보호하고, 민감한 키인 경우 접근 자체를 건너뛰도록 개선하는 것이 좋습니다.

Suggested change
const sanitizedObject = keys.reduce<Record<string, unknown>>((acc, key) => {
acc[key] = SENSITIVE_KEY_PATTERN.test(key)
? REDACTED
: sanitizeValue(entryValue, depth + 1, seen);
: sanitizeValue((value as Record<string, unknown>)[key], depth + 1, seen);
return acc;
}, {});
const sanitizedObject = keys.reduce<Record<string, unknown>>((acc, key) => {
if (SENSITIVE_KEY_PATTERN.test(key)) {
acc[key] = REDACTED;
return acc;
}
try {
acc[key] = sanitizeValue((value as Record<string, unknown>)[key], depth + 1, seen);
} catch (e) {
acc[key] = "[Error accessing property]";
}
return acc;
}, {});

RegExp 는 패턴 문자열로 바로 로깅되도록 분기했습니다.
throwing getter, Proxy, inspect 불가능한 객체로 인해 로거가 다시 실패하지 않도록
property access 와 type 조회를 방어하고 fallback 값을 추가했습니다.
@ArticPenguin
Copy link
Copy Markdown
Contributor Author

@codex issue fixed review agian

@ArticPenguin
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist issue fixed review agian

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves the logger utility by refining environment detection and enhancing object sanitization. It switches to import.meta.env.MODE to ensure debug logs are correctly enabled in local builds and updates sanitizeValue to better handle non-plain objects, including non-enumerable properties and class type hints. A bug was identified in the object sanitization logic where empty plain objects would incorrectly trigger the UNINSPECTABLE_OBJECT fallback; a suggestion was provided to ensure empty plain objects are returned correctly and to optimize type name retrieval.

Comment thread src/utils/logger.ts
Comment on lines +204 to +213
if (!plainObject) {
const typeName = getObjectTypeName(value as object);
if (typeName) {
sanitizedObject["[type]"] = typeName;
}
}

if (allKeys.length === 0 && Object.keys(sanitizedObject).length === 0) {
return getObjectTypeName(value as object) ?? UNINSPECTABLE_OBJECT;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

빈 일반 객체({})를 로깅할 때 [Uninspectable Object]가 반환되는 버그가 있습니다. plainObjecttrue인 경우에는 이 폴백 로직을 타지 않고 빈 객체({})를 반환해야 합니다. 또한 getObjectTypeName을 중복 호출하지 않도록 변수에 저장하여 재사용하는 것이 좋습니다.

Suggested change
if (!plainObject) {
const typeName = getObjectTypeName(value as object);
if (typeName) {
sanitizedObject["[type]"] = typeName;
}
}
if (allKeys.length === 0 && Object.keys(sanitizedObject).length === 0) {
return getObjectTypeName(value as object) ?? UNINSPECTABLE_OBJECT;
}
let typeName: string | null = null;
if (!plainObject) {
typeName = getObjectTypeName(value as object);
if (typeName) {
sanitizedObject["[type]"] = typeName;
}
}
if (!plainObject && allKeys.length === 0 && Object.keys(sanitizedObject).length === 0) {
return typeName ?? UNINSPECTABLE_OBJECT;
}

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9f34c6c02

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/logger.ts
Comment on lines +211 to +213
if (allKeys.length === 0 && Object.keys(sanitizedObject).length === 0) {
return getObjectTypeName(value as object) ?? UNINSPECTABLE_OBJECT;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return empty plain objects as objects

sanitizeValue now converts any object with zero own keys into the "[Uninspectable Object]" string, which regresses normal {} logging behavior and can violate the Record<string, unknown> contract of getErrorLogDetails when a plain empty object is thrown. In that case callers that spread the result (e.g. response-parse error logging paths) can get string-character keys instead of a structured object, so this fallback should be limited to non-plain/uninspectable host objects only.

Useful? React with 👍 / 👎.

@Turtle-Hwan Turtle-Hwan merged commit 5dcbbf0 into Turtle-Hwan:main Apr 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants