문제
문자열 myString이 주어집니다. myString에서 알파벳 "a"가 등장하면 전부 "A"로 변환하고, "A"가 아닌 모든 대문자 알파벳은 소문자 알파벳으로 변환하여 return 하는 solution 함수를 완성하세요.
제한사항
- 1 ≤ myString의 길이 ≤ 20
- myString은 알파벳으로 이루어진 문자열입니다.
고민한 점 & 해결 과정
일단, 대소문자 변환은 toLowerCase() 메서드와 toUpperCase() 메서드를 사용하면 된다는 것을 알고 있었기에 해당 메서드를 활용해 풀고자 했습니다.
<첫 번째 시도 코드>
function solution(myString) {
const aList =[]; if (myString.includes('a')) {
aList.push(myString.toUpperCase());
} else {
aList.push(myString.toLowerCase());
} return aList;
}
하지만 첫 번째 코드는 돌아는 갔으나 적용된 로직이 해당 문제를 풀기에는 적합하지 않았습니다. 위의 코드 대로라면
문자열 'a'를 포함하기만 하면 문자열 전체를 대문자로 바꿔버리기 때문입니다.
조건의 범위가 문자열 전체에 걸려있기 때문에 특정 문자만 핀 포인트로 바꿔주고 싶다면 일단 myString배열을 분해하여 조건을 건 다음 마지막에 합쳐줘야 겠다고 생각했습니다. 스프레드문법과 join()메서드를 활용하면 해당 문제를 해결 할 수 있을 것 같았습니다.
<두 번째 시도 코드>
function solution(myString) {
return [...myString].map(alpha => alpha ==='a'?'A':alpha.toLowerCase()).join(''); }
map() 메서드와 삼항 연산자도 같이 활용하니 첫 번째 코드에 비해 훨씬 간결해지고 문제에 요구하는 로직도 갖추었습니다.
그러나 제출 후 테스트를 돌려본 결과, 단 하나의 테스트를 통과하지 못해서 정답이 아닌 코드라는 판정을 받았습니다. 뭐가 문제인지 생각해보며 문제와 조건을 다시 한 번 살펴봤습니다.
myString에서 알파벳 "a"가 등장하면 전부 "A"로 변환하고, "A"가 아닌 모든 대문자 알파벳은 소문자 알파벳으로 변환
문제를 다시 살펴본 결과, 저의 두 번째 코드는 'a'가 등장하면 대문자로 바꿔주는 것 까지는 잘했지만 뒤의 조건인 'A'가 아닌 모든 대문자를 소문자로 바꾸는 조건은 완벽하게 충족하지 못했다는 사실을 깨달았습니다.
바로 'a'만 대문자 'A'로 바꿔주고 처음부터 대문자 'A'가 나오는 경우는 고려하지 못한 것이었습니다. 지금의 로직은 대문자 'A'마저 소문자로 바꿔버리는 문제가 있었던 것입니다. 해당 문제를 해결하기 위해 처음 조건에서 문자열 상의 모든 a를 대소문자 구분없이 판단하기 위해 toLowerCase()로 소문자로 바꾼 뒤 판단했습니다.
<최종 코드>
function solution(myString) {
return [...myString].map(alpha => alpha.toLowerCase() ==='a'?'A':alpha.toLowerCase()).join('');
}
그 결과, 드디어 모든 경우를 고려하여 문제를 해결할 수 있었습니다.
문제를 해결 후, 다른 사람들의 코드를 보며 또 어떻게 해결할 수 있을 지 살펴봤습니다.
<다른 사람의 코드>
const solution=s=>s.toLowerCase().replaceAll('a','A');
replace()메서드가 있었구나 하면서 놀라다가 replace()메서드가 아닌 replaceAll()메서드임을 보고 의문이 들었습니다. replaceAll()이란 메서드가 있었고 replace()메서드와는 뭐가 다른지 궁금해 져서 MDN을 살펴보았습니다.
replace() 와 replaceAll()
replace()메서드는 첫 번째 인자로 전달된 특정 문자열을 두 번째 인자의 문자열로 모두 변경합니다.
replace(pattern, replacement)
replaceAll()메서드는 첫 번째 인자로 전달된 정규 표현식 패턴과 일치하는 모든 부분을 두 번째 인자의 문자열로 변경합니다.
replaceAll(pattern, replacement)
둘의 차이가 문법이 아닌 정규 표현식 (Regular Expression, Regex) 사용 유무임을 깨달았습니다. 그렇다면 정규 표현식이란 정확히 무엇인지 알고 가고자 했습니다. 이전에도 지나가듯이 경험한 개념이었는데 코드 상에서 활용해 본적은 없기 때문입니다.
정규 표현식 (Regular Expression, Regex)
정규 표현식, 또는 정규식은 문자열에서 특정 문자 조합을 찾기 위한 패턴입니다. 특정한 규칙을 가진 문자열의 집합을 표현하는 형식 언어로, 문자열에서 원하는 패턴을 찾거나(검색) 변경(치환)하는 데 사용됩니다.
이는 복잡한 문자열 처리 작업을 간단하고 강력하게 처리할 수 있게 해주는 도구로, 전화번호 유효성 검사, 이메일 형식 검사, 특정 파일 이름 찾기 등에 광범위하게 활용됩니다.
주요 특징 및 용도
- 패턴 기반 검색/치환: \d+ (하나 이상의 숫자), A.* (A로 시작하고 뒤에 어떤 문자든 오는)와 같은 특수 기호(메타 문자)를 조합하여 복잡한 규칙을 정의합니다.
- 강력한 문자열 처리: 수백 줄의 코드로 할 일을 몇 글자의 정규식으로 표현할 수 있어 개발 효율성을 높여줍니다.
- 다양한 활용 분야: 프로그래밍 언어(자바, 파이썬 등), 에디터, 데이터베이스 등 다양한 환경에서 문자열을 처리하는 데 필수적입니다.
즉, 이번 문제의 경우 처럼 특정 문자를 바꾼다기 보다는 특정 문자 패턴 전체를 바꿀 때 활용하기 좋은 개념이었습니다.
추가적으로 그렇다면 좀 더 강력한 문자열 처리가 가능한 정규 표현식을 사용하지 않는 replace()메서드는 이제 활용도가 떨어지는 것이 아닌가 하는 생각에 찾아보니 컴파일 및 매칭 과정 때문에 replace()처럼 단순치환하는 경우가 정규 표현식을 사용하는 경우보다 빠른 장점이 있다는 사실도 깨닫게 되었습니다.
최종 결과 및 느낀 점
문제 해결 과정에서 모든 경우를 확실히 케어하는 로직을 고려하고 세우는 것이 중요하다는 것을 깨달았습니다.
이제는 코딩 테스트 문제 해결 뿐만 아니라 관련된 개념과 그에 관련된 개념을 꼬리 물기식으로 공부하는 법이 익숙해 지고 있는 거 같아 뿌듯했습니다.
모든 프로그래밍적 개념에는 장점과 단점이 존재하고 만능은 없다는 것을 다시금 느꼈습니다.
'코딩 테스트 공부' 카테고리의 다른 글
| 프로그래머스 자바스크립 코딩 기초 트레이닝 - 특정 문자열로 끝나는 가장 긴 부분 문자열 찾기 (lastIndexOf()메서드, substring()메서드) (0) | 2026.01.08 |
|---|---|
| 프로그래머스 자바스크립 코딩 기초 트레이닝 - 조건에 맞게 수열 변환하기 1 (&& 연산자, map()메서드) (0) | 2026.01.02 |
| 프로그래머스 자바스크립 코딩 기초 트레이닝 - 수열과 구간 쿼리1 (이중 for 문) (0) | 2026.01.02 |
| 프로그래머스 자바스크립 코딩 기초 트레이닝 - 가까운 1 찾기 & 첫 번째로 나오는 음수 (0) | 2025.12.26 |
| 프로그래머스 자바스크립 코딩 기초 트레이닝 - 접미사 배열 (0) | 2025.12.17 |