Go๋ฏผ๋ณด๋‹ค Go

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž

Create

[React] ์™œ ๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ๋ฐ•์Šค๋Š” ์Šคํƒ€์ผ๋กœ ๋งŒ๋“œ๋Š”๊ฐ€?

SleepingOff 2024. 5. 11. 22:38

๐Ÿพ๋“ค์–ด๊ฐ€๋ฉฐ

๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ๋ฐ•์Šค๋ž€?

  • ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์— ๋”ฐ๋ผ์„œ ํฌ๊ธฐ๊ฐ€ ์ž๋™ ์กฐ์ ˆ๋˜๋Š” ํ…์ŠคํŠธ ๋ฐ•์Šค. ์—‘์…€์˜ ์…€ ํ•˜๋‚˜๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋œ๋‹ค.
  • ํ™”๋ฉด์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ์„œ ๋น„์œจ์ด ์ž๋™ ์กฐ์ ˆ๋˜๋Š” ํ…์ŠคํŠธ ๋ฐ•์Šค.

๋ณดํ†ต ์œ„์˜ ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ ์Šคํƒ€์ผ๋กœ ์กฐ์ ˆํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์—์„œ ๊ถ๊ธˆ์ฆ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.
textarea์˜ ๊ธฐ๋ณธ ์†์„ฑ ์ค‘ rows์™€ cols๊ฐ€ ์žˆ๋Š”๋ฐ, ๋ณดํ†ต ์ด๊ฒƒ์œผ๋กœ ํฌ๊ธฐ๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์Šคํƒ€์ผ๋กœ ์กฐ์ ˆํ•  ๊ฒฝ์šฐ ์ตœ์ดˆ ์„ ์–ธํ•œ rows์™€ cols๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด cols์™€ rows๋กœ ๋ฐ˜์‘ํ˜•์„ ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ผ๊นŒ?

๊ถ๊ธˆํ•ด์„œ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค!!

โœจ๋ณธ๊ฒฉ์ ์œผ๋กœ

โœ…cols = 1 ์ด ์˜๋ฏธํ•˜๋Š” ๊ฒƒ

  • cols๋Š” ๊ฐ€๋กœ์˜ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • cols๋Š” ์ˆซ์ž๋ฅผ ๊ฐ’์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.
    ๊ทธ๋ ‡๋‹ค๋ฉด cols=1์ด ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ผ๊นŒ์š”?

๋ฐ”๋กœ, 1byte์ž…๋‹ˆ๋‹ค. ๋„ต... ์‚ฌ์‹ค ์—ฌ๊ธฐ์—์„œ ๋ฉˆ์ท„์–ด์•ผ ํ•œ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๋“ฑ์žฅํ•˜๋Š” ๊ธ€์ž์˜ byte ๊ฐœ๋…..! ์ด๋ฏธ ์–ด๋Š ์ •๋„ ๋“ค์–ด์„œ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ํ•œ๊ธ€์˜ ๊ฒฝ์šฐ ํ•˜๋‚˜์˜ ๋ชจ์Œ, ์ž์Œ ๋‹น 2byte, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž, ์˜์–ด๋Š” 1byte๋ฅผ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•œ๊ธ€๊ณผ ์˜์–ด๋ฅผ ์ž…๋ ฅํ•  ๋•Œ์˜ cols๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ์ •๋„๊ฐ€ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ๊ธ€๋กœ ์ž…๋ ฅํ•ด๋„, ์ˆซ์ž์™€ ํŠน์ˆ˜๋ฌธ์ž์˜ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋‹ˆ ์ž…๋ ฅ๋ฐ›๋Š” ์–ธ์–ด๋ฅผ ํ•œ๊ธ€๋กœ ํ†ต์ผํ•˜๋Š” ๊ฒƒ๋„ ํž˜๋“ญ๋‹ˆ๋‹ค. (์ฐธ๊ณ ๋กœ ์—”ํ„ฐ๋ฅผ ์น  ๋•Œ๋„ 1byte๊ฐ€ ํ•„์š”)

์•„, ๋‹คํ–‰ํžˆ rows๋Š” ์ค„ ์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค...

-> cols๋ฅผ ์กฐ์ ˆํ•˜๊ธฐ ์œ„ํ•ด์„  ์ž…๋ ฅ๋ฐ›์€ ๊ฐ’์˜ byte๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.

  const getByteOfValue = (str: string) => {
    let byte = 0;
    for (let i = 0; i < str.length; i++) {
      // ๊ธฐ๋ณธ ํ•œ๊ธ€ 2๋ฐ”์ดํŠธ ์ฒ˜๋ฆฌ
      str.charCodeAt(i) > 128 ? (byte += 2) : byte++;
    }
    return byte;
  };

โœ…textarea์—์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ž…๋ ฅํ•œ ๊ธ€์ž

textarea๋ฅผ ๋ฆฌ์•กํŠธ์—์„œ ๋งŒ๋“ค ๋•Œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import { FormEventHandler, useState } from 'react';
import styles from './Textarea.module.scss';

const Textarea = ({ ...props }: React.HTMLProps<HTMLTextAreaElement>) => {
  const [value, setValue] = useState('');
  const onChangeTextarea: FormEventHandler<HTMLTextAreaElement> = event => {
    const elem = event.target as HTMLTextAreaElement;
    setValue(elem.value);
  };
  return (
    <textarea
      value={value}
      onChange={onChangeTextarea}
      className={styles.textarea}
      {...props}
    />
  );
};

export default Textarea;

๊ทธ๋ ‡๋‹ค๋ฉด value์˜ ๊ฐ’์—๋Š” ์–ด๋–ค ๊ฒŒ ๋“ค์–ด์˜ฌ๊นŒ์š”?

์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ: "hello" / value: "hello"
์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ: "hello ใ……" / value: "hello ใ……"
์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ: "hello ์„ธ" / value: "hello ์„ธ"

๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. value๋Š” ์—ฌํƒœ๊นŒ์ง€ ์ž…๋ ฅํ–ˆ๋˜ ๋ชจ๋“  ๊ธ€์ž๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋งˆ์ง€๋ง‰์œผ๋กœ ์ž…๋ ฅํ•œ ๊ธ€์ž๋Š” value[vlaue.length - 1]์ž…๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” "o", "ใ……", "์„ธ"๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์„ธ์ƒ์—๋‚˜... ์ฒซ๋ฒˆ์งธ์™€ ๋‘๋ฒˆ์งธ๋Š” ์ด ๊ธ€์ž์ˆ˜๊ฐ€ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ๋‘๋ฒˆ์งธ์™€ ์„ธ๋ฒˆ์งธ๋Š” ๊ธ€์ž์ˆ˜๊ฐ€ ๋˜‘๊ฐ™๊ตฐ์š”.
'ใ……'๊ณผ 'ใ…”' ๋ชจ๋‘ ํ•œ๊ธ€์ด๋ผ์„œ cols์— ๊ทธ๋Œ€๋กœ 2byte์”ฉ ๋”ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹Œ 'ใ……'์„ ์ž…๋ ฅํ–ˆ์„ ๋•Œ 2๋ฅผ ๋”ํ•ด์ฃผ๊ณ , 'ใ…”'๋ฅผ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ์ด ๊ธ€์ž ์ˆ˜๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜์œผ๋‹ˆ ๋”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด 0์„ ํ•ด์•ผ ๋ฉ๋‹ˆ๋‹ค.

-> ๊ธ€์ž ์ˆ˜์˜ ๋ณ€๋™์— ๋”ฐ๋ผ cols์— ์–ผ๋งˆ์˜ byte๋ฅผ ๋”ํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค.

  • ๊ธ€์ž ์ˆ˜๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š” ์ง€ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜

    //์ด์ „ ๊ธธ์ด ์ €์žฅ
    const [prevInputLength, setPrevInputLength] = useState(0);
    //์ž…๋ ฅ๋ฐ›์€ value์˜ ๊ธธ์ด(ํ˜„์žฌ ๊ธธ์ด)์™€ ์ด์ „ ๊ธธ์ด ๋น„๊ต
    const checkIncreasingValueByte = (value: string) => {
      const inputTextLength = value.length;
      const hasIncreasedValue = prevInputLength <= inputTextLength - 1;
      setPrevInputLength(inputTextLength);
      //๊ธธ์ด๊ฐ€ ๋Š˜์—ˆ๋‹ค๋ฉด true ์•„๋‹ˆ๋ผ๋ฉด false
      return hasIncreasedValue;
    };
  • ์ž…๋ ฅํ•œ ๊ธ€์ž์˜ byte๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜

    //์ด์ „์— ๊ณ„์‚ฐํ•œ byte ์ €์žฅ
    const [prevByte, setPrevByte] = useState(0);
    //์ด์ „์— ๊ณ„์‚ฐํ•œ byte์™€ ์ž…๋ ฅ๋ฐ›์€ str์˜ byte๋ฅผ ๋น„๊ต
    const getGapOfBytes = (str: string) => {
    //์ „์ฒด byte ๊ณ„์‚ฐ
      const byte = getByteOfValue(str);
      let returnValue = 1;
      //1byte์˜ ์ฐจ์ด๋ผ๋ฉด 1์„ ๋ฐ˜ํ™˜
      if (byte - prevByte === 1) returnValue = 1;
      //์•„๋‹ˆ๋ผ๋ฉด 2๋ฅผ ๋ฐ˜ํ™˜
      else returnValue = 2;
      //๊ณ„์‚ฐํ•œ byte ์ €์žฅ
      setPrevByte(byte);
      return returnValue;
    };

์ฆ‰, ๋งŒ์•ฝ ๊ธ€์ž ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ–ˆ๋‹ค๋ฉด, ์ด์ „ ๊ธ€์ž์˜ ์ด byte์™€ ํ˜„์žฌ ๊ธ€์ž์˜ ์ด byte๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ทธ ์ฐจ์ด๋งŒํผ๋งŒ cols์— ๋”ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

if(checkIncreasingValueByte()) cols += getGapOfBytes(value);

์—ฌ๊ธฐ์—์„œ ์™œ checkIncreasingValueByte์ธ๋ฐ getGapOfBytes๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„๊นŒ์š”?
getGapOfBytes ํ•จ์ˆ˜๋Š” getByteOfValue์˜ ํ•จ์ˆ˜์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  getByteOfValue์˜ ๋‚ด๋ถ€์—๋Š” ์ „์ฒด ๊ธ€์ž๋ฅผ ๋Œ๋ฉด์„œ byte๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ฐจ๋ผ๋ฆฌ length๋ฅผ ์ด์šฉํ•ด์„œ ๋‹จ์ˆœํ•˜๊ฒŒ ๊ณ„์‚ฐํ•˜๋Š” ํŽธ์ด ๋” ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (์‚ฌ์‹ค ๊ธ€ ์ ๋‹ค๊ฐ€ ๋ฐœ๊ฒฌํ•จ) ์ด ๊ธ€์ฒ˜๋Ÿผ ๊ธด ๊ธ€์„ ์ ๋Š”๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ ๋ชจ๋“  ๊ธ€์ž์ˆ˜๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค!

โœ…๊ฐ€๋กœ(horizontal) ๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ๋ฐ•์Šค

  • rows: ์„ธ๋กœ ๋†’์ด๋Š” ๊ณ ์ •์ž…๋‹ˆ๋‹ค. ์„ธ๋กœ ๊ธธ์ด๋ฅผ ๊ฐ’์œผ๋กœ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • maxCols: ์ตœ๋Œ€ ๊ฐ€๋กœ ๊ธธ์ด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • cols: ์ตœ์†Œ ๊ฐ€๋กœ ๊ธธ์ด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•์„ ํ•  ๋•Œ ๊ณ ๋ คํ•  ์ ์€ ์ตœ๋Œ“๊ฐ’๊ณผ ์ตœ์†Ÿ๊ฐ’ ์‚ฌ์ด์—์„œ ์ž์œ ๋กญ๊ฒŒ ๋‚ ์•„?๋‹ค๋…€์•ผ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ตœ์†Ÿ๊ฐ’๊ณผ ์ตœ๋Œ“๊ฐ’์˜ ๋ฒ”์œ„ ๋‚ด์— ์žˆ๋Š”์ง€, ๋„˜์ง€๋Š” ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋“ค์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

cols์™€ maxCols์˜ ๊ฒฝ์šฐ ๊ฐ’์ด ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌดํ•œ๋Œ€๋กœ ๊ฐ€๋กœ ๊ธธ์ด๊ฐ€ ๋Š˜์–ด๋‚  ์ˆ˜ ์žˆ์„ ์ˆ˜๋„ ์žˆ์ง€ ์•Š์„๊นŒ์š”?

  const isOverMinCols = !!cols && cols <= currentCols;
  const isUnderMaxCols = !!maxCols && currentCols <= maxCols;
  const isOverMaxCols = !maxCols || !isUnderMaxCols;
  const isValidHorizontal = horizontal && (isUnderMaxCols || isOverMinCols) && !isOverMaxCols;

์ด์ œ ์ด ์นœ๊ตฌ๋“ค์„ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ํ™•์ธ์„ ํ•ด์ค„ ๊ฒ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ž…๋ ฅ๋ฐ›๋Š” value๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง ๋˜์ง€๋งŒ, ์ด ์นœ๊ตฌ๋“ค์€ ํ˜„์žฌ cols์˜ ๊ฐ’์— ์˜์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ˜„์žฌ cols(currentCols)๋ฅผ ์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด์ฃผ๊ณ , textarea์˜ cols์— ๊ฐ’์œผ๋กœ ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค.

  const [currentCols, setCurrentCols] = useState(cols ?? 1);
/** ์ƒ๋žต */
 <textarea
      value={value}
      ref={textarea}
      className={styles.textarea}
      onChange={handleChangeTextarea}
      onKeyUp={handleKeyEnter}
      cols={currentCols}
      rows={currentRows}
      {...props}
    />

cols๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 1์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. cols ๊ฐ’์ด ์—†์„ ์ˆ˜๋„ ์žˆ๊ณ , ์ปค์„œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ตœ์†Œ ํฌ๊ธฐ๋Š” ๋˜์–ด์•ผ ํ•˜๋‹ˆ๊นŒ์š”.

์ด์ œ ๊ฐ’๋„ ๋ฐ›์•˜๊ณ , ๋ฒ”์œ„๋„ ์„ค์ •ํ–ˆ์œผ๋‹ˆ ์ž…๋ ฅ์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค cols๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ค„ ์ผ๋งŒ ๋‚จ์•˜์Šต๋‹ˆ๋‹ค. value๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•ด์ฃผ๋Š” handleChangeTextarea์˜ ํ•จ์ˆ˜์—์„œ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•ด์ฃผ์–ด๋„ ๋˜์ง€๋งŒ, value๊ฐ€ ๋ฐ”๋€œ์— ๋”ฐ๋ผ cols๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ถ€์ˆ˜ ํšจ๊ณผ๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ useEffect๋กœ ๊ด€๋ฆฌํ•ด์ค๋‹ˆ๋‹ค.

  useEffect(() => {
    if (!textarea.current) return;
    const elem = textarea.current as HTMLTextAreaElement;
    updateCountOfTextAfterEnter(value); //์ด ์นœ๊ตฌ๋Š” ๋ฌด์—‡์ผ๊นŒ?
    const isOverCurrentCols = checkOverCurrentCols();

    if (isValidHorizontal) {
      elem.cols = isOverCurrentCols ? countOfTextAfterEnter : currentCols;
    }
    setCurrentCols(elem.cols);
  }, [value]);

์—ฌ๊ธฐ์—์„œ ์ € updateCountOfTextAfterEnter๋ผ๋Š” ํ•จ์ˆ˜์™€ ์ด๋ฆ„์ด ๋น„์Šทํ•œ countOfTextAfterEnter๋ผ๋Š” ์นœ๊ตฌ๊ฐ€ ์ƒˆ๋กญ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์œ„์˜ ๋‚ด์šฉ์ด ๋‹ค์‹œ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. cols์˜ ๊ฐ’์€ ๊ธ€์ž์˜ byte๊ฐ’์ด๋‹ค...

  //ํ˜„์žฌ ์ž…๋ ฅํ•œ ํ…์ŠคํŠธ์˜ ๊ธธ์ด. ์—”ํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆ”. ์นธ์ด ๋ชจ์ž๋ผ์„œ ์ค„๋ฐ”๊ฟˆ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹˜!
  const [countOfTextAfterEnter, setCountOfTextAfterEnter] = useState(0);

  const updateCountOfTextAfterEnter = (value: string) => {
    const inputLanguageByte = getGapOfBytes(value);
    //์ „์ฒด ๊ธ€์ž ์ˆ˜์— ๋ณ€๋™์ด ์žˆ๋‹ค๋ฉด, ๋ณ€๋™๋œ byte ์ˆ˜๋งŒํผ ๋”ํ•˜๊ธฐ. ์—†๋‹ค๋ฉด 0์„ ๋”ํ•˜๊ธฐ.
    const countOfText = checkIncreasingValueByte(value) ? inputLanguageByte : 0;
    setCountOfTextAfterEnter(prev => prev + countOfText);
  };

ํ˜„์žฌ ์ž…๋ ฅํ•œ ๊ธ€์ž์˜ ์ˆ˜๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ cols๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ํ˜„์žฌ ์ž…๋ ฅํ•œ ๊ธ€์ž๋ฅผ ํ™•์ธํ•˜๊ณ  ๊ธ€์ž ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ–ˆ๋‹ค๋ฉด ์ฆ๊ฐ€ํ•œ byte ๋งŒํผ ๋”ํ•ด์ฃผ๊ณ , ์•„๋‹ˆ๋ผ๋ฉด 0๋งŒํผ ๋”ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ธ€์ž๋ฅผ ์ง€์› ๋‹ค๋ฉด ์Œ์ˆ˜๋ฅผ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ž, ์ด๋ ‡๊ฒŒ ๋์ธ ์ค„ ์•Œ์•˜์ฃ ..? ๐Ÿ˜ˆ

๋งŒ์•ฝ cols๊ฐ€ ๊ธฐ๋ณธ 20์œผ๋กœ ์„ค์ •๋˜์—ˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ํ˜„์žฌ๋Š” ๊ธ€์ž๋ฅผ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค cols๊ฐ€ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •ํ•œ 20์— ๋” ์ถ”๊ฐ€๋ฅผ ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด์ฃ . ๊ทธ๋Ÿฌ๋‹ˆ, 20์„ ๋‹ค ์ฑ„์šธ ๋•Œ๊นŒ์ง„ ์›€์ง์ด๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  useEffect(() => {
    if (!textarea.current) return;
    const elem = textarea.current as HTMLTextAreaElement;
    updateCountOfTextAfterEnter(value);
    const isOverCurrentCols = checkOverCurrentCols();
    //ํ˜„์žฌ cols๊ฐ€ ๊ธ€์ž๋กœ ๋‹ค ์ฐผ๋Š”์ง€ ์•Œ๋ ค์ค˜! 
    const isPullCurrentCols = elem.cols === currentCols;
    if (isValidHorizontal && isPullCurrentCols) {
      elem.cols = isOverCurrentCols ? countOfTextAfterEnter : currentCols;
    }
    setCurrentCols(elem.cols);
  }, [value]);

์ด๋ ‡๊ฒŒ ์กฐ๊ฑด์„ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด์„œ ๋“œ๋””์–ด!! ๊ฐ€๋กœ ๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ๋ฐ•์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค...ใ…Žใ…Ž

์ถ”๊ฐ€์ ์œผ๋กœ enter ํ‚ค๋ฅผ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ํ˜„์žฌ cols๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…์ŠคํŠธ์˜ ์ค‘๊ฐ„์—์„œ ์—”ํ„ฐ๋ฅผ ์นœ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์ฃ .
๊ทธ๋ž˜์„œ enter ํ‚ค๋ฅผ ๋ˆ„๋ฅธ๋‹ค๋ฉด ๋จผ์ €, ๋‹ค์‹œ ํ˜„์žฌ ๊ฐ€์ง„ ์ตœ๋Œ€ cols๊ฐ€ ์–ผ๋งŒ์ง€ ์•Œ์•„๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  const handleKeyEnter: React.KeyboardEventHandler<HTMLTextAreaElement> = event => {
    if (event.key === 'Enter') {
      if (isValidHorizontal) {
      //์—ฌ๊ธฐ์—์„œ ์ผ๋‹จ ์—”ํ„ฐ๋ฅผ ํ–ˆ์œผ๋‹ˆ ํ˜„์žฌ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ดˆ๊ธฐํ™”.. ์—ฌ๊ธฐ์—์„œ ๋งŽ์€ todo๊ฐ€ ์ƒ๋žต๋จ..
        setCountOfTextAfterEnter(0);
        //enter๋ฅผ ํ…์ŠคํŠธ ์ค‘๊ฐ„์—์„œ ํ–ˆ์„ ๊ฒฝ์šฐ currentMacCols๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.
        const currentMaxCols = calcMaxColsByte(value);
        setCurrentCols(currentMaxCols);
      }
  };

   const calcMaxColsByte = useMemo(
    () => (value: string) => {
    //์—”ํ„ฐ์™€ ์—”ํ„ฐ ์‚ฌ์ด์— ์žˆ๋Š” ๊ธ€์ž๋“ค์„ ์—”ํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž˜๋ผ์„œ ๋ฐฐ์—ด์— ์ €์žฅ
      const ArrayOfBetweenEnterValues = splitByEnter(value); //value.split(์—”ํ„ฐ ๊ณจ๋ผ๋‚ด๋Š” ์ •๊ทœํ‘œํ˜„์‹)
      //ํ•ด๋‹น ๊ธ€์ž๋“ค์˜ ๊ธธ์ด๋ฅผ ๋ฐฐ์—ด์— ์ €์žฅ
      const ArrayOfLength = ArrayOfBetweenEnterValues.map(
        values => +values.length
      );
      //๊ฐ€์žฅ ๊ธด ๊ธ€์ž์˜ ๊ธธ์ด๋ฅผ ์ €์žฅ
      const maxLengthOfValues = Math.max(...ArrayOfLength);
      //์œ„์˜ ๊ธธ์ด์˜ ์ธ๋ฑ์Šค === ๊ฐ€์žฅ ๊ธด ๊ธ€์ž์˜ ์ธ๋ฑ์Šค
      const indexOfMaxLength = ArrayOfLength.indexOf(maxLengthOfValues);
      //๊ฐ€์žฅ ๊ธด ๊ธ€์ž์˜ byte๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ return
      return getByteOfValue(ArrayOfBetweenEnterValues[indexOfMaxLength]);
    }, [value] );

๋งŽ์€ todo ๋“ค์ด ์žˆ๊ฒ ์ง€๋งŒ ์ผ๋‹จ ๊ตฌ์‹ค์€ ํ•œ๋‹ค! ์ •๋„๋กœ ๋งŒ๋“ค์–ด ๋ณธ ๊ฐ€๋กœ ๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ ๋ฐ•์Šค ์ฝ”๋“œ ์„ค๋ช…์€ ์—ฌ๊ธฐ๊นŒ์ง€์ž…๋‹ˆ๋‹ค! ์„ธ๋กœ ๋ฐ˜์‘ํ˜•๊ณผ ์–‘๋ฐ˜์‘ํ˜• ํ…์ŠคํŠธ ๋ฐ•์Šค์˜ ๊ฒฝ์šฐ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋งํฌ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.
https://gist.github.com/Sleepingoff/879d368e87bb7e5f29585ab39561edd9

ํ˜น์‹œ... ์—ฌ๊ธฐ์—์„œ ๋” ํ•˜๊ณ  ์‹ถ์€ ๋ถ„๋“ค์„ ์œ„ํ•ด ์•Œ๋ ค๋“œ๋ฆฌ๋Š” ๋‚จ์€ todo๋“ค...์„ ๋น™์žํ•œ ๋‹จ์  ๋Œ€๋ฐฉ์ถœ
[ ] ์ตœ๋Œ“๊ฐ’๊นŒ์ง€ ๋ชจ๋‘ ์ฐฌ ํ…์ŠคํŠธ ๋ฐ•์Šค์— ์Šคํฌ๋กค ๋ณด์ด๊ฒŒ ํ•˜๊ธฐ
[ ] ๊ธ€์ž๋ฅผ ์ง€์› ์„ ๋•Œ colsํ˜น์€ rows์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ
[ ] ์ตœ๋Œ“๊ฐ’๊นŒ์ง€ ๋ชจ๋‘ ์ฑ„์› ์ง€๋งŒ ๊ธ€์ž๋ฅผ ์ง€์›Œ ๋‹ค์‹œ ๋ฒ”์œ„ ๋‚ด๋กœ ๋“ค์–ด์™”์„ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ
[ ] width 100% ๋“ฑ ์ƒ๋Œ€ ๋‹จ์œ„์— ๋Œ€ํ•œ ๋Œ€์‘(์ ์‘ํ˜•)... cols๋Š” byte๊ฐ’์ธ๋ฐ.. ๋ณ€ํ™˜ ์–ด๋–ป๊ฒŒ ํ•ด...
[ ] vertical, horizontal์„ ๋ชจ๋‘ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ์—๋Ÿฌ์ฒ˜๋ฆฌ
[ ] ์—”ํ„ฐ ์ •๊ทœํ‘œํ˜„์‹์— ๊ฑธ๋ฆฌ๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
[ ] ๋งค์šฐ ๋งŽ์€ useState ์ •๋ฆฌ

โœ”๏ธ๊ฒฐ๋ก 

ํ•˜์ง€ ์•Š๋Š” ๊ฑฐ์—๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค.
๊ทผ๋ฐ ํ•˜๋ฉด ๋˜ ์žฌ๋ฏธ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œํ—˜ ๊ธฐ๊ฐ„์— ๋”ด์ง“ํ•˜๋Š” ๋Š๋‚Œ์ด๋ผ์„œ ์ง‘์ค‘์ด ์ž˜ ๋˜์—ˆ๋„ค์š”ใ…Žใ…Ž

728x90