0%

들어가며

약 2주동안 진행했던 프로젝트가 종료되었다. 개발 공부를 시작한지도 얼마 안 되었고 처음으로 해본 프로젝트인지라 2주가 정말 정신없이 지나가버렸다. 배운점도 많았고 아쉬운점도 많았는데 회고를 하며 정리해보려고 한다.

완성된 결과물은 https://woowahal-6go5.vercel.app/ 에서 확인 가능하다.


프로젝트 우아할

이전글에서 언급했듯이 우리 팀은 배달의 민족 앱을 웹 페이지로 클론하기로 했다(그래서 팀명도 우아할형제들로 정했다).

개발 기간은 2022-09-19 ~ 2022-09-30로 약 2주 동안 진행되었고, 팀원은 나를 포함해 총 3명이었다.

프로젝트 기간이나 인원에 비해 배달의 민족이 가지고 있는 콘텐츠가 너무 많아 모든 페이지를 클론 할 수는 없었고 배달의 민족에서 배달하기 까지의 주요 프로세스를 메인,카테고리, 리스트, 디테일, 오더, 장바구니, 결과의 7개 페이지로 나누어 구현해 보았다.

나는 그 중 메인페이지와 카테고리 페이지를 주로 담당했다.


기술 스택

페이지를 구현하면서 Figma, Git, npm, HTML, CSS, Sass, JS, Vercel을 이용했다.

Figma

구현해야 하는 페이지들의 와이어프레임 및 컴포넌트들을 시각적으로 구성해보기 위해 Figma를 이용했다.

페이지에서 주사용되는 컬러를 시스템화해서 플러그인을 통해 변수로 쉽게 추출할 수 있었다.

아직 툴 사용이 미숙해 많은 기능을 활용하지는 못한것 같아 아쉽다

Git, Github

프로젝트의 버전관리를 위해 Git을 이용했다. Git flow 전략을 모방해 메인을 제외한 develop, subdev, release 3개의 branch를 만들었다.

기본적으로 모든 변경사항을 subdev에 push하였고, merge가 잘 완료되면 log를 추가해 develop으로 옮겼다. 최종적으로 public 폴더만 build해 release에 저장했다.

npm

개발환경 세팅과 최종적인 프로젝트 파일의 최적화를 위해 npm을 이용했다.

rimraf, npm-run-all, live-server, sass는 개발환경 세팅을 위해 webpack, postcss는 최적화를 위해 사용해 보았다.

HTML

HTML의 경우 시맨틱 마크업을 제일 중요시 여겼는데 먼저 손으로 페이지의 구조를 설계 한 후 코드로 작성했다. 그 후 코드리뷰를 시간을 가져 팀원들끼리 왜 그렇게 코드를 작성했는지, 구조가 논리적인지 설득하는 시간을 가졌다.

CSS, Sass

CSS를 효과적으로 사용하기 위해 Sass를 이용했고 이 때 가장 중요시 여긴점은 컨벤션이였다. 기본적으로 BEM 방식을 이용한 Naming과 최대한 구체적인 클래스명을 사용하기로 정했다.


KPT

Keep

  • 프로젝트를 시작하기 전 환경설정을 중요시 여기고 이 부분에 대해 많이 논의 했는데 그 결과 git 충돌도 거의 없었고 일어난 충돌도 금방 해결 할 수 있었다.

  • 1차적인 프로젝트 결과물을 가지고 lighthouse 검사를 통해 부족한 부분을 찾고 개선하기 위해 노력했다. 실질적인 성능 향상을 볼 수 있어서 좋았다.

  • 의견충돌이 있을때 그냥 넘어가지 않고 서로를 설득하기 위해 노력했는데 생각에 대한 근거를 찾고 정리해보며 의견을 구체화 시킬 수 있었다.

Problem

  • Sass 사용의 아쉬움 - Sass 를 사용하기 위해 폴더 구조를 잘 분리한것은 좋았으나 중첩규칙, 변수 이외에는 잘 사용하지 못했다. 특히 중복적으로 사용되는 코드들을 믹스인으로 분리했어야 했는데 그러지 못했다.

  • 미숙했던 초반 소통

Try

  • 문서화의 중요성 - 서로 상의해 결정했던 부분들이나 컴포넌트에 대한 문서들을 남겨 서로 참고할 수 있도록 하자고 말했었지만 실제 프로젝트를 진행하면서 잘 수행되지 못했다. 문서화가 잘 되어 있는 다른 프로젝트 조의 경우 전체적인 프로젝트 상황에 대한 파악이 수월해 보였다. 다음 프로젝트를 진행할 때에는 꼭 문서화에 신경써봐야겠다.

마치며

첫 프로젝트를 진행하며 많은 것을 배울 수 있어 정말 좋았다. 하지만 역시 머리에 계속해서 남는것은 아쉬운 점들인 것 같다.

평소 배달의 민족을 많이 사용하면서 이런 기능이 있으면 좋겠다고 생각해 오던것이 있다. 나는 결정장애가 심한 편이라 어떤것을 먹을지, 또 메뉴를 정해도 어디서 시킬지 정말 많이 고민한다. 그래서 카테고리만 선택하면 룰렛이 돌아가듯이 랜덤으로 가게와 메뉴가 선택되면 좋겠다고 생각했다.

마침 배달의 민족을 웹으로 구현하기로 결정해서 이 기능도 추가해 보려고 했는데 막상 스스로의 자바스크립트 실력도 너무 부족하고 어떤 데이터베이스를 기반으로 정보를 가져와야 할지 아이디어 역시도 너무 구체적이지 않아 쉽지 않았다.

스스로 많이 부족하다고 느끼는 점이 가장 아쉬웠다.
다만 앞으로 3개월 동안 커넥to 과정을 통해 모던 자바스크립트 Deep Dive의 저자이신 이웅모 강사님에게 자바스크립트 강의를 듣게 되었는데, 정말 좋은 기회이니 만큼 열심히 배우고 또 평상시 가지고 있던 아이디어들에 대해서도 구체화해 프로젝트를 리팩토링해봐야 겠다.

Sass?

CSS를 사용해 웹 애플리케이션 스타일을 관리하는 것은 애플리케이션 규모가 커지고 복잡해질수록 매우 어렵다.

반면 Sass와 같은 프리프로세서(Pre-Processor, 전처리기)를 사용하면 매우 효과적으로 복잡한 애플리케이션 스타일을 관리할 수 있다.

Sass란 Syntactically Awesome Style Sheets의 준말로 CSS가 아직은 할 수 없는 다양한 기능(중첩, 함수, 믹스인, 상속 등)을 제공한다.

Sass말고도 Stylus, Less와 같은 전처리기가 존재하지만 현재 Sass가 통계상 가장 사용자가 많으면서 만족도가 높아 배웠을 때 가장 유용하다고 할 수 있다. (설문결과)


설치

Sass를 이용하기 위해선 먼저 설치를 해야한다. 공식사이트를 참고해 다양한 방식으로 설치가 가능하다. 나는 Node.js를 이용하고 있기에 npm을 통해 설치해 주었다.

1
npm install -g sass

컴파일

Sass를 설치해 이용하고자 할 때, 웹 브라우저는 Sass파일을 해석할 수 없기에 Sass파일을 CSS파일로 변경해야 한다. 이를 컴파일이라 하는데 다음과 같이 사용 가능하다.

1
sass input.scss output.css

단일 파일이 아니라 폴더 단위의 변경을 처리한다면 :을 이용할 수 있다.

1
sass src/scss:public/css

더 많은 옵션은 Dart Sass CLI를 참고할 수 있다.


문법

Sass파일은 사용하는 문법에 따라 .scss의 확장자를 가진 SCSS 구문과 .sass를 가진 Sass구문 2가지로 나뉜다.

Sass 구문

Sass 구문은 중괄호, 세미콜론을 생략하고 들여쓰기 문법을 사용한다. 좀 더 간결하고 작성하기 편리하며 {};를 사용하지 않아도 되어 코드가 깔끔하다.

1
2
3
4
.button
cursor: pointer
&:disabled
cursor: not-allowed

SCSS 구문

SCSS 구문은 CSS와 유사한 문법을 사용한다. 인라인 코드를 작성할 수 있고, CSS와 유사한 문법을 가지기 때문에 코드 통합이 훨씬 쉽다.

1
2
3
4
5
6
.button {
cursor: pointer;
&:disabled {
cursor: not-allowed;
}
}

서로 장단점이 있기 때문에 회사나 팀에서 원하는 방식 혹은 개인의 취향에 따라서 선택할 수 있다. 일반적으로 CSS 구문과 문제없이 호환되는 SCSS구문이 많이 사용된다.


Sass Basics

수업을 들으면서 Sass의 두 가지 구문중 SCSS를 사용했기에 Sass Basics에 대해 SCSS를 이용한 방법으로 정리하겠다.

변수(Variables)

CSS도 변수 사용이 가능하지만 Sass에서는 $를 이용해 더 쉽게 변수를 사용할 수 있다.

CSS 변수

1
2
3
4
5
6
7
8
9
10
11
:root {
--spacing-1: 4px;
--spacing-2: 8px;
--primary-400: hsl(250, 75%, 60%);
--primary-500: hsl(250, 75%, 50%);
}

.container {
margin-top: var(--spacing-2);
color: var(--primary-500);
}

SCSS 변수

1
2
3
4
5
6
7
8
9
$spacing-1: 4px;
$spacing-2: 8px;
$primary-400: hsl(250, 75%, 60%);
$primary-500: hsl(250, 75%, 50%);

.container {
margin-top: $spacing-2;
color: $primary-500;
}

중첩(Nesting)

CSS는 HTML과 달리 시각적인 계층 구조와 명확히 중첩된 구문을 작성할 수 없다. 하지만 Sass는 HTML과 동일하게 시각적 계층 구조를 따르는 방식으로 스타일을 작성하는 방법을 지원한다.

CSS 구문

1
2
3
4
5
6
7
8
9
10
11
12
13
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}

SCSS 구문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}

li {
display: inline-block;
}

a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}

Sass 중첩 구문은 시각적으로 계층 구조를 파악할 수 있어 CSS 보다 직관성이 높다. 하지만 많은 중첩은 오히려 복잡성을 증가시켜 가독성이 떨어지므로 피해야한다.

모듈(modules)

모듈은 독립적으로 묶인 작은 코드 조각으로, Sass는 관심사에 따라 여러 조각의 코드로 묶인 파일을 관리할 수 있는 기능인 모듈화를 제공한다. 모듈은 애플리케이션 스타일을 유지 관리하기 쉽게 만들어 주는 매우 효과적인 방법이다.

Sass(정확히는 Dart Sass)에서는 @import rule대신 @use를 이용해 다른 스타일 모듈을 불러올 수 있다. Sass 파일 확장자와 언더스코어(_)는 생략 가능하다.

_base.scss

1
2
3
4
5
6
7
$font-stack: Helvetica, sans-serif;
$primary-color: #333;

body {
font: 100% $font-stack;
color: $primary-color;
}

불러온 모듈은 기본적으로 파일 이름을 네임스페이스(namespace)로 가지며 점(.) 문법을 사용해 모듈의 변수 등에 접근할 수 있다.

styles.scss

1
2
3
4
5
6
@use 'base';

.inverse {
background-color: base.$primary-color;
color: white;
}

네임스페이스 이름을 다른 이름으로 변경해 사용하고자 할 경우 as를 사용한다. 특히 as에 별(*) 기호를 사용할 경우 네임스페이스 없이 바로 모듈에서 내보낸 변수를 사용할 수 있다.

1
2
3
4
5
6
@use 'base' as *;

.inverse {
background-color: $primary-color;
color: white;
}

CSS

1
2
3
4
5
6
7
8
9
body {
font: 100% Helvetica, sans-serif;
color: #333;
}

.inverse {
background-color: #333;
color: white;
}

믹스인(mixins)

CSS는 코드를 재사용 할 수 있는 기능이 제공되지 않기 때문에 코드 중복이 잦은 언어이다. 하지만 Sass는 코드를 효율적으로 재사용할 수 있도록 믹스인 기능을 제공한다. 믹스인을 이용해 재사용할 코드 그룹을 선언할 수 있다.

SCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@mixin theme($theme: DarkGray) {
background: $theme;
box-shadow: 0 0 1px rgba($theme, 0.25);
color: #fff;
}

.info {
@include theme;
}
.alert {
@include theme($theme: DarkRed);
}
.success {
@include theme($theme: DarkGreen);
}

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.info {
background: DarkGray;
box-shadow: 0 0 1px rgba(169, 169, 169, 0.25);
color: #fff;
}

.alert {
background: DarkRed;
box-shadow: 0 0 1px rgba(139, 0, 0, 0.25);
color: #fff;
}

.success {
background: DarkGreen;
box-shadow: 0 0 1px rgba(0, 100, 0, 0.25);
color: #fff;
}

@mixin과 이름을 통해 믹스인을 만들 수 있다. 믹스인을 만든 후에는 @include와 이름을 선언해 믹스인을 이용 할 수 있다. 또한 믹스인은 JavaScript 함수처럼 매개변수를 설정할 수 있는데, 매개변수를 사용하면 믹스인 외부에서 사용자가 전달한 값을 믹스인 내부에서 사용해 재사용성을 더 높여줄 수 있다.

확장/상속 (extend/inheritance)

선택자 이름 앞에 %를 사용해 선언한 플레이스홀더 클래스는 스타일을 확장할 때만 사용되는 특수한 유형의 클래스로 여러 선택자에서 공유할 수 있다. 스타일 집합을 공유할 때는 @extend를 사용한다.

이 방법은 스타일 코드를 반복 생성하는 믹스인과 달리, 스타일 코드 집합 하나를 재사용하는데 목적을 두고 있어 보다 코드를 깨끗하게 유지하는데 도움이 될 수 있다.

SCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%message-shared {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}

.message {
@extend %message-shared;
}

.success {
@extend %message-shared;
border-color: green;
}

.error {
@extend %message-shared;
border-color: red;
}

.warning {
@extend %message-shared;
border-color: yellow;
}

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.message,
.success,
.error,
.warning {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}

.success {
border-color: green;
}

.error {
border-color: red;
}

.warning {
border-color: yellow;
}

연산자 (operators)

CSS에서 수학은 매우 유용하다. Sass는 산술연산자(+, -, *, %) 및 수학 함수(예: math.div())를 제공한다.

SCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@use 'sass:math';

.container {
display: flex;
}

article[role='main'] {
width: math.div(600px, 960px) * 100%;
}

aside[role='complementary'] {
width: math.div(300px, 960px) * 100%;
margin-left: auto;
}

CSS

1
2
3
4
5
6
7
8
9
10
11
12
.container {
display: flex;
}

article[role='main'] {
width: 62.5%;
}

aside[role='complementary'] {
width: 31.25%;
margin-left: auto;
}

특히 math.div()를 이용하기 위해서는 @use "sass:math"를 이용해 Sass에서 기본으로 제공하는 math 모듈을 불러와야 한다. 이때 as *를 이용해 사용한다면 div 태그와 구분이 가지 않으므로 math.div()의 기본 형태로 사용하는 것이 추천된다.


참고

이미지 스프라이트란 여러 개의 이미지를 하나로 합쳐서 관리하는 이미지를 의미한다.

웹 페이지에 이미지를 사용한다면 웹 브라우저는 해당 이미지의 다운로드를 위해 서버에 요청을 보낸다. 만약 사용된 이미지가 많을 경우 요청 하는 횟수가 많아지므로 웹 페이지의 로딩 시간이 오래 걸리게 된다. 하지만 만약 이미지 스프라이트를 사용한다면 스프라이트 이미지 파일 하나가 여러 이미지를 가지고 있기에 서버 요청 횟수를 줄일 수 있다.

개인적인 블로그와 같은 일반적인 사이트에서는 굳이 이미지 스프라이트를 사용 할 필요가 없지만, 트래픽이 매우 많거나 많은 사람이 이용하는 검색포털과 같은 사이트에서는 이미지 스프라이트를 사용하여 서버 요청을 줄이고 웹 페이지의 로딩 시간을 단축시켜 사이트의 품질을 높일 수 있다.

다음은 네이버 메인페이지의 스프라이트 이미지이다.

이처럼 여러개의 이미지를 하나로 합쳐두고 CSS의 background-position을 이용해 사용하려는 이미지만을 보여 줄 수 있다. 이 때 background-position의 값은 하나씩 position값을 변경해보며 찾을 수 도 있지만 Sprite Cow와 같은 사이트를 이용 할 수 있다.

추가적으로 스프라이트 이미지를 만들기 위해 포토샵, 피그마 등으로 에디팅 할 수 도 있지만 CSS Sprites Generator라는 사이트를 이용 가능하다.


참고