JavaScript로 윈도우 탐색기처럼 정렬하기

2019. 10. 16. 12:24· 개발/Frontend

JavaScript에는 많은 정렬 함수가 있지만, 우리가 흔히 보는 파일 정렬 순서와는 결과가 좀 다르다.

 

Electron으로 파일 관련 프로젝트를 개발하다 파일 정렬 때문에 골머리를 앓았다.

 

앞서 이야기한 것처럼JavaScript에는 많은 정렬 함수가 있지만 윈도우 탐색기에서 보는 정렬 순서와는 결과가 좀 다르다.

JavaScript로는 이런 결과가 흔히 나타난다.

var arr = ["filename 0.txt","filename 1.txt","filename 9.txt","filename 10.txt","filename 11.txt"];
arr.sort();
console.log(arr);
// 0: "filename 0.txt"
// 1: "filename 1.txt"
// 2: "filename 10.txt"
// 3: "filename 11.txt"
// 4: "filename 9.txt"

9가 10보다 뒤로 간다!

 

이걸 볼 때마다 뒷목을 잡으면서 쓰러지고 싶어진다.

 

JavaScript의 Array.sort 함수는 매개변수로 정렬 순서에 사용할 함수를 넘길 수 있다.

그렇기 때문에 https://tonks.tistory.com/124 같은 많은 정렬 순서 함수들이 넘쳐난다.

 

하지만 결과는 위 테스트 결과와 크게 다르지 않다.

 

왜냐하면 Windows 탐색기는 자연 정렬 순서라고 하는 별도의 정렬 방식이 있기 때문에 단순한 정렬 함수로는 차이가 나올 수 밖에 없다.

 

Windows 탐색기는 API 함수 StrCmpLogicalW()기능을 사용하여 정렬을 수행한다고 한다. (참고링크 1, 2)

WindowsExplorerSort 알고리즘은 크게 아래와 같은 규칙을 따른다고 한다.

 

  • 파일 이름은 부분적으로 비교된다. (숫자와 공백, 나머지가 따로따로 비교된다)
  • 파일 이름의 숫자는 비교 가능한 숫자로 간주한다. (string이 아닌 int로 비교한다.)
  • 숫자는 숫자형으로 비교되지만 같으면 더 긴 문자열이 우선된다. (filename00.txt, filename0.txt 순서임)
  • 만약 숫자와 숫자가 아닌 부분을 비교하게 되면 둘다 텍스트로 간주한다.
  • 텍스트는 대소문자를 구분하지 않고 비교된다.

이러한 규칙을 조금이라도 따라하기 위해선 localeCompare를 사용하면 된다. (참고링크 3)

 

단, 많은 수의 문자열을 정렬 할 때 성능을 높이기 위해서는 Intl.Collator객체 를 만들고 해당 compare속성에서 제공하는 함수 를 사용하는 것이 좋다고 한다. (참고링크 4)

var collator = new Intl.Collator('en', {numeric: true, sensitivity: 'base'});
var arr = ["filename 0.txt","filename 1.txt","filename 9.txt","filename 10.txt","filename 11.txt"];
console.log(arr.sort(collator.compare));
// 0: "filename 0.txt"
// 1: "filename 1.txt"
// 2: "filename 9.txt"
// 3: "filename 10.txt"
// 4: "filename 11.txt"

드디어!

좀 봐줄만하게 나왔다.

 

다만 WindowsExplorerSort 알고리즘 중 3번째는 적용이 되지 않는다.

현재 코드로는 짧은 문자열이 우선되고 있다.

var collator = new Intl.Collator('en', {numeric: true, sensitivity: 'base'});
var arr = ["filename 0.txt","filename 1.txt","filename 9.txt","filename 10.txt","filename 11.txt","filename00.txt","filename 00.txt","FILENAME 2.txt","새 텍스트.txt"];
console.log(arr.sort(collator.compare));
// 0: "filename 0.txt"
// 1: "filename 00.txt"
// 2: "filename 1.txt"
// 3: "FILENAME 2.txt"
// 4: "filename 9.txt"
// 5: "filename 10.txt"
// 6: "filename 11.txt"
// 7: "filename00.txt"
// 8: "새 텍스트.txt"

이건 좀 아쉬운 부분이다.

그래도 이것만 빼면 윈도우 탐색기와 제일 유사하게 나온다.

 

실제 WindowsExplorerSort는 아래와 같다

 

영어가 우선이고 한글이 그 다음에 오는데, 한글을 위로 올리고 싶으면 아래 코드를 사용하면 된다.

var collator = new Intl.Collator('kr', {numeric: true, sensitivity: 'base'}); // kr 명시
var arr = ["filename 0.txt","filename 1.txt","filename 9.txt","filename 10.txt","filename 11.txt","filename00.txt","filename 00.txt","FILENAME 2.txt","새 텍스트.txt"];
console.log(arr.sort(collator.compare));
// 0: "새 텍스트.txt"
// 1: "filename 0.txt"
// 2: "filename 00.txt"
// 3: "filename 1.txt"
// 4: "FILENAME 2.txt"
// 5: "filename 9.txt"
// 6: "filename 10.txt"
// 7: "filename 11.txt"
// 8: "filename00.txt"

 

 

여기서 실수할 수 있는데,

테스트 정렬이 잘 된다고 이 코드를 그냥 붙여넣으면 안 된다.

 

테스트와 동일하게 배열이 key 없이 value만 있으면 이 코드를 그대로 사용해도 무방하지만

실제 파일 리스트를 담고 있는 File 객체는 배열이 아닌 객체다!

 

따라서 File 객체에 담긴 실제 파일명을 비교해줘야 한다. (File.name)

혹은 파일의 전체 경로인 File.path도 괜찮다.

 

Electron에선 File 객체에 path 속성도 제공해주고 있어 난 path를 사용했다.

 

File.name 혹은 File.path를 정렬하는 코드는 아래 코드를 사용하면 된다.

// var files = 실제 파일 배열
var collator = new Intl.Collator('en', {numeric: true, sensitivity: 'base'});
files = files.sort((a, b) => collator.compare(a.name, b.name)) // 혹은 a.path, b.path

 

 

참고 링크.

1. https://stackoverflow.com/questions/23205020/java-sort-strings-like-windows-explorer

2. https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strcmplogicalw

3. https://stackoverflow.com/questions/2802341/javascript-natural-sort-of-alphanumerical-strings

4. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

5. https://codepen.io/TimPietrusky/pen/rKzoGN

 

 

저작자표시 비영리 변경금지 (새창열림)

'개발 > Frontend' 카테고리의 다른 글

[Vue] pinia store로 테마 관리하기  (0) 2024.04.28
[CSS] 다크모드 완벽 지원하기  (1) 2024.01.24
'개발/Frontend' 카테고리의 다른 글
  • [Vue] pinia store로 테마 관리하기
  • [CSS] 다크모드 완벽 지원하기
HuiYa
HuiYa
8년차 Backend / Frontend 개발자의 기술 블로그
HuiYa
by HuiYa
HuiYa
전체
오늘
어제
  • 분류 전체보기 (24)
    • 공지 (0)
    • 일상 (0)
    • 개발 (19)
      • Network (1)
      • Backend (9)
      • Frontend (3)
      • Electron (2)
      • 기타 (4)
    • 프로젝트 (1)
      • Penly (1)
    • IT 기기 (3)
      • 리디 페이퍼 (1)
    • 취미 (0)

인기 글

최근 글

최근 댓글

태그

  • 핸드폰불
  • ds920
  • 인증처리
  • 스크롤다크모드
  • 최소일치
  • natural sort order
  • DS920+
  • 엔진엑스
  • 최소매치
  • pinia
  • spring
  • 일렉트론
  • 시놀로지
  • 빌드
  • jjwt
  • 피니아
  • build
  • synology
  • SpringBoot
  • electron-builder
  • nginx
  • electron
  • 아파치
  • apache
  • javascript
  • js
  • CVE-2021-44228
  • html
  • 0.12.3
  • 메일
hELLO · Designed By 정상우.v4.2.2
HuiYa
JavaScript로 윈도우 탐색기처럼 정렬하기
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.