-
유틸성 함수(utility function)JavaScript 2023. 6. 23. 15:32
안녕하세요! 😎
오늘은 유틸성 함수(utility function)에 대해서 알아보려 합니다. 저번주에 멘토님께 코드 리뷰를 받는데 비교에 대한 코드가 반복되면 유틸성 함수를 사용해 보라는 리뷰를 주셨어요! 유틸성 함수가 뭐죠...? 그래서 한번 정리해 보려고 합니다!반성문 : curly 룰을 지키겠습니다.
우선 utilie 이라는 단어를 찾아보면 유용한, 도움이 되는, 쓸모 있는 이라는 뜻으로 변역 돼요.
흠... 그럼 utility function은 쓸모있는 함수...? 쓸모없는 함수도 있나...? 전혀 도움이 안 되네요.
좀 더 이용목적에 초점을 두고 찾아보니 '코드의 크기가 작고, 애플리케이션 비즈니스와는 관련이 적으며, 굉장히 일반적인 기능을 담당하는 코드'라고 나오네요! 프로젝트에 관련된 중요한 코드 기능보다는 자주 사용되는 작은 snippet 단위의 코드를 하나의 함수로 만들어서 코드를 간결하게 하고 시간을 절약하기 위해 사용하는 것 같아요. 일종의 단축키 같은 느낌의 함수네요!
utility 함수는 array utility, dom utility 등 다양하게 javascript 코드 작성에 이용되고 있어요. 이 중 가장 사용성이 높은 부분이 DOM과 관련된 부분이에요. DOM 관련된 것 외에도 몇 개 더 살펴볼게요!
사용 예시와 함께 살펴볼게요!
1. querySelector(), querySelectorAll()
- 바닐라 자바스크립트를 사용하면서 정말 자주 사용되는 메소드죠.
const title = document.querySelector("h1"); const className = document.querySelector(".class"); const message = formElem.querySelector("#message"); //utility function const select = (selector, parent = document) => { return parent.querySelector(selector); }; const title = select("h1"); const className = select(".class"); const message = select("#message", formElem);
- 위와 같이 utility function을 사용하게 되면 document.querySelector() 했던걸 select()로 간단하게 사용가능해요!
- 그리고 우리는 자주 querySelectorAll() 메서드로 데이터를 불러와서 map()이나 forEach() 메서드들로 값들을 가공하는 경우가 많잖아요? 이때도 utility function을 사용하면 너무 편하게 사용할 수 있습니다.
const selectAll = (selector, parent = document) => { return [...parent.querySelectorAll(selector)] } selectAll("#todo").map((todo) => return ... );
2. addEventListener()
- addEventListener()도 정말 자주 사용하는 메서드죠 click event가 적용 안 되는 웹 페이지는 없으니까요. 그럼 한 페이지에 수많은 click event와 그 외 수많은 event 처리가 있을 텐데 그때마나 addEventListener을 코드를 길게 치는 것이 시간 낭비라고 충분히 느낄 수 있을 거 같아요.
//utility function const listen = (type, selector, callback, options, parents = document) => { parent.addEventListener( type, e => { if(e.target.matches(selector)) callback(e) }, options ) }; listen("click", buttonElem, () => console.log("Clicked!")); listen("submit", formElem, () => { console.log("Form submitted!"); }, { once: true } ); //once 설명 A boolean value indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked. If not specified, defaults to false.
facility function을 쓰게 되다면 섞어서 쓰게 될 텐데 그러면 확실히 코드 길이가 짧아지고 시간을 절약할 수 있을 거 같아요.
document.addEventListener("click", (e) => { if(e.target.matches(".btn")) { alert("clicked!") } document.querySelector(".wrapper") }) //utility fucntion //parent를 wrapper 클래스를 가지고 있는 요소로 설정함. select() 유틸성 함수로 간단하게 설정가능. listen( "click", ".btn", () => console.log("clicked"), {}, select(".wrapper") )
3.localStorage
- localStrorage에서도 우리가 값을 저장하고 가져오는 일 또는 그 외 localStorage 내장 함수를 사용하는 작업을 많이 하죠?
- 이 부분도 facility function으로 바꿔주면 간단하게 코드를 작성할 수 있어요.
const storage = { get: (key, defaultValue = null) => { const value = localStorage.getItem(key); return value ? JSON.parse(value) : defaultValue; }, set: (key, value) => localStorage.setItem(key, JSON.stringify(value)), remove: (key) => localStorage.removeItem(key), clear: () => localStorage.clear(), }; storage.set("motto", "Eat, Sleep, Code, Repeat"); storage.get("motto");
4. Math.random()
- 0~1 사이의 랜덤 한 숫자를 생성할 때 자주 쓰는 메서드죠? 하지만 0~1 사이의 소수를 사용하는 일은 거의 없고 랜덤한 정수를 뽑아내고 싶을때 이 메서드를 사용 하는 경우가 더 많은거 같아요. 예를 들어 1~100 사이의 랜덤한 숫자를 가져오는 일처럼요! 이럴 때도 utility 함수를 만들어 사용하면 간단하게 사용이 가능합니다.
function randomNumberBetween(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) } //1~100 사이의 랜덤한 정수를 원할때 randomNumberBetween(1, 100);
이렇게 해서 여러 utility function을 적용해 보았어요.
다시 한번 정리를 하면 자주 쓰이는 코드는 함수로 만들어서 사용하자!인 거 같아요.
오답 노트를 적어 봅시다.
저번주 과제에서 전위, 중위, 후위 트리 순회를 구현해 봤는데 만약 첫 번째 root 노드가 null 값이면 실행을 멈춘다고 저는 코드를 반복적으로 적었어요. 이걸 유틸성 함수로 만들어 봅시다. 아래 정도로 간단하게 만들 수 있을 거 같아요.
function isLeafNode(node) { return (node.children || node.value !== null) ? false : true }
그리고 이건 이번주 투두리스트 만드는 과제였는데 오늘 공부하면서 제가 코드를 정말
더럽게짜는구나 반성했습니다.아래는 원래 제 코드예요.
$todoList.addEventListener("click", (e) => { e.preventDefault(); const $target = e.target; //toggle if ($target.tagName === "SPAN") { this.state.map((todo) => { if (todo.id.toString() === $target.id) { return (todo.isCompleted = !todo.isCompleted); } }); storage.setItem("todos", JSON.stringify(this.state)); toggleTodo(this.state); this.render(); }
아래처럼 바꿔볼 수 있겠네요!
listen( "click", ".toggle-btn", () => { //콜백 함수 안은 조금 수정이 필요할 것 같네요. this.state.map((todo) => { if (todo.id.toString() === $target.id) { return (todo.isCompleted = !todo.isCompleted); } }, e.preventDefault(); storage.set("todos", this.state); toggleTodo(this.state); this.render(); )
이렇게 utility 함수에 대해서 살펴봤어요! 평소에 아.. 기본도 잘 못하는데 이런 걸 안다고 해도 내가 적용을 잘할 수 있을까? 괜히 남이 보기 힘들어지는 코드가 될 수도 있으니 길게 풀어쓰는 게 차라지 낫지 않을까?라고 생각했는데 확실히 모르고 안 쓰는 것과 완전히 모르는 건 다르기도 하고 이렇게 한번 정리를 하니 다음에는 한번 적용해 볼까?라는 자신감이 생깁니다!
반응형'JavaScript' 카테고리의 다른 글
자바스크립트에서 비동기 처리는 어떻게 이루어 질까? (+자바스크립트 동작 원리) (1) 2024.04.21 [JS + TS / 🔥 Tadak Tadak 🔥] 공백 입력 방지를 위한 폼 유효성 검사 구현하기 ( trim() 메서드 + as 단언 ) (0) 2024.02.02 디바운싱과 쓰로틀링 (0) 2023.07.14 렉시컬 스코프(정적 스코프) (4) 2023.06.15 [프로그래머스 FE 데브코스/TIL] 브라우저 동작원리, 메모리, 스코프 (0) 2023.06.04