1st Team Project retrospective : Tabom Galagsin

Havaianas clone coding

ยท

6 min read

1st Team Project retrospective : Tabom Galagsin

์ฒซ Team Project์˜ ์‹œ์ž‘!

๐Ÿ‘ ํŒ€ ๋ช… : Tabom Galagsin (FE - 4 / BE - 2)

  • ํŒ€๋ช…์€ ํŒ€์›๋“ค๊ณผ ์˜์‹์˜ ํ๋ฆ„๋Œ€๋กœ ์ง“๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ์ผ๋‹จ ์ชผ๋ฆฌ(ใžใ†ใ‚Š)๊ฐ€ ์ผ๋ณธ์–ด๋ผ ํ•œ๊ตญ์–ด๋กœ ์ชผ๋ฆฌ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ฐพ์•„๋ณด๋‹ˆ '๊ฐ€๋ฝ์‹ ' ์ด์˜€๊ณ  ๋ธŒ๋ผ์งˆ ๋ธŒ๋žœ๋“œ์˜€๊ธฐ ๋•Œ๋ฌธ์— ์•ž์— ๋”ฐ๋ด‰(๋ธŒ๋ผ์งˆ์–ด๋กœ estรก bom = it's good)์„ ๋ถ™์—ฌ '๋”ฐ๋ด‰ ๊ฐ€๋ฝ์‹ ' ์ด ๋˜์—ˆ๋‹ค. ๐Ÿ˜‚

๐Ÿ“† ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„

  • 2022. Aug. 16 ~ 2022. Aug. 26 (11 days)

๐Ÿ“ ํ”„๋กœ์ ํŠธ ์„ค๋ช…

  • ์Šฌ๋ฆฌํผ๋กœ ์œ ๋ช…ํ•œ Havaianas์˜ ์›น์‚ฌ์ดํŠธ๋ฅผ ํด๋ก  ์ฝ”๋”ฉ ํ•˜์˜€๋‹ค. ์›น์‚ฌ์ดํŠธ์˜ ์ƒ‰์ƒ์ด ๋‹ค์–‘ํ•˜๊ณ  ํ™”๋ คํ•˜๋ฉฐ ์‹œ๋„ ํ•ด ๋ณด๋ฉด ์žฌ๋ฏธ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค์ด ๋งŽ์ด ์žˆ๋‹ค. (ex. Carousel, Dropdown ๋“ฑ๋“ฑ)

โœ”๏ธ ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด React๋ฅผ ๋ฐฐ์šฐ๋ฉฐ ๋Š๋‚€ ์ 

  • ์ดˆ๊ธฐ์— React๋ฅผ ์ ‘ํ–ˆ์„ ๋•, html ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์ƒ๊ฒจ์„œ ์ข‹์•„ํ–ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ ‘ํ•˜๋ฉด์„œ ๊ณง vanilla JS๊ฐ€ ๋” ์“ฐ๊ธฐ ํŽธํ•˜๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ ์  React๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํšŸ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋‹ˆ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ React์— ์ ์‘์ด ๋˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ  ์ง€๊ธˆ์€ React๊ฐ€ Vanilla JS๋ณด๋‹ค ์‚ฌ์šฉํ•˜๊ธฐ ๋” ์‰ฌ์šฐ๋ฉฐ ๋ฐฐ์šฐ๋ฉด ๋ฐฐ์šธ ์ˆ˜๋ก ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ๋ฌด๊ถ๋ฌด์ง„ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์•„์ง๋„ ๊ฐˆ ๊ธธ์€ ๋ฉ€์ง€๋งŒ ๊ทธ๋ž˜๋„ ์ ์  React์™€ ์นœํ•ด์ง€๋Š” ์ค‘์ด๋‹ค. React ๊ณ ์ˆ˜๊ฐ€ ๋˜๋Š” ๊ทธ๋‚ ๊นŒ์ง€.. ๐Ÿƒโ€โ™€๏ธ

โœ”๏ธ ํ˜ผ์ž ํ•  ๋•Œ์™€ ํŒ€์œผ๋กœ ์ง„ํ–‰ํ•  ๋•Œ ๋‹ค๋ฅธ ์  ๋ฐ ํŒ€์—์„œ ๋‚ด๊ฐ€ ๋งก์€ ์—ญํ• 

  • ํ”„๋กœ์ ํŠธ ์ด์ „์— ํ˜ผ์ž์„œ Instagram์„ clone coding ํ–ˆ์—ˆ๋‹ค. ํ˜ผ์ž์„œ ํ•  ๋•Œ๋Š” git์„ ํ†ตํ•ด mergeํ•  ํ•„์š”๋„ ์—†๊ณ  conflict๋„ ์—†์–ด์„œ ํ˜ผ์ž ๋ ˆ๊ณ ๋กœ ์„ฑ์„ ์ง“๋Š” ๋Š๋‚Œ์ด์˜€๋‹ค. ํ•˜์ง€๋งŒ ํŒ€์›๋“ค๊ณผ ํ•จ๊ป˜ ์ง„ํ–‰์„ ํ•ด๋ณด๋‹ˆ ๋‚ด๊ฐ€ ๋งก์€ ์—ญํ• ์„ ์ž˜ ๊ตฌํ˜„ํ•ด์„œ merge ํ–ˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ–ˆ๋‹ค. ๋‚˜์˜ ๋กœ์ปฌ ์ปดํ“จํ„ฐ์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋˜ Sass๊ฐ€ nesting์ด ์ž˜๋ชป๋˜์–ด ๋‹ค๋ฅธ ํŒ€์›๋“ค ๊ฐ์ž์˜ ๋กœ์ปฌ๋กœ mergeํ–ˆ์„ ๋•Œ, ์•„์›ƒ๋ผ์ธ ์žก์•„๋†“์€๊ฒŒ ์—ฌ๊ธฐ์ €๊ธฐ ๋‹ค ํŠ€์–ด๋‚˜๊ฐ”๊ณ  ๋™๊ธฐ๋“ค์—๊ฒŒ ์ฒดํฌ๋‹นํ•  ๋ป”ํ–ˆ๋‹ค.. ๐Ÿ˜… ์ด๋ฒˆ ์‹ค์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ์•„๋ฌด๋ฆฌ ๋‚ด file์— ๋ฌธ์ œ๊ฐ€ ์—†์–ด๋„ ๋‹ค๋ฅธ ํŒ€์›๋“ค๊ณผ์˜ ํ˜‘์—…์„ ์œ„ํ•ด์„œ๋Š” nesting์ด ์ •๋ง ์ •๋ง ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฑธ ๊นจ๋‹ฌ์•˜๋‹ค!

  • havaianas๋Š” ๋‚ด๊ฐ€ ์ œ์•ˆ ํ•œ ์›น์‚ฌ์ดํŠธ์—ฌ์„œ PM์˜ ์—ญํ• ์„ ๋งก์•˜๋‹ค. 1์ฐจ sprint์—์„œ ์ดˆ๊ธฐ์— ํ”„๋กœ์ ํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰ํ•  ๊ฒƒ์ธ์ง€ ๊ทธ๋ฆฌ๊ณ  ๋ˆ„๊ฐ€ ์–ด๋–ค ticket์„ ๋ฐ›์•„๊ฐˆ ๊ฒƒ์ธ์ง€๋ฅผ ์ •ํ–ˆ๊ณ  ๋งค์ผ ์•„์นจ standup meeting์„ ํ•ด์„œ ์–ด์ œ ํ•œ ์ผ, ์˜ค๋Š˜ ํ•œ ์ผ, ๊ทธ๋ฆฌ๊ณ  blocker๋ฅผ ์„œ๋กœ ๊ณต์œ ํ•˜๋ฉด์„œ ์ง„ํ–‰์‚ฌํ•ญ์„ ํ™•์ธํ–ˆ๋‹ค. ์Šค์ผ€์ฅด ๋ฐ ticket๊ด€๋ฆฌ๋Š” Trello๋ฅผ ์ด์šฉํ•ด ์ง„ํ–‰ํ•˜์˜€๋‹ค.

  • ํ”„๋ก ํŠธ์—”ํŠธ ํŒ€ ์•ˆ์—์„œ๋Š” Navbar ๋ฐ ์ œํ’ˆ ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ๋งก์•˜๋‹ค.

โœ”๏ธ๊ธฐ์–ตํ•˜๊ณ  ์‹ถ์€ ์ฝ”๋“œ

  • ํ๋ญ‡ํ•œ ์ฝ”๋“œ : Dropdown
jsx
    <div
            onMouseEnter={() => setIsMouseEnter(!isMouseEnter)}
        onMouseLeave={() => setIsMouseEnter(!isMouseEnter)}
       >
       <i className="fa-solid fa-bars navIcon menu" />
        {isMouseEnter && <Dropdown />}
    </div>

Dropdown ๋ฉ”๋‰ด๋ฅผ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ! ๋งˆ์šฐ์Šค๊ฐ€ menu icon์„ hoverํ•  ๋•Œ dropdown์ด ์ƒ๊ฒผ์ง€๋งŒ ๋งˆ์šฐ์Šค๊ฐ€ ๋– ๋‚˜์ž๋งˆ์ž dropdown์ด ์‚ฌ๋ผ์กŒ๋Š”๋ฐ ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ๊ณ ์น˜์ง€ ํ•˜๊ณ  ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ๋ฐœ๊ฒฌํ•œ ๋ฐฉ๋ฒ•! Icon๊ณผ dropdown์„ ํ•œ <div>๋กœ ๋ฌถ์–ด ์ด div์— mouseEnter``mouseLeave์ด๋ฒคํŠธ๋ฅผ ์ฃผ๋ฉด ๋œ๋‹ค. ์ƒˆ๋กœ์šด ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์„œ ํ๋ญ‡ํ•œ ์ฝ”๋“œ๋กœ ์„ ์ •!

dropdown.gif

  • ์‹ ๊ธฐํ–ˆ๋˜ ์ฝ”๋“œ : useState๋ฅผ ์ด์šฉํ•œ scroll event
jsx
    const [scroll, setScroll] = useState(0);

      useEffect(() => {
        const handleScroll = e => setScroll(e.currentTarget.scrollY);
        window.addEventListener('scroll', handleScroll);

        return () => window.removeEventListener('scroll', handleScroll);
      });

      return (
        <nav
          className="nav"
          style={scroll < 32 ? { top: 0 - scroll } : { top: -32 }}
        >

Navbar๊ฐ€ ์ด 2๊ฐœ์˜€๋Š”๋ฐ scroll down ํ–ˆ์„ ๋•Œ ์•„๋ž˜์˜ navbar๋งŒ ์ƒ๋‹จ์— fix๋˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„. ์ฒ˜์Œ ์จ๋ณด๋Š” scroll event์—ฌ์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”์ง€ ์ž˜ ๋ชฐ๋ž์—ˆ๊ณ  ํ—ค๋ฉ”์—ˆ๋‹ค. ์Šคํฌ๋กค ์ž์ฒด๋ฅผ useState์— ๋„ฃ์–ด์ฃผ์–ด ๊ธธ์ด๋ฅผ ๊ธฐ์ค€์œผ๋กœ postion:fixed ๋œ ์ƒ๋‹จ navbar์˜ top์„ ๋ณ€๊ฒฝํ•ด ์ฃผ์–ด ๋ณด์ด์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

nav bar.gif

  • ๊ฐ€์žฅ ์–ด๋ ค์› ๋˜ ์ฝ”๋“œ : useInterval(custom)์„ ์ด์šฉํ•œ carousel ๊ตฌํ˜„

์ฝ”๋“œ๋ณด๊ธฐ
jsx
        import { useState } from 'react';
        import useInterval from '../../../useInterval';
        import './NavTopContainer.scss';

        function NavTopContainer() {
          const [currentPosition, setCurrentPosition] = useState(-2);
          const [transitionTime, setTransitionTime] = useState(0.5);
          const [resetAuto, setResetAuto] = useState(1);

          const currentData = [...CAROUSEL_DATA, ...CAROUSEL_DATA, ...CAROUSEL_DATA];

          const clickButton = event => {
            if (
              event.target.className !== 'fa-solid fa-chevron-left arrow flipflopCursor'
            ) {
              if (currentPosition > 2) {
                setTransitionTime(0);
                setCurrentPosition(-2);
                setTimeout(() => {
                  setTransitionTime(0.5);
                  setCurrentPosition(-1);
                }, 0);
              } else {
                setCurrentPosition(currentPosition + 1);
              }
            } else {
              if (currentPosition < -2) {
                setTransitionTime(0);
                setCurrentPosition(2);
                setTimeout(() => {
                  setTransitionTime(0.5);
                  setCurrentPosition(1);
                }, 0);
              } else {
                setCurrentPosition(currentPosition - 1);
              }
            }
          };

          useInterval(() => {
            if (currentPosition > 2) {
              setTransitionTime(0);
              setCurrentPosition(-2);
              setTimeout(() => {
                setTransitionTime(() => 0.5);
                setCurrentPosition(() => -1);
              }, 100);
            } else {
              setCurrentPosition(prev => prev + 1);
            }
          }, 3000 + resetAuto);

          return (
            <div className="navTopContainer">
              <div className="carousel">
                <div className="leftCover">
                  <i
                    className="fa-solid fa-chevron-left arrow flipflopCursor"
                    onClick={event => {
                      clickButton(event);
                      setResetAuto(prev => prev * -1);
                    }}
                  />
                </div>
                <div className="slider">
                  <div
                    className="sliderInner"
                    style={{
                      transform: `translate(${(currentPosition * -100) / 15}%)`,
                      transition: `all ${transitionTime}s`,
                    }}
                  >
                    {currentData.map((data, index) => {
                      return (
                        <section className="list" key={index}>
                          {data.item}
                        </section>
                      );
                    })}
                  </div>
                </div>
                <div className="rightCover">
                  <i
                    className="fa-solid fa-chevron-right arrow flipflopCursor"
                    onClick={event => {
                      clickButton(event);
                      setResetAuto(prev => prev * -1);
                    }}
                  />
                </div>
              </div>
            </div>
          );
        }

        export default NavTopContainer;

        const CAROUSEL_DATA = [
          { item: '์ƒํŒŒ์šธ๋ฃจ์‹œ๋กœ ํŠน๊ธ‰๋ฐฐ์†ก' },
          { item: '๋ฐฐ์†ก ์˜ต์…˜ ๋ฐ ์„œ๋น„์Šค๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์šฐํŽธ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ํ™•์ธํ•ด ๋ณด์„ธ์š”.' },
          { item: '์ƒํŒŒ์šธ๋ฃจ์‹œ๋กœ ํŠน๊ธ‰๋ฐฐ์†ก' },
          { item: '๋ฐฐ์†ก ์˜ต์…˜ ๋ฐ ์„œ๋น„์Šค๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์šฐํŽธ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ํ™•์ธํ•ด ๋ณด์„ธ์š”.' },
          { item: '๋”ฐ๋ด‰ ๊ฐ€๋ฝ์‹   ํ™”์ดํŒ…!' },
        ];

์ด ์ฝ”๋“œ๋Š” ์ง„์งœ ๋‘๊ณ ๋‘๊ณ  100% ์ดํ•ดํ•  ๋•Œ ๊นŒ์ง€ ๊ณต๋ถ€ํ•ด์•ผํ•˜๋Š” ์ฝ”๋“œ! ์ตœ์ƒ๋‹จ Navbar์— ์‚ฌ์šฉ๋œ carousel์€ ์ž๋™ํ”Œ๋ ˆ์ด๊ฐ€ ๋˜๋ฉด์„œ ๋™์‹œ์— ํ™”์‚ดํ‘œ๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค ( + ๋ฌดํ•œ์Šฌ๋ผ์ด๋“œ๊นŒ์ง€!) ์ฒ˜์Œ carousel์„ ๊ฒจ์šฐ๊ฒจ์šฐ ๋งŒ๋“ค์—ˆ์ง€๋งŒ ํ™”์‚ดํ‘œ๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋ฒ„ํŠผ๊ธฐ๋Šฅ๊ณผ ์ž๋™ํ”Œ๋ ˆ์ด ๊ธฐ๋Šฅ์ด ๊ฒน์น˜๋ฉด์„œ ๋‘์นธ์ด ํ•œ๋ฒˆ์— ๋„˜์–ด๊ฐ€๋ฒ„๋ ธ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด custom์œผ๋กœ useInterval์„ ์‚ฌ์šฉํ•ด์„œ ๋„˜์–ด๊ฐ€๋Š” ์†๋„๊ฐ€ resetํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ๋ฒ„ํŠผ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ด๋„ ๋‘์žฅ์”ฉ ๋„˜์–ด๊ฐ€์ง€ ์•Š๊ฒŒ ๊ตฌํ˜„!

carousel.gif

  • ์ƒˆ๋กœ ์•Œ๊ฒŒ ๋œ ์ฝ”๋“œ : state ์ดˆ๊ธฐ ๊ฐ’ ์—†์ด re-rendering ์‹œ์ผœ์ฃผ๋Š” ์ฝ”๋“œ. ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ์œ ์šฉํ•  ๊ฒƒ ๊ฐ™๋‹ค.

    const setSelectColour = useState(0)[1];
    

    ๐Ÿ’ก ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ์น˜๊ณ  ๋Š๋‚€ ์ 

  • ๊ฐœ๋ฐœ๊ณต๋ถ€๋ฅผ ์‹œ์ž‘ํ•œ ์ดํ›„๋กœ ํ•ด๋ณด๋Š” ์ฒซ ํŒ€ ํ”„๋กœ์ ํŠธ!! ๊ธฐ๋Œ€๋ฐ˜ ๊ฑฑ์ •๋ฐ˜์œผ๋กœ ์ง„ํ–‰ํ–ˆ๋Š”๋ฐ ์ข‹์€ ํŒ€์›๋“ค๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์œผ์Œฐ์œผ์Œฐ ํ•˜๋ฉฐ ์›น์‚ฌ์ดํŠธ๋ฅผ ์™„์„ฑ ํ•ด ๋‚˜๊ฐ”๊ณ  ๊ทธ ๊ณผ์ •์†์—์„œ ์„œ๋กœ ์†Œํ†ตํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋” ์ƒ๊ฐํ•ด ๋ณด๋Š” ๊ณ„๊ธฐ๊ฐ€ ๋˜์—ˆ๋‹ค. ๋‚ด ๋จธ๋ฆฟ์†์— ์žˆ๋Š” ์ƒ๊ฐ์„ ์ƒ๋Œ€๋ฐฉ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๋ช…ํ•˜๋Š”๊ฑด ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ค์› ๊ณ  ๋” ๋งŽ์€ ์—ฐ์Šต์ด ํ•„์š” ํ•  ๊ฒƒ๊ฐ™๋‹ค.

  • ํŒ€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ํ”„๋กœ์ ํŠธ ์ „๋ฐ˜์ ์ธ ํ๋ฆ„์„ ์ฃผ๋„ํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์•„๋ฌด๋ฆฌ ํž˜๋“ค๊ณ  ์ง€์ณ๋„ ๊ธ์ •์ ์œผ๋กœ ํ•จ๊ป˜ ์ด๊ฒจ๋‚ด์ž๋ผ๋Š” ๋งˆ์ธ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์ž„ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.
  • ์ดˆ๊ธฐ์— ๊ณ„ํš์„ ์–ด๋–ป๊ฒŒ ์งœ์•ผํ•  ์ง€ ๋ชฐ๋ผ์„œ 1์ฃผ์ฐจ๋Š” A,B,C๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ  2์ฃผ์ฐจ๋Š” D,E,F๋ฅผ ๊ตฌํ˜„ํ•˜์ž๊ณ  ์ •ํ–ˆ๋Š”๋ฐ ์ด๊ฒƒ ๋ณด๋‹ค๋Š” 1์ฃผ์ฐจ๋ถ€ํ„ฐ A,B,C,D,E,F์˜ ๋ ˆ์ด์•„์›ƒ์„ ์™„์„ฑ์‹œํ‚ค๊ณ  ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ๊ดœ์ฐฎ์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ณธ๊ฒฉ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ๊ฐ™์ด ์–ด๋–ป๊ฒŒ ์ง„ํ–‰ํ•  ๊ฒƒ์ธ์ง€ ํฐ ์ง€๋„๋ฅผ ๊ทธ๋ ค๋ณด๋Š” ๊ฒƒ๋„ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š”๊ฒƒ์— ์žˆ์–ด ๊ต‰์žฅํ•œ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™๋‹ค.
  • ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋” ์ ๊ทน์ ์œผ๋กœ ์†Œํ†ตํ•˜๊ณ  ์‹œ๊ฐ„๊ด€๋ฆฌ์™€ ๊ธฐ๋ก์„ ์ž˜ ํ•ด์„œ ๋” ์ฒด๊ณ„ํ™”๋œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค.

๐Ÿ‘ฉโ€๐Ÿ’ป ์•ž์œผ๋กœ ์–ด๋–ค ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ  ์‹ถ์€์ง€์— ๋Œ€ํ•œ ์ƒ๊ฐ

  • ๋‚˜๋Š” ๊พธ์ค€ํžˆ ๊ธฐ๋กํ•˜๋Š”๊ฒƒ์— ์•ฝํ•œ ํŽธ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ณ„์† ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ธฐ๋ก์„ ๊พธ์ค€ํžˆ ์ž˜ ํ•ด์•ผํ•  ๊ฒƒ ๊ฐ™๋‹ค. Notion์ด๋‚˜ Trello๋ฅผ ์ž˜ ํ™œ์šฉํ•ด ๊ธฐ๋ก์„ ์ž˜ํ•˜๊ณ  ๋‚˜ ์Šค์Šค๋กœ๋ฅผ ๊ฐ๊ด€์ ์œผ๋กœ ๋ถ„์„ํ•˜์—ฌ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ ์‹ถ๋‹ค.

๐Ÿ“ฝ ์‹œ์—ฐ ์˜์ƒ

๐Ÿ“ KPT

Keep : ํŒ€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ์ข‹์•„์„œ ์žฌ๋ฏธ์žˆ๊ฒŒ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ํ–ˆ๋‹ค. ๋‹ค์Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ํ•  ๋•Œ๋„ ์ข‹์€ ๋ถ„์œ„๊ธฐ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•ด์•ผ๊ฒ ๋‹ค!

Problem : ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๊ฐœ๋ฐœ์„ ํ•  ๋• ์†Œํ†ต์ด ์ •๋ง ์ค‘์š”ํ•˜๋‹ค๊ณ  ๊ฐ•์กฐํ•˜๋Š”๋ฐ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ ์ •๋ง ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋Š๋‚„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋‚˜๋Š” ์ œํ’ˆ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ๋งก์•˜๋Š”๋ฐ ์ดˆ๊ธฐ ๋ฏธํŒ… ๋•Œ, ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š”์ง€ ํšŒ์˜๋ฅผ ํ–ˆ๊ณ  ๋ ˆ์ด์•„์›ƒ์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ BE์ชฝ์— ํ•œ๋ฒˆ ์ฒดํฌ ํ•ด ๋ดค๋”๋‹ˆ ์ƒˆ์ƒํ’ˆ, ์žฌ๊ณ  ๋“ฑ ๊ธฐ์กด ๊ฒฐ์ •๋œ ์‚ฌํ•ญ๊ณผ ๋น„๊ตํ•˜๋ฉด ์ƒˆ๋กœ ๋“ค์–ด๊ฐ€๋Š” ๋ฐ์ดํ„ฐ๋“ค์ด ์žˆ์—ˆ๋‹ค. ๋ ˆ์ด์•„์›ƒ์„ ๋‹ค ๋งŒ๋“ค๊ณ  ํ™•์ธ ํ–ˆ๋‹ค๋ฉด ํ˜น์€ ์ดˆ๊ธฐ ๋ฏธํŒ…๋งŒ ์ƒ๊ฐํ•˜๊ณ  ์•„์˜ˆ ํ™•์ธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด double job์„ ํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค. ์ƒˆ๋กœ์šด ์ผ์„ ์ง„ํ–‰ ํ•  ๋•Œ ๋งˆ๋‹ค ํ•ญ์ƒ ํ•œ๋ฒˆ ๋” ์ฒดํฌํ•˜๋Š” ์Šต๊ด€์„ ๊ธธ๋Ÿฌ์•ผ ๊ฒ ๋‹ค.

Try : ํ”„๋กœ์ ํŠธ๋Š” 2๋ฒˆ์˜ sprint๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ์—ˆ๊ณ  ๊ฐ sprint๋งˆ๋‹ค ์ •ํ•ด์ง„ ticket์ด ์žˆ์—ˆ๋Š”๋ฐ ์•„๋ฌด๋ž˜๋„ ์ฒ˜์Œํ•ด๋ณด๋Š” ํ”„๋กœ์ ํŠธ๋ผ ์–ด๋ ค์šด ์ ์ด ์žˆ์—ˆ๊ณ  ์ด ์‚ฌํ•ญ์„ ๋นจ๋ฆฌ ํŒ€์›๋“ค์—๊ฒŒ ๊ณต์œ ํ•˜์—ฌ ๊ธฐ๊ฐ„ ๋‚ด์— ๋งก์€ ์—ญํ• ์„ ์™„์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์˜€๋‹ค.

ย