[JavaScript] Lv0 - 0 떼기

Moon·2025년 11월 30일
post-thumbnail

0떼기

문제 설명

정수로 이루어진 문자열 n_str이 주어질 때, n_str의 가장 왼쪽에 처음으로 등장하는 0들을 뗀 문자열을 return하도록 solution 함수를 완성해주세요.


제한사항

  • 2 ≤ n_str ≤ 10
  • n_str이 "0"으로만 이루어진 경우는 없습니다.

입출력 예

n_strresult
"0010""10"
"854020""854020"

입출력 예 설명

입출력 예 #1

  • "0010"의 가장 왼쪽에 연속으로 등장하는 "0"을 모두 제거하면 "10"이 됩니다.

입출력 예 #2

  • "854020"는 가장 왼쪽에 0이 없으므로 "854020"을 return합니다.

1. 문제 정리

  • 입력: "0010", "854020" 같은 정수로 이루어진 문자열 n_str
  • 해야 할 일:
    • 문자열 왼쪽에서부터 연속해서 등장하는 '0'들을 전부 제거
    • 단, 중간이나 끝에 있는 0은 유지
  • 보장 조건:
    • 길이는 2 이상 10 이하
    • "0"으로만 이루어진 문자열은 없다 → 결과 문자열은 반드시 비어있지 않다

즉, “첫 번째 0이 아닌 문자가 나올 때까지의 0들을 제거하고, 그 뒤는 그대로 둔다”는 문제다.


2. 권장 풀이 — 정규식 replace 사용

가장 간결하면서도 의도가 잘 드러나는 방식은 정규식을 이용한 치환이다.

function solution(n_str) {
  return n_str.replace(/^0+/, '');
}

코드 해설

  • ^0+ 정규식의 의미
    • ^ : 문자열의 시작을 의미한다.
    • 0+ : 문자 '0'1개 이상 연속해서 나오는 구간을 의미한다.
  • n_str.replace(/^0+/, '')
    • 문자열 시작 부분에서 연속된 0들을 찾아서
    • 빈 문자열로 치환 → 즉, 제거한다.

예시 동작

  • "0010".replace(/^0+/, '')"10"
  • "854020".replace(/^0+/, '')"854020" (앞에 0이 없으므로 변경 없음)
  • "00012300".replace(/^0+/, '')"12300" (맨 앞 0만 제거, 뒤의 00은 유지)

왜 이 풀이를 1순위로 추천하는가?

  1. 의도가 선언적으로 드러난다

    “문자열 시작(^)에서 0들을 제거하겠다”라는 의도가 코드 레벨에서 바로 보인다.

  2. 구현이 매우 간단하고, 에지 케이스까지 자연스럽게 처리한다.

  3. 문제의 요구사항(앞쪽 0만 제거)에 정확히 대응하는 패턴이다.

실무에서도 정규식 기반의 replace입력 정제, 포맷팅, 마스킹 등에 매우 자주 쓰이는 패턴이므로 익숙해질 가치가 크다.


3. 대안 풀이 1 — 인덱스를 직접 찾는 방식

정규식을 쓰지 않고, 문자열을 직접 순회하며 첫 번째 0이 아닌 문자의 위치를 찾아 slice 하는 방식도 있다.

function solution(n_str) {
  let index = 0;

  while (index < n_str.length && n_str[index] === '0') {
    index++;
  }

  return n_str.slice(index);
}

코드 해설

  1. index를 0부터 시작한다.
  2. 문자열을 왼쪽에서 오른쪽으로 보면서:
    • 현재 문자가 '0'이면 index++
    • '0'이 아닌 문자를 만나면 반복 종료
  3. n_str.slice(index)로 해당 위치부터 끝까지 잘라서 반환

장점

  • 동작 방식이 매우 직관적이다.
  • 정규식을 모르는 사람에게도 쉽게 설명 가능하다.
  • 시간 복잡도는 O(n) → 이 문제 크기(최대 10)에서는 의미 없지만, 길이가 매우 길어져도 효율적이다.

단점

  • 같은 기능을 수행하는데 코드 라인이 늘어난다.
  • 정규식 풀이에 비해 “패턴 기반 문자열 처리”라는 관점에서는 덜 선언적이다.

정규식을 팀에서 선호하지 않거나, 정규식 사용이 부담되는 초기 학습 단계라면 이 방법도 좋은 선택이다.


4. 대안 풀이 2 — 숫자로 변환 후 다시 문자열로

이 문제는 입력이 “정수로 이루어진 문자열”이며, "0"으로만 이루어진 문자열은 주어지지 않는다고 명시되어 있다.

따라서 숫자로 한 번 변환했다가 다시 문자열로 바꾸는 방식도 동작한다.

function solution(n_str) {
  return String(Number(n_str));
}

혹은:

function solution(n_str) {
  return String(parseInt(n_str, 10));
}

동작 원리

  • Number("0010")10 (숫자 타입)
  • String(10)"10"

즉, 숫자 변환 과정에서 자동으로 선행 0들이 제거된다.

이 방식의 문제점 (왜 “보조적” 방법인가?)

  1. 문제의 요구는 “문자열 처리”인데, 중간에 불필요하게 숫자 타입으로 바꾼다.
    • 문자열 포맷을 유지해야 하는 문제(예: 전화번호, 카드번호 등)에서는 위험할 수 있다.
  2. 향후 문제 확장 시, 숫자 범위가 커지면 Number정확도 문제(IEEE 754, 2^53 - 1 초과)가 생길 수 있다.
  3. "0000000007" 같은 값을 BigInt나 문자열 그대로 다뤄야 하는 케이스에선 부적절하다.

이 문제의 제한(길이 ≤ 10, 모두 정수 문자열)에서는 정상적으로 동작하지만,

타입 변환을 로직으로 쓰는 패턴은 “습관”으로 가져가기엔 위험하다는 점을 인지하는 것이 중요하다.


5. 세 가지 접근 방식 비교

접근예시 코드장점단점실무에서의 위치
정규식 replacen_str.replace(/^0+/, '')선언적, 간결, 의도 명확정규식 문법 이해 필요문자열 전처리의 주력 패턴
인덱스 스캔while (n_str[i] === '0') i++구현 과정이 직관적코드가 다소 장황정규식 기피 시 대안
숫자 변환 후 문자열String(Number(n_str))코드 짧고 깔끔의미적으론 “숫자 변환”이지 “문자열 처리”가 아님제한된 상황에서만 사용 권장

6. 문제 확장/변형 시 고려할 포인트

실무적인 관점에서 이 문제를 확장하면 다음과 같은 질문들이 생긴다.

  1. "0"으로만 이루어진 문자열이 들어올 수도 있다면?
    • 예: "0000" → 어떤 결과를 원할 것인가? "0"인지, ""인지?
    • 일반적으로는 "0"으로 normalize(정규화)하는 편이 자연스럽다.
  2. 길이가 매우 긴 숫자 문자열 (예: 1000자리) 이라면?
    • Number로 변환하는 방식은 정확도를 잃는다.
    • 이럴 때는 무조건 문자열 기반 처리(정규식 또는 인덱스)를 사용해야 한다.
  3. 중간의 0도 제거할 것인가, 앞부분만 제거할 것인가?
    • 이 문제는 “앞부분만” 제거이므로, 정규식에서도 ^를 쓰는 것이 중요하다. (/0+/g처럼 전체에서 0을 제거하면 완전히 다른 동작을 한다.)

이런 고민을 통해 “현재 제약 조건에서 왜 이 풀이가 맞는지”뿐 아니라,

“제약이 바뀌면 어느 지점에서 깨지는지”까지 생각하는 습관이 실무에서 큰 힘이 된다.


7. 최종 정리

이 문제에 대한 가장 추천하는 풀이는 다음과 같다.

function solution(n_str) {
  return n_str.replace(/^0+/, '');
}
  • 정규식으로 “문자열 시작 지점의 연속된 0”만 제거한다.
  • 문제의 요구사항과 정확히 일치하며, 확장성·가독성 측면에서도 우수하다.
profile
MOON.DEVLOG

0개의 댓글