이미지 불러오기

이미지 파일은 import구문을 통해 불러오고, 불러온 이미지 주소를 src 속성으로 사용하면 된다.

import diceImg from './assets/dice.png';

function Dice() {
  return <img src={diceImg} alt="주사위 이미지" />;
}

export default App;

인라인 스타일

리액트에서 인라인 스타일은 문자열이 아닌 객체형으로 사용한다. 프로퍼티 이름은 CSS 속성 이름으로, 프로퍼티 값은 CSS 속성 값으로 쓰는데, 이때 프로퍼티 이름은 아래의 boarderRadius 처럼 대시 기호 없이 카멜 케이스로 써야 한다.

import diceImg from './assets/dice.png';

const style = {
  borderRadius: '50%',
  width: '120px',
  height: '120px',
};

function Dice() {
  return <img style={style} src={diceImg} alt="주사위 이미지" />;
}

export default App;

CSS 파일 불러오기

import 구문으로 파일을 불러올 수 있는데 from 키워드 없이 사용하면 된다.

import diceImg from './assets/dice.png';
import './Dice.css';

function Dice() {
  return <img src={diceImg} alt="주사위 이미지" />;
}

export default App;

클래스네임 사용하기

CSS 파일에 정의된 클래스명을 className prop에 문자열로 넣어주면 된다. 이 때 재사용성을 위해 clasName prop을 부모 컴포넌트에서 받으면 더 좋다.

import diceImg from './assets/dice.png';
import './Dice.css';

function Dice({ className = '' }) {
  const classNames = `Dice ${className}`;
  return <img className={classNames} src={diceImg} alt="주사위 이미지" />;
}

export default App;

🍯더 편리하게 클래스네임 사용하기

  • 위에서 여러 className을 템플릿 문자열로 합쳐서 사용해봤는데, 몇 개 없을 때는 상관 없지만 개수가 늘어 날수록 아래처럼 알아보기 힘들어진다는 문제점이 있다.

1. 템플릿 문자열을 사용

function Button({ isPending, color, size, invert, children }) {
  const classNames = `Button ${isPending ? 'pending' : ''} ${color} ${size} ${invert ? 'invert' : ''}`;
  return <button className={classNames}>{children}</button>;
}

export default Button;

2. 배열을 사용

function Button({ isPending, color, size, invert, children }) {
  const classNames = [
    'Button',
    isPending ? 'pending' : '',
    color,
    size,
    invert ? 'invert' : '',
  ].join(' ');
  return <button className={classNames}>{children}</button>;
}

export default Button;

위 예시 코드처럼 지저분하게 느껴지고, 매번 반복되는 코드를 작성한다는 번거로움이 있다. 개발자들은 이럴 때 라이브러리라는 걸 사용하는데, 다른 개발자가 미리 만들어 놓은 코드를 이용해서 편하게 개발하는 것이다.

클래스네임의 경우에도 편리하게 사용할 수 있는 라이브러리가 많이 있다. 그중에서도 이번에 사용할 라이브러리는 바로 classnames라는 라이브러리이다. 아래 예시 코드를 보시면 알겠지만, 클래스네임에만 집중할 수 있어 훨씬 읽기 편하다. 이렇게 적절한 라이브러리를 쓰면 개발 생산성이 엄청 좋아진다.

3. classnames 라이브러리를 사용

import classNames from 'classnames';

function Button({ isPending, color, size, invert, children }) {
  return (
    <button
      className={classNames(
        'Button',
        isPending && 'pending',
        color,
        size,
        invert && 'invert',
      )}>
     { children }
   </button >
  );
}

export default Button;

classnames 은 NPM이라는 프로그램을 통해 설치할 수 있다. 터미널에서 npm install classnames 을 입력하고 설치한 다음에, 위 예시처럼 import 로 불러와서 사용하면 된다. NPM 저장소 사이트로 들어가면 사용 방법과 설명이 나와있으니, 아래 링크를 한 번 살펴보고 사용해보는 것도 좋다.

NPM classnames 패키지

'코린이 개념잡기 > React' 카테고리의 다른 글

브라우저가 리액트를 알아듣는 원리  (0) 2025.01.04
리액트 렌더링  (0) 2025.01.03
State  (2) 2025.01.03
Props와 Children  (1) 2025.01.03
컴포넌트 문법  (0) 2025.01.03
  • 변수의 범위(scope)가 코드의 구조에 따라 결정되는 방식
  • 즉, 함수가 정의된 위치에 따라 어떤 변수에 접근할 수 있는지를 결정한다.
  • JavaScript에서는 렉시컬 스코프를 따른다.

특징

1. 함수가 정의된 위치에 따라 그 함수가 접근할 수 있는 변수의 범위가 결정된다. (함수가 호출되는 위치와는 무관)

2. 함수 안에 다른 함수를 정의할 수 있다. 내부 함수는 외부 함수의 변수에 접근할 수 있지만 반대는 성립되지 않는다.

function outer() {
    const outerVar = 'I am outer';

    function inner() {
        console.log(outerVar); // 'I am outer' 출력
    }

    inner();
}

outer();

3. 전역에서 정의된 변수는 모든 내부 함수에서 접근할 수 있지만, local에서 정의된 변수는 그 지역의 함수 내에서만 접근할 수 있다.

const globalVar = 'I am global';

function myFunction() {
    const localVar = 'I am local';

    console.log(globalVar); // 'I am global' 출력
    console.log(localVar); // 'I am local' 출력
}

myFunction();
console.log(localVar); // ReferenceError 발생

렉시컬 스코프와 클로저(Closure)

  • 렉시컬 스코프와 관련된 중요한 개념 중 하나는 클로저(closure)이다.
  • 클로저는 함수 안에 있는 함수로, 외부 함수의 변수를 기억하고 사용할 수 있는 내부함수이다.
function myHouse() {
  let toy = "축구공";

  function playGround() {
    console.log(toy); // '축구공'을 출력
  }

  return playGround;
}

let play = myHouse();
play(); // '축구공'을 출력
  • myHouse 함수는 toy라는 장난감을 가지고 있다.
  • playGround 함수는 toy를 기억하고 있고,
  • 나중에 playGround 함수를 실행할 때 toy를 사용할 수 있다.

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

자바스크립트 this  (0) 2025.01.03
웹 브라우저의 동작 원리  (2) 2024.12.28
var, let, const  (0) 2024.12.28
얕고(Shallow), 깊은(Deep) 복사(Copy)  (1) 2024.12.20
==와 ===의 차이  (1) 2024.12.20
  • this가 가리키는 값은 호출되는 방식에 따라 달라진다.

1. 전역 컨텍스트(코드가 전역에서 실행될때의 환경): 전역에서 함수가 호출될 때, this는 전역 객체(브라우저에서는 window)를 가리킨다. 일반적으로 브라우저에서의 전역객체는 window이며 서버(node.js)에서의 전역객체는 global이다.

console.log(this); //window
console.log(this === window); //true

2. 객체 메소드 : 객체의 메소드로 호출될 때 this는 그 메소드를 호출한 객체를 가리킨다. 메소드를 호출하면 기본적으로 this는 해당 메소드를 가지고 있는 객체에 바인딩(binding, 어떤 코드에서 함수를 호출할 때 그 해당 함수가 위치한 메모리 주소로 연결)된다.

const obj = {
    name: 'Elsa',
    greet: function() {
        console.log(this.name);
    }
};
obj.greet(); // 'Elsa' 출력

3. 생성자 함수 : 생성자 함수에서 this는 새로 생성된 객체를 가리킨다.

function Person(name) {
    this.name = name;
}
const person = new Person('Arony');
console.log(person.name); // 'Arony' 출력

4. 화살표 함수 : 화살표 함수에서는 this가 상위 스코프의 this를 그대로 사용한다. 즉, 화살표 함수 내에서 this는 자신이 정의된 위치의 this를 참조한다.

‼️단, 메소드가 화살표 함수로 작성되었을 경우 화살표 함수의 this는 상위 컨텍스트의 this를 계승받기 때문에 this가 전역객체에 바인딩된다.
const obj = {
    name: 'Charlie Puth',
    greet: function() {
        const arrow = () => console.log(this.name);
        arrow();
    }
};
obj.greet(); // 'Charlie Puth' 출력

-----

const zoo = {
  tiger: function() {
    console.log('tiger this:', this);
  },
  rabbit() {
    console.log('rabbit this:', this);
  },
  pig: () => {
    console.log('pig this:', this);
  }
}

zoo.tiger(); //object
zoo.rabbit(); //object
zoo.pig(); //window

5.이벤트 핸들러 : DOM 이벤트 핸들러에서 this는 이벤트가 발생한 요소를 가리킨다.

const button = document.querySelector('button');
button.addEventListener('click', function() {
    console.log(this); // 버튼 요소를 출력
});

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

렉시컬 스코프(Lexical scope)  (3) 2025.01.03
웹 브라우저의 동작 원리  (2) 2024.12.28
var, let, const  (0) 2024.12.28
얕고(Shallow), 깊은(Deep) 복사(Copy)  (1) 2024.12.20
==와 ===의 차이  (1) 2024.12.20

+ Recent posts