Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save shingonu/84bc5e829059238b99f12b641e9568aa to your computer and use it in GitHub Desktop.
Save shingonu/84bc5e829059238b99f12b641e9568aa to your computer and use it in GitHub Desktop.
12 tips for writing clean and scalable JavaScript.md
### 1. Isolate your code
topic๊ณผ ๋ถ„๋ฆฌํ•ด์„œ ๋ช…๋ฐฑํ•œ ๋กœ์ง์˜ ๋ฉ์–ด๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋ฐ˜๋“œ์‹œ **ํ•˜๋‚˜์˜ ๋ชฉ์ **์„ ๊ฐ€์ง€๋Š” ๊ฒƒ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค. ํ•˜๋‚˜์˜ ํ•จ์ˆ˜์—์„œ ์—ฌ๋Ÿฌ ๋ชฉ์ ์˜ ๊ธฐ๋Šฅ์ด ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋œ๋‹ค.
๋˜ํ•œ ์—๋Ÿฌ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ผ์œผ์ผœ์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๊ณ ์ž ํ•  ๋• ํ•จ์ˆ˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌํ„ด๋ฐ›์•„์„œ ์‚ฌ์šฉํ•œ๋‹ค.
### 2. Modularization
๋งŒ์•ฝ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•จ์ˆ˜๊ฐ€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋น„์Šทํ•œ ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•  ๋• ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
```javascript
function add(a, b) {
return a + b
}
function subtract(a, b) {
return a - b
}
module.exports = {
add,
subtract
}
```
```javascript
const { add, subtract } = require('./calculations')
console.log(subtract(5, add(3, 2))
```
### 3. Prefer multiple parameters over single object parameters
ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ(object parameter)๋ณด๋‹จ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค(specific parameters)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ์ข‹๋‹ค.
```javascript
// GOOD
function displayUser(firstName, lastName, age) {
console.log(`This is ${firstName} ${lastName}. She is ${age} years old.`)
}
// BAD
function displayUser(user) {
console.log(`This is ${user.firstName} ${user.lastName}. She is ${user.age} years old.`)
}
```
๊ทธ๊ฒƒ์ด ์ข‹์€ ์ด์œ ๋Š” ํ•จ์ˆ˜ ์„ ์–ธ๋ถ€๋งŒ ๋ณด๊ณ ๋„ ์–ด๋–ค ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์š”ํ• ์ง€ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งŒ์•ฝ์— ๊ฐ์ฒด๋งŒ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์„ ์ฝ์–ด์•ผ ํ•œ๋‹ค.
ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ถ€์ž‘์šฉ์ด ์žˆ๋Š” ์ง€์ ์ด ์žˆ๋‹ค. ๊ทธ ์ง€์ ์€ ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ 4๊ฐœ์—์„œ 5๊ฐœ ์ด์ƒ์œผ๋กœ ๋Š˜์–ด๋‚  ๋•Œ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํ•จ์ˆ˜์˜ parameter๊ฐ€ ๋งŽ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋Š” object parameter๋ฅผ ์“ฐ๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ”์•ผ ํ•œ๋‹ค.
ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์€ ํ•จ์ˆ˜์—์„œ ์ •ํ•ด์ง„ ์ˆœ์„œ๋Œ€๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ optional parameter๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒฝ์šฐ์—๋Š” undefined / null ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์„ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ๋งŒ์•ฝ object ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋„ˆ๋Š” ๊ทธ๋ƒฅ whole object๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
### 4. Destructuring
Destructuring์€ ES6์— ๋„์ž…๋œ ์ข‹์€ ๋„๊ตฌ๋‹ค. ์ด๊ฒƒ์€ object๋กœ๋ถ€ํ„ฐ ํŠน์ •ํ•œ ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์„œ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•œ๋‹ค.
```
// EXAMPLE FOR MODULES
const { add, subtract } = require('./calculations')
```
์ด๋Ÿฐ ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ object๊ฐ€ ์‚ฌ์šฉ๋  ๋•Œ Destructuring์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
```javascript
function logCountry({name, code, language, currency, population, continent}) {
let msg = `The official language of ${name} `
if(code) msg += `(${code}) `
msg += `is ${language}. ${population} inhabitants pay in ${currency}.`
if(contintent) msg += ` The country is located in ${continent}`
}
logCountry({
name: 'Germany',
code: 'DE',
language 'german',
currency: 'Euro',
population: '82 Million',
})
logCountry({
name: 'China',
language 'mandarin',
currency: 'Renminbi',
population: '1.4 Billion',
continent: 'Asia',
})
```
object parameter๋ฅผ ํ•จ์ˆ˜์— ๋„ฃ์ง€๋งŒ ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ ์ทจํ•จ์— ๋”ฐ๋ผ ํ•จ์ˆ˜์— ์–ด๋–ค ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์ง๊ด€์ ์œผ๋กœ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
### 5. Use default values
Default values for destructuring or even basic function parameters are very useful. Firstly, they give you an example of what value you can pass to the function. Secondly, you can indicate which values are required and which are not. Using the previous example, the full setup for the function could look like this:
default value๋ฅผ ๋‘๋Š” ๊ฒƒ์€ destructuring ๋˜๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค. ์šฐ์„  ํ•จ์ˆ˜์— ์–ด๋–ค ๊ฐ’๋“ค์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋กœ์„œ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ์„œ optionalํ•œ ๊ฑด์ง€ requiredํ•œ ๊ฑด์ง€ ์‰ฝ๊ฒŒ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค.
```javascript
function logCountry({
name = 'United States',
code,
language = 'English',
currency = 'USD',
population = '327 Million',
continent,
}) {
let msg = `The official language of ${name} `
if(code) msg += `(${code}) `
msg += `is ${language}. ${population} inhabitants pay in ${currency}.`
if(contintent) msg += ` The country is located in ${continent}`
}
logCountry({
name: 'Germany',
code: 'DE',
language 'german',
currency: 'Euro',
population: '82 Million',
})
logCountry({
name: 'China',
language 'mandarin',
currency: 'Renminbi',
population: '1.4 Billion',
continent: 'Asia',
})
```
๋ช…๋ฐฑํ•˜๊ฒŒ ๋•Œ๋ก  default value๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  error๋ฅผ throwํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
### 6. Data scarcity
์ด์ „ ํŒ์„ ํ†ตํ•ด ํ•œ ๊ฐ€์ง€ ๊ฒฐ๋ก ์„ ๋‚ด๋ ธ๋‹ค. ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ๋ง์ž. ํŠน์ • ์ง€์ ์—์„œ ์–ด๋–ค ๊ฐ’์ด ์‚ฌ์šฉ๋˜๋Š”์ง€ ์ •ํ™•ํžˆ ์•„๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.
### 7. Line and indentation limit
์ข…์ข… ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด 3,000์ค„์ด ๋„˜์–ด๊ฐ€๋Š” ํŒŒ์ผ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ํŒŒ์ผ์„ ๋ณผ ๋• logic์„ ์ฐพ๊ธฐ ๋งค์šฐ ํž˜๋“ค๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— file size๋ฅผ ์˜๋„์ ์œผ๋กœ ์ œํ•œํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ๋งŒ์•ฝ ์ฝ”๋“œ๊ฐ€ 100์ค„์ด ๋„˜์–ด๊ฐ„๋‹ค๋ฉด ์ƒˆ ๋ชจ๋“ˆ๊ณผ ํŒŒ์ผ์„ ์ฃผ์ €ํ•˜์ง€ ๋ง๊ณ  ๋งŒ๋“ค์ž. ๋งˆ์น˜ ์•Œํ”„์Šค ์‚ฐ๋งฅ์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ ํŒŒ์ผ์ด ๊ฑฐ๋Œ€ํ•œ ์‚ฐ๋งฅ์„ ์ด๋ฃจ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋ถˆํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค.
### 8. Use prettier
eslint๋ฅผ ๊ทธ ๋•Œ๋งˆ๋‹ค ํ•ด์ฃผ์ง€ ๋ง๊ณ  prettier๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ํ˜•์‹ํ™” ํ•˜์ž. prettier๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ formatting์„ ์ž๋™์ ์œผ๋กœ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•ด ํฐ ๊ฑฑ์ •์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
### 9. Use meaningful variable names
์ด์ƒ์ ์œผ๋กœ ๋ณ€์ˆ˜ / ํ•จ์ˆ˜์˜ ์ด๋ฆ„์€ ์ปจํ…ํŠธ์˜ ๋‚ด์šฉ์„ ๋‹ด๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.
#### Functions
ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์–ด๋– ํ•œ ์•ก์…˜์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜์˜ ์ด๋ฆ„์€ ๋™์‚ฌ๋กœ ์ง“๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
e.g., `convertCurrency` or `displayUserName`.
#### Arrays
These will usually hold a list of items; therefore, append an `s` to your variable name. For example:
```
const students = ['Eddie', 'Julia', 'Nathan', 'Theresa']
```
#### Booleans
Simply start with `is` or `has` to be close to natural language. You would ask something like, โ€œIs that person a teacher?โ€ โ†’ โ€œYesโ€ or โ€œNo.โ€ Similarly:
```
const isTeacher = true // OR false
```
#### Array functions
`forEach`, `map`, `reduce`, `filter`, etc. are great native JavaScript functions to handle arrays and perform some actions. I see a lot of people simply passing `el` or `element` as a parameter to the callback functions. While this is easy and quick, you should also name these according to their value. For example:
```
const cities = ['Berlin', 'San Francisco', 'Tel Aviv', 'Seoul']
cities.forEach(function(city) {
...
})
```
#### IDs
Oftentimes, you have to keep track of the ids of specific datasets and objects. When ids are nested, simply leave it as id. Here, I like to map MongoDB `_id`to simply `id` before returning the object to the frontend. When extracting ids from an object, prepend the type of the object. For example:
```
const studentId = student.id
// OR
const { id: studentId } = student // destructuring with renaming
```
An exception to that rule is MongoDB references in models. Here, simply name the field after the referenced model. This will keep things clear when populating references documents
### 10. Use async / await where possible
callback์€ ๊ฐ€๋…์„ฑ์„ ์•ˆ์ข‹๊ฒŒ ๋งŒ๋“ ๋‹ค. promise๋ผ๋Š” ์ข‹์€ ํˆด์ด ์žˆ์ง€๋งŒ ์ด ๋˜ํ•œ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง„๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์™ ๋งŒํ•˜๋ฉด async / await๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
### 11. Module import order
tips1๊ณผ 2์—์„œ ๋ณด์•˜๋“ฏ์ด, ์ ์ ˆํ•œ ์žฅ์†Œ์— logic์„ ๋‘๋Š” ๊ฒƒ์€ maintainability๋ฅผ ์ง€ํ‚ค๋Š” ํ•ต์‹ฌ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, ๋‹ค๋ฅธ ๋ชจ๋“ˆ์„ ์–ด๋–ป๊ฒŒ import ์‹œํ‚ค๋ƒ๋„ ์ฝ”๋“œ๋ฅผ ๋ดค์„ ๋•Œ์˜ ํ˜ผ๋™์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
```javascript
// 3rd party packages
import React from 'react'
import styled from 'styled-components'
// Stores
import Store from '~/Store
// reusable components
import Button from '~/components/Button'
// utility functions
import { add, subtract } from '~/utils/calculate'
// submodules
import Intro from './Intro'
import Selector from './Selector'
```
### 12. Get rid of console
console์€ ๋””๋ฒ„๊น…ํ•˜๋Š”๋ฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ด์ง€๋งŒ, ์ด๊ฒƒ์ด ๋„ˆ๋ฌด ๋งŽ์œผ๋ฉด ์ฝ”๋“œ์˜ ํ˜ผ์žก์„ ์ผ์œผํ‚จ๋‹ค.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment