초보자에게 적합한 코딩 챌린지 중에는 엔지니어처럼 사고하는 법을 익히는 데 큰 도움이 되는 것들이 많습니다. 그중 하나가 바로 주어진 문자열에서 모든 단어의 첫 글자를 대문자로 바꾸는 문제입니다. 이 글에서는 문제의 요구사항과 함께 JavaScript로 풀 수 있는 여러 가지 방법을 살펴보겠습니다.
문제 소개
capitalize 함수가 str을 매개변수로 받으면, 모든 단어의 첫 글자가 대문자로 변환된 str을 반환해야 합니다. 풀이 과정에서 엣지 케이스(입력값이 없는 경우, 잘못된 타입의 입력 등)도 함께 고려해 보세요.
접근 방법
- 문제를 다시 한번 읽고, 문장 속에서 핵심 키워드를 적어두거나 표시하세요.
- 문제의 의미를 조합해 전체 그림을 이해하세요. 코딩 챌린지에서 가장 어려운 부분 중 하나는 문제가 무엇을 요구하는지 파악하는 것입니다. 문제를 정확히 이해하면 해결의 절반은 끝난 것이나 다름없습니다.
- 가능한 해결책을 의사코드(pseudocode)로 작성해 보세요. 실제 실행 가능한 코드일 필요는 없습니다. IDE나 브라우저 콘솔에서 돌아갈 필요 없이 일반 문장으로 작성해도 충분합니다:
주어진 것 이해하기: 함수가 하나 주어짐 어떤 형태의 입력을 받음 반환해야 할 것 이해하기: 문자열 가장 먼저 해야 할 일은 무엇일까? 입력이 문자열이라는 걸 알 때 어떤 선택지가 있을까? 활용할 수 있는 문자열 메서드가 있을까? 모르겠다면 어떻게 찾아볼 수 있을까? 입력이 비어 있거나 숫자, 객체라면 어떻게 처리할까? 일단 for 루프를 작성해 문자열을 순회하는 것부터 시작해 보자. 그다음은? ... 이런 식으로 계속...
문제를 단계별로 철저하게 분해해 보세요. 이 과정은 엣지 케이스 — 잘못된 입력이 전달되거나 빈 문자열이 들어오는 경우 — 를 떠올리고, 문제를 논리적인 단계로 나누는 방법을 고민하는 데 큰 도움이 됩니다. 이는 일종의 실험 단계로, 정답이 없습니다. 문제에 접근하는 방법에 대한 생각만 있으면 충분합니다. 그 생각이 엉뚱한 방향일 수도 있지만, 그렇기 때문에 어떤 접근이 작동하지 않는지 배울 수 있습니다.
저는 문제를 소리 내어 설명하며 분해하면 로직이 더 쉽게 떠오른다는 것을 경험했습니다. 사람마다 맞는 방식은 다르겠지만, 여러분에게도 도움이 될 수 있으니 한번 시도해 보시길 권합니다! 이렇게 작은 문제에 의사코드를 작성하는 게 다소 과해 보일 수 있지만, 지금 이 습관을 들여 두면 훨씬 어려운 문제를 만났을 때 훨씬 수월해질 것입니다.
해결 방법
방법 1: split()과 for 루프, replace(), charAt() 메서드 활용
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>for loop</title>
</head>
<body>
<div id="root"></div>
<script async defer>
let capitalize = (str) => {
let arr = str.split(' ');
for(let i = 0; i < arr.length; i++ ) {
arr[i] = arr[i].replace(arr[i].charAt(0), arr[i].charAt(0).toUpperCase());
}
return arr.join(' ');
}
let root = document.getElementById('root');
root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
</script>
</body>
</html>
첫 번째 방법에서는 문자열을 공백을 기준으로 분리(split)합니다. 그러면 각 단어가 개별 인덱스에 담긴 배열(arr)이 만들어집니다. 배열을 순회하면서 각 단어의 개별 문자에 접근할 수 있습니다. 인덱스 i에 해당하는 문자열(arr[i])을, 0번째 문자(arr[i].charAt(0))를 대문자로 바꾼 결과로 재할당합니다. 마지막으로 join 메서드로 배열을 다시 공백으로 연결된 하나의 문자열로 합쳐 반환합니다.
방법 2: split()과 map 메서드, slice() 활용
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Map</title>
</head>
<body>
<div id="root"></div>
<script async defer>
let capitalize = (str) => {
// 공백을 기준으로 문자열을 분리해 다룰 대상을 파악합니다.
let arr = str.split(' ') // 따옴표 사이에 반드시 공백이 있어야 합니다.
// map 메서드를 사용합니다.
arr.map((word, index, array) => {
array[index] = array[index][0].toUpperCase() + array[index].slice(1);
return array[index];
})
console.log(arr)
return arr.join(' ');
}
let root = document.getElementById('root');
root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
</script>
</body>
</html>
이 방법 역시 시작점은 비슷하지만, 이후에는 ES6 배열 메서드인 map을 사용해 배열을 순회하며 각 단어의 첫 글자를 대문자로 변환한 새 값을 만듭니다. 첫 글자에는 toUpperCase() 메서드를, 나머지 부분에는 slice() 메서드를 적용하고, 문자열 연결(concatenation)로 새로운 단어를 완성합니다. 그다음 배열을 join하여 반환합니다.
방법 3: 정규표현식(regular expression) 활용
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
</head>
<body>
<div id="root"></div>
<script async defer>
let capitalize = (str) => {
let regex = /(^|\s)\S/g
return str.replace(regex, letter => letter.toUpperCase());
}
let root = document.getElementById('root');
root.innerHTML = JSON.stringify(capitalize('the quick brown fox jumped over the lazy dog'));
</script>
</body>
</html>
이 방법에서는 정규표현식을 사용해 문자열의 시작(^) 또는 공백 문자(\s) 바로 뒤에 오는 모든 비공백 문자(\S)를 찾아냅니다. 패턴 끝의 g 플래그는 전역(global) 검색을 의미하며, 패턴과 일치하는 모든 항목을 찾을 수 있게 해줍니다. 이후 replace 메서드로 해당 패턴을, 일치한 글자를 대문자로 반환하는 함수로 교체합니다.
마무리하며
위에서 소개한 방법들이 이 문제의 유일한 해결책은 아닙니다. 이런 유형의 문제를 계속 풀다 보면 글이나 블로그에서 제시하는 것과 같거나, 혹은 전혀 다른 자신만의 해결책을 찾게 될 것입니다. 그것은 좋은 신호입니다. 여러분이 엔지니어처럼 생각하기 시작했다는 뜻이고, 그것이 바로 목표이기 때문입니다.
부트캠프 참가자의 81%가 수료 후 기술 직군 취업 전망에 대해 더 자신감을 느꼈다고 답했습니다. 지금 바로 자신에게 맞는 부트캠프를 찾아보세요.
부트캠프 졸업생은 평균적으로 부트캠프를 시작한 시점부터 첫 직장에 입사하기까지 6개월 이내의 짧은 기간 동안 커리어 전환을 완료했습니다.
포기하지 말고 계속 도전하세요. 위의 해결책들은 엣지 케이스를 처리하지 않았습니다. 인수가 빈 문자열이거나 숫자라면 어떻게 해야 할까요? 위 코드에 엣지 케이스 처리 로직을 직접 추가해 보세요.
힌트: 느낌표(bang, !)를 활용해 str이 존재하는지 조건문으로 확인해 보세요. 또한 MDN 문서를 참고하면, 타입을 알 수 없는 값의 타입을 확인하는 메서드를 찾을 수 있습니다.
한 가지 더: 아직 도전하지 않았다면 JavaScript 문자열 뒤집기(String Reverse) 코드 챌린지에도 도전해 보세요!
추가로 참고할 만한 자료
Ruby에서 정규표현식 사용하기 – Ruby 전용 글이지만, 정규표현식은 대체로 언어에 독립적입니다. 방법 3의 RegExp 문법을 더 깊이 이해하고 싶다면 확인해 보세요.
JavaScript Replace Text: 단계별 가이드 – 방법 1에서 사용된 replace 메서드를 집중적으로 다루는 튜토리얼입니다.