CSS 설계를 위한 기본 가이드

변경과 확장에 강하고 안정적인 CSS 구조를 위한 기법

다양한 예제로 배우는 CSS 설계 실전가이드에서 소개하는 설계의 핵심을 알아보자.

CSS의 여러 설계 기법들도 결국에는 다음 여덟 가지 리스트에 속한다고 하니 핵심을 관통하는 포인트라고 볼 수 있다.

1. 특성에 따른 CSS 분류
2. 느슨한 스타일의 결합
3. 적당한 영향 범위
4. 특정 컨텍스트에 대한 적절한 의존도
5. 적절한 명시도(specificity)
6. 영향 범위가 유추 가능한 클래스 네임
7. 형태, 기능, 역할의 유추가 가능한 클래스 네임
8. 확장 용이성

1. 특성에 따른 CSS 분류

첫 번째는 CSS 역할이나 특성에 따라 분류하는 것이다.

베이스 그룹 : 사이트에서 베이스가 되거나 공통으로 적용되는 사항 등
레이아웃 그룹 : 헤더(header), 푸터(footer), 콘텐츠(content) 영역 등
모듈 그룹 : 재사용되는 모듈 등

모듈 자체에는 레이아웃과 관련된 부분은 설정하지 않는 것이 좋다. 모듈은 자신의 레이아웃에는 관여하지 않고 해당 모듈 자체의 역할 및 자녀 요소의 스타일링에만 관심을 가져야 한다. 여기서 레이아웃과 관련된 부분이란 다음과 같다.

-position, z-index, top/right/bottom/left, float, width, margin

/* 베이스 */
body {
  font-family: 'Noto Sans';
}

/* 레이아웃 */
layout_content {
  width: 1000px;
  padding: 10px;
  margin: 0 auto;
}

/* 모듈 */
.bl_media {
  display: flex;
  justify-items: center;
  align-items: center;
}

.bl_media_title {
  margin: 5px;
  font-weight: bold;
}

2. 느슨한 스타일의 결합

정확히는 HTML과 스타일링의 느슨한 결합이다. 느슨한 결합이란 의존하지 않는 상태를 이야기하는데 가장 간단한 방법으로는 요소형 셀렉터를 피하고 클래스 셀렉터를 사용하는 것이다.

p{}, div{}, h1{}과 같이 요소의 스타일을 직접 정의하는 요소형 셀렉터는 요소의 변경이 발생하게 되면 스타일이 중복되거나 누락될 가능성이 크므로 클래스를 사용해서 정의하는 것이 좋다.

3. 적당한 영향 범위

영향 범위를 가능한 좁게 하거나 영향 범위가 넓은 CSS의 스타일을 최소화한다.

영향 범위를 고려하지 않은 채 스타일을 추가하다보면 의도하지 않은 부분에서 오류가 발생하므로 최대한 범위를 줄이기 위해 가장 가까운 부모 요소를 포함시키거나 손자와 자녀 셀렉터의 사용도 함께 검토하는 것이 좋다.

4. 특정 컨텍스트에 대한 적절한 의존도

컨텍스트란 위치 또는 상황을 의미하며, 이 컨텍스트가 변할 때 코드가 동작하지 않을 수 있는 상황을 주의해야 한다. 사용 목적이 명확하다면 문제없지만 그렇지 않은 경우에는 셀렉터를 불필요한 부분까지 구체화하게 되면 해당 문제가 발생하기 쉽다.

/* id인 main을 지정하게 되면 해당 모듈 내부에서만 사용 가능한 .title_top 클래스가 되어 의존도가 높아짐. -> 불필요한 #main 제거 */
#main .title_top{
  display:flex;
  align-items: center;
  color: green;
}

5. 적절한 명시도(specificy)

우선순위를 나타내는 명시도와 관련된 내용은 여기를 클릭하면 확인할 수 있다.

명시도가 높은 CSS의 단점은 다음과 같다.

– 셀렉터 예측이 어려움
– 다른 요소(부모 요소 등)에 대한 의존도 상승
– 덮어쓰기의 어려움
– 유지 보수의 어려움

당연히 !important는 사용하지 않는 것이 기본이며, 셀렉터를 사용할 때는 클래스 셀렉터를 사용한다. id 셀렉터는 우선순위가 매우 높으며 한 페이지 안에서 동일한 값은 한번 밖에 사용하지 못하는 제약도 있으므로 id를 사용하는 이점은 많지 않다.

따라서 기본적으로 클래스 셀렉터를 사용해서 의도하지 않은 우선 순위가 뒤섞이지 않도록 해야 한다.

6. 영향 범위가 유추 가능한 클래스 네임

규모가 커질수록 모듈이나 클래스도 늘어나므로 하나의 클래스 수정이 어떤 범위까지 영향을 미칠지를 이름에서 판단할 수 있도록 해야 한다.

HTML에서 정의된 요소의 클래스 네임만 보고도 CSS의 영향 범위를 유추할 수 있도록 하자.

클래스 네임으로 영향 범위를 쉽게 유추하기 위해서는 자녀 요소에 루트 요소의 클래스 네임을 포함하도록 하는 것이 좋다.

7. 형태, 기능, 역할의 유추가 가능한 클래스 네임

영향 범위와 마찬가지로 형태, 기능, 역할도 유추가 가능하도록 네임을 지정해야 한다.

– title1, title2, title3
– main-title, nav-title, sub-title

두 항목 중 형태나 기능, 역할의 유추가 쉬운 쪽이 어디인지는 분명하다. 각 모듈의 기능이나 역할에 맞춰 이름을 붙이는 것이 매우 중요하다. 특히 작은 규모의 코드라면 title1, title2와 같이 네임을 대충 지정하기 쉽다. 하지만 규모란 언제 어떤 방식으로 커질지 모르므로 항상 습관적으로 이름에서 형태, 기능, 역할을 유추할 수 있고 구체성과 범용성의 균형을 맞추도록 하는 노력이 필요하다.

8. 확장 용이성

확장성이란 결국 기능의 추가나 유지와 연결되는 부분으로, 항상 가능성을 열어두어야 한다.

확장이 쉽도록 클래스를 설계하거나 추가하는 클래스에는 기능, 역할에 따라 적절한 상세도와 영향 범위를 갖도록 한다.

확장이 쉬운 클래스란 멀티 클래스를 사용하는 것으로, 하나의 클래스에는 보편적인 속성, 추가 클래스에는 특정 속성을 추가하여 덮어쓰기를 통해 여러 클래스로 스타일을 지정하는 방식이다.

이를 통해 HTML은 복잡해지지만 CSS는 매우 간단해지는 트레이드오프가 발생하기도 한다. 하지만 멀티 클래스의 이점은 불규칙한 상황에서도 클래스 하나만으로 원하는 작업을 완료할 수 있는 간결함이다.

결국 모든 항목은 별개의 사항이 아니라 다 연결되어 있음을 알 수 있고, 작은 수정 하나가 큰 나비효과를 불러올 수도 있다는 점을 명심해야 한다.

매번 하나하나 체크해가면서 코드를 작성하기보다는 작성 방식이 고민되거나 자율성이 주어졌을 때, 해당 리스트를 떠올리면서 작성하다보면 생각보다도 더 견고한 구조를 만들 수 있을 것이다.


참고 : 다양한 예제로 배우는 CSS 설계 실전가이드(2021, 제이펍)

[BOOK] 프레임

세상을 바라보는 마음의 창

지구를 ‘구sphere’라고 부르는 이유는 평균 때문이다. 울퉁불퉁한 면이 있더라도 평균적으로 보면 지구는 둥글다. 사람을 보는 우리의 눈도 그래야 한다.

주변에서 일어나는 모든 일을 자신과 관련시켜 해석하는 경향은 정신 건강을 해치는 주범 중 하나이다. 심리학 연구에서 ‘자기’에 대해 지나친 생각이 남들과 자신을 자주 비교하게 만들고 행복을 저하시킨다는 점을 보여준다. 물론 자신이 세상을 바라보는 소통의 창구가 되는 것을 막을 수는 없다.

진정한 지혜는 나 자신의 행동을 설명하는 것과 동일한 방법으로 다른 사람의 행동을 설명하는 마음의 습관이다.

사람은 마음 속에 CCTV를 설치해놓고 자신을 감시하고 있으면서 다른 사람이 자신을 주목하고 있다고 착각한다. 다른 사람들이 나를 주시하고 있다고 생각하지만 정작 우리를 보는 것은 남이 아닌 자기 자신이다.

우리는 연극의 주인공이 아니지만 자신은 스타들처럼 조명 받고 있다고 착각하면서 다른 사람들의 시선을 필요 이상으로 신경 쓴다.

어떤 것이든 자신과 관련지어 바라볼 때 기억이 잘되는 현상을 자기 준거(self-reference)효과라고 한다. 똑같은 것이라도 자신과 관련지어 생각하면 기억을 더 잘하게 된다.

세상은 아직 살 만한 곳이고 주변에는 좋은 사람들이 많다고 생각하는 사람은 가까이 해도 좋다. 이런 사람은 누구와 있어도 상대의 장점부터 보기 때문이다.

자기 주변에 남을 비방하는 사람이 많다고 불평하는 사람은 가까이 하지 않는 것이 좋다. 자신이 남의 허물을 습관적으로 들춰내는 사람일 가능성이 높기 때문이다.

우리가 다른 사람을 평가하는 내용을 보면 다른 사람보다 자신이 어떤 사람인지를 더 많이 드러낸다.

허위 합의 효과에 사로잡힌 우리가 깨달아야 할 사실은 세상에는 자신의 생각과 다른 사람들이 생각보다 훨씬 많다는 것이다.

자기중심적 프레임 때문에 다른 사람들도 나와 비슷할 것이라고 생각한다. 이런 현상을 허위 합 효과(false consensus effect)라고 하며, 자신의 의견이나 선호, 신념, 행동이 실제보다 더 보편적이라고 착각하는 자기중심성을 나타내는 개념이다.

지혜가 기대림의 대상이 아니라 적극적인 훈련의 대상이 될 수 있는 이유는 지혜의 본질이 우리 마음의 한계를 지각하는 데 있기 때문이다.

기본적으로 제시되는 양이 ‘사회적으로 바람직한 평균적인 양’이라고 해석하는 경향이 있어 이에 따라 사람의 행동도 변한다.

현명한 소비자는 소유보다는 경험의 프레임을 가지기 위해 노력한다. 경험을 위해 구매한 물건은 대부분 사람들과의 관계에 사용되는 것들이다. 이는 어떤 물건의 구매 행위를 통해 새로운 삶을 경험하는 것이 소유 자체를 위해 구매하는 것보다 많은 사람들에게 더 큰 행복감을 안겨준다.

같은 물건을 사면서도 경험 프레임을 갖고 구매하는 사람은 물건을 통해 맛보게 될 새로운 경험에 주목한다.

일상에서 소유의 프레임과 경험(존재)의 프레임이 가장 빈번하게 대비를 이루는 분야는 소비의 영역이다.

어떤 문제에 봉착했을 때 해결점을 찾지 못하는 이유는 처음부터 문제의 본질이 무엇인지 제대로 프레임하지 못했기 때문이다.

상위 프레임은 왜 이 일이 필요한지 그 이유와 의미, 목표를 묻는다. 비전을 묻고 이상을 세운다. 하위 수준의 프레임에서는 일의 난이도와 시간의 소요, 성공 가능성 등의 구체적인 절차부터 묻는다.

상위 수준의 프레임은 우리가 죽을 때까지 가져야 할 삶의 태도이며 자손에게 물려줄 수 있는 가장 위대한 유산이다. 상위 프레임에서는 Why를 묻지만 하위 프레임에서는 How를 묻는다.

행복은 ‘무엇’이 아니라 ‘어떻게’의 문제이며 행복은 대상이 아니라 재능이다.

프레임은 결심의 대상보다는 설계의 대상이다. 언어와 은유, 가정과 전제, 단어와 질문, 경험과 맥락 등을 점검하여 더 나은 것으로 설계해야 한다.

우리의 프레임을 확인할 수 있는 하나의 일화가 있다.

‘아버지와 아들이 야구 경기를 보러 가기 위해 집을 나섰다. 그런데 아버지가 운전하던 차의 시동이 기차 선로 위에서 갑자기 꺼졌다. 달려오는 기차를 보며 아버지는 시동을 걸려고 황급히 자동차 키를 돌렸지만 소용이 없었고, 결국 기차는 차를 그대로 들이받고 말았다. 둘 다 크게 다쳐서 응급실로 옮겨졌다. 수술을 하기 위해 응급실로 달려온 외과 의사가 아들의 차트를 보고 “난 이 응급 환자를 수술할 수 없어. 얘는 내 아들이야!”라며 절규를 한다. 대체 어떻게 된 영문일까?’

프레임의 영향을 받지 않는다면 쉽게 이 의사는 아들의 엄마인 것을 알 수 있다. 그러나 ‘외과 의사=남자’라는 프레임에 영향을 받는다면 삼류 소설을 쓰기 시작할 수도 있다.

프레임의 또 다른 경우도 있다.

만약 안 좋을 일과 좋은 일을 하나씩 경험할 수 있다면 무엇을 먼저 경험하는 것이 좋을까? 답은 대체로 안 좋은 일을 먼저 경험하는 것이 낫다. 안 좋은 일 다음에 경험하는 좋은 일은 더 달콤하게 느껴질 뿐만 아니라 뒤의 좋은 경험이 앞의 안 좋은 경험을 긍정적으로 재해석해주기 때문이다.

인생에서는 순서가 중요하다. 젊어서 고생은 사서 한다는 말이 있듯이 젊은 시절의 고생이 인생 후반의 경험을 더 달콤하게 만들어주기 때문이다.

질문의 순서가 중요한 이유도 앞의 질문이 뒤에 나오는 질문을 해석하는 프레임으로 작동한다.

앞의 경험이 뒤에서 하게 될 경험을 바라보는 프레임으로 작동하는 것이다.

자기 삶에 대한 평가가 시시하다면 내가 시시한 질문을 던지고 있기 때문인지 모른다. 답이 안 나오는 인생을 살고 있다면 질문에 문제가 있을 가능성이 있다. 무언가 더 나은 답을 찾고 싶은 사람은 세상을 향해 던지고 있는 질문부터 점검해야 한다.

마지막에 대한 우리의 기대는 각별하다. 그래서 마지막이라고 정의를 내리면 그 프레임은 대상에 대한 우리의 기대와 평가를 극적으로 바꾼다.

어떤 상황에 처하기 전에는 보지 못했던 것들이 이후의 맥락에서는 보이기 마련이다. 역지사지란 상대의 맥락을 이해해주는 것이다.

프레임은 우리가 지각하고 생각하는 과정을 선택적으로 제약하고 궁극적으로 지각과 생각의 결과를 결정한다.

우리 마음의 한계를 자각하는 것은 역설적으로 한계 밖에 존재하는 새로운 곳으로의 적극적인 진군을 의미한다.

건물 어느 곳에 창을 내더라도 그 창만큼의 세상을 보게 되듯이 우리도 프레임이라는 마음의 창을 통해 보게 되는 세상만을 바라본다.

세상은 강자와 약자, 성공과 실패로 나뉘지 않는다. 세상을 배우는 자와 배우지 않는 자로 나뉠 뿐이다.

[BOOK] 나는 앞으로 몇 번의 보름달을 볼 수 있을까

사카모토 류이치의 세상을 대하는 태도

아름다운 선율의 음악을 만드는 사람들이라도 저마다 세상을 대하는 태도는 모두 다르겠지만 사카모토 류이치의 음악은 그의 마음가짐과 세상을 바라보는 따뜻한 시선을 그대로 담은 것만 같다.

이 책은 인생의 마지막에서 누구보다 죽음에 가까운 상태에서 인생을 돌아보며 쓴 글이다. 어떠한 마음가짐으로 하루하루를 지내야 할지 다시 한번 생각해보게 한다.

Merry Christmas, Mr.Lawrence는 영화 제목이자 사카모토 류이치의 가장 유명한 곡이기도 하다. 주연으로 캐스팅된 사카모토 류이치가 전공(도쿄예술대 작곡)을 살려 음악 감독도 맡겨달라고 청하게 되고 그의 요청이 이루어지게 되면서 음악이 탄생하게 된다.

물론 별모자가 사카모토 류이치의 젊은 시절이다.

마음에 와닿았던 부분들을 간략하게 적어본다.

설령 위선자라 비판을 받는다 해도 그로 인해 사회가 조금이라도 나아질 수 있다면 좋은 일이 아닌가. 환경에 관한 운동도, 지진 재해 후 활동도 이런 신념의 힘으로 실천하고 있다. 한번 연결되면 쉽게는 그만둘 수 없다.

역시 인간은 일하지 않고 돈만 받는다고 만족할 수 있는 생물이 아니다.

결국 사용 편리성의 좋고 나쁨은 기술 그 자체보다 설계자가 얼마나 사용자의 입장을 깊이 고려했는가에 의해 좌우된다고 생각한다.

환갑을 넘기고, 큰 병을 앓고, 속세의 욕망에 휘둘리지 않는 청빈한 상태가 되었기 때문에 비로소 자신이 올라야 할 산이 모습을 드러내기 시작한 것 같다. 큰 나선을 그리듯 빙 돌아서 원점으로 돌아온 셈이다.

기본적으로는 자연스럽게 살다 자연스럽게 죽어가는 것이 동물 본래의 순리이자 생명 본연의 모습이라고 믿는다. 인간만 거기서 벗어나 있다.

몸이 건강할 때는 시간의 영원함이나 일방향성을 전제로 하는 면이 있었지만 생의 유한함에 직면한 지금은 이제까지와는 다른 각도에서 다시 생각해볼 필요가 있다고 느낀다.

친구끼리는 사상이나 신념, 취미가 달라도 아무런 문제가 되지 않는다. 그저 묵묵히 기댈 수 있는 사람, 그런 이들이 많지 않아도 확실하게 존재하므로 그것만으로도 나는 행복한 사람이라고 느낀다.

인간은 자신의 죽음을 예측하지 못하고, 인생을 마르지 않는 샘이라고 생각한다. 하지만 세상 모든 일은 고작 몇 차례 일어날까 말까이다. 자신의 삶을 좌우했다고 생각할 정도로 소중한 어린 시절의 기억조차 앞으로 몇 번이나 더 떠올릴 수 있을지 모른다. 나는 앞으로 몇 번이나 보름달을 더 볼 수 있을까. 사람들은 이런 사실을 모르고 기회가 무한하다고 여긴다.

자바스크립트, class를 문법적 설탕(syntactic sugar)이라 부르는 이유

function으로 구현하는 class의 동작 방식

‘문법적 설탕’은 통용되는 단어이지만 어감이 이상한 건 어쩔 수 없다. 의역하여 ‘편리한 구문 용법’ 정도가 더 이해하기 쉬울 것 같다.

위키에서 syntactic sugar의 정의는 다음과 같다.

In computer science, syntactic sugar is syntax within a programming language that is designed to make things easier to read or to express.
컴퓨터 과학 분야에서 ‘편리한 구문 용법’이란 읽기 쉽고 표현하기 쉽도록 구성된 프로그래밍 언어 내의 구문이다.

즉, 달콤한 초콜릿처럼 손이 자주 가는 구문이라고 볼 수 있을 것 같다.

자바스크립트는 처음부터 모든 기능을 갖고 태어나지 않았으므로 ES 버전으로 대표되는 추가 기능은 기존의 문법으로 구현된 것이 많다.

class 또한 기존의 OOP에서 차용한 개념을 자바스크립트에서 구현한 것으로 구현 방식은 자바스크립트의 문법을 벗어나지 않는다.

따라서 사용자가 선언하고 사용하는 방식은 다르지만 다음에서 확인할 두 코드의 작동 방식은 동일하다.

function으로 선언된 부분이 기본 동작 방식이며 class가 선언되면 이 function과 완전히 동일한 방식으로 구현된다.

같은 기능을 구현할 때 function과 class 중 어떤 것에 더 선뜻 손이 가는지를 묻는다면 설탕의 의미를 생각해볼 수 있다.

function 사용

function createGame( user, point ) {
  this.user = user;
  this.point = point;
}

createGame.prototype.addPoint = function() { this.point++; };

const myGame = new createGame("Yoon", 0);

myGame.addPoint();

class 사용

class CreateGame {
  constructor (user, point) {
    this.user = user;
    this.point = point;
  }
  addPoint() { this.point++; }
}

const myGame = new CreateGame("Yoon", 0);
myGame.addPoint();

React에서 iframe 전체화면 전환하기(속성 체크 포함)

allowfullscreen 그리고 document.fullscreenEnabled

화면 내부에 삽입된 iframe에서 전체 화면 설정, 해제 기능을 구현하려고 한다.
구현은 생각보다 간단하다.

먼저 iframe 태그에 allowfullscreen 속성을 추가해야 한다.
allowfullscreen 속성을 갖는 iframe은 자바스크립트에서 제공하는 메서드를 통해 전체화면 설정, 해제가 가능하며 ESC도 사용할 수 있다.

<iframe src=”https://choonse.com” allowfullscreen />

전체 화면 설정 메서드 document.documentElement.requestFullscreen()
전체 화면 해제 메서드 document.exitFullscreen()

전체화면 설정/해제 버튼에 이벤트를 걸어서 사용할 수 있으며, 반환형은 Promise이다.

만약 allowfullscreen 속성이 없는 iframe에서 해당 메서드를 호출하면 어떻게 될까?disallowed by permissions policy 에러로 사람을 당황시킨다.

이 때는 allowfullscreen 속성의 존재 여부(true)를 체크해주면 되는데, 해당 속성은
document.fullscreenEnabled 속성을 사용해 true/false로 확인한다.

만약 iframe에 allowfullscreen 속성이 없을 때 전체 화면 버튼을 비활성화하고 싶을 때는 어떻게 할까?

document.fullscreenEnabled를 체크해서 활성/비활성을 결정하면 되는데 document is not defined와 같은 에러를 피하기 위해서는 useEffect 내부에서 해당 작업을 처리하여 렌더링이 완료된 시점에 document에 접근하도록 해야 한다.

[BOOK] 사용자의 마음을 움직이는 UX 디자인의 힘

사용자의 목소리가 제품에 미치는 영향

문제를 해결하기 위해서는 문제에 먼저 다가가야 한다. 문제의 발원지인 사용자를 탐구하는 것이 시작이다.

문제의 해결 방향은 사용자의 목소리에서 나온다.

정량적인 가치만으로는 설명하기 어려운 것들이 있다. 목표에 더 빨리 도달한다고 해서 매력적인 제품이 되는 건 아니기 때문이다.

Nielsen Norman Group이 정의하는 User Experience

서비스 및 제품, 회사와 사용자 간에 발생하는 상호작용의 모든 것
(All aspects of the end user’s interaction with the company, its services, and its products)

서비스 또는 제품이라는 대상과 이를 사용하는 사용자의 접점을 중심으로 다양한 상호작용이 발생하며 이 상호작용에서 발생하는 모든 현상을 사용자 경험(UX)이라고 정의한다.

문제를 발견하고 발견된 문제를 해결하는 것이 UX 디자인의 본질이다.

눈에 보이는 것에 치중하기보다 상호작용하는 경험에 집중해야 한다.

UX 디자인은 제품이나 서비스 경험을 상품 가치가 있는 형태로 환원하는 일이다. 순수 미술이 아니므로 멋진 경험만 설계하는 것은 의미가 없고 가치를 만들어야 한다. 디자인은 근본적으로 상업적인 속성을 담고 있기 때문이다. 따라서 상품으로서의 가치 또한 중요하다.

문제에 대한 답은 시간을 정해놓고 찾는 것이 아니라 문제를 발견했을 때 바로 고민하고 찾아야 한다. 이를 통해 왜곡시키지 않은 날 것 상태의 문제를 제대로 바라볼 수 있다.

불편함을 개선하고 필요에 의해 무엇인가를 만들어내는 인간의 근본적인 속성은 지금이나 예전이나 다를 것이 없다. 문제를 발견하고 그것을 해결하는 메커니즘이 동일하기 때문이다. 현대에서는 그 개념이 고도화된 것일 뿐이다.

UI를 설계하는 과정은 수납공간 정리 과정과 매우 유사하다. 정보의 크기와 중요도에 따라 정보의 우선 순위를 정하고 자주 사용하는 것을 가까이에 배치한다. 이 때는 직관성과 효율성을 고려한 설계가 필수적이다. 불필요한 정보는 과감하게 숨기거나 삭제하고 새로운 것을 수용할 수 있는 공간까지 여유를 두도록 해야 한다.

디자인을 통해 사용자를 목표 지점으로 안내해야 한다. 안내에서 가장 중요한 것은 여정을 편안하게 만드는 것이다.

효율성보다 더 중요한 것은 이면에 숨겨진 사람들의 욕구이다. 덜 수고로운 길을 찾아 행동하는 사람의 욕구에 집중해야 한다. 따라서 Desire Path라는 말은 경험 디자인의 핵심을 담고 있는 용어이다. 자연스럽게 형성된 사람들의 경험을 존중하는 것이다.

사용자는 디자이너 못지 않게 창의적인 존재이므로 사용자를 틀에 가두려고 하면 디자이너가 만들어 놓은 길에는 균형이 생기기 쉽다.

디자이너는 일반 사용자를 대표할 수 없으므로 디자이너가 모두를 만족시킬 수 있다는 생각은 버려야 한다. 따라서 철저하게 사용자의 입장에서 접근해야 한다.

행위를 유도하는 물건에 사람들이 필요로 하는 장치를 더해주면 그 가치는 더 올라간다.

겉으로 드러나지 않는 숨겨진 욕구를 찾는 일은 혁신 포인트를 발굴하기 위한 중요한 지점이다. 이를 찾는 방법은 현장으로 들어가 날것의 경험을 수집하고 입체적인 접근을 통해 깊이 빠져드는 것이다.

디자이너의 가장 큰 무기는 사용자의 목소리이다.

좋은 정보 디자인이라고 하면 시각적으로 멋진 그래픽이나 자극적인 데이터를 떠올리기 쉽지만 진짜 좋은 정보 디자인은 사람들이 궁금해하는 정보를 재료로 맛있게 먹을 수 있는 형태로 제공하는 것이다. 단순히 눈에 보기 좋은 그래픽이 아니라 잘 차려진 밥상이 되어야 한다.

UX 디자인은 과격한 진화보다는 본질을 지키면서 혁신을 이루는 것이 멋이다.

기획자가 간결한 문장으로 핵심 정보와 색깔을 다 담아낼 수 있다면 실력있는 기획자로 볼 수 있다. 감각적인 부분도 중요하며 전두엽을 후려치는 표현을 만들 수 있어야 한다.

내용이 뻔하지 않고 세련된 날카로움을 갖는 디자인을 위해서는 상대방의 입장이 되어보는 것이 중요하다.

아이디어는 자연 발생 아이디어와 집단 지성을 활용하는 두 가지 방식이 있다.
자연 발생하는 아이디어는 주로 인터뷰에서 사용자의 불만을 청취하면서 해결책이 떠오르는 경우이며 집단 지성은 여러 사람이 모이면 아이디어의 양이 풍성해지는 이점을 노리는 것이다.

브레인스토밍은 아이디어를 쏟아내는 행위를 말한다. 아이디어를 발산할 때는 깊이 고민하지 말고 먼저 양에 집중한다. 발상은 한 번 터지기 시작하면 연쇄적으로 반응이 오기 때문이다. 가지는 또 다른 가지를 낳고 확장하면서 거대한 아이디어 트리를 만들어낸다. 그리고 자극을 통해 연상을 유도한다.

브레인스토밍은 옳고 그름을 판단하기 전에 먼저 아이디어의 숫자를 늘리는 것에 집중한다. 현실성이 없는 아이디어는 걸러지며 잘못된 아이디어라도 새로운 아이디어를 떠올리는데 유용한 자극제로 활용될 수 있기 때문이다. 때로는 잘못된 아이디어가 잘못된 것을 바로잡는 가이드로 작용하기도 한다. 따라서 직관적 사고가 분석적 사고로 전환되지 않도록 주의한다.

아이디어는 작은 새싹과도 같아서 줄기가 자라고 잎이 나고 열매를 맺기 위해 구체적인 설계가 필요하다.

사용자와 제품이 상호작용을 할 때는 다툼이 없는 관계로 만들어 주는 것이 중요하다.

문제 해결은 결국 검증과 선택의 문제이다. 촘촘한 검증에도 실패의 경우가 있지만 이 때는 뒤로 돌아와 실패의 원인을 파악하고 방법을 수정한다. 문제만 바로 정의되어 있다면 해결 방법이 틀렸다고 해도 다시 돌아오면 된다.

큰 방향이 바르다면 언제든지 추진력을 얻을 수 있다.

[BOOK] 개발자로 살아남기

시간 관리와 방향성, 그리고 꾸준한 배움

세상은 약한 자나 강한자, 성공한 자와 실패한 자, 만들거나 만들지 못하는 자로 나누는 것이 아니라 배우는 자와 배우지 않은 자로 나뉜다. 

하늘 아래 완전히 새로운 제품은 없으므로 경쟁 제품의 장점과 단점을 파악해서 장점과 단점을 도입하고 개선한다면 사용자에게 좋은 제품을 제공할 수 있다.

측정할 수 없으면 관리할 수 없고 관리할 수 없으면 개선할 수도 없다. 따라서 측정할 수 없는 변화는 의미가 없으므로 제품에 주는 모든 변화는 측정이 가능해야 한다.
지속적인 변화만이 최고의 제품을 만든다.

도그푸딩(dogfooding)이란 내가 만든 개밥을 스스로 먹는다는 뜻으로 본인이 만든 제품을 직접 써본다는 뜻이다. 자신이 만든 제품에 대한 이해가 중요하며 자신이 만드는 서비스를 직접 써보고 경쟁 제품을 직접 분석해봐야 한다.

한마디로 내가 제품을 써보고 좋아해야 사용자도 제품을 좋아하게 된다.

개발은 좋은 제품 만들기가 목적이다. 멋진 코드와 확장성 있는 아키텍쳐도 좋지만 기술은 좋은 제품을 만들어내야 의미가 있다.

제품은 기획자의 인사이트를 넘어 사용자 반응 데이터를 활용해 빠르게 방향과 기능을 결정하며 발전해야 한다. 따라서 좋은 제품을 만들려면 좋은 데이터를 수집하고 분석하는 능력이 필수이다. 

애자일 선언 이면의 원칙은 다음과 같다.

– 최우선 순위는 가치있는 소프트웨어를 일찍 그리고 지속적으로 전달해서 고객을 만족시키는 것이다.
– 애자일 프로세스는 변화를 활용해 고객의 경쟁력에 도움이 되게 하므로 개발의 후반부일지라도 요구사항의 변경을 환영한다.
– 작동하는 소프트웨어를 자주 전달하고 비즈니스 담당의 사람들과 매일 함께 일해야 한다.
-동기가 부여된 개인들을 중심으로 프로젝트를 구성하고 필요로 하는 환경과 자원, 그리고 신뢰를 준다.
– 개발팀 내부에서 정보를 전달하는 가장 효율적인 방법은 1:1 대화이다.
– 작동하는 소프트웨어가 진척의 척도이다.
– 기술적 탁월성과 좋은 설계에 대한 지속적 관심이 기민함을 높인다.
– 단순성(안하는 일의 양을 최대화)이 필수이다.
– 팀은 정기적으로 효율을 숙고하고 팀의 행동을 조율하고 조정해야 한다.

애자일(agile)은 각 단계를 너무 작게 만들거나 건너뛰고 빠르게 개발해서 출시하는 개념이 아니라 굉장히 작은 기능, 최소한의 기능으로 최대한 빠르게 개발하는 방법이다.

애자일 이외에도 다양한 개발 방법이 존재하지만 모든 기능은 모든 개발 주기를 거치게 된다. 

애자일은 짧은 주기를 반복하여 큰 프로젝트를 완성해 나가는 방법론으로 유용한 프로젝트 관리 방법으로는 스크럼이나 칸반이 있다.

스크럼은 소규모 팀으로 제품을 기민하게 개발하는 방법으로 스프린트라는 업무 주기를 반복한다.

제품 책임자(Product Owner)가 할 일 목록에서 스프린트동안 수행할 일을 결정하고 스프린트마다 결과물을 산출한다. 팀이 성과를 낼 수 있도록 스크럼 마스터가 장애 요소를 제거하며 프로세스를 인도한다. 

스크럼이 시간을 제한하는 방법론인 반면 칸반은 수를 제한하는 방법론이다. 칸반은 ‘할 일’, ‘진행중인 일’, ‘완료된 일’ 열을 만들고 중요도에 따라 색이 다른 업무로 관리한다. 칸반은 진행중인 일로 옮길 수 있는 업무의 최대 숫자를 제한한다.

애자일을 효과적으로 실천하려면 도구를 사용해야 한다.

프로젝트 관리 도구는 지라(Jira), 협업 문서 관리 도구는 노션(Notion), 소통에는 슬랙(Slack)을 많이 사용한다. 또한 구글 닥스(Google Docs)는 협업 문서를 만드는 최고의 도구로 표현된다. 도구는 프로세스를 구체화하는 것이다.

프로덕트 백로그(Backlog)는 구현해야 할 사항을 정의한 문서로 미래 업무 후보들을 넣어두고 백로그에 있는 아이템이나 사업상 또는 기술적으로 중요한 아이템을 정리해서 분기 계획을 만든다.

출시는 일정 주기로 진행하는 것이 제일 안전하다. 정기적인 출시를 통해 지속적으로 시장의 반응을 확인하기 좋고 안정성 확보에도 도움이 되기 때문이다.

또한 출시에는 항상 위험이 따르므로 롤백에 대한 계획도 항상 필요하다.

동시에 여러 기능을 구현한다면 소스 코드 분리와 통합에 신경써야 한다.

애자일에서 중요한 포인트는 회고이다. 매달 또는 분기에 한 번 정도씩 정기적으로 조직, 기술, 제품, 프로세스에 대해 논의하고 문제 개선 방안에 대해 깊게 살펴보는 과정이다. 

애자일이 원활히 동작하려면 적극적인 소통이 중요하며 소통은 모든 방향에서 원활히 이루어져야 한다. 

매니지먼트는 프로젝트 관리, 팀 관리, 프로세스 관리로 구분한다. 

프로젝트 관리는 출시 시기와 중점을 둬야 하는 일을 관리하는 기술이다. 팀 관리는 사람 관리이며, 프로세스는 진행 과정을 관리하는 기술이다. 

프로젝트 관리는 기본적으로 비용(리소스/인력), 시간(출시일), 제품 범위(기능)를 관리한다. 시간과 인력은 늘 부족하므로 제품의 범위를 줄여야 한다. 기능의 80-90%만 넣어 최소기능제품을 출시하고 지속적으로 기민하게 업데이트하는 방법론이 애자일이다. 이 때 핵심기능을 빠트리면 품질과 경쟁력에 영향을 미치므로 주의해야 한다.

팀을 만들게 되면 forming -> storming -> norming -> performing의 단계를 거치게 된다. 즉 폭풍처럼 싸우고 잔잔해지고 사람들이 친해져서 결과를 만들어내는 단계에 이른다.

여기서 핵심은 신뢰와 지식이다. 팀이 잘 돌아가게 되면 시너지가 생겨 함께 일하며 더 큰 성과를 만든다. 팀 관리자는 팀원에게 큰 그림을 보여줘야 팀에서 위치를 파악하고 자신이 무엇을 어떻게 해야 할지 알 수 있다. 

팀 존재의 이유는 서로의 장점을 공유해서 극대화하고 약점을 보완해주는 것이므로 서로가 강점과 약점을 알아야 한다. 

프로세스란 일을 하는 과정을 정리하는 것으로 한 번 했던 일을 다시 할 때 잘하기 위한 장치이다. 프로세스를 만들면 규격화해 측정할 수 있게 되며 두 세번 반복하면서 최적화할 수 있다. 프로세스 관리는 실패를 막고 우연을 막고 철저하게 품질을 관리하고 최적화하는 과정을 만드는 것이다. 개발 주기, 코드 리뷰 등 개발과 관련된 모든 것이 프로세스에 해당한다. 프로세스가 정립되어야 회사의 현 상태를 측정하고 고도로 최적화할 수 있다.

매니지먼트 역량의 바탕이 되는 다섯가지 소프트 스킬은 소통, 협업, 긍정적인 자세, 프로 의식, 리더십이다. 매니지먼트 역량은 직원에게도 필요하며 더 멀리 내다보고 자신이 바라는 관리자 모습을 그려보고 관리자를 해당 방식으로 유도해야 한다.

소통에는 투명성이 중요하며 투명성이란 사람들이 알아야 할 정보를 충분히 공급해주는 것이다. 상사가 투명하게 이야기하면 더 쉽게 의도가 전달되고 부하는 상사를 더 쉽게 예측할 수 있다. 투명성과 예측 가능성이 확보되면 직원에게 자율성이 생긴다. 자율성이 보장될 때 창의성이 발현되고 직원은 더 행복해지므로 결과적으로 더 나은 성과를 도출하게 된다. 투명성은 개방성과 함께일 때 더 빛을 발하며 리더라면 개방성을 갖고 경청할 줄 알아야 한다. 결국 투명성과 개방성이 소통의 핵심이다.

협업은 논쟁 테이블 위에서 벌어지는 관철과 양보의 줄다리기이다. 좋은 리더는 협업을 잘해야하고 그러려면 8할을 양보해야 한다. 제대로 된 협업은 이견이 생길 때 모두의 의견이 조금씩 관철되어야 하는 것이며, 한 사람이 항상 이기는 것은 욕심에서 비롯된 문제이다. 좋은 리더라면 작은 것을 버리고 큰 것을 얻어야 한다. 중요하지 않은 일은 원하는 대로 하게 두고 정말 중요한 일을 관철하도록 해야 한다. 중요한 일에는 물러서지 말고 끝까지 이겨야 한다. 건강한 조직이라면 협업 테이블에서 치열한 논쟁이 벌어져야 최고의 선택을 할 수 있다.

여기서 양보란 무관심이 아니라 자율 선택권을 주는 양보와 타협이다. 

리더십에서 중요한 것 중 하나는 인사이트로 현재 시장을 파악하고 향후 변화의 큰 물줄기를 분간하는 능력이다. 인사이트가 있어야 기술 변화를 내다보고 개발 방식과 방향을 결정할 수 있다. 리더에게 인사이트가 없으면 개발만 하다가 도태될 가능성이 크다.

인사이트를 계발하기 위해서는 좋은 책과 좋은 사람 그리고 비판적 사고가 중요하다. 이를 통해 얻어진 것들을 실제 업무에 적용해보고 비판적 사고를 확장하면서 좋은 피드백을 반영해 나갈 때 집단 지성을 이끌어내며 발전할 수 있다.

중간 관리자의 역할은 프로젝트 리딩, 테크니컬 리딩, 피플 매니징이다. 세 가지를 모두 다 잘하기는 쉽지 않으므로 관리자는 본인이 잘하는 부분에 집중하고 부족한 부분은 도움을 받아 메워야 한다. 하지만 각 역할에 대해 명확한 이해는 필요하다.

개발 주기는 요구 사항을 분석하고 시스템 구조를 설계하고 개발하고 테스트와 출시하고 피드백을 받아 업데이트하는 전체 과정이다. 최소한의 개발 계획을 갖고 계획 안에서 실행해야 리소스가 관리된다. PM은 전체 과정과 목표를 이해하고 리소스를 관리해야 하며 프로젝트 관리를 하면서 연 단위, 월 단위, 일단위 계획을 세워야 한다.

계획을 세우는 이유는 완벽한 준수를 위해서가 아니라 성공을 위해서 세우는 것이다. 따라서 상황에 맞게 수정하면서 대비해야 한다. 

우선 순위 정하기와 시간을 효율적으로 관리해야 성공적으로 제품을 출시할 수 있다.

역할은 팀 크기에 따라 달라질 수 있으며 사람들이 적절히 부딪히며 일할 수 있게 역할을 정의해야 한다. 완벽히 격리된 역할을 주면 의욕이 떨어지고 역할 이기주의에 빠질 수 있다. 따라서 모든 사람에게 기본적인 역할을 정해주되 약간은 자기 범위 밖에서 일할 수 있도록 자유를 제공해야 생산적인 충돌이 발생하여 협동이 원활해진다.

시간을 아끼는 최고의 방법은 낭비를 없애는 것이다. 시간을 잡아먹는 요인은 필요없는 코드, 개발 과정에서 준비 미비로 인한 기다림, 불명확한 요구사항, 내부 정치, 느린 내부 소통이 있다.

필요없는 코드는 요구 사항이 명확하지 않거나 기술 구조를 잘 정의하지 않았을 때 발생하므로 요구 사항을 명확히 정의하고 기술 구조를 초기에 제대로 잡아야 한다.

시간을 아끼기 위한 방안 모색으로 미팅이나 워크숍보다는 일상에서 하나씩 낭비를 줄이는 방식이 낭비를 만들지 않는 더 효과적인 방법이 될 수 있다.

때로는 돈을 더 많이 버는 것보다 덜 쓰는 게 더 쉬운 방법이 될 수 있는 것처럼 낭비를 줄이면 업무 효율과 생산성이 올라간다. 생산성을 올리는 방법은 모두를 바쁘게 하는 것이 아니라 낭비를 없애고 서로에게 병목이 되는 요소를 없애는 것이다.

문제는 항상 발생하고 일이란 문제를 잘 정리하고 계산하고 해결하는 행위이므로 문제가 재발되지 않게 하는 것이 중요한 것이다. 따라서 문제를 싫어하지 않는 것이 중요하다. 

문제 해결 시스템을 통해 시간 낭비를 줄일 수 있으며 문제 해결을 나누는 단계는 다음과 같다.

1 문제 고르기
2 고른 문제 정의하기
3 문제 분석하기
4 해결책을 찾고 최선의 해결책 선택하기
5 선택한 해결책 실행여부 승인받기
6 문제 해결 확인하기

문제 해결의 핵심은 하나의 해결책만 적용하는 것이 아니라 여러 해결책을 고안하고 그 중에서 제일 좋은 해결책을 고르고 실패 시 다른 해결책을 적용하는 것이다. 하나의 해결책만으로는 적용 실패 시 더 위험한 상황이 올 수 있기 때문이다.

제한된 시간을 효과적으로 사용하려면 산적한 문제를 효과적으로 분류하고 대응해야 한다. 문제의 경중과 해결 가능성을 따져서 중요하고 풀 수 있는 문제는 풀고 중요하지만 풀 수 없는 문제를 미뤄두고 중요하지 않지만 풀 수 있는 문제는 위임한다. 그리고 중요하지도 않고 풀 수도 없는 문제는 무시하는 것이 중요하다. 이를 통해 시간의 낭비를 줄이고 해결할 수 있는 문제에 집중하여 재발하지 않는 해결책을 만드는 것이 효율적으로 프로젝트를 리드하는 방법이다.

프로젝트 관리는 우선 순위를 정하는 것이 중요하다. 우선 순위대로 일하고 문제를 해결하고 낭비를 없애 사람들의 역할을 연결해야 한다. 우선 순위의 기본은 시급성과 중요성에 있다. 대게는 생각할 시간이 없고 눈앞에 닥친 일만 하다보니 급한 것 위주로 일을 하게 된다. 그러나 급한 일의 늪에 빠지지 않고 중요한 일을 해야 한다. 할 일을 고를때는 시급성을 따지지 말고 한 발 물러서서 중요성에 따라 일을 진행해야 한다. 따라서 중요하고 급한 일로 분류될 일을 먼저 처리하고 난 뒤 중요하고 급하지 않은 일 위주로 처리하면 자신의 삶과 시간을 주도하면서 살 수 있다. 급한 일만 하게 되면 일에 쫓기고 끌려다니게 된다.

테크니컬 리드는 실현 가능성과 기술의 이점을 고려해야 하며 개발 환경 자체도 최적화해야 한다.

프로젝트 리드가 what to do를 고민한다면 테크니컬 리드는 how to do를 고민한다. 남이 안 만든 서비스를 출시해야 성공 가능성이 높으므로 테크니컬 리드는 모르는 일을 어떻게하면 잘할 수 있을지 고민해야 한다. 초보 개발자는 시키는 일을 잘하고 중급 개발자는 시키지 않아도 잘하고 고급 개발자는 남에게 시키는 일을 잘하면 된다. 그보다 위는 모르는 일과 한번도 안해본 일을 하는 것이다.

필요한데 모르는 일에는 리소스가 얼마나 투입될지 알 수 없으므로 필요하지만 잘 모르는 일을 먼저 진행해야 한다. 어렵고 큰 일이나 모르는 일을 먼저 해야 하며 성공을 목표로 한다면 어려운 문제를 먼저 푸는 게 좋다. 테크니컬 리드가 이를 관리해야 하고 모르는 일을 잘게 쪼개고 나눠서 모르는 일 하나를 아는 일 100개로 만들어야 한다. 모르는 것을 아는 것으로 바꾸는 능력이 테크니컬 리드에게 가장 중요하다.

일은 올바른 방향으로 빠르게 가는 게 가장 좋지만 대게 일은 잘못된 방향으로 엄청 느리게 간다. 따라서 성공보다 실패하는 제품이 많다. 프로젝트는 성공하더라도 제품은 실패할 수 있다. 프로젝트를 진행하면서 일이 너무 잘 돌아간다면 멈춰서서 돌아봐야 한다. 속도보다 방향에 중요하므로 항상 바른 방향으로 가고 있는지 점검해야 하며 속도에 집중하면 안된다. 이 방향에 대한 확인 작업을 짧은 주기로 진행하는 것이 애자일 방식이며 목적지에 따라 방향을 수시로 수정하며 개발해야 한다. 따라서 느리더라도 올바른 방향의 선택이 중요하다.

일은 make it working, make it right, make it fast의 격언과도 같다. 먼저 방향을 정해 일을 시작하고 일하는 방식을 개선한다. 그 후 모든 것이 정해지면 속도를 올리는 방식으로 단계별로 접근해야 한다. 모든 일에는 지속 가능성이 중요하므로 속도보다 방향이 중요하다. 지속가능한 성공이 중요하므로 항상 방향과 지속적이고 안정적인 속도에 집중해야 한다.

최소기능제품을 만들 때는 기능만큼 기술도 중요하다. 빨리 만들려면 알려진 기술을 써야하고 개발 속도를 높이려면 개발 환경이 좋아야 한다. 물리 환경까지 쾌적하게 만들고 최적의 개발 방법론을 적용해 짧은 주기의 속도감 있는 개발을 진행해야 한다. 개발 과정에서 기술 부채가 늘어나지 않도록 상황과 전략에 맞춰 개발을 해야 한다. 경쟁력은 기획에서 나오므로 좋은 기획을 빠르게 구현하는 개발 역량을 키워야 한다.

사람은 저마다의 성향이 있으며 why, what, how로 구분할 수 있다. 각각 고객, 제품, 기술에 대한 집중도를 나타낸다. 미국 회사에는 여러 성향의 사람이 섞여 있어 프로젝트 진행 시 성향별로 질문이 고르게 나오는 장점이 있다. 

관리자라면 팀을 구성할 때 성향을 골고루 배치하는 것이 좋으며 각각의 성향이 다를수록 시너지를 낼 수 있어서 좋다. what if의 성향은 굉장히 독특하거나 큰 기여를 하기도 하므로 엉뚱한 말을 하는 사람이 있더라도 다양성을 존중해주는 것이 중요하다. 

일의 진행 시점별로도 일을 시작하는 사람, 일을 수행하는 사람, 일을 마무리하는 사람이 있다. 각각의 성향을 잘 섞어주면 좋은 효과를 낼 수 있다. 프로젝트 초기에는 시작하는 사람이 많을수록, 출시 직전에는 마무리하는 사람이 많을수록 좋다.

관리자와 직원의 관계는 정확한 기대치를 알려주고 결과가 나왔을 때 좋았던 점과 아쉬웠던 점을 알려주며 피드백을 주는 사이가 좋은 관계이다.

관리자는 직원의 성과, 행복, 성장에 신경써야 한다. 관리자도 리소스의 일부이므로 직원이 일을 잘 할 수 있도록 돕는 사람이 되어야 한다. 직원이 스스로 성과, 행복, 성장을 확인하고 관리자를 사용하도록 해야 한다. 관리자가 모든 것을 다 해줄 수는 없으므로 스스로 자신의 역량과 행복을 이끌어 내도록 도와주는 역할을 한다. 성과를 확인할 때는 개인이 일을 잘하는지, 팀이 잘하는지, 무엇을 잘했는지, 무엇이 힘들었는지 구체적으로 질문해야 하며 가장 중요한 것은 회사 차원에서 일이 잘 진행되는지, 개인이 만족하는지, 의미있는 일을 하는지의 여부이다. 

훌륭한 개발자의 7가지 요건은 다음과 같다.

– 생산성 (의미있는 제품과 코드를 많이 만드는지)
– 프로의식 (책임감)
– 팀워크 (협업, 소통)
– 지식 (도메인, 소프트웨어)
– 기능성 (제품성)
– 코딩 능력 (코드의 간결함)
– 구조 설계와 아키텍쳐

회사는 위 기본을 갖춘 사람의 성장을 도와야 하며 성과와 성장이 연결되지 않으면 현재의 성과가 지속될 수 없다. 지금 성장해야 미래의 성과도 보장되는 것이다.

직원은 회사에서 의미있는 일을 했을 때 가장 큰 행복과 만족감을 느낀다. 회사에 자신이 기여를 했다고 느낄 때 자존감이 생기고 자존감이 높아질 때 직원은 행복을 느낀다. 사내에서 직원의 행복은 일과 관련된 것이어야 한다. 일을 하는 이유는 일 자체의 즐거움, 일을 통한 성장, 비전, 목표와 일과의 연결성이다. 생각한 꿈과 현재의 일이 연결되어 있으면 하는 일이 힘들지 않다. 먼 미래가 아닌 10년 후, 5년 후, 내일하고 싶은 일을 정해두어야 과정에서 오는 시련을 이겨낼 힘이 생긴다. 직원이 성장해서 다른 회사를 가게 되더라도 아깝지만 어쩔 수 없다. 오히려 성장하지 못하는 직원이 회사에 짐이 된다.

하고 싶은 일을 계획해두면 계획대로 살게 된다.
세상은 계획을 가진 사람의 계획대로 움직이는 것이다. 

관리자라면 팀원에게 원하는 바를 듣고 도와주는 성장형 조직을 만들어야 하며 스타트업이라면 특히 더욱 중요하다. 

성장은 역량, 잠재력, 현재 성과를 함께 살펴야 한다. 성과는 역량보다 아래에 있으므로 역량을 넘어서는 일을 하면 실패하기 마련이다. 역량과 비슷하거나 조금 더 어려운 일을 수행하면 크고 작은 실패를 경험하면서 성장하게 된다. 역량도 근육과 같아서 비슷하거나 조금 높은 수준의 일을 해야 역량이 높아지며 쉬운 일은 아무리 많이 해도 역량이 늘지 않는다.

잠재력은 높은데 역량이 자라지 않는다는 고민이 생긴다면 쉬운 일만 해서 그런 것이다. 어려운 일을 통해 실패를 경험하고 깨달음을 통해 역량을 올려야 잠재 능력을 실현할 수 있다. 실패는 초기에 하는게 좋으며 감당할 수 없는 큰 실패나 막바지 실패를 하지 않도록 유의해야 한다. 사람은 성공만이 아니라 실패에서도 배우므로 실패에서 교훈을 얻고 성장할 수 있도록 성공과 실패 요인을 분석하고 다시 시도할 때의 방법을 고민한다. 

프로세스는 모든 것의 바탕이다. 제품, 기술, 사람 등 모든 영역에서 프로세스가 필요하다. 문서와 인력으로 진행하는 프로세스는 언제 어긋날지 모르므로 모든 프로세스는 최대한 시스템에 녹여내는 게 좋다. 사내 프로세스가 동일해야 다른 조직 업무에 투입되어도 빠르게 일할 수 있으므로 시너지를 낼 수 있다. 회사가 커질수록 프로세스를 통일시키는 것이 중요하므로 회사가 작을 때부터 프로세스를 통일하는 것이 좋다. 

혁신적인 아이디어는 어디서든 얻을 수 있다는 신념을 가지고 업무 시간의 15%를 아이디어 창출에 사용하는 3M의 원칙은 혁신을 이끄는 원동력으로 볼 수 있으며 지속적으로 최적화하는 회사의 좋은 사례이다. 회사의 생애 주기 진행 속도는 회사마다 천차만별이며 생명을 길게 가져가기 위해서는 프로세스가 제대로 잡혀있어야 한다. 

프로세스 관점에서 팀 성과는 개인 성과와 다르다. 팀 성과 평가는 생산성, 소통, 프로세스를 기준으로 평가한다. 모든 조직에는 문제가 있으며 문제를 해결하려면 프로세스가 제대로 세워져 있어야 한다. 

회사를 네 가지 관점에서 점검할 수 있는 balanced card는 재정 안전성, 고객의 제품 만족도, 내부 프로세스, 교육과 성장이다.

재정 안전성은 매출과 지출 규모를 통해 확인한다. 고객을 만족시키려면 고객을 생각하며 제품을 개발해야 하며 고객이란 회사 외부만이 아닌 내부에 있는 모든 직원도 고객이다. 모두가 제품을 사용하고 좋아해야만 성공할 수 있다.

프로세스는 일이체계적으로 돌아가는지에 대한 여부이며 교육은 직원과 회사가 함께 성장하기 위한 방법이다. 

변화는 회사에서 매우 중요한 부분으로 회사는 변하지 않으면 망하지만 변화는 어렵기 때문에 매우 조심히 관리해야 한다. 변화는 한 군데에서 시작하지만 모든 분야로 퍼져나가며 변화가 무뎌질 때 조직에 어려움이 온다. 

비전이 정립되어 있으면 회사가 하나로 뭉쳐 비전 안에서 문화가 탄생한다. 비전에 대한 세세한 가이드나 사상을 핵심 가치(core value)라고 하며 핵심 가치를 정하고 지키면 조직 문화가 만들어진다.

문화는 미리 세워진 가치와 정책에 의해 결정되므로 비전과 가치가 결정되어야 문화가 따라간다.

조직 문화는 사람들이 생각하고 행동하고 일하는 방식이다. 문화는 제품, 기술, 프로세스의 바깥 영역에서 돌아가며 사람들이 생각하고 행동하고 해야할 일을 자연스럽게 결정해주는 큰 개념이다. 제품, 기술, 프로세스가 결과에 가깝다면 조직문화는 모두를 아우르는 운영체제에 가깝다. 운영 체제에 따라 프로세스가 만들어지고 프로세스에 따라 모든 일이 결정된다. 

직원을 채용할 때는 좋은 사람을 뽑는데 집중하기보다는 잘못된 사람을 뽑지 않기 위해 노력해야 한다. 좋은 회사를 다녔다고 해서 좋은 사람인 것은 아니므로 이전 회사에서 어떤 일을 했고 어떤 성공과 어떤 실패를 경험했는지가 중요하다. 한 사람의 경력을 회사를 기준으로 봐서는 안되고 좋은 회사를 짧게 다녔어도 위험할 수 있다. 반대 입장에서도 마찬가지이므로 채용을 대충 진행하는 회사가 있다면 대충 채용한 사람들과 함께 일하게 되는 것이다. 

면접관은 지원자를 너무 마음에 들어하면 객관적인 평가를 하기가 어렵다. 블리자드는 면접 후 면접관이 모여서 점수로 투표하는데 최고점과 최저점을 제외한다. 본인과 코드가 맞는다는 이유만으로 최고점을 주거나 반대의 경우가 발생할 수 있기 때문이다. 따라서 지원자도 면접 분위기에 따라 당락의 기준을 잡는 것이 아니라 전문 지식과 이력에 집중해야 한다. 

프로세스는 도로 체계와 같아서 좋은 프로세스라면 문제가 발생하지 않아야 하며 적합하고 효율적이어야 한다. 잘 만든 프로세스는 반복해서 사용하는 것이 중요하며 기술, 서비스, 문화의 변화에 맞게 프로세스도 변해야 한다. 그리고 프로세스는 데이터를 근거로 해야 한다. 

개발자가 실력을 키우는 방법은 공부하고 반복하고 경험하기다. 개발자는 어떤 자리나 회사를 목표로 하는 것이 아니라 어떤 사람이 되거나 어떤 것을 해야겠다는 것을 목표로 삼아야 한다. 어떤 회사에 지원하는 이유는 그 곳에 하고 싶은 일이 있어서이다. 따라서 나의 역량에 집중하면 기업의 흥망과 상관없이 내가 원하는 일을 할 수 있게 된다.

이력서는 지원하는 회사에 최적화해서 해당 회사에 왜 가고 싶은지, 왜 뽑아야 하는지, 무엇을 하고 싶은지를 이력서에 꼭 써서 제출해야 한다. 그동안 해온 일과 지원하는 회사를 매칭해야 하며 읽는 사람이 보고싶어 할 내용으로 최적화해야 한다.

코딩 테스트는 기초 지식과 연결되며 알고리즘 문제의 난이도가 높아짐에 따라 업무만으로는 테스트를 통과하기가 쉽지 않다. 따라서 시니어라도 코딩테스트를 따로 준비하는 게 좋으며 과정이 무의미하다고 생각할 필요는 없다.

역량이 없는 상태에서 취업 성공은 위험하다. 역량이 있으면 다시 시도할 수 있으므로 실패하더라도 역량을 키우는 실패가 낫다. 역량없이 이룬 성공은 우연이며 우연은 반복되지 않는다. 한 프로그램을 여러번 다시 만들어보면 더 잘 만드는 방법을 고민하게 되고 개발 역량이 자란다.

면접 시 지원 동기를 묻는 질문은 중요하며 모범 답안은 이직할 회사의 서비스나 기술에 대한 흥미이다. 

소프트웨어 개발자로 성공하는 3가지 요소는 재능, 노력, 기회이다. 재능이 있더라도 많은 노력이 필요하며 지속적으로 노력하면 언젠가는 기회가 찾아오기 마련이다. 따라서 기회가 올 때까지 자신에게 집중하고 가고자하는 길을 구체적으로 그려보고 필요한 역량을 채워나가면 된다. 

스티브 잡스가 똑똑한 사람들을 고용해서 무엇을 할지 알려주는 것은 이치에 맞지 않으므로 그들을 고용해서 우리가 무엇을 해야할 지 알려줄 수 있도록 해야한다고 하였다. 그러므로 스타트업은 새로 채용한 사람의 말을 듣고 기존 아이디어와 새 아이디어가 합쳐져 자연스럽게 제품이 진화하도록 해야 한다. 이후 제품을 빠르게 출시하고 반응을 보면서 계속 업데이트하는 지속적인 피봇팅(pivoting)이 중요하다.

기술의 우월성도 중요하지만 시장에서 최고의 기술만이 대표 상품이 되는 것은 아니다. 잘 만들었다면 역시 잘 팔아야 한다. 조금 느리더라도 변화를 계속 만들고 변화에 유동적으로 방향을 맞춰야 탁월한 기술력이 빛을 발하고 사업을 지속적으로 영위할 수 있다.

모든 것을 잘하는 직원은 훌륭한 관리자가 필요없지만 반대로 문제가 많은 직원에게는 훌륭한 관리자가 필요하다. 따라서 훌륭한 관리자가 되고 싶다면 문제있는 직원을 만나고 훌륭한 직원이 되고 싶다면 문제있는 관리자와 일해야 성장한다. 다른 사람의 약점은 자신의 강점을 키울 기회이다. 

개발자는 기술적, 제품적인 면에서 실패할 가능성을 파악하고 제거해야 하며 성공은 시장이 결정하지만 실패는 개발자가 의도치않게 만들어낼 수 있다.

경쟁 회사가 만든 제품도 써보고 분석도 해야 하지만 그와 같은 제품을 만들 수 있었던 과정인 회사의 조직 문화도 확인하고 문화를 개선해야 한다. 

기민한 조직이 되려면 모두가 비전을 정확하게 맞춰야 하고 목표 달성에 헌신하지 않을거라면 뒤로 물러나야 한다.

쇠사슬의 강도는 가장 강한 부분이 아니라 가장 약한 부분이 결정하므로 다양성도 이 관점에서 보고 약한 부분을 빨리 발견하는 것이 좋다. 다양성이 있는 문화는 모두가 기여하고 싶어하므로 자신의 생각을 이야기하고 이런 환경에서는 문제와 약점을 조기에 발견하고 개선할 기회가 주어진다. 

일을 어제처럼 하면 어제만큼의 성과만 나온다. 따라서 더 나은 성과를 만들려면 한계를 뛰어넘는 것이 아니라 한계를 치워버려야 한다. 

조직 문화에 변화를 주려면 변화를 하겠다는 말을 하지 않고 천천히 조금씩 안 보이게 시도하는 것이 중요하다. 변화를 이야기하는 순간 오랜 시간 체득한 습관을 바꾸어야 하므로 쉽게 움츠러들기 때문이다. 습관은 개인에게 해당하는 프로세스로, 변화를 만들려면 습관을 바꿔야 하고 습관을 바꿀 때는 작은 것부터 시작해야 한다.

조직이 애자일하다는 것은 실무자한테 권한을 더 주는 것이다. 실무자의 의견을 많이 들어야 빨리 움직일 수 있다. 한 사람만 결정권을 가지고 있으면 속도가 나올 수 없으므로 모두가 결정권을 가지고 있어야 한다. 정책, 시스템, 문화를 바꾸고 실무자에게 권한을 주고 리더 교육을 진행할 때 변화가 생기고 변화가 조직 문화를 바꾼다. 

개인이 모여 조직과 회사가 되므로 회사가 변하려면 구성원 개인이 변해야 한다. 일본 경제학자 오마에 켄이치(大前研一)가 말하는 사람이 바뀌는 세 가지 효과적인 방법은 다음과 같다.

– 시간 배분을 변경한다. (時間配分を変える)
– 사는 장소를 바꾼다. (住む場所を変える)
– 함께 어울리는 사람을 바꾼다. (付き合う人を変える)

그리고 새로운 결심이 가장 무의미하다. 

직원이 오래 근무해야 조직과 회사가 오래가고 다양한 일을 경험해 볼 수 있는 문화를 만들어야 큰 그림을 볼 수 있다. 따라서 다양한 직군의 사람과 교류하는 것이 중요하다.

무작정 모든 것을 열심히 하기보다는 시간 관리가 중요하다. 효율보다는 생산성이 중요하므로 중요한 일을 잘하는 것이 중요하다. 속도보다 방향이 중요하므로 시간을 아껴서 뭔가를 빠르게 해내는 것이 아니라 정해진 시간 안에 무엇을 어떤 방향으로 어떻게 할지 고민해야 한다.

시간 관리는 시간을 쓰는 프로세스를 바꾸는 것이다. 항상 목표와 계획을 세우고 실천한 뒤 측정해야 하며 반복을 통해 최적화를 해야 한다. 시간을 쓸 때도 목표를 세우고 그 안에서 계획을 만든 뒤 실천하고 반복한다. 어떤 일을 하든 일하는 방식 자체를 체계적으로 관리해야 시간도 체계적으로 쓸 수 있다. 계획을 세우는 것은 목표가 있다는 것이며 목표가 계획을 만들게 한다. 바쁘기만 한 평범한 직장인이 일상에서 벗어나지 못하는 이유는 계획이 없기 때문이다.

혼자만의 몰입이 팀과 회사의 성과에 도움이 되어야 하며 혼자 풀지 못하는 일은 주변에 도움을 요청해야 한다. 결국 도움을 요청하는 것이 시간을 절약하는 것이다. 따라서 일을 시작할 때는 기한을 정하고 중간 점검을 통해 몰입의 역기능을 방지하고 팀 전체의 시간을 관리해야 한다.

사람은 자기가 하는 일을 남에게 주지 않고 끌어 안으려는 경향이 있으므로 계속 버리는 연습을 해야 한다. 

결과를 바꾸고 싶으면 과정을 바꿔야 한다. 결과에 차이가 없다면 일하는 방식, 즉 시간을 쓰는 방식을 바꿔야 한다. 방식을 바꾸려면 쓰는 시간을 측정해서 전체 상태를 파악하고 쓰는 시간을 바꿔서 방향을 바꿔야 한다. 

쓴 시간을 측정하는 목적은 최적화이다. 최적화의 우선 순위는 가장 덩치가 큰 것부터다. 시간 최적화는 낭비를 없애 일하는 방법으로 낭비만 없어져도 시간 관리에 큰 도움이 된다. 주식과 마찬가지로 시간을 벌려면 시간을 써야 하며 바쁠수록 시간을 잘 사용하고 있는지 체크해야 한다. 

회의는 프로덕트가 아니므로 일하는데 시간을 써야 한다. 따라서 회의를 시간을 잡아먹는 하마라고 생각하고 꼭 필요할 때만 써야 한다. 

브레인스토밍 회의는 회의에 적합하지만 정보 전달회의는 이메일이 더 적합하다. 토론 회의는 많은 준비가 필요하므로 준비하지 않으면 생산적이지 않고 정보 전달에 그치므로 미리 자료를 공유하고 아이디어를 가지고 모여야 한다. 따라서 토론 회의는 정말 준비된 사람들만 모여야 한다. 

휴식도 시간을 사용하는 행위이며 계획적으로 몰입해서 쉬어야 효과가 좋고 창조 능력을 유지할 수 있으며 더 효율적으로 일할 수 있다. 

어느 직군이나 똑같겠지만 시간 관리와 방향성 그리고 자신의 분야에 대한 꾸준한 관심과 연구, 학습만이 오래도록 즐겁게 일을 할 수 있게 해주는 묘약인 것 같다.

성능에 중요한 repaint, reflow에 대해 알아보자

reflow와 repaint가 발생하는 요인 분석하기

먼저 페이지가 렌더링되는 과정에서 reflow와 repaint의 단계는 다음과 같다.

(DOM + CSSOM) render tree > layout(reflow) > paint(repaint) > composite

여기서 성능과 관련이 깊은 reflow, repaint 단계에 관해 알아보자.

reflow

reflow(또는 layout)는 render tree 생성 후 요소의 크기와 위치를 계산하는 단계이다. 초기 렌더링 시 최초로 발생하고 요소의 크기나 위치 변경, 요소의 추가나 삭제 등 레이아웃이 변경될 때마다 reflow가 다시 발생한다.

reflow는 자식과 부모 그리고 요소 자신에게도 영향을 미치므로 성능에 영향을 주며, 레이아웃을 계산하는 reflow 후 가시적인 요소를 생성하는 paint 단계가 발생한다.

reflow가 발생하는 구체적인 상황은 다음과 같다.
(https://www.geeksforgeeks.org/what-is-dom-reflow/).

Reflow 발생 원인

– DOM에 요소 삽입, 제거, 업데이트
– 페이지에서 수정 작업 발생(Ex. input 박스 텍스트 수정)
– DOM의 요소 이동
– DOM의 요소 애니메이션 효과
– offsetHeight 또는 getComputedStyle()를 사용한 요소 계산
– CSS 스타일 변경
– 요소의 클래스 이름 변경
– 스타일시트 추가 또는 제거
– 윈도우 리사이징
– 웹 페이지 스크롤
– 폰트 변경
– CSS 슈도 클래스(의사 클래스) 활성화(Ex. :hover)
– 요소에 style 어트리뷰트 설정

reflow 단계에서 많은 연산이 발생하고 repaint, composite 단계도 이어서 발생하므로 성능에 영향을 줄 수 밖에 없다. 따라서 페이지를 구성하는 방식, 성능과 애니메이션의 타협 등을 통해 reflow를 최소화하는 방법을 찾아야 한다.

기본적으로 reflow를 줄일 수 있는 방법은 다음과 같다.

Reflow 줄이는 방법

– 여러 개의 인라인 스타일을 지정하지 않고 개별 스타일 설정을 최소화하기
– 요소에 클래스명을 사용하고 DOM 트리에서 최대한 하부에서 사용하기
– 새로운 스타일을 추가하기 전에 DOM에서 요소를 제거한 뒤 다시 추가하기
– 스타일을 위한 잦은 연산 피하기
– 애니메이션은 fixed 또는 absolute로 지정하기
– 가능한 테이블 레이아웃보다 블록 레이아웃을 사용하기
– 고정된 크기로 테이블 생성하기
– 클래스를 통해 스타일 변경하기
– 테이블 레이아웃을 fixed로 지정하기

REPAINT

repaint(또는 redraw)는 레이아웃이 아닌, 요소의 가시적인 부분이 변경되면 발생하는 단계이다. 요소의 visibility, background, outline 등이 변경될 때마다 repaint가 발생하지만 해당 속성은 레이아웃에 영향을 주지 않으므로 reflow는 발생하지 않는다.

repaint는 render tree를 레이어별로 나누어 처리하므로, repaint 발생 시 해당 레이어만 수정할 수 있는 장점이 있다.

Reflow와 Repaint는 stacking context와도 관련이 있는데, stacking context는 간단하게 3차원인 z축을 의미하는 것이다.

여러 요소가 하나의 레이어로 묶이게 되면 차지하는 메모리를 줄일 수 있지만 묶인 요소 중 하나의 요소에서 변경이 생기면 해당 레이어에 있는 요소를 모두 다시 그려야 하는 상황이 발생한다.

따라서 변경이 생길 가능성이 있는 요소를 하나의 레이어로 만들어서 관리하면 해당 레이어만 다시 그리면 되기 때문에 효율적으로 리렌더링을 할 수 있다.

이렇게 해당 요소를 하나의 레이어로 분리하기 위한 조건은 다음 사이트에서 확인할 수 있다.
stacking context 자세히 알아보기(MDN)

조건 중 ‘opacity < 1’이 있는데, opacity 값이 0~0.99인 상황에서만 레이어가 별도로 생성된다는 의미이다.

opacity가 1일 때는 reflow가 발생할 수 있는데 이는 opacity:1인 경우 다른 요소와 하나의 레이어를 이루기 때문에 발생한다고 볼 수 있다.

Composite

상황에 따라 Reflow, Repaint가 발생하지 않는 속성으로 transform, opacity 등이 있는데 이 속성은 렌더링의 마지막 단계인 composite만 실행된다.

해당 속성은 CPU가 아닌 GPU에서 작업을 수행하는 graphic layer를 사용하기 때문인데 composite 단계에서 layer를 병합한다.

GPU는 CPU에 비해 연산이 빠르고 이미지와 애니메이션의 보정 기능도 가지고 있으므로 이미지나 애니메이션 처리에 좋은 대안이 될 수 있다.

GPU를 사용하는 조건은 다음과 같다.

GPU 사용 조건

– 3D transforms 사용(translate3d, translateZ 등)
– <video>, <canvas>, <iframe> 요소 사용
– transform, opacity를 사용하는 애니메이션
– position:fixed 요소
– will-change 사용
– filter 사용

GPU의 장점은 빠른 연산이지만 메모리를 많이 차지하는 단점도 있으므로 적정선에서 사용해야 쾌적한 환경을 만들 수 있다.

참고
Understanding Repaint and Reflow in Javascript
What is DOM reflow
GPU animation: Doing It Right
Stacking Context

Typescript 유틸리티 타입(Partial, Pick, Omit, Record, Readonly)

공통 타입 변환을 위한 유틸리티 타입

타입스크립트에서 제공하는 유틸리티 타입(Utility Types)은 type, interface를 입맛에 맞게 사용할 수 있도록 도와주는 유용한 기능이다.

유틸리티 타입의 종류는 다음 그림과 같이 매우 많다(타입스크립트 공식 페이지).

이 중 사용 빈도가 잦은 Partial, Pick, Omit, Record, Readonly에 대해 알아보자.

1. Partial

partial은 ‘부분적인’이라는 뜻으로, 정의된 타입의 속성을 모두 옵셔널로 사용하여 부분적으로 원하는 속성만 사용하도록 할 수 있다.

우선 Partial의 정의는 다음과 같다.

type Partial<T> = {
  [P in keyof T]?: T[P];
};

Partial<Type>의 방식을 통해 속성을 옵셔널하게 사용하며, 예시는 다음과 같다.

 
interface Hardware{
    cpu: string;
    gpu: string;
    memory: number;
    storage: number;
    accessary: string;
}

const selectOptions = (default: Hardware, selected: Partial<Hardware>) => {
    setOptions({...default, ...selected});
};

const defaultOption = {
    cpu: "M1";
    gpu: "10-core";
    memory: 16;
    storage: 512;
    accessary: "Touch ID";
}

const selectedOption = {
    cpu: "M2";
    memory: "32";
    storage: "1024";
}

이와 같은 방법으로 사용하지 않는 속성을 옵셔널로 변경하여 사용할 수 있다.

2. Pick

pick은 ‘뽑다’는 뜻으로, 정의된 타입에서 속성을 지정하여 사용할 수 있다.

Pick의 정의는 다음과 같다.

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

Pick<Type, Keys>의 방식을 사용해 사용할 속성을 문자열이나 유니온 타입으로 Keys에 지정하여 해당 속성만 사용한다.

interface Exercise{
    title: string;
    type: string;
    time: number;
    complete: boolean;
}

type BriefExercise = Pick<Exercise, "title" | "complete">;

const today = {
    title: "jogging";
    complete: true;
}

Partial은 모든 속성을 옵셔널로 사용하지만 Pick은 속성을 지정하여 필요한 타입만 정의하는 방식으로 사용한다.

3. Omit

omit은 ‘생략하다’라는 뜻으로, 정의된 타입에서 생략할 속성을 지정하여 사용할 수 있다.

Omit의 정의는 다음과 같다.

type Omit<T, K extends keyof any> = {
  [P in Exclude<keyof T, K>]: T[P]
}

Omit<Type, Keys>의 방식으로 사용하며, Pick과 반대로 필요하지 않은 타입을 지정하여 정의하는 방식으로 사용한다.

interface Exercise{
    title: string;
    type: string;
    time: number;
    complete: boolean;
}

type BriefExercise = Omit<Exercise, "type" | "time">;

const today = {
    title: "jogging";
    complete: true;
}

Pick과 Omit의 용도는 같지만 정의 방법은 상반된다.

정의된 타입에서 생략하고 싶은 속성이 많을 때는 Pick, 생략하고 싶은 속성이 적을 때는 Omit을 사용하면 효과적이다.

4. Record

record는 ‘기록하다’는 뜻으로, key-value 세트를 생성하여 사용할 수 있다.

Record의 정의는 다음과 같다.

type Record<K extends string, T> = {
  [P in K]: T;
};

Record<Keys, Type>의 방식으로 사용하며, 두 개의 타입에서 한 타입을 Keys, 한 타입을 Type으로 조합하여 사용할 수 있다.

type MacBookType = "air13" | "air15" | "pro13" | "pro14" | "pro16";

interface Performance{
    cpu: string;
    memory: number;
    storage: number;
};

const OnTheMarket: Record<MacBookType, Performance> = {
    air13: { cpu:"M1", memory:8, storage: 256 };
    air15: { cpu:"M2", memory:16, storage: 512 };
    pro13: { cpu:"M2", memory:16, storage: 1024 };
    pro14: { cpu:"M2 pro", memory:32, storage: 1024 };
    pro16: { cpu:"M2 ultra", memory:96, storage: 2048 };
}

위와 같은 방식으로 두 타입을 조합해서 사용할 수 있다.

5. Readonly

readonly는 ‘읽기 전용’이므로 타입을 읽기 전용으로 정의하여 사용할 수 있다.

Readonly의 정의는 다음과 같다.

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

타입을 사용해 readonly 속성을 부여하고 싶은 경우에 사용할 수 있다.

interface LimitSize{
    size: number;
}

const myData: Readonly<LimitSize> = {
    size: 32;
}

myData.size = 64; // error

CSS의 em, rem, vh, vw, %의 단위를 알아보자

반응형을 위한 단위의 활용

CSS에서 가장 기본이 되는 크기 단위가 픽셀(px)인데요.

1px은 0.00264cm로 환산되는 길이로, 300px은 약 8cm가 됩니다.

16px은 0.42cm인데요. 이 16px이 바로 CSS에서 기본값입니다.

font-size : 16px은 세로 길이가 16px(0.423cm)인 폰트 사이즈라는 의미로, 출판물에서 기본적으로 사용되는 사이즈입니다.

그럼 이 기본 사이즈 16px을 기반으로 em, rem에 대해 알아보겠습니다.

em

em은 기준 크기에 대한 배수를 의미합니다.

기준은 font-size이며 같은 요소의 사이즈에서 시작해 부모로 차근차근 올라갑니다.

예를 들어 같은 요소에 font-size:16px이 설정된 경우 em의 기준은 16px이 됩니다.

.child-size{
    font-size : 16px;
    width : 2em;   // 2 * 16px = 32px;
}

위 코드에서 child-size 내부에 font-size가 있으므로 해당 요소의 width : 2em는 16의 2배인 32px이 됩니다.

만약 다음과 같이 같이 child-size 내부에 font-size가 정의되어 있지 않으면 해당 요소를 감싸고 있는 부모 클래스에서 기준 사이즈를 가져오게 됩니다.

.parent-size{
    font-size : 20px;
}
.child-size{
    width : 2em;   // 2 * 20px = 40px;
}

최상단까지 이동해도 font-size가 없는 경우에는 위에서 말한 기본값인 16px을 기준으로 지정합니다.

rem

rem은 em과 비슷하지만 r은 root를 의미합니다.

따라서 최상단인 html에 정의된 값을 기준으로 사용합니다.

html{
    font-size : 20px;
}
.child-size{
    font-size : 16px;
    width : 2rem;   // 2 * 20px = 40px;
}

최상단의 크기를 기준하므로 20px이 기준이 되어 2rem은 40px로 계산됩니다.

vw

Viewport Width는 스크롤을 포함한 윈도우의 너비를 의미하며, 반응형을 위해 상대적 크기를 사용할 수 있습니다.

1vw는 뷰포트 너비의 1%에 해당하는 값으로 너비가 1000px인 경우 1vw는 10px, 100vw는 1000px이 됩니다.

브라우저의 사이즈 변경이나 모바일 등에서 전체 비율을 맞추고 싶을 때 효과적으로 사용할 수 있으며, 화면을 가로로 가득 채우고 싶을 때 100vw를 사용할 수 있습니다.

.layout{
    width : 100vw;
}

vh

Viewport Height는 윈도우의 높이를 의미하며 vw와 마찬가지로 뷰포트 높이의 1%를 의미합니다.

화면을 가득 채우고 싶을 때는 다음과 같이 너비와 높이를 지정하면 됩니다.

.layout{
    width : 100vw;
    height: 100vh;
}

%

%는 부모 요소에 따라 크기가 결정됩니다.

높이를 100%로 설정하는 경우는 부모의 높이의 100%를 설정하게 됩니다.

따라서 부모의 높이가 100px인 경우 자식 요소에서 height : 100%를 설정하면 높이는 50가 됩니다.

width : 100%인 경우 스크롤바의 너비를 생략한 크기를 나타냅니다.

font-size : 100%의 경우 부모 요소의 사이즈를 기준으로 사용하게 되므로 기본값은 16px이 됩니다.