본문 바로가기

카테고리 없음

ㅇㄹ

좋습니다! webpack 청크를 찾았네요. 이제 그 안에서 axios를 직접 꺼내보겠습니다.

```javascript
// Snippet: Extract Axios from Webpack Chunk
(function extractAxiosFromWebpack() {
  const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
  const refreshToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
  
  console.log('🔧 Webpack 청크에서 axios 추출 시작...\n');
  
  // 1. Storage 설정
  localStorage.setItem('accessToken', accessToken);
  localStorage.setItem('refreshToken', refreshToken);
  console.log('✅ Storage 설정 완료\n');
  
  // 2. Webpack 청크 접근
  const webpackChunk = window.webpackChunk_sovo_vo;
  
  if (!webpackChunk) {
    console.error('❌ Webpack 청크를 찾을 수 없습니다');
    return;
  }
  
  console.log('✅ Webpack 청크 발견');
  console.log('청크 타입:', Array.isArray(webpackChunk) ? 'Array' : 'Object');
  console.log('청크 길이/크기:', webpackChunk.length || Object.keys(webpackChunk).length);
  
  // 3. Webpack 청크 구조 분석
  console.log('\n🔍 청크 구조 분석...');
  
  let modules = {};
  let moduleCache = {};
  
  // webpack 5 형식: 배열 형태
  if (Array.isArray(webpackChunk)) {
    console.log('Webpack 5 형식 감지');
    
    webpackChunk.forEach((chunk, index) => {
      console.log(`  청크 ${index}:`, Array.isArray(chunk) ? `배열 [${chunk.length}]` : typeof chunk);
      
      if (Array.isArray(chunk) && chunk.length >= 2) {
        // chunk[0]: chunk id
        // chunk[1]: modules object
        const chunkModules = chunk[1];
        
        if (typeof chunkModules === 'object') {
          Object.assign(modules, chunkModules);
          console.log(`    → ${Object.keys(chunkModules).length}개 모듈 발견`);
        }
      }
    });
  }
  
  // webpack push 메서드 후킹
  if (webpackChunk.push !== Array.prototype.push) {
    console.log('✅ Webpack push 메서드가 오버라이드됨 (정상)');
  }
  
  // 4. __webpack_require__ 찾기
  console.log('\n🔍 __webpack_require__ 검색...');
  
  let webpackRequire = null;
  
  // window에서 검색
  for (let key in window) {
    try {
      const obj = window[key];
      // webpack require는 보통 .c (cache), .m (modules) 속성을 가짐
      if (obj && typeof obj === 'object' && (obj.c || obj.m)) {
        console.log(`✅ webpack require 발견: window.${key}`);
        webpackRequire = obj;
        
        if (obj.c) {
          console.log('  캐시된 모듈:', Object.keys(obj.c).length);
          moduleCache = obj.c;
        }
        if (obj.m) {
          console.log('  전체 모듈:', Object.keys(obj.m).length);
          modules = obj.m;
        }
        break;
      }
    } catch (e) {}
  }
  
  // 5. 모든 모듈에서 axios 찾기
  console.log('\n🔎 모듈에서 axios 검색...');
  
  let axiosFound = 0;
  const axiosModules = [];
  
  // 캐시된 모듈 우선 검색
  const allModules = { ...moduleCache, ...modules };
  
  for (let moduleId in allModules) {
    try {
      const module = allModules[moduleId];
      
      // module.exports 확인
      let exports = module.exports || module;
      
      // 함수형 모듈이면 실행 시도 (위험할 수 있음)
      if (typeof module === 'function') {
        try {
          const mockModule = { exports: {} };
          const mockRequire = () => ({});
          module(mockModule, mockModule.exports, mockRequire);
          exports = mockModule.exports;
        } catch (e) {
          // 실행 실패 시 무시
        }
      }
      
      // axios 패턴 체크
      function checkAxios(obj, path = moduleId) {
        if (!obj || typeof obj !== 'object') return;
        
        // 패턴 1: defaults.headers.common
        if (obj.defaults?.headers?.common) {
          axiosFound++;
          axiosModules.push({ obj, path });
          console.log(`✅ ${axiosFound}. axios 발견: ${path}`);
          console.log('   현재 Authorization:', obj.defaults.headers.common.Authorization);
          
          // 즉시 토큰 설정
          obj.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
          obj.defaults.headers.common.authorization = `Bearer ${accessToken}`;
          console.log('   ✅ 토큰 설정 완료');
          return true;
        }
        
        // 패턴 2: interceptors
        if (obj.interceptors?.request && obj.interceptors?.response) {
          axiosFound++;
          axiosModules.push({ obj, path });
          console.log(`✅ ${axiosFound}. axios 발견 (interceptors): ${path}`);
          
          if (obj.defaults?.headers) {
            obj.defaults.headers.common = obj.defaults.headers.common || {};
            obj.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
            console.log('   ✅ 토큰 설정 완료');
          }
          return true;
        }
        
        return false;
      }
      
      // exports 직접 체크
      if (checkAxios(exports, moduleId)) continue;
      
      // exports의 속성들 체크
      if (typeof exports === 'object') {
        for (let key in exports) {
          try {
            if (checkAxios(exports[key], `${moduleId}.${key}`)) break;
          } catch (e) {}
        }
      }
      
      // default export 체크
      if (exports.default) {
        checkAxios(exports.default, `${moduleId}.default`);
      }
      
    } catch (e) {
      // 모듈 접근 실패 무시
    }
  }
  
  console.log(`\n📦 총 ${axiosFound}개의 axios 인스턴스 발견 및 설정 완료`);
  
  // 6. axios 못 찾았으면 다른 방법 시도
  if (axiosFound === 0) {
    console.log('\n⚠️ 모듈에서 axios를 찾지 못했습니다');
    console.log('🔄 대체 방법 시도...\n');
    
    // 방법 1: 전역 axios 검색
    console.log('1️⃣ 전역 변수 검색...');
    for (let key in window) {
      try {
        const obj = window[key];
        if (obj?.defaults?.headers?.common) {
          obj.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
          console.log(`✅ window.${key} 설정 완료`);
          axiosFound++;
        }
      } catch (e) {}
    }
    
    // 방법 2: 네트워크 요청 강제 후킹
    console.log('\n2️⃣ 네트워크 요청 후킹 (강제 모드)...');
    
    const originalFetch = window.fetch;
    window.fetch = function(url, options = {}) {
      if (!options.headers) options.headers = {};
      
      // Headers 객체 처리
      if (options.headers instanceof Headers) {
        options.headers.set('Authorization', `Bearer ${accessToken}`);
      } else {
        options.headers['Authorization'] = `Bearer ${accessToken}`;
      }
      
      console.log(`🔐 FETCH 토큰 주입: ${url}`);
      return originalFetch.call(this, url, options);
    };
    
    const XHR = XMLHttpRequest.prototype;
    const open = XHR.open;
    const send = XHR.send;
    
    XHR.open = function(...args) {
      this._url = args[1];
      return open.apply(this, args);
    };
    
    XHR.send = function(...args) {
      if (!this.getResponseHeader || !this.getResponseHeader('Authorization')) {
        this.setRequestHeader('Authorization', `Bearer ${accessToken}`);
        console.log(`🔐 XHR 토큰 주입: ${this._url}`);
      }
      return send.apply(this, args);
    };
    
    console.log('✅ 네트워크 후킹 완료');
  }
  
  // 7. 최종 상태 출력
  console.log('\n📊 === 최종 상태 ===');
  console.log('✅ localStorage:', localStorage.getItem('accessToken') ? '설정됨' : '없음');
  console.log('✅ axios 설정:', axiosFound > 0 ? `${axiosFound}개` : '네트워크 후킹으로 대체');
  console.log('📍 현재 경로:', window.location.pathname);
  
  // 8. 모듈 정보 저장 (디버깅용)
  window.__debugAxios = {
    modules: axiosModules,
    webpackChunk,
    webpackRequire,
    moduleCache,
    totalModules: Object.keys(allModules).length
  };
  
  console.log('\n💡 디버깅 정보가 window.__debugAxios에 저장되었습니다');
  
  // 9. 대시보드로 이동
  console.log('\n🚀 3초 후 대시보드로 이동합니다...');
  
  setTimeout(() => {
    if (window.history) {
      window.history.pushState({}, '', '/dashboard');
      window.dispatchEvent(new PopStateEvent('popstate'));
    }
    
    setTimeout(() => {
      window.location.href = '/dashboard';
    }, 1000);
  }, 3000);
  
})();
```

## 추가: 더 강력한 모듈 검색

```javascript
// Snippet 2: Deep Module Search
(function deepModuleSearch() {
  console.log('🔬 심층 모듈 검색 시작...\n');
  
  const webpackChunk = window.webpackChunk_sovo_vo;
  
  // webpack의 모든 내부 구조 출력
  console.log('Webpack 청크 구조:');
  console.dir(webpackChunk, { depth: 2 });
  
  // push된 모든 청크 확인
  if (Array.isArray(webpackChunk)) {
    console.log('\n청크 상세:');
    webpackChunk.forEach((chunk, i) => {
      console.log(`\n청크 ${i}:`);
      console.log('  타입:', Array.isArray(chunk) ? 'Array' : typeof chunk);
      
      if (Array.isArray(chunk)) {
        console.log('  길이:', chunk.length);
        chunk.forEach((item, j) => {
          console.log(`  [${j}] 타입:`, typeof item);
          if (typeof item === 'object' && item !== null) {
            console.log(`  [${j}] 키:`, Object.keys(item).slice(0, 10));
          }
        });
      }
    });
  }
  
  // 특정 키워드로 모듈 검색
  console.log('\n\n🔍 "axios" 키워드 검색...');
  
  function searchInObject(obj, path = '', depth = 0, maxDepth = 8) {
    if (depth > maxDepth || !obj) return;
    
    try {
      const objStr = JSON.stringify(obj).toLowerCase();
      
      if (objStr.includes('axios') ||
          objStr.includes('interceptor') ||
          objStr.includes('bearer')) {
        console.log(`✅ 발견: ${path || 'root'}`);
        console.log('  미리보기:', objStr.substring(0, 200));
        
        // axios 인스턴스인지 확인
        if (obj.defaults?.headers?.common) {
          console.log('  🎯 이것은 axios 인스턴스입니다!');
          console.log('  객체:', obj);
          return obj;
        }
      }
      
      if (typeof obj === 'object' && depth < maxDepth) {
        for (let key in obj) {
          const result = searchInObject(obj[key], `${path}.${key}`, depth + 1, maxDepth);
          if (result) return result;
        }
      }
    } catch (e) {}
  }
  
  const found = searchInObject(webpackChunk);
  
  if (found) {
    console.log('\n🎉 axios 인스턴스 발견!');
    window.__foundAxios = found;
    console.log('window.__foundAxios에 저장되었습니다');
  } else {
    console.log('\n❌ axios를 찾지 못했습니다');
  }
})();
```

이 스크립트를 실행하고 결과를 알려주세요. 특히:
1. "axios 발견" 메시지가 나오는지?
2. "청크 상세" 섹션의 구조는 어떤지?
3. Console에 에러가 있는지?