NEW
1
/ 5
[3] 타입스크립트 선택적 타입을 통해 누락된 값이 있어도 타입 추론을 해보기
개요여러가지를 통해 api로 값을 받아올때면 일부 값은 누락되어 오는 경우가 허다하게 발생하는데,이번에는 타입스크립트의 선택적 타입 정의를 통해 특정 값이 누락되어도 타입 정의를 통해 추론이 잘 이루어질 수 있게끔 해보겠습니다!선택적 타입 정의?타입을 정의하게 되면 해당 타입과 관련된 값이 꼭 존재해야하는 불편함이 있는데선택적 타입 정의를 사용하게 되면 값의 존재 유무에 따라 타입을 검사해주는 고마운 친구였습니다 ㅎ사용방법코드보기export type UserCardProps = { name: string; age?: number; // 선택적 props skills?: string[]; // 선택적 배열 props}선택적 타입 정의를 위해서는 원하시는 값에다가 ?를 뒤에 붙여주시면 됩니다.그럼 아래와 같은 상황에서 age가 없으면 타입 추론을 안하게 되며,age 존재시 age의 타입이 number인지 추론을 하게 됩니다.코드보기export const UserCard = ({ name, age, skills = [], address }: UserCardProps) => {}마치며알면 알수록 편리하고 다양한 기능이 타입스크립트에 있는거 같네요정말 스크립트의 세계는 방대하네요...
NEW
2
/ 5
클로저란 무엇일까
사진: Unsplash의 Mārtiņš Zemlickis개요사실상 면접을 대비한 공부라고 할수도 있고일상생활에 있다보니 그러려니 하고 쓰다가 명칭을 알게된 경우였는데이번 기회에 클로저에 대해 알기쉽게 이해해보고자 작성하게 되었습니다.클로저란?쉽게 얘기하면 클로저란 함수 자체에 독자적인 변수가 존재하고 이걸 콜백함수로 제어가 가능해야 하며 이 함수를 변수에 담아 호출해야 합니다,스코프(변수의 범위)가 함수와 그 함수가 선언될 당시의 스코프를 기억하는 구조로,이를 통해 함수가 외부 스코프의 변수에 접근할 수 있도록 해줍니다.조건은 뭘까?1.내부 함수가 존재해야 합니다.2.이 내부 함수가 외부 변수에 접근하고 있어야 합니다.3.이 내부 함수가 반환되어 외부에서 호출될 수 있어야 합니다.특성은 뭐가 있을까?변수 접근: 클로저를 통해 내부 함수는 외부 함수의 변수를 계속해서 참조할 수 있어서 이로 인해 외부 함수가 실행된 후에도 변수의 값을 사용할 수 있게 됩니다.정보 은닉: 클로저를 사용하면 특정 변수를 외부에서 직접 접근하지 못하도록 숨길 수 있어서 이렇게 하면 데이터의 캡슐화가 이루어지고, 해당 데이터에 대한 제어가 가능해집니다.상태 유지: 클로저를 통해 생성된 내부 함수는 외부 변수의 상태를 기억하고, 이 상태를 변화시킬 수 있어서 그래서 특정 기능을 구현할 때 유용하게 사용됩니다.예시클로저를 생성하는법const counter = makeCounter();클로저의 핵심은 함수를 호출했을때 그 결과가 콜백함수여야 한다는 것입니다.그래야 함수 속 외부 변수를 이용해 콜백함수로 그 외부변수에 값을 변화 시킬 수 있겠죠?쉬운 예제const makeCounter = () => { let like = 0; // 외부 변수 return () => { // 콜백 함수 = 클로저 return like += 1; };};// 클로저 생성const counter = makeCounter();ㅊconsole.log(counter()); // like 변수의 값 반환 1console.log(counter()); // like 변수의 값 반환 2console.log로 makeCounter가 호출될때마다 like += 1 를 반환해주고 있기 때문에,해당 변수의 반환된 값이 counter 상수에 저장되어 사용되어집니다.비스무리한 다른 예제function makeCounter() { let count = 0; // 외부 변수 return function() { count += 1; // 외부 변수를 변경 return count; // 변경된 외부 변수를 반환 };}const counter = makeCounter(); // 클로저 생성console.log(counter()); // 1console.log(counter()); // 2console.log(counter()); // 3makeCounter 함수에는 독자적인 count라는 변수가 있고그 외부 변수를 제어 하고 반환하는 콜백함수를 리턴하고 있으며makeCounter 함수를 counter라는 상수에 담아console.log로 호출해 사용하고 있습니다.클로저가 아닌 경우다음과 같은 경우는 클로저가 아닙니다.let count = 0;const increment = () => { count += 1; // 외부 변수에 접근하지만, 반환되는 것이 없음};increment(); // 단순히 호출만 됨단순히 외부 변수를 접근해 변화시키고만 있지increment함수 자체가 변수를 기억하고 반환되는것이 아니기 때문에 클로저라 할 수 없습니다.
NEW
3
/ 5
[2] 타입스크립트의 타입 정의 상속에 대하여
사진: Unsplash의 Markus Spiske개요저번에는 타입을 어떻게 정의하고 사용하는지에 대해 알아봤는데이번에는 상속을 이용해서 타입을 조합해 정의해보겠습니다!타입 정의 방법type Test = { name: string, // 이름 description: string, // 설명 age: number, // 나이 func: () => void // 함수}테스트로 타입을 정의 해보았습니다.이 부분이 저번에 알려드린 내용과 같은데요.하지만 이렇게 사용하게 되면 특수한 상황,예를 들면 name과 age의 타입만 필요한 상황, func와 name의 타입 정의만 필요한 상황 같은 특수한 상황이 있을 수 있는데요이럴때 필요한게 상속입니다.상속이란?마치 레고를 조립하듯이 기본이 되는 기본 블럭이 있고거기에 특수한 기능을 가진 블럭을 붙이는 겁니다.예시// 형태type Shape = { style: string // 스타일 color: string // 색상}// 상세정보type Details = { name: string, // 이름 description: string, // 설명 date: number // 날짜}// 자동차 베이스type Car = { company: string, // 이름 country: string // 설명}만약 이러한 값이 있다고 하였을때자동차 베이스에 형태 + 상세정보를 합쳐야 하는 상황이 있는데지금과 같은 경우엔 나뉘어져 있어 조립이 필요한 상황입니다.이 경우 다음과 같이 하면 됩니다.// 형태interface Shape { style: string; // 스타일 color: string; // 색상}// 상세정보interface Details extends Shape { name: string; // 이름 description: string; // 설명 date: number; // 날짜}// 자동차 베이스interface Car extends Details { company: string; // 이름 country: string; // 설명}결과이렇게 할 경우 Car 타입을 사용하면 이런 형태를 지니게 됩니다.const myCar: Car = { style: "SUV", color: "red", name: "My Car", description: "This is a great car!", date: 2024, company: "Toyota", country: "Japan"};상속의 방법상속의 방법은 interface의 extends만 있는게 아닌데요 type에 &를 붙여 조합하는것 또한 가능합니다.그럼 결국 둘은 똑같은게 아니냐는 생각이 들수도 있을텐데비유로 다름을 설명해보자면const(상수)는 재선언 재할당이 불가능합니다.var(변수)는 재선언 재할당이 가능합니다.extends와 &는 이 차이인겁니다.interface의 extends는 재선언 재할당이 불가능합니다.type의 &는 재선언 재할당이 가능합니다.예시interface의 경우interface User { name: string;}interface User { age: number; // 병합됨}const user: User = { name: "CODi", age: 28,};type의 경우type User = { name: string;};type User = { // 오류 발생 age: number;};마무리이번에는 타입의 상속에 대해 알아보았습니다.그래도 블럭으로 비유하며 생각해보니 상속이라고 외우는것보다 더 쉽네요 ㅋㅋㅋ
NEW
4
/ 5
FSD 구조를 통해 프로젝트의 폴더 구조를 명확히 해보자
사진: Unsplash의 Leiada Krozjhen개요항상 토이프로젝트를 만들다 보면 문득 고민에 빠지는 것들이 있었습니다.공용 컴포넌트의 경우, 이 컴포넌트는 여러 곳에서 사용되지만, 모든 곳에서 쓰지는 않습니다. 과연 여기 위치해도 괜찮은 것일까요?전역 사용 컴포넌트의 경우, 이 컴포넌트는 모든 곳에서 사용되긴 하는데, 하나의 컴포넌트 때문에 공용으로 사용하는 폴더에 넣는 것이 올바른 선택인지 고민됩니다.그 고민을 해결해보고자 이번에는 FSD에 대해 알아보고자 합니다.FSD 구조란기능 단위로 나누어 개발하는 방식으로, 프로젝트의 복잡도가 증가할 때 관리와 확장성을 쉽게 해주는 아키텍처 패턴입니다.FSD의 핵심 개념은 각 기능이 독립적인 모듈로 구성된다는 것!즉, UI 컴포넌트, 상태 관리, 스타일링, 비즈니스 로직 등을 하나의 기능 단위로 묶어서 관리합니다.다음과 같은 이점들이 있습니다.1.모듈화: 각 기능은 독립적인 모듈로 분리되어 있기 때문에, 다른 기능에 영향을 주지 않고 개발 및 수정이 가능합니다.2.유지보수 용이성: 기능별로 코드를 관리하므로 특정 기능에 문제가 발생했을 때 쉽게 문제를 파악하고 해결할 수 있습니다.3.협업 효율성: 팀원들이 각 기능별로 작업을 나누어 진행할 수 있기 때문에 대규모 프로젝트에서 협업이 더 원활합니다.4.재사용성: 기능별로 모듈화된 코드를 다른 프로젝트나 페이지에서도 쉽게 재사용할 수 있습니다.구조 예시/src /app # 앱 초기화 및 전역 설정 관련 (store, routing 등) /entities # 핵심 비즈니스 로직을 처리하는 객체들 (도메인 모델, 상태 등) /features # 개별 기능 단위 (서브 도메인) /pages # 페이지 구성 (라우팅된 주요 화면) /widgets # 페이지나 여러 기능에 걸쳐 재사용될 수 있는 UI 구성 요소들 /shared # 앱 전반에서 사용되는 공통 리소스 (유틸리티, 상수, API 함수 등)폴더 구조를 역할에 따라 나눈 후, 각 역할에 맞는 하위 폴더로 세분화합니다.예를 들어, 기능(feature)을 정리할 경우에는 다음과 같이 각 기능에 맞는 폴더를 구성합니다./features /write /delete /like
NEW
5
/ 5
Google Analytics를 세팅하여 내 페이지 통계를 확인해보자!
개요본 웹사이트를 만들고 나니, 그동안 티스토리만 사용해왔던 탓에 통계를 어떻게 확인할지 고민이 생겨,여러 자료를 찾아본 끝에 ‘Google Analytics’를 통해 통계를 확인해보기로 결정했습니다.어떻게 되는걸까요건 제가 예전에 등록했던 티스토리에 대한 통계인데요!만약 측정을 시작하면 이렇게 세세하게 내 페이지를 방문한 사용자들이나의 페이지를 어떻게 이용했는지, 어떻게 유입했는지 확인이 가능합니다.시작해보자1. Google Analytics 방문Google Analytics를 방문하면 왼쪽 하단의 톱니바퀴를 눌러주세요!2. + 만들기 클릭왼쪽 상단 '+ 만들기' - '속성' 클릭3. 속성 이름 및 보고 시간대 선택속성 이름은 이 사이트를 구분할 이름(원하는 이름), 보고 시간대는 한국을 선택하시면 됩니다.4. 내 사이트 카테고리전 교육이나 취업에 관련된 내용에 치중되어있다 생각되어서 '취업 및 교육'으로 선택하였습니다.규모는 '작음'으로 선택하였습니다.5. 비즈니스 목표 선택모든 항목에 대한 통계를 보기위해 모두 선택 후 '만들기를 선택하였습니다'6. head 태그 안에 Google Tag 관련 스크립트 추가만들기를 통해 나온 gtag 코드를 head태그에 삽입해주세요.예를 들어 아래 코드가 head 태그 안에 삽입 후 배포가 되어있어야Google Analytics가 접속해 확인이 가능합니다.<script> // <!-- Google tag (gtag.js) --> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-');</script>완료!하단과 같이 '데이터 수집이 활성화되었습니다.' 가 표시되었다면 세팅이 완료된거에요이제 사람들이 우리들의 사이트를 어떻게 훑어보고 있는지 확인해보면 될거같습니다,,,,ʕ◍·̀·́◍ʔฅ
typescript
[3] 타입스크립트 선택적 타입을 통해 누락된 값이 있어도 타입 추론을 해보기
javascript
클로저란 무엇일까
typescript
[2] 타입스크립트의 타입 정의 상속에 대하여
typescript
[3] 타입스크립트 선택적 타입을 통해 누락된 값이 있어도 타입 추론을 해보기
개요여러가지를 통해 api로 값을 받아올때면 일부 값은 누락되어 오는 경우가 허다하게 발생하는데,이번에는 타입스크립트의 선택적 타입 정의를 통해 특정 값이 누락되어도 타입 정의를 통해 추론이 잘 이루어질 수 있게끔 해보겠습니다!선택적 타입 정의?타입을 정의하게 되면 해당 타입과 관련된 값이 꼭 존재해야하는 불편함이 있는데선택적 타입 정의를 사용하게 되면 값의 존재 유무에 따라 타입을 검사해주는 고마운 친구였습니다 ㅎ사용방법코드보기export type UserCardProps = { name: string; age?: number; // 선택적 props skills?: string[]; // 선택적 배열 props}선택적 타입 정의를 위해서는 원하시는 값에다가 ?를 뒤에 붙여주시면 됩니다.그럼 아래와 같은 상황에서 age가 없으면 타입 추론을 안하게 되며,age 존재시 age의 타입이 number인지 추론을 하게 됩니다.코드보기export const UserCard = ({ name, age, skills = [], address }: UserCardProps) => {}마치며알면 알수록 편리하고 다양한 기능이 타입스크립트에 있는거 같네요정말 스크립트의 세계는 방대하네요...
2024-11-17
javascript
클로저란 무엇일까
사진: Unsplash의 Mārtiņš Zemlickis개요사실상 면접을 대비한 공부라고 할수도 있고일상생활에 있다보니 그러려니 하고 쓰다가 명칭을 알게된 경우였는데이번 기회에 클로저에 대해 알기쉽게 이해해보고자 작성하게 되었습니다.클로저란?쉽게 얘기하면 클로저란 함수 자체에 독자적인 변수가 존재하고 이걸 콜백함수로 제어가 가능해야 하며 이 함수를 변수에 담아 호출해야 합니다,스코프(변수의 범위)가 함수와 그 함수가 선언될 당시의 스코프를 기억하는 구조로,이를 통해 함수가 외부 스코프의 변수에 접근할 수 있도록 해줍니다.조건은 뭘까?1.내부 함수가 존재해야 합니다.2.이 내부 함수가 외부 변수에 접근하고 있어야 합니다.3.이 내부 함수가 반환되어 외부에서 호출될 수 있어야 합니다.특성은 뭐가 있을까?변수 접근: 클로저를 통해 내부 함수는 외부 함수의 변수를 계속해서 참조할 수 있어서 이로 인해 외부 함수가 실행된 후에도 변수의 값을 사용할 수 있게 됩니다.정보 은닉: 클로저를 사용하면 특정 변수를 외부에서 직접 접근하지 못하도록 숨길 수 있어서 이렇게 하면 데이터의 캡슐화가 이루어지고, 해당 데이터에 대한 제어가 가능해집니다.상태 유지: 클로저를 통해 생성된 내부 함수는 외부 변수의 상태를 기억하고, 이 상태를 변화시킬 수 있어서 그래서 특정 기능을 구현할 때 유용하게 사용됩니다.예시클로저를 생성하는법const counter = makeCounter();클로저의 핵심은 함수를 호출했을때 그 결과가 콜백함수여야 한다는 것입니다.그래야 함수 속 외부 변수를 이용해 콜백함수로 그 외부변수에 값을 변화 시킬 수 있겠죠?쉬운 예제const makeCounter = () => { let like = 0; // 외부 변수 return () => { // 콜백 함수 = 클로저 return like += 1; };};// 클로저 생성const counter = makeCounter();ㅊconsole.log(counter()); // like 변수의 값 반환 1console.log(counter()); // like 변수의 값 반환 2console.log로 makeCounter가 호출될때마다 like += 1 를 반환해주고 있기 때문에,해당 변수의 반환된 값이 counter 상수에 저장되어 사용되어집니다.비스무리한 다른 예제function makeCounter() { let count = 0; // 외부 변수 return function() { count += 1; // 외부 변수를 변경 return count; // 변경된 외부 변수를 반환 };}const counter = makeCounter(); // 클로저 생성console.log(counter()); // 1console.log(counter()); // 2console.log(counter()); // 3makeCounter 함수에는 독자적인 count라는 변수가 있고그 외부 변수를 제어 하고 반환하는 콜백함수를 리턴하고 있으며makeCounter 함수를 counter라는 상수에 담아console.log로 호출해 사용하고 있습니다.클로저가 아닌 경우다음과 같은 경우는 클로저가 아닙니다.let count = 0;const increment = () => { count += 1; // 외부 변수에 접근하지만, 반환되는 것이 없음};increment(); // 단순히 호출만 됨단순히 외부 변수를 접근해 변화시키고만 있지increment함수 자체가 변수를 기억하고 반환되는것이 아니기 때문에 클로저라 할 수 없습니다.
2024-10-23
typescript
[2] 타입스크립트의 타입 정의 상속에 대하여
사진: Unsplash의 Markus Spiske개요저번에는 타입을 어떻게 정의하고 사용하는지에 대해 알아봤는데이번에는 상속을 이용해서 타입을 조합해 정의해보겠습니다!타입 정의 방법type Test = { name: string, // 이름 description: string, // 설명 age: number, // 나이 func: () => void // 함수}테스트로 타입을 정의 해보았습니다.이 부분이 저번에 알려드린 내용과 같은데요.하지만 이렇게 사용하게 되면 특수한 상황,예를 들면 name과 age의 타입만 필요한 상황, func와 name의 타입 정의만 필요한 상황 같은 특수한 상황이 있을 수 있는데요이럴때 필요한게 상속입니다.상속이란?마치 레고를 조립하듯이 기본이 되는 기본 블럭이 있고거기에 특수한 기능을 가진 블럭을 붙이는 겁니다.예시// 형태type Shape = { style: string // 스타일 color: string // 색상}// 상세정보type Details = { name: string, // 이름 description: string, // 설명 date: number // 날짜}// 자동차 베이스type Car = { company: string, // 이름 country: string // 설명}만약 이러한 값이 있다고 하였을때자동차 베이스에 형태 + 상세정보를 합쳐야 하는 상황이 있는데지금과 같은 경우엔 나뉘어져 있어 조립이 필요한 상황입니다.이 경우 다음과 같이 하면 됩니다.// 형태interface Shape { style: string; // 스타일 color: string; // 색상}// 상세정보interface Details extends Shape { name: string; // 이름 description: string; // 설명 date: number; // 날짜}// 자동차 베이스interface Car extends Details { company: string; // 이름 country: string; // 설명}결과이렇게 할 경우 Car 타입을 사용하면 이런 형태를 지니게 됩니다.const myCar: Car = { style: "SUV", color: "red", name: "My Car", description: "This is a great car!", date: 2024, company: "Toyota", country: "Japan"};상속의 방법상속의 방법은 interface의 extends만 있는게 아닌데요 type에 &를 붙여 조합하는것 또한 가능합니다.그럼 결국 둘은 똑같은게 아니냐는 생각이 들수도 있을텐데비유로 다름을 설명해보자면const(상수)는 재선언 재할당이 불가능합니다.var(변수)는 재선언 재할당이 가능합니다.extends와 &는 이 차이인겁니다.interface의 extends는 재선언 재할당이 불가능합니다.type의 &는 재선언 재할당이 가능합니다.예시interface의 경우interface User { name: string;}interface User { age: number; // 병합됨}const user: User = { name: "CODi", age: 28,};type의 경우type User = { name: string;};type User = { // 오류 발생 age: number;};마무리이번에는 타입의 상속에 대해 알아보았습니다.그래도 블럭으로 비유하며 생각해보니 상속이라고 외우는것보다 더 쉽네요 ㅋㅋㅋ
2024-10-21
tip
FSD 구조를 통해 프로젝트의 폴더 구조를 명확히 해보자
사진: Unsplash의 Leiada Krozjhen개요항상 토이프로젝트를 만들다 보면 문득 고민에 빠지는 것들이 있었습니다.공용 컴포넌트의 경우, 이 컴포넌트는 여러 곳에서 사용되지만, 모든 곳에서 쓰지는 않습니다. 과연 여기 위치해도 괜찮은 것일까요?전역 사용 컴포넌트의 경우, 이 컴포넌트는 모든 곳에서 사용되긴 하는데, 하나의 컴포넌트 때문에 공용으로 사용하는 폴더에 넣는 것이 올바른 선택인지 고민됩니다.그 고민을 해결해보고자 이번에는 FSD에 대해 알아보고자 합니다.FSD 구조란기능 단위로 나누어 개발하는 방식으로, 프로젝트의 복잡도가 증가할 때 관리와 확장성을 쉽게 해주는 아키텍처 패턴입니다.FSD의 핵심 개념은 각 기능이 독립적인 모듈로 구성된다는 것!즉, UI 컴포넌트, 상태 관리, 스타일링, 비즈니스 로직 등을 하나의 기능 단위로 묶어서 관리합니다.다음과 같은 이점들이 있습니다.1.모듈화: 각 기능은 독립적인 모듈로 분리되어 있기 때문에, 다른 기능에 영향을 주지 않고 개발 및 수정이 가능합니다.2.유지보수 용이성: 기능별로 코드를 관리하므로 특정 기능에 문제가 발생했을 때 쉽게 문제를 파악하고 해결할 수 있습니다.3.협업 효율성: 팀원들이 각 기능별로 작업을 나누어 진행할 수 있기 때문에 대규모 프로젝트에서 협업이 더 원활합니다.4.재사용성: 기능별로 모듈화된 코드를 다른 프로젝트나 페이지에서도 쉽게 재사용할 수 있습니다.구조 예시/src /app # 앱 초기화 및 전역 설정 관련 (store, routing 등) /entities # 핵심 비즈니스 로직을 처리하는 객체들 (도메인 모델, 상태 등) /features # 개별 기능 단위 (서브 도메인) /pages # 페이지 구성 (라우팅된 주요 화면) /widgets # 페이지나 여러 기능에 걸쳐 재사용될 수 있는 UI 구성 요소들 /shared # 앱 전반에서 사용되는 공통 리소스 (유틸리티, 상수, API 함수 등)폴더 구조를 역할에 따라 나눈 후, 각 역할에 맞는 하위 폴더로 세분화합니다.예를 들어, 기능(feature)을 정리할 경우에는 다음과 같이 각 기능에 맞는 폴더를 구성합니다./features /write /delete /like
2024-10-21
tip
Google Analytics를 세팅하여 내 페이지 통계를 확인해보자!
개요본 웹사이트를 만들고 나니, 그동안 티스토리만 사용해왔던 탓에 통계를 어떻게 확인할지 고민이 생겨,여러 자료를 찾아본 끝에 ‘Google Analytics’를 통해 통계를 확인해보기로 결정했습니다.어떻게 되는걸까요건 제가 예전에 등록했던 티스토리에 대한 통계인데요!만약 측정을 시작하면 이렇게 세세하게 내 페이지를 방문한 사용자들이나의 페이지를 어떻게 이용했는지, 어떻게 유입했는지 확인이 가능합니다.시작해보자1. Google Analytics 방문Google Analytics를 방문하면 왼쪽 하단의 톱니바퀴를 눌러주세요!2. + 만들기 클릭왼쪽 상단 '+ 만들기' - '속성' 클릭3. 속성 이름 및 보고 시간대 선택속성 이름은 이 사이트를 구분할 이름(원하는 이름), 보고 시간대는 한국을 선택하시면 됩니다.4. 내 사이트 카테고리전 교육이나 취업에 관련된 내용에 치중되어있다 생각되어서 '취업 및 교육'으로 선택하였습니다.규모는 '작음'으로 선택하였습니다.5. 비즈니스 목표 선택모든 항목에 대한 통계를 보기위해 모두 선택 후 '만들기를 선택하였습니다'6. head 태그 안에 Google Tag 관련 스크립트 추가만들기를 통해 나온 gtag 코드를 head태그에 삽입해주세요.예를 들어 아래 코드가 head 태그 안에 삽입 후 배포가 되어있어야Google Analytics가 접속해 확인이 가능합니다.<script> // <!-- Google tag (gtag.js) --> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-');</script>완료!하단과 같이 '데이터 수집이 활성화되었습니다.' 가 표시되었다면 세팅이 완료된거에요이제 사람들이 우리들의 사이트를 어떻게 훑어보고 있는지 확인해보면 될거같습니다,,,,ʕ◍·̀·́◍ʔฅ
2024-10-20