원문 링크 https://martinfowler.com/articles/2025-nature-abstraction.html 

 

LLMs bring new nature of abstraction

A long-form article entitled: "LLMs bring new nature of abstraction"

martinfowler.com

 

 이 바닥의 많은 떠벌이들과 마찬가지로, 나는 최근 생성형 AI  시스템이 소프트웨어 개발에 어떤 역할을 할 수 있을지에 대해 주목하고 있다. 내 생각엔 LLM의 등장이 가져올 변화는 어셈블리시절 고차원 프로그래밍언어(high-level programming languages)의 등장이 가저온 변화와 비슷할 것이라고 본다. 고차원 프로그래밍 언어와 프레임워크들은 우리의 추상화 레벨과 생산성을 향상시켰지만 프로그래밍의 본질에 대한 영향은 별로 없었다. LLM은 프로그래밍의 본질에 영향을 주고 있지만 단순히 추상화 수준을 끌어올리는 것에 그치지 않고 비결정론적(non-determinisitic)인 도구로 프로그래밍한다는 것이 무엇을 의미하는지에 대해서도 다시 한번 생각하게 만든다. 

 고차원 프로그래밍 언어들은 새로운 레벨의 추상화를 아주 빠르게 전달했다. 어셈블리 언어를 사용할 때는 특정 머신의 명령어 집합 만을 염두해두고 작업하게 되고 간단한 작업조차도 어떻게 하면 데이터를 올바른 레지스터에 등록해서 특정 행위를 할 수 있게 만들지에 대해 스스로 고민하고 파악해야 했지만. 고차원 언어에서는 명령문, 조건문을 통한분기, 데이터 컬렉션에 반복문을 돌리면서 작업을 수행하는 방법을 생각할 수 있게 되었다. 내의 코드에 이름(식별자)을 붙일 수 있게 되어서 각 값들이 무엇을 의미하는지 명확하게 표현할 수 있게 되었다. 초기의 언어들에는 명백한 한계가 있었다. 나의 첫 번째 프로그래밍 언어는 포트란4였다. 포트란4에는 'if'문에 'else'가 없었고, 정수형 변수를 선언할때는 변수명을 "I"부터 "N"사이의 문자로 시작해야 한다는 규칙이 있었다. 

 그러한 제약을 제거하고 블록 구조를 더했을 때(IF 문 이후에 한 줄 이상의 코드를 쓸 수 있게 되었다.) 프로그래밍은 쉬워지긴(그리고 더 재미있어졌다) 했으나 이러한 변화는 모두 같은 부류의 진보였다. 요즘 나는 반복문을 거의 사용하지 않는다. 나는 함수도 자연스럽게 data처럼 전달하지만 기계에게 명령을 내리는 방법은 포트란을 사용하던 시기와 크게 변하지 않았다. Ruby는 포트란과 비교하면 훨씬 정교하고 세련된 언어지만 포트란과 동일한 분위기를 가진다. 마치 포트란과 PDP-11 기계어 명령사이에서는 느낄 수 없는 분위기의 차이다.

 비록 지금까지 나는 최고의 생성형 AI 도구 들을 가볍게 만져보는 정도밖에 해보지 못했지만 친구들과 동료들의 AI 툴 경험을 듣는 것에 매료되어 있다. 나는 기계와 대화하는 방식이 루비에서 프롬프트로 변화된 것은 포트란과 어셈블리 언어 사이의 변화만큼 큰 변화라는 것을 확신한다. 추상화의 관점에서 보면 이는 더 큰 변화다. 내가 포트란 함수를 작성할 때, 나는 코드를 수백 번 컴파일을 할 수 있고 수백 번 컴파일해도 내가 작성한 코드의 결과는 변하지 않는다(버그가 있었다면 매번 같은 버그가 발 생한다). LLM은 확정적이지 않은 추상화를 가지고 왔다. 그 결과 내가 git에 동일한 프롬프트를 올려둔다고 해서 그 프롬프트를 실행한 결과가 매번 같지 않다. 나의 동료 브리기테가 말한 것처럼 우리는 추상 레벨을 위로 올리는 동시에 '비결정성'이라는 방향으로 옆으로 이동하고 있다. 

illustration: Birgitta Böckeler

 우리가 LLM을 업무에서 적용하는 방법을 배우는 것과 동시에 우리는 이 '비결정성'과 함께 살아가는 방법을 알아내야 한다. 이런 변화는 매우 극적이고 나를 흥분시키고 있다. 나는 어느 순간 우리가 잃게 될 것에 대한 아쉬움을 느낄 수도 있겠지만 대부분 이해하지 못한 새로운 것을 얻게 될 거란 사실도 알고 있다. 이런 '비결정성'의 진화는 아직까지 우리 업계 역사 속에서는 유래없는 진화이다. 

반응형

eventHandling

  • react의 component는 상태를 가지고, 상태의 변화에 따라 컴포넌트가 리 랜더링됨
    • 즉, 리엑트 컴포넌트의 상태를 변경시키는 무언가가 있다.
      • 그 무언거의 대부분이 바로 이벤트
  • javaScript의 event와 약간차이는 있으나 비슷하다.
    • react도 결국 javaScript다.
  • JSX에선 카멜케이스로 구성된 속성에 이벤트 함수를 넣는다.
    • <button onClick={handleClick}>Button </buttonn>

  • react의 이벤트에선 이벤트함수가 호출되면 인자로 SyntheticEvent 객체가 전달됨
    • SyntheticEvent는 javascript의 event 객체를 래핑한 객체임.
    • 거의 유사한 인터페이스를 가지고 있음
    • 원본 이벤트 객체도 접근 가능 SyntheticEvent.nativeEvent

eventHandler함수를 만들때는 react lifecycle을 고려해야한다.

  • 컴포넌트 내부에서 함수를 만들면 리랜더링 될때마다 새로 함수가 쓰여진다.
    • 이게 필요한 순간도 있겠으나 아닌 순간도 있다.
    • 새로 함수를 쓸 필요가 없다면 컴포넌트 외부에서 이벤트 핸들러 함수를 만들자.
    • 또는 useCallback으로 감싸주면 리랜더링을 피할 수 있다.
import { useCallback } from "react";

// 컴포넌트 외부에 함수 선언
function handleClickOutOfComponent(e) {
  console.log("click2", e);
}

function App() {
  // 컴포넌트 내부의 함수 
  function handleClick(e) {
    console.log("click1", e);
  }
  const handleChange = useCallback((e) => {
    console.log("change", e.target.value);
  }, []);

  return (
    <div>
      <button onClick={handleClick}>Button1</button>
      <button onClick={handleClickOutOfComponent}>Button2</button>
      <div>
        <input type="text" onChange={handleChange} />
      </div>
    </div>
  );
}
export default App;

이벤트의 종류

Mouse event

  • onClick : 마우스 클릭 (down + up )
  • onMouseDown : 버튼 누를시
  • onnMouseUp : 버튼 뗄시
  • onMouseEnter : 요소 밖에서 안으로 마우스 커서가 들어감
  • onMouseLeave : 요소 안에서 밖으로 마우스 커서가 나감
  • onMouseMove : 요소 안에서 마우스 커서가 움직임

Keyboard event

  • onKeyDown : 키를 눌렀을때 (물리적인 키에 반응)
  • onKeyUp : 키를 떼었을때
  • onKeyPress : 키를 눌러서 문자가 입력될때(눌린 문자에 반응함)

Focus, Form event

  • Focus
    • onFocus : 요소가 포커스 될때
    • onBlur : 요소의 포커스가 사라질경우
  • Form
    • onChange : 요소의 값이 변경될때

그외

  • 필요할때마자 찾아가면서 사용하도록하자.

Form 요소 컨트롤

  • Form 요소를 컨트롤할때는 이벤트를 자주 사용한다.

Controlled Component

  • 제어 컴포넌트 라고도 함.
  • React에 의해 입력 요소 값이 제어되는 컴포넌트
import { useState } from 'react';

function TextArea() {
  const [textAreaVal, setTextAreaVal] = useState('');

  console.log('[TextArea] render', value);

  return (
    <textarea
      value={textAreaVal}
      onChange={(e) => {
        setTextAreaVal(e.target.value);
      }}
    />
  );
}

export default TextArea;
  • 위 코드에서 textAreavalue 속성에 textAreaVal 스테이트 값을 넣어줌
  • onChange 에서는 setTextAreaVal를 호출함
  • 유저가 값을 입력하면 state에 유저의 입력이 반영 되면서 상태가 업데이트됨

장점

  • 컴포넌트의 state 와 input value가 완전히 동일함(신뢰가능한 단일 출처)
  • 다른 컴포넌트에 input value를 전달하거나 다른 이벤트 핸들러에서값을 재설정 할 수 있음

단점

  • 값이 변경되는 매 순간 렌더링이 됨
  • 컴포넌트의 영향 범위가 클수록 성능 저하됨

Uncontrolled Component

  • Controlled Component와는 반대로 input value를 컴포넌트 State에 연결하지 않고 사용하는 컴포넌트
  • 값은 dom을 통해 가져온다.
    • ex: document.querySelector('#{id}').value
  • useRef를 사용해 가져올 수 도 있다.
    • useRef는 Hooks의 한 종류. 특정 요소의 레퍼런스를 직접 가져올때 사용
    • 연결된 값이 변경되더라도 리랜더링이 되지 않는다.
import { useRef } from 'react';

function UncontrolledTextInput() {
  const inputRef = useRef(); //1. useRef를 이용해 ref를 만든다.

  console.log('[UncontrolledTextInput] render');

  return (
    <>
    /* jsx에서 ref속성에 연결한다.  */
      <input ref={inputRef} type="text" id="input" />
      <button
        onClick={() => {
          console.log(inputRef.current.value);
        }}
      >
        Get value
      </button>
    </>
  );
}

export default UncontrolledTextInput;

반응형

'프로그래밍 > react 학습노트' 카테고리의 다른 글

react 학습노트 | 3.Hooks  (0) 2025.04.20
react 학습노트 | 2.Component  (0) 2025.04.11
react 학습노트 | 1.JSX란?  (0) 2025.03.30

Hooks

  • react의 life cycle을 알려면 Hooks를 알 필요가 있다.
  • Hooks에 대해 알아보자.

Hooks의 종류

  • useState
  • useEffect
  • useCallback
  • useMemeo, useContext, useRef, useLayoutEffect
  • 위와 같이 10개 정도가 있는데, 그중 상위 3개정도가 주로 사용된다. 나머지는 필요할때 찾아서 쓰면된다.

useState

  • component의 State를 생성하는 Hook
    const [value, setValue] = useState(0) //인자는 초기값
    // 첫번째 요소(value) => state 값
    // 두번째 요소(setValue) => state를 set 해주는 setter 함수

useEffect

  • component가 랜더링 될때 현재 상태 변화에 따라 조건적으로 특정 작업을 실행하기 위한 Hook
    • 처음 랜더링 될때
    • 컴포넌트가 언마운트 될때
      • cleanup 함수를 이용해서 component unmount시 자원, 이벤트 등을 정리해준다.
        useEffect(() => {
        ...
        return () => {
        ... // cleanup 함수. component 가 unmount될때 실행됨
        }
        },[])
  • 상태가 변할때
    • useEffect()함수에 인자로 상태 변화를 감지할 state를 배열로 전달한다.
    • 이 경우 클린업 함수는 상태 변화를 감지하고 useEffect를 재실행하기 직전에 실행됨.
      const [value, setValue] = useState(0) 
      useEffect(() => {
      ...
      return () => {
      ... // cleanup 함수. component 가 unmount될때 실행됨
      }
      }, [value])

useCallback

  • 리 랜더링 시 기존에 만든 함수를 재생성 하지 않고 재활 용 하기 위해 사용하는 Hooks
  • memoization
const fooFun =useCallback(()=>{
  console.log("bar");
})

Hooks 사용시 주의사항

  • 조건적으로 사용하면 안된다.
  • Hooks 는 React Component에서만 사용 가능하다.

React의 렌더링 과정

Rerendering

  • Component의 상태(state, props)가 변경 되면서 해당 컴포넌트를 다시 실행하여 화면에 그린다는 의미.
  • Rerendering시 매번 다른 동작을 하게되고 이를 우리는 life cycle이라고함

React의 Life Cycle

  • Class형 과 Function형이 약간 다름
  • Class
    1. constructor 실행
      • 최초 실행
        1. getDerivedStateFromProps() 실행 : props로 넘어온 값을 state와 동기화하는 메소드
        2. render method 실행 : 화면에 그릴 JSX를 반환
        3. componentDidMount() 실
      • 업데이트 시
        1. getDerivedStateFromProps()
        2. shouldComponentUpdate() 실행 : 현재 일어난 상태변화를 확인하여 컴포넌트를 다시 랜더링 할지 말지를 결정
        3. componentDidUpdate()
      • 컴포넌트 삭제시
        1. 제거
        2. componentWillUnmount()실행
  • function형
    • 최초 실행
      1. 자기자신을 실행하여 JSX를 리턴하고 DOM에 반영
      2. useEffect Hook 실행: componentDidMount, componentDidUnMount, componentDidUpdate()를 커버해줌.
    • 업데이트시
      1. 자기 자신 실행 후 JSX반한
      2. useEffect 실행
    • unmount 시
      1. useEffect만 실행
반응형

'프로그래밍 > react 학습노트' 카테고리의 다른 글

react 학습노트 | 3.EventHandling  (0) 2025.04.26
react 학습노트 | 2.Component  (0) 2025.04.11
react 학습노트 | 1.JSX란?  (0) 2025.03.30

+ Recent posts