TIL 23. 10. 25

오늘 한 일

  • 타이포라(Typora) 결제
  • 프로젝트 생성 및 초기 세팅 (+github)
    • 자바스크립트 모듈화
    • HTML, CSS 세팅
    • 컨벤션 설정
  • 깃 전략 수립
    • 커밋
    • Issue
    • Projects
    • PR
    • Wiki
    • 브랜치 전략

들어가며

팀 협업은 어렵다. 그렇기 때문에 사전 준비가 많다. 개발 단계로 들어서기 전에 개발 프로세스, git 사용 전략과 컨벤션 등 공유한 내용을 기록했다.

타이포라 결제

타이포라가 유료화 되고 나서 마크다운 에디터로 ‘markText’를 사용하고 있었다. 사용한 후기를 말해보자면 꽤 불편했다. 특히 코드블럭에서 작성한 텍스트가 없어지는 일이 비일비재했다. 마크다운 에디터로 노트 정리와 블로그 글을 작성하는데 나중에 검토하면 꼭 삭제된 부분이 있었다. github 블로그 글은 수정해서 다시 커밋을 날려야 했기에 스트레스를 받고 있었다.

좋은 개발툴을 사용하여 개발 생산성을 높이는 것 역시 개발자의 필요한 역량이랬다. 그래서 가장 잘 사용했던 마크다운 에디터 타이포라를 결제했다. (한화로 22,000원..)

타이포라 사고 나서 내 인생이 달라졌다. 우선 한글 지원에 글 작성도 부드럽고 여러 테마 적용되고 미리보기도 된다. 그리고 이미지 첨부도 간편해졌다. 설정을 하면 이미지를 삽입했을 때 작성한 경로에 이미지 파일이 자동으로 생성된다. (markText도 가능했지만 영어라서 안 써봤다.)

이 글도 타이포라로 작성중이다. 벌써 업무 생산성이 높아진 듯! ctrl + / 하면 마크다운 소스코드와 실제 보여지는 화면을 왔다갔다 할 수 있어 편하다. 아깝지 않은 결제였다.

프로젝트 생성 및 초기 세팅 (+github)

이제 팀원들과 개발을 시작하기 위해 프로젝트를 생성한다. 이번 팀 과제는 지난 개인 과제를 수행했던 ‘영화 검색 사이트’를 팀원들의 프로젝트 중 하나를 선택해 발전시키는 것이다. 팀원들끼리 살펴보고 보라님의 프로젝트로 팀 과제를 진행하기로 했다.

먼저 개인 과제 해설 영상을 보고 어느 정도 리팩토링을 하고 진행하는 것이 좋겠다고 생각했다. 각자 브랜치 단위로 작업하게 되면 충돌이 불가피할 것이라 자바스크립트 파일도 모듈화하여 작업 단위를 나누었다. 사실 튜터님의 해설 코드를 거의 가져다가 사용했다. 좋은 코드를 알아야 좋은 코드를 작성할 것이고 아름답게 짠 코드를 보니 지나칠 수 없었다.. 책임과 역할로 확실히 관심사를 분리하고 자바스크립트의 문법에 대한 이해를 바탕으로 깔끔한 코드를 작성하신 것에 자극이 많이 되었다.

자바스크립트 모듈화

// apis.js

const options = {
  method: 'GET',
  headers: {
    accept: 'application/json',
    Authorization:
      'Bearer ',
  },
};

export const fetchMovies = async (url) => {
  try {
    const response = await fetch(url, options);
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
    throw error;
  }
};

추가 기능 확장을 고려해서 api 호출 로직을 따로 분리했다. 다른 자바스크립트 파일에서 import 해서 사용한다.

// movie.js

'use strict';
import { fetchMovies } from './apis.js';

const $movieList = document.querySelector('.movie-list');

const handleClickCard = (event) => {
  if (event.target === $movieList) return;

  if (event.target.matches('.movie-card')) {
    alert(`영화 ID: ${event.target.id}`);
  } else {
    alert(`영화 ID: ${event.target.parentNode.id}`);
  }
};

export const generateMovieCards = async (
  apiUrl = 'https://api.themoviedb.org/3/movie/top_rated?language=en-US&page=1',
) => {
  const { results: movies } = await fetchMovies(apiUrl);

  $movieList.innerHTML = movies
    .map((movie) => {
      return `<li class="movie-card" id=${movie.id}>
        <img src=${'https://image.tmdb.org/t/p/w300' + movie['poster_path']}>
        <h5>${'⭐ Rating: ' + movie['vote_average']}</h5>
        <h2>${movie['title']}</h2>
        <p>${movie['overview']}</p>
      </li>
      `;
    })
    .join('');

  $movieList.addEventListener('click', handleClickCard);
};

처음에는 자바스크립트로 HTML 요소를 생성할 때 일일이 생성Document.createElement() 하고 붙였다Node.appendChild(). 그랬더니 코드가 엄청 늘어났고 무언가 잘못됨을 느꼈다. 템플릿 리터럴 문법을 사용하면 간단하게 자바스크립트로 HTML 요소를 생성할 수 있다. 상위 요소를 선택하고 해당 요소 내에 HTML 마크업을 집어넣는 것. 여기서 API 응답으로 구조 분해 할당하여 movies로 이름을 붙여주었고 배열을 순회하며 반환된 배열을 하나의 문자열로 만들어 삽입했다.

click 이벤트리스너의 콜백 함수도 따로 선언해서 함수명으로 기능을 명시하고 유지 보수 쉽게 하도록 변경했다. 클릭 이벤트는 클릭하는 카드 li가 아닌 상위 요소인 ul에서 발생하도록 했는데 결론부터 말하자면 메모리 절약을 위함이다.

이벤트 위임이란? 하위 요소에서 발생한 이벤트를 상위 요소에서 대신 처리할 수 있도록 위임하는 것 (메모리 절약)

이벤트 위임을 활용하면 일일이 li 태그에 이벤트 생성을 하지 않아도 된다. 만약 20개의 li가 있다면 addEventListener로 전달한 콜백함수가 20번 생성될 것이다. 이는 매우 비효율적이다. 부모 요소인 ul 태그에 이벤트 핸들러를 등록해서 하위 요소인 li를 클릭했을 때 li 태그의 id를 가져온다. <li class="movie-card" id={movie.id}> li의 자식 요소는 id가 없으므로 부모 요소인 li의 id값을 가져와야 한다.

// search.js

'use strict';

export function performSearch(inputValue) {
  const searchText = inputValue.toLowerCase();
  const $movieCards = document.querySelectorAll('.movie-card');

  $movieCards.forEach((card) => {
    const title = card.querySelector('h2').textContent.toLowerCase();
    if (title.includes(searchText)) {
      card.style.display = 'block';
    } else {
      card.style.display = 'none';
    }
  });
}

전달 받은 문자열과 영화 제목을 소문자로 만들어 비교한다. .movie-card 클래스를 가진 모든 HTML 요소를 가져와 순회하며 전달 받은 문자열을 포함하는지 확인 후 display 속성값으로 영화 목록을 보이거나 숨긴다.

// main.js

import { generateMovieCards } from './movie.js';
import { performSearch } from './search.js';

generateMovieCards();

const $form = document.querySelector('#search');
const $searchInput = document.getElementById('search-input');

$form.addEventListener('submit', (event) => {
  event.preventDefault();
  performSearch($searchInput.value);
});

main.js 파일은 Application의 전체 로직을 확인할 수 있다. main.js의 관심사는 영화 데이터를 가져와서 화면에 나타내는 것과 영화 검색 두 가지이다. 기능은 각자 파일로 분리하여 작성하고 main에서는 실행만 담당한다. 선언부와 실행부를 분리하면 독립된 특정 기능에 집중하여 코드를 파악하기 쉽고 기능을 추가하거나 변경하기도 쉽다.

협업을 위해서도 독립된 기능에 집중하여 훨씬 효율적으로 개발할 수 있게 된다. 특히 역할을 나누어 담당 기능을 개발하게 될 것이므로 관심사를 분리하는 것은 꼭 필요했다. 추가 이점으로는 github으로 작업할 때도 충돌 가능성이 줄어들지 않을까. 자바스크립트 모듈화는 마쳤고 다음은 HTML과 CSS.

HTML, CSS 세팅

개인적인 개발 중점 사항으로 HTML은 시맨틱 태그 사용하기, CSS는 flex, grid 사용과 함께 유지 보수성 높이기가 목표이다. html을 수정하는 것은 차차 개발하며 진행하고자 했다. 어떤 태그가 더 의미와 목적에 부합한지 좀 더 고민해봐야겠다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./style/reset.css" />
    <link rel="stylesheet" href="./style/style.css" />
    <link rel="icon" href="./assets/favicon.ico" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap"
      rel="stylesheet"
    />
    <script src="./src/main.js" type="module"></script>
    <title>Movie Collection</title>
  </head>
  <body>
    <div class="main">
      <h1>Movie Collection</h1>
      <form id="search" class="search_area">
        <input
          id="search-input"
          type="text"
          class="input-text"
          autocomplete="off"
          placeholder="영화 제목을 검색해 보세요"
          autofocus
        />
        <button id="search-btn">검색</button>
      </form>
    </div>

    <section id="movies-container">
      <div>
        <ul id="movie-list" class="movie-list"></ul>
      </div>
    </section>
  </body>
</html>

CSS 변수를 사용하는데 rgb()로 변수를 선언하면 vscode에서 컬러 배경을 입혀주지 않았다. ‘rgb to hex’를 검색해 hex로 변환해서 선언하기는 했는데 후에 vscode 익스텐션을 찾아봐야겠다.

:root {
  --color_card_bg: #f5f3f3;
  --color_card_shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
  --color_card_rating: #f39c12;
  --color_card_container: #b4a6a6;
  --color_body: #f7f4f4;
  --color_input: white;
  --color_input_btn: black;
  --color_input_btn_bg: white;
  --color_title: white;
}

body {
  background-color: var(--color-body);
}

.main {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 350px;
  background-image: url(../assets/banner.jpg);
  background-repeat: no-repeat;
  background-position: center right;
  background-size: cover;
}

.main h1 {
  margin-bottom: 20px;
  text-shadow: 0 0 15px black;
  font-size: 55px;
  color: var(--color_title);
}

.....(생략)

🎨 CSS 변수(–variable) 사용법 & 응용 정리

컨벤션 설정

코드 컨벤션

각자 코드 작성 스타일이 다르다. css 프로퍼티 속성 순서, class 네이밍, 들여쓰기, 변수명 등등.. 코드 가독성과 유지 보수성을 높이기 위해 팀 내의 약속이 필요하다.

코딩 컨벤션은 Organization Repo의 wiki에 기록했다. CSS naming, property 선언 순서, 변수 네이밍, prettier 설정 등을 포함한다.

Home · nbcamp-react/movie-app Wiki

깃 전략 수립

github으로 협업하며 프로젝트 전반을 관리하기 위해 제공하는 기능들을 사용한다. 순서대로 기록해보았다.

커밋

커밋 메시지도 각자 작성하는 방식이 다르다. 특정 커밋을 보고 어떤 내용인지 충분히 추측 가능해야 한다. 그래야 가독성이 높아지고 개발 속도가 빨라지며 코드에 대한 리뷰도 수월해진다. 따라서, 공통적인 커밋 메시지 규칙을 정한다.

커밋 유형: 작업 내용 (#이슈 넘버)

type: subject (#issue_number)

커밋 유형

  • feat : 새로운 기능 추가
  • fix : 버그 수정
  • docs : 문서 수정
  • style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
  • refactor : 코드 리펙토링
  • test : 테스트 코드, 리펙토링 테스트 코드 추가
  • chore : 빌드 업무 수정, 패키지 매니저 수정

규칙

  • type은 소문자로 작성
  • 제목 끝에 마침표 넣지 않기
  • 명사형으로 작성

Issue

이슈(Issue)란 프로젝트 작업 단위이다. 개발, 오류, 건의 등 프로젝트에서 발생한 문제들을 이슈로 생성하여 관리한다. 커밋 메시지에 이슈 번호를 포함하면 이슈에 대한 커밋 내역들을 해당 페이지에서 확인할 수 있다. 작업을 시작하기 전 이슈를 생성하는 것이 가장 먼저 하는 일이다. 작업할 일을 명시하는 작업.

이슈 템플릿을 사용하면 일관된 양식으로 작성할 수 있다. 템플릿을 등록하면 이슈를 기능 구현과 버그 수정으로 구분하여 선택할 수 있다.

image-20231025124249000

이슈를 생성할 때는 담당자(assignees)를 지정하고 Labels을 사용해 작업 유형을 구분한다. 그리고 Projects를 지정하면 프로젝트에서 이슈들을 한 눈에 확인할 수 있다. 제목은 다음과 같이 작성한다. [작업유형/기능명] 내용 작업유형은 커밋 메시지 컨벤션을 따른다.

Github Issue Templates으로 Issue 쉽고 체계적이게 작성해보기

image-20231025122556076

image-20231025123108320

Issue 작성법

  1. 템플릿에 맞게 Issue 내용 작성
  2. 담당자(Assignee)를 지정
  3. 라벨 달기
  4. 프로젝트 지정

Projects

잠시 살펴봤지만 Projects는 프로젝트의 작업 내용과 진행 사항을 볼 수 있는 페이지다. 이슈들과 PR(Pull Request)를 한 눈에 볼 수 있다. PR을 생성할 때도 Projects에 추가할 수 있다. Projects를 사용하면 작업을 추적하고 프로젝트를 직관적으로 관리할 수 있다.

  • To Do: 해야할 작업
  • In Progress: 진행 중인 작업
  • Done: 완료된 작업

노션에도 동일한 기능이 있지만 github에서 전반적으로 관리할 수 있다는 장점이 있어 사용한다. 템플릿은 변경할 수 있지만 칸반 보드 형식이 자주 사용되므로 Board를 사용한다.

Projects에서 Workflows를 수정하면 Issue 생성 시 Projects에 배치될 기본값을 설정할 수 있다.

PR

이슈를 기반으로 작업을 수행한 뒤 PR을 생성한다. 마찬가지로 정의된 템플릿을 활용해 PR을 생성하고 git-flow 개발 프로세스에 따라 개발한다. 커밋과 PR은 최대한 작은 단위로 쪼개는 것이 좋다.

규칙

  • 제목은 이슈 제목과 동일하게 하고 이슈 번호 붙이기
    • [feature/search] 검색 기능 구현 (#1)
  • Reviewers, Assignees, Labels, Projects, Linked issues 지정
  • 검토가 끝나면 본인이 직접 PR을 merge하고 브랜치 삭제

▶ git 연습 레포에서 이미 생성된 PR을 가지고 왔다.

image-20231025125240862

develop 브랜치와 main 브랜치는 브랜치 보호 규칙을 설정해 3명 이상 approve가 있어야 merge할 수 있도록 할 예정이다.

Wiki

문서를 공유하기 위해 github의 Wiki를 사용한다. 팀 소개와 프로젝트 내용, 개발 관련 문서 등 모두 Wiki에서 관리한다. 비슷한 유형의 문서끼리 분류하고 가독성을 높이기 위해 사이드바를 이용해 Wiki 문서를 표시할 수 있다.

image-20231025125734367

브랜치 전략

브랜치 전략이란 여러 개발자가 협업하는 환경에서 git 저장소를 효과적으로 활용하기 위한 workflow이다. git-flow라는 브랜치 전략을 사용한다.

git-flow: 5가지의 브랜치를 이용해 운영하는 브랜치 전략

우린 Git-flow를 사용하고 있어요 | 우아한형제들 기술블로그

  • main: 배포 가능한 브랜치
  • develop: 개발한 기능이 모여있는 브랜치
  • feature: 기능을 개발하는 브랜치 (develop 에서 분기)
  • release: QA(품질검사)를 하기위한 브랜치 (출시 준비)
  • hotfix: main 브랜치에 발생한 버그를 긴급수정하는 브랜치

git-flow_overall_graph

실제 적용은 main, develop, feature, hotfix 네 개의 브랜치만 사용할 듯하다.

브랜치 네이밍 컨벤션

  • main
  • develop
  • feature/{feature_name}
  • hotfix/{issue_name}

git-flow 개발 프로세스

  1. develop 브랜치에서 새로운 기능 개발 브랜치 생성 feature/{feature_name}

  2. 개발 후 feature/{feature_name} 브랜치에 push

  3. develop 브랜치에 pull requests

  4. reviewer들의 리뷰가 승인되면 본인이 merge (merge한 브랜치는 삭제)

  5. 최종 테스트 후 main 브랜치에 merge

    5.1. main 브랜치에서 버그가 발생한다면 hotfix 브랜치 생성

    5.2. 버그 수정이 끝나면 develop과 main 브랜치에 각각 merge

느낀점

타이포라 짱.

관심사 분리. 효율적인 코드 짜기. 고수들의 코드를 더 많이 봐야겠다.

git 전략을 공유하며 연습도 했다. 역할 분담도 했다. 드디어 개발 시작.

카테고리:

업데이트:

댓글남기기