학습 & 성장 (Learning & Growth)/개발 공부 (Development Study)

[클린코드] 주석: 숙명인가 함정인가? (feat. 코드로 말해요, 우리)

vanillinav 2024. 7. 18. 05:25
728x90
반응형

코드가 어려우면 주석을 달면 되지!"라는 말, 개발자라면 누구나 한 번쯤 들어봤을 겁니다.

하지만, 주석과의 관계는 참으로 복잡미묘합니다.

 

처음엔 친절한 메시지처럼 보이지만, 시간이 지나면서 코드와 따로 놀고,

오히려 이해를 방해하는 경우가 너무 많았습니다.

클린 코드 (Clean Code) - 로버트 C. 마틴

 

클린 코드 9장 "주석"에서는 주석을 잘못 사용하는 경우를 지적하며,

이상적으로는 코드 자체로 설명이 가능해야 한다고 강조합니다.

하지만, 현실은 그렇게 이상적이지만은 않죠.

 

 

그렇다면 우리는 주석과 어떻게 공존해야 할까요? 🤔

1. 나쁜 주석: 우리를 괴롭히는 악당들 👿

1.1 중복된 주석: 코드만 봐도 아는데... 🤦‍♀️

흔히 볼 수 있는 예시죠. 접근성을 위해 aria-label 속성까지 추가했습니다.

// components/SearchInput.tsx
import React from 'react';
import './SearchInput.scss';

const SearchInput: React.FC = () => (
  // 검색 입력 컴포넌트
  <input 
    type="text" 
    className="search-input" 
    placeholder="검색어를 입력하세요" 
    aria-label="검색어 입력" 
  />
);

export default SearchInput;
// components/SearchInput.scss
.search-input {
  // 입력 필드 스타일
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px; 

  &:focus {
    // 포커스 스타일
    outline: none;
    border-color: #007bff; 
  }
}

코드만으로도 충분히 의미가 명확한데 굳이 "// 검색 입력 컴포넌트", "// 입력 필드 스타일"과 같은 주석이 필요할까요? 오히려 코드 분석 흐름만 방해할 뿐입니다.

1.2 주석 처리된 코드: 망령의 흔적을 지워주세요! 👻

// components/DropdownMenu.tsx
import React, { useState } from 'react';
import './DropdownMenu.scss';

const DropdownMenu: React.FC = () => {
  const [isOpen, setIsOpen] = useState(false);

  // const handleMouseEnter = () => {
  //   setIsOpen(true);
  // };

  return (
    <div className="dropdown-menu">
      <button 
        className="dropdown-button" 
        aria-expanded={isOpen} 
        onClick={() => setIsOpen(!isOpen)} 
      >
        메뉴
      </button>
      {isOpen && (
        <ul className="dropdown-list" role="menu">
          {/* <li role="menuitem">메뉴 1</li> */}
          <li role="menuitem">메뉴 2</li>
        </ul>
      )}
    </div>
  );
};

export default DropdownMenu;

주석 처리된 코드는 마치 과거의 망령처럼 코드베이스를 떠돌며 유지보수를 방해합니다. 과감하게 삭제하고 깨끗한 코드를 유지하세요! 버전 관리 시스템은 우리의 든든한 아군입니다. 😉

1.3 잘못된 주석: 거짓말은 나빠요! 🤥

// components/Modal.tsx
import React, { useState } from 'react';
import './Modal.scss';

interface ModalProps {
  children: React.ReactNode;
  onClose: () => void; // 모달 닫기 콜백 함수 (실제로는 열림 상태 업데이트)
}

const Modal: React.FC<ModalProps> = ({ children, onClose }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div 
      className={`modal ${isOpen ? 'open' : ''}`} 
      aria-hidden={!isOpen} 
      aria-modal="true" 
      role="dialog" 
    >
      <div className="modal-content">
        {children}
        <button onClick={() => setIsOpen(true)}>닫기</button>
      </div>
    </div>
  );
};

export default Modal;

주석이 코드와 일치하지 않는다면? 차라리 없는 게 낫습니다. 잘못된 정보는 오류를 유발하고 디버깅 시간을 늘리는 주범입니다. 주석을 업데이트하거나 삭제하여 항상 코드와 일치하도록 유지해야 합니다.

1.4 장황한 주석: 간결함이 최고의 미덕 ✨

// components/ImageGallery.tsx
import React from 'react';
import './ImageGallery.scss';

interface ImageGalleryProps {
  images: string[]; // 이미지 URL 배열
}

// 이 컴포넌트는 이미지 갤러리를 렌더링합니다.
// images prop으로 이미지 URL 배열을 전달받아 각 이미지를 표시합니다.
const ImageGallery: React.FC<ImageGalleryProps> = ({ images }) => (
  <ul className="image-gallery" role="list">
    {images.map((image, index) => (
      <li key={index}>
        <img src={image} alt={`갤러리 이미지 ${index + 1}`} />
      </li>
    ))}
  </ul>
);

export default ImageGallery;

장황한 주석은 코드의 가독성을 떨어뜨리고, 개발자의 집중력을 저하시킵니다. 코드만큼이나 주석도 간결하고 명확하게 작성하는 것이 중요합니다. 위 코드에서 컴포넌트 선언 부분 주석은 삭제해도 충분히 의미가 전달됩니다.

2. 좋은 주석: 가끔은 한 줄기 빛 ✨ ... 정말 가끔은!

모든 주석이 나쁜 것은 아닙니다. 때로는 복잡한 로직이나 의도를 명확히 설명하기 위해 주석의 도움이 필요한 경우도 있습니다. 하지만, 정말 필요한 경우에만, 최소한으로 사용해야 합니다.

2.1 주석이 필요한 경우

법적인 주석: 저작권, 라이선스 정보는 명확하게 명시해야 합니다.

// components/App.tsx 
// Copyright 2023. John Doe. All rights reserved.

정보 제공: 복잡한 정규식이나 알고리즘을 설명할 때 유용합니다. 다만, 코드 리팩토링을 통해 주석 없이도 이해될 수 있다면 더욱 좋습니다.

// components/Form.tsx 
const validateEmail = (email: string): boolean => { 
  // RFC 5322 기반 이메일 유효성 검사 정규식 
  const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; 
  return emailRegex.test(email); 
};

경고: 특정 코드 수정 시 주의 사항을 명시합니다.

// components/DataSynchronizer.tsx 
// 주의: startSync() 함수 호출 이전에 반드시 설정 파일을 로드해야 합니다. 
// 설정 파일이 로드되지 않으면 동기화 오류가 발생할 수 있습니다. 
const startSync = () => { 
  // ... 데이터 동기화 로직 
};

TODO: 아직 구현하지 못했지만, 향후 추가해야 할 작업을 남겨놓을 때 유용합니다.

// components/UserList.tsx 
const UserList: React.FC = () => { 
  // TODO: 사용자 목록 무한 스크롤 기능 구현 
  const users = []; 
  return ( 
    <ul role="list"> 
      {users.map((user) => ( 
        <li key={user.id}> 
          {user.name} 
        </li> 
      ))} 
    </ul> 
  ); 
}; 
export default UserList;

3. 주석 없이 코드 가독성 높이기: 코드로 말해요, 우리! 🗣️

주석을 최소화하고 코드 자체로 의미를 명확히 전달하는 것이 클린 코드의 핵심입니다.

3.1 의미 있는 이름: 변수, 함수, 클래스 등에 의미 있는 이름을 사용하면 코드를 읽는 것만으로도 목적을 파악할 수 있습니다.

// components/User.tsx
interface UserProps {
  // 나쁜 예:
  n: string; 
  s: 'online' | 'offline'; 

  // 좋은 예:
  name: string; 
  status: 'online' | 'offline'; 
}

3.2 함수/메서드 분리: 긴 함수를 여러 개의 작은 함수로 분리하고, 각 함수에 명확한 이름을 부여하면 자연스럽게 코드가 설명됩니다.

// components/Form.tsx

// 나쁜 예:
const handleSubmit = () => {
  // ... 입력값 검증
  // ... API 요청
  // ... 성공/실패 처리
};

// 좋은 예:
const validateInput = () => {
  // ... 입력값 검증 로직
};

const sendApiRequest = () => {


  // ... API 요청 로직
};

const handleResponse = () => {
  // ... 성공/실패 처리 로직
};

const handleSubmit = () => {
  if (validateInput()) {
    sendApiRequest()
      .then(handleResponse)
      .catch(handleError);
  }
};    

3.3 적절한 추상화: 클래스, 인터페이스 등을 활용하여 코드를 모듈화 하면 불필요한 주석을 줄일 수 있습니다.

// components/Button.tsx

// 나쁜 예:
interface ButtonProps {
  // ... 버튼 공통 속성
  // ... primary 버튼에만 필요한 속성
  // ... secondary 버튼에만 필요한 속성
}

// 좋은 예:
interface BaseButtonProps {
  // ... 버튼 공통 속성
}

interface PrimaryButtonProps extends BaseButtonProps {
  // ... primary 버튼에만 필요한 속성
}

interface SecondaryButtonProps extends BaseButtonProps {
  // ... secondary 버튼에만 필요한 속성
}

4. 주석과의 동행: 더 나은 개발을 향해 🚶‍♀️🚶‍♂️

코드만으로 모든 걸 설명할 수 있다면 좋겠지만, 현실은 그렇지 않죠. 😅 

 '클린 코드'에서 로버트 C. 마틴은 바로 이 지점을 강조합니다. 

주석은 코드를 장황하게 풀어쓰는 게 아니라, 코드로는 드러나지 않는 숨은 의도나 중요한 정보를 명확하게 전달하는 도구라는 거죠.

다시 말해, 주석을 추가하기 전에 코드 자체를 명확하게 만드는 데 집중해야 합니다. 🤔  

진정한 클린 코드는 주석 없이도 스스로 이야기하는 코드니 까요! ✨



여러분은 어떤 유형의 주석을 주로 사용하시나요?

혹시 불필요한 주석을 남기는 습관 때문에 고민하고 있지는 않으신가요? 🤔

함께 고민하고 토론하며, 주석을 현명하게 활용하는 개발 문화를 만들어나가면 좋겠습니다! 😊

 

 

[참고]
클린 코드 (Clean Code) - 로버트 C. 마틴

요즘IT, 클린 코드는 왜 중요하고 어떻게 실천해야 할까?

728x90
반응형