입문 과제 가이드를 제공받은 후, 가이드에서는 생각보다 컴포넌트를 많이 나눈다는 것을 알게 되었다. 기능은 이미 다 구현이 되었고 반드시 수정이 필요한 것은 아니었지만, 어차피 시간도 좀 남았고, 하라는대로 해서 나쁠 건 없다고 생각해서 진행하게 되었다.
기존의 컴포넌트는 다음과 같았다.
우선 전체적으로 코드가 거의 다 App.jsx에 몰려 있었고, Todo.jsx 파일은 각 todo item에 대한 컴포넌트였다. Button.jsx 파일은 강의에서 분리하는 걸 보았기에 컴포넌트로 만들었다.
특별히 더 나눌 필요가 없다고 생각했으나, 가이드를 보고 더 세부적으로 나누게 되었다. 수정한 컴포넌트는 다음과 같다.
(편의상 .jsx는 생략하도록 한다.)
우선 App에 있던 코드들을 TodoContainer에 몰아 넣고, App 파일에서는 TodoContainer만 import해서 넣어주었다. 제목 및 내용을 입력하는 TodoForm 컴포넌트, 각 리스트를 화면에 나타내는 TodoList 컴포넌트를 만들었고, 기존의 Todo 컴포넌트는 파일명이 직관적이지 않아 TodoItem으로 변경했다. 그리고 기존의 Button까지 총 6개의 컴포넌트가 제작되었다.
확실히 느낀 장점은 컴포넌트가 나뉘어있으니 좀 더 각 코드가 무슨 역할을 하는지 알아보기 쉽다는 점이다.
머쓱이는 태어난 지 11개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음과 네 가지 발음을 조합해서 만들 수 있는 발음밖에 하지 못하고 연속해서 같은 발음을 하는 것을 어려워합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.
우선 내가 작성한 코드이다.
function solution(babbling) {
let arr = ["aya", "ye", "woo", "ma"]
for (let i=0; i<babbling.length; i++){
for (let j=0; j<arr.length; j++){
if (babbling[i].includes(arr[j])){
babbling[i] = babbling[i].replace(arr[j], "");
}
}
}
return babbling.filter((item)=>item==="").length;
}
상당히 많은 테스트 케이스에서 실패했다. 100점 중 55점. 그래서 일단 질문하기 페이지에서 살펴보다가, 한 번씩만 replace되기 때문에 같은 발음이 반복될 경우 replace 되지 않는 문제점이 있었다. 때문에 replaceAll로 수정해보았다.
babbling[i] = babbling[i].replaceAll(arr[j], "");
이제 같은 발음이 여러 개일 경우의 문제는 해결되었다. 그러나 문제는 "yeye"처럼 같은 발음이 연속으로 있을 경우에는 발음이 불가능하다는 것이다. 때문에 연속된 발음일 경우의 조건을 추가하면 되지 않을까 하는 가설을 세워보았다.
function solution(babbling) {
let newBabbling = [...babbling];
let arr = ["aya", "ye", "woo", "ma"]
for (let i=0; i<babbling.length; i++){
for (let j=0; j<arr.length; j++){
if (babbling[i].includes(arr[j]+arr[j])){
continue;
} else if (babbling[i].includes(arr[j])){
newBabbling[i] = newBabbling[i].replaceAll(arr[j], "");
}
}
}
return newBabbling.filter((item)=>item==="").length;
}
우선 연속되는 발음이 있을 경우 replace 되지 않게 하는 조건문을 세웠고, 따로 떨어져있다가 다른 요소가 replace되어 연속되는 발음이 될 경우를 대비해 기존 배열을 복사해 새로운 배열에서 값을 변경하도록 했다. 이 조건으로 했을 경우 75점이 나왔고, 아까보단 나아졌지만 여전히 여러 테스트 케이스에서 실패했다. (1,11,14,16,17)
슬슬 머리가 아파오기 시작했다... 대체 뭐가 문제인가? 하다가 질문하기 페이지에서 반례를 보았다. 만약 babbling의 요소가 "ayamayaa"일 경우, 내 방식을 사용하면 "ayamayaa"=>"ma"=>"" 순서로 변한다. 원래는 "yaa"만 남아야하기 때문에, 이 방법은 잘못됐다고 생각했다. 그러면 어떻게 해야하는가? 이 역시도 질문하기 페이지에서 팁을 얻어 해결했다. 결국 여러 도움을 받고 풀었지만, 직접적인 정답에 대한 힌트를 받진 않았다. 결과적인 코드는 다음과 같다.
function solution(babbling) {
let newBabbling = [...babbling];
let arr = ["aya", "ye", "woo", "ma"]
for (let i=0; i<babbling.length; i++){
for (let j=0; j<arr.length; j++){
if (babbling[i].includes(arr[j]+arr[j])){
continue;
} else if (babbling[i].includes(arr[j])){
newBabbling[i] = newBabbling[i].replaceAll(arr[j], " ");
}
}
newBabbling[i] = newBabbling[i].replaceAll(" ","")
}
return newBabbling.filter((item)=>item==="").length;
}
replaceAll 시 지워주는 방법을 사용했는데, 이 때 ""가 아닌 " "로 변경하여, 공백을 넣어주었다. 이렇게 했을 경우 "ayamayaa"는 " m a"가 되기 때문에, replace되지 않는다. 그리고 나중에 다시 공백 문자열을 ""로 replace 시켜줘서 정답을 이끌어낼 수 있었다.
역대급으로 어렵게 푼 문제였다. 하지만 이런 류의 문제를 푸는 데에 있어서 약간의 힌트를 얻고 가는 것 같아서, 성장에 도움이 된 것 같아 만족스럽게 생각한다.
function solution(babbling) {
const regexp1 = /(aya|ye|woo|ma)\1+/;
const regexp2 = /^(aya|ye|woo|ma)+$/;
return babbling.reduce((ans, word) => (
!regexp1.test(word) && regexp2.test(word) ? ++ans : ans
), 0);
}
정규식으로 하면 이렇게 간단하게 풀릴 수 있는 거였다... 확실히 정규식은 공부해두면 정말 도움이 많이 될 것 같기는 하다. 하지만 당장의 내 실력을 키우기 위해서는 위의 방법을 사용하는 것이 더 좋을 것이라고 생각한다...^^
리액트의 장점은 역시 컴포넌트 분리에 있다. 컴포넌트를 나누니 훨씬 보기가 좋고 이해가 쉽다.