티스토리 뷰

반응형

 

얼마 전 회사 서비스에서 드디어 URL에 붙어있던 hash를 제거하게 되었다.

우리 서비스는 SPA(싱글 페이지 어플리케이션) 서비스라서 hash가 항상 붙어있었는데 이유는 Vue Router에서 기본 모드가 hash mode 이기 때문. 히스토리 모드로 변경해주면 hash가 없는 깔끔한 URL을 가질 수 있다.

 

공식 문서에 따르면 mode: 'history' 이 속성 하나만 추가해주면 되는 간단한 일이지만 우리는 기존에 레거시 코드도 많았고 이미 외부에 알려진 hash가 있는 URL에 대응하는 등의 작업도 있었기에 작업자 분이 2주에 걸쳐 작업해 주셨다.

 

작업자 분이 올려주신 PR을 보면서 내가 가장 의문이 갔었던 부분이 vue.config.js 파일에 multi page 설정 부분이었는데, 이걸 이해하기 위해 여러가지를 찾아보면서 내가 그동안 webpack 지식이 너무 없었다는 것을 깨달았고, 그래서 이해한 과정들을 정리해보기로 했다.

 

기존 문제점

먼저 기존의 문제점은 우리가 multi page 모드로 프로젝트를 운영하고 있었는데 아래 vue.config.js파일에 설정된 '/' 경로에 대응되는 'index' 키에서 빌드되는 페이지는 사실상 현재 사용하고있지 않은 소스였다. 그래서 'app'키에 대응되는 소스가 우리의 주요 페이지이고 기존 hash mode에 따라 URL에 '/app/#/'가 항상 붙어 있었다.

pages: {
    index: {
      entry: 'src/pages/index/main.js',
      template: 'public/index.html',
      filename: 'index.html',
    },
    app: {
      entry: 'src/pages/app/main.js',
      template: 'public/app/index.html',
      filename: 'app/index.html',
    },
}

여기서 router에 history 모드를 적용하게 되면 '/app/#/'가 사라지고 라우터에 설정한 path에 따라 뷰와 URL이 결정된다. 그래서 만약 '/app/#/user/' 라는 페이지가 있었다면 변경 후에는 '/user/' 이렇게 단순하게 변경된다. 그러나 여기서 새로고침을 하게 되면 hash가 사라졌기 때문에 바로 index.html 파일을 찾게 되고 해당 파일은 vue.config.js 설정에 따라 사용하지 않는 소스가 빌드되어 있기 때문에 엉뚱한 페이지가 출력되게 된다.

 

해결 방법

이를 해결하기 위해서는 두 가지 방법이 있는데

1. 기존 'index'키에 매핑된 사용하지 않는 소스를 'app'키에 매핑된 사용하는 소스로 변경한다.

2. app키에 매핑된 소스에서 사용되는 router에 baseURL을 설정한다.

 

2번 방법은 멀티 페이지 SPA를 운영하는 서비스에서 보편적으로 사용하는 방식인 것 같다. 앞서 설명한 '/app/#/user/'에서 라우터에 base: '/app/'을 적용하면 '/app/user/'로 URL이 설정되고 새로고침시에도 app/index.html 파일을 찾기 때문에 우리가 의도한 코드가 제대로 빌드될 것이다.

그러나 우리 코드는 기존 'index'에 매핑된 소스가 불필요 했으므로 아래와 같이 1번 방식을 사용하여 해결하였다.

pages: {
    main: {
      entry: 'src/pages/app/main.js',
      template: 'public/app/index.html',
      filename: 'index.html',
    },
    app: {
      entry: 'src/pages/app/main.js',
      template: 'public/app/index.html',
      filename: 'app/index.html',
    },
}

코드를 살펴보면 일단 기존에 있던 'index' 키가 사라지고 'main'이 추가되었는데, 나는 여기서 key name이 변경된것 자체에 초점을 맞추다보니 많이 헷갈렸었는데 사실 이름 변경 자체는 크게 의미있는 부분은 아니었다. 나중에야 깨달았지만 결국 index.html로 빌드 되기 때문에 키값은 전혀 상관없이 '/' 경로에 대응된다. 그리고 '/' 이하 경로에 기존 'app/' 이하 코드를 빌드하기 위해 entry와 template을 변경해 주었다. 사실상 'app'키와 filename 빼고 동일하게 작성해 주면 된다. 왜냐하면 'app'키는 기존 hashURL에 대한 대응을 위해 존재하는 것으로 기존에는 '/app/#/' 이러한 구조를 가지고 있었기 때문에 여기서 'app/' 이하에 대응해주기 위해 app/index.html로 아웃풋 파일을 도출하고 거기에 빌드되는 js 파일은 그대로 가져가는 것이다. 해당 빌드 파일에서 (정확히는 vue router guard에서) URL에 'app/#/' 문자열이 포함되어 있다면 해당 문자열을 제거해주는 작업을 수행하기 때문에 다시 '/' 경로로 이동되고 history 모드에 맞는 path로 진입할 수 있는 것이다.

 

좀 복잡해 보이지만 간단히 말하면 'main'키는 history 모드로 인한 '/'이하 경로의 진입점을 설정해 준 것이고, 'app'키는 외부에 알려진 기존의 'hashURL'에 대한 대응을 위해 남겨둔 것이다. 결국 둘다 똑같은 소스를 빌드하게 된다.

 

추가 정리

여기까지가 해결방법이었고, 내가 해결한 것은 아니지만 작업자 분의 코드를 보고 내가 이해하기까지의 과정을 정리해보았다. 여기서 궁금증이 완전히 해소되지 않은 부분이 있어서 몇가지 동작을 테스트 해보았다.

 

처음에는 vue.config.js 파일에서 일반적으로 '/'경로에는 'index'키가 예약어처럼 쓰이고 그 외 다른 키를 사용하면 '/main' 또는 '/app' 이렇게 경로가 대응되는 줄 알았다. 실제로 공식문서에도 "The value should be an object where the key is the name of the entry" 이렇게 쓰여있기 때문이다. 그러나 이건 반은 맞고 반은 틀리다. 

 

라우터가 'hash'모드이든, 'history'모드이든 filename을 중첩 경로 없이 index.html파일로만 빌드했다면 키값이 뭐든 상관이 없다. 왜냐하면 페이지 키값에 관계없이 일단 접속해서 '/' 경로에서 찾은 파일은 해당 빌드 파일이 될테니깐!

(대신 히스토리 모드에서는 '/' 뒤에 정확한 경로를 입력해줘야 하고, 해시 모드에서는 'localhost:8080/아무값이나입력#/' 이렇게 해줘도 결국 '#'뒤에 경로로만 라우터를 판단하기 때문에 접속이 가능하다.)

 

그러나 아웃풋 파일명(filename)에 중첩경로를 적용하면 키값이 중요하게 작동한다.

아래 코드를 예로 들어보면 해당 페이지는 'localhost:8080/temp'와 'localhost:8080/app/test' 두 경로로 접근할 때에만 페이지가 로드된다.

temp: {
    entry: 'src/pages/app/main.js',
    template: 'public/index.html',
    filename: 'app/test/index.html'
}

그리고 위 코드를 'history'모드로 작동시키면 더 복잡해진다. 'hash' 모드는 'localhost:8080/temp#/'이렇게 #아래 경로만 신경쓰면 되는데 'history'모드는 '/temp'나 '/app/test'에 해당하는 라우터 경로가 없으면 해당 라우터 뷰는 물론이고, '/'이 라우터 패스를 가진 컴포넌트도 볼 수 없다. (404 컴포넌트를 지정해줬다면 404가 나온다는 소리)

아무튼 히스토리모드인데 중첩 경로로 아웃풋을 낸다면 해당 폴더명 또는 키값과 일치하는 라우터 path를 반드시 지정해줘야 한다. 아니면 해당 값들을 앞서 해결방법 2에서 언급한 baseURL로 적용해줘야한다. 그렇기에 이 때는 키값이 중요한 역할을 하게되는 것이다.

 

내가 이해한 과정이 복잡해서 그런지 설명도 복잡해져 버렸는데,,, 암튼 index.html 파일의 위력과 중요성을 깨달은 좋은 시간이었다ㅠ_ㅠ

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함