[프론트엔드 데브코스 TIL] 2023.11.23 Day48 Vue 4일차

SoJuSo·2023년 11월 23일
0

2023.09 ~ 2024.01 TIL

목록 보기
51/105

폴더 5개, 브랜치 5개 소요시간은 체감상 500분..?

📚금일 학습 내용 Vue

Vue를 가장한 노드 패키지 매니저, package.json, package-lock.json, eslint 등 주변 지식도 포함해서 학습한 하루


🏫데브코스

오늘 TIL은 Vue에 대한 내용만 다룬다. 왜냐하면 npm, parcel, 번들러, eslint에 대한 내용이 의미 없다는 것은 절대 아니지만 그거 다 쓰면 TIL을 2시간은 써야한다. 선택과 집중을 위해 오늘은 Vue에 관련된 내용만 기술하고자 한다. 하지만 노션에는 다 정리해뒀으니 필요하시면 DM을..

📌VUE Day4

몇 가지를 기술하자면 VSC에서 Vue의 코드가 다른 코드처럼 알록달록하게 보이게 하려면 Volar를 검색해서 설치하자. 예전에는 Vetur가 사용되었는데 이제는 Volar를 추천하신다.


<style lang="scss">
  $color: orange;
  h1 {
    color: $color;
  }
</style>

sass는 패키지를 설치해주어야 한다. parcel에서는 npm i sass -D만 설치하면 되고 webpack에서는 아래 use 배열 안에 있는 로더들을 npm i -D 옵션으로 설치해주면 된다. 또한 로딩 순서가 거꾸로이기 때문에 순서를 잘 나열해주어야 한다.


ctrl + shift + R << 강력 새로고침이다. css파일을 바꿨는데 페이지가 안 바뀌면 적용하도록 하자.


📌컴포넌트

📌전역 등록

아래와 같이 컴포넌트를 어디서든 사용 가능하도록 전역등록 할 수 있다. 하지만 언제 어디서든 사용할 수 있다는 장점이 있지만 관리가 어려우므로 그 아래에 있는 지역 등록을 권장한다.

// 전역 등록
const app = createApp(App);
app.component("Btn", Btn);
app.mount("#app");

// 특정 컴포넌트에서 지역등록
<template>
  <h1>Hello Vue!</h1>
  <Btn />
  <Hello />
</template>

<script>
import Hello from "./components/Hello.vue";
export default {
  components: {
    Hello,
  },
};
</script>

📌props 동적 할당

props를 지금까지는 아래와 같이 정적인 값만 전달했지만 이제 동적으로 할당해줄 수 있다.각종 숫자, 문자, 변수 뿐만 아니라 객체, 배열까지 모두 props로 전달할 수 있다.

<!--정적 할당-->
<blog-post title="Vue와 떠나는 여행"></blog-post>

<!-- 변수의 값을 동적으로 할당 -->
<blog-post :title="post.title"></blog-post>
<!-- 복잡한 표현을 포함한 동적 값 할당 -->
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>

특히 객체는 아래와 같이 한번에 객체 통째로 보내줄 수 있다.

<blog-post v-bind="post"></blog-post>
<!--위 아래 두 코드는 같은 의미를 지닌다.-->
<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>

props 유효성 검사는 공식 문서의 코드가 너무 잘 되어 있어서 가져왔다.

app.component('my-component', {
  props: {
    // 기본 타입 체크 (`null`과 `undefined`는 모든 타입 유효성 검사를 통과합니다.)
    propA: Number,
    // 여러 타입 허용
    propB: [String, Number],
    // 문자열 필수
    propC: {
      type: String,
      required: true
    },
    // 기본 값을 갖는 숫자형
    propD: {
      type: Number,
      default: 100
    },
    // 기본 값을 갖는 객체 타입
    propE: {
      type: Object,
      // 객체나 배열의 기본 값은 항상 팩토리 함수로부터 반환되어야 합니다.
      // 함수로 할 수도 있고 이걸 팩토리? 라고 부른다
			// 이렇게 하는 이유는 참조형 데이터는 한쪽이 수정되면 다른쪽도 수정될 수 있다.
			// 그래서 리턴 키워드로 별도의 객체 리터럴을 반환해주어야 문제가 없다.
      default: function() {
        return { message: 'hello' }
      }
    },
    // 커스텀 유효성 검사 함수
    propF: {
      validator: function(value) {
        // 값이 꼭 아래 세 문자열 중 하나와 일치해야 합니다.
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    },
    // 기본 값을 갖는 함수
    propG: {
      type: Function,
      // 객체나 배열과 달리 아래 표현은 팩토리 함수가 아닙니다. 기본 값으로 사용되는 함수입니다.
      default: function() {
        return 'Default function'
      }
    }
  }
})

추가로 props는 대소문자를 구분하지 않으므로(HTML 속성 이름이 그렇기 때문에) 대쉬 케이스를 사용해야한다.

📌 non-prop 속성

컴포넌트에 class를 추가하면 어떻게 될까? 의외로 올바르게 동작한다. 하지만 전제 조건이 있다.

여러 개가 추가되면 컴포넌트 속성이 적용이 안된다. 어디로 들어가야 할 지 모르기 때문에 그렇다. 하지만 div로 감싼다면? 가능해진다. 또는 Vue문법에서 부모 컴포넌트에서 자식 컴포넌트로 전달된 모든 속성을 포함하는 객체$attrs를 사용하면 된다.

<!-- 특정 속성을 가져오려면 : 바인드 문법으로 가져오면 되고-->
<h1 :class="$attrs.class" :style="$attrs.style" @click="$attrs.onClick">Hello</h1>

<!-- 아래와 같이 선언하면 다 가져온다. -->
<h1 v-bind="$attrs">Hello</h1>

하지만 이런 $attrs를 사용하지 못하는 경우가 있는데

위 예시처럼 선언한 경우이다. 왜냐하면 $attrs는 props로 지정되지 않는 나머지 속성을 다루는 객체이다. 그래서 props를 통해서 지정을 하게 되면 스타일은 나머지 속성이 아니게 되었기에 attrs로 들어갈 필요가 없어져서 제대로 동작하지 않는 것이다. 그래서 이번 강의 주제가 non-props이다.


☕2nd팀 첫 커피챗

오늘 2차 멘토님이신 희진멘토님과 첫 멘토링을 가졌다! 현주 멘토님과 마찬가지로 단순한 질문들에도 불구하고 정말 많은 이야기를 해주셔서 너무 감사했다.

특히 멘토가 되신 이유가 너무 인상 깊었다. 멘토님이 우리와 같은 취준생 시절에 너무 힘들었기에 그런 길을 걷지 않았으면 하는 이유에서 멘토링을 시작하셨다니.. 경이롭고 존경스럽다는 생각이 들었다.

이제 매주 목요일에 고정적으로 멘토님을 만나게 되는데 여러 질문들을 동기적 혹은 비동기적으로 나누고 싶고 여러 이야기를 듣고 나누고 싶다.


⭐️TS 스타~디 중 의문

멘토링이 끝난 후 3주차 스터디 목표 중 문제풀이를 모두 해야겠다고 생각했다. 근데... 8시쯤 시작했는데 정신차리니 밤 11시30 분이였다. 여튼 풀던 문제 중 하나에서 깊게 파봐라를 실시해봤다.

문제 링크

// 이번에는 머리를 썼다. type cases에 입력 예제를 좀 참조하면서 풀이했다.

// 배열이 빈 값이라면 당연히 타입은 모르는 거 아닌가? 하고 unknown을
// 입력했는데 type cases에서 에러를 출력했다.
// type First<T extends any[]> =  T extends [] ? unknown : T[0]

// 그래서 그거 보고 바꿨다.
type First<T extends any[]> = T extends [] ? never : T[0];

/*
  // 예제를 통한 해석을 해보자 
  type arr1 = ['a', 'b', 'c']

  type head1 = First<arr1> // expected to be 'a'

  위 코드에서 일단 head1이 실행되게 되면 First
*/

/*
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]

type head1 = First<arr1> // expected to be 'a'
type head2 = First<arr2> // expected to be 3

type First<T extends any[]> = T extends [] ? never : T[0];

const vari:head1 = 'ab'
console.log(vari)

위와 같은 코드를 실행해봤는데 에러가 난다. 이 코드를 실행해본 이유는
vari에 할당되는 타입이 'a'일까 아니면 string일까에 대한 의문이였는데
a가 할당된다. 그렇다면 여기서 'a'가 아닌 string에 할당되게 하려면?

아래와 같이 간단하게 string으로 해줘도 되지만
type First<T extends any[]> = T extends [] ? never : string;

// 요런 방식도 있다.
type First<T extends any[]> = T extends [] ? never : (T[0] extends string ? string : number);

조금 더 깊게 알아봤는데
TypeScript에서는 타입스크립트의 타입 시스템이 런타임에 있는 값의 타입에 접근하는 것을 지원하지 않는다. 
컴파일러는 T[0]의 타입이 무엇인지 알 수 있지만, 우리는 이 정보에 접근할 수 없다..

*/

vsc 전문을 가져와봤는데 사실 문제 이후의 상황에서 좀 더 집중해보았다. 이 경우 예제에서 head1의 type이 'a'로 지정된다. 여기까지는 OK인데 만약 여기서 'a'가 아닌 string을 쓰고 싶을 경우 어떻게 지정할까에 대해서 추가적으로 고민해 봤다.

결론을 언급하자면 해당 타입을 콕 찝어서 가져오는 것은 내가 알아본 바로는 불가능하다. 왜냐하면 TypeScript에서는 타입스크립트의 타입 시스템이 런타임에 있는 값의 타입에 접근하는 것을 지원하지 않는다. 컴파일러는 T[0]의 타입이 무엇인지 알 수 있지만, 우리는 이 정보에 접근할 수 없다. 라는 이유가 있었다.

그래서 내가 작성한 최선의 코드는 type First<T extends any[]> = T extends [] ? never : (T[0] extends string ? string : number); 요정도 인 것 같더라..

물론 내가 틀렸을 것이다. 더 좋은 방법이 있겠지... 근데 일단 찾아보고 결론 내린 것은 저것이다.


📖소회

요즘 이상한데에 꽃혀서 한자들을 많이 접하고 있는데 그런 겸에 이번 단위기간의 키워드를 정해봤다. 바로 死活이다. 이번 단위 기간에는 사활을 걸고 해봐야겠다고 생각했고 오늘이 그 첫날이였다.

개인 프로젝트는 건들지 않았지만 강의 완강, 운동, TS 스터디, 이력서 수정, 커피 챗 등 평소보다 많은 일정을 소화했다. 대충 순공시간은 한 8시간 되는 것 같다. 하지만 오후 2시 ~ 4시는 여전히 마의 구간이다. 유튜브에 자꾸 이끌린다.

그래도 오전, 오후 시간에 정말 잘 집중해서 기분 좋은 하루였다. 내일도 열심히 뛰어봅시다🔥🔥
TIL 작성 소요시간 약 35분

profile
Junior Frontend Engineer

0개의 댓글