<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>progressay</title>
        <link>https://velog.io/</link>
        <description>응애 나 애기 개발자</description>
        <lastBuildDate>Mon, 29 Jan 2024 06:54:13 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>progressay</title>
            <url>https://velog.velcdn.com/images/welloff_jj/profile/7c4d6301-e6ec-4b42-ba61-5ec880904c4d/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. progressay. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/welloff_jj" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SSAFY] 11기 입학식 그리고 웰컴킷 💕]]></title>
            <link>https://velog.io/@welloff_jj/SSAFY-11th-welcome</link>
            <guid>https://velog.io/@welloff_jj/SSAFY-11th-welcome</guid>
            <pubDate>Mon, 29 Jan 2024 06:54:13 GMT</pubDate>
            <description><![CDATA[<p>블로그 진짜진짜 오랜만인데 냅다 웰컴킷&gt;&lt;<del>~</del>!! 이렇게 글 올리는 게 부끄럽지만 ,,,,
아무튼 어쩌고 저쩌다 보니 드디어 졸업(예정)을 하고 싸피 11기가 되었다 😊</p>
<p>11기 일정은 다음과 같이 진행되었다.</p>
<p>11/06: 서류 지원 마감
11/07: 에세이 접수 시작
11/18: 에세이 접수 마감
11/19: 코딩테스트 (전공자)
12/11: 인터뷰 (날짜랑 시간 다 달랐는데 언제부터 언제까지였는지 기억 안남)
12/21: 결과 발표
~ 12/26: 입과 확정</p>
<p>졸업 후 백수 예정이었기에 삼보일배하는 마음으로 입과 확정을 했다 ,,
그리고 1/2부터 2주간의 스타트캠프 기간을 보낸 뒤, 1/16에 진행된 입학식 😊</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/39f4ddc8-e20e-45d2-8d20-569f1426c2ed/image.jpg" alt=""></p>
<p>각 층마다 라운지가 있는데 입학식이라 싸피의 상징인 파란색으로 예쁘게 꾸며주셨다 &gt;&lt;
입학식 프로그램 정말 많았는데 이것도 킹외비인가 싶어서 적기 두려움 ,,,</p>
<p>삼성전자 임원 분들이 오셔서 좋은 말씀도 해주시고, 선배들과의 큐앤에이 등 앞으로의 싸피 생활에 도움이 될 유익한 프로그램들도 진행되었다.
그리고 싸피는 제페토를 통해 멀티캠퍼스를 제공하고 있는데 (<a href="https://zep.us/play/8r9VmO">링크</a>)
여기서 반 친구들(?)과 사진도 찍었다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/b4d9ee8f-d283-419b-bddf-faef0e109b78/image.png" alt=""></p>
<p>멀티캠퍼스는 모두가 자유롭게 접속할 수 있는 공간이니 싸피에 관심 있는 분들이라면 접속해 보면 좋을 것 같다 ! 지금까지 싸피에서 진행된 프로젝트들도 볼 수 있음</p>
<p>이제 슬슬 웰컴킷 얘기를 해보려고 한다 ,, 두구두구,,,
근데 사실 웰컴킷은 입학식 시작하기 전에 받았긴 함 ,,,
아무튼 짜잔 !
🎉🎉🎉</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/a53d7e55-c966-4279-9af9-c1ce7cc3ba96/image.jpg" alt=""></p>
<p>뭔가 허전한 느낌이 드는 건 왜냐면 후드집업은 반에다 놓고 와서 구렇다
사진은 없지만 아무튼 구글에 싸피 후드집업 치면 나오는 검정색 후드집업을 받았다
ㅋㅎ</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/50d4de91-116d-4dae-9e37-7ea6562fa28c/image.jpg" alt=""></p>
<p>열면 이렇게 생김
노꾸(노트북꾸미기라는뜻)에 관심있다면 정말 조아할 기여운 싸피 스티커가 있고 ,
박스 안에는 뭔가 알차 보이는 아이템 세 개가 들어이씀
그래서 뭐가 들어있냐면</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/4127f9be-b626-415f-bcad-f7c332906a51/image.jpg" alt=""></p>
<p>일단 전체샷 이렇게 생김
그런데 벨로그는 사진을 inline-block으로 여러 개 못 올리나 ,,?
별거 아닌 사진인데 한 장씩 올라가니까 아쥬 부끄러움</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/ab5de994-42d0-41eb-a876-4b5181ec6f7f/image.jpg" alt=""></p>
<p>텀블러는 흰색 검은색 두 가지 종류가 있는 것 같았는데 굉장히 튼튼해서 마치 스탠리처럼 차가 전소되어도 절대 타지 않을 것 같은 멋진 검은색 텀블러를 받았당
깨알같이 싸피 로고가 박혀있어서 더 조음 !</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/9fca4b99-21cb-4d8c-8664-260b671def8c/image.jpg" alt=""></p>
<p>비대면 수업에(사실 여행 갈 때 더) 잘 사용할 수 있을 것 같은 짐벌 😉
저기도 싸피 로고가 살포시 박혀있는데 사진을 한 장밖에 안 찍음 ㅜㅜ</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/81234f5b-c520-4d8e-aec5-27a7bd991812/image.jpg" alt=""></p>
<p>하찮고 귀여운 싸피 에코백 ,,
싸피 갈 때 짐 들고 갈 게 별로 없어서 넘 잘 사용할 것 같음</p>
<p>이렇게 쓰고 보니 굉장히 허접한 후기가 되어서 매우 부끄럽지만 ,, 
아무튼 싸피 입학식과 웰컴킷 간단한 후기 끗 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[많은 변화가 있었던 2022년 회고하기 ✨]]></title>
            <link>https://velog.io/@welloff_jj/Looking-back-on-2022</link>
            <guid>https://velog.io/@welloff_jj/Looking-back-on-2022</guid>
            <pubDate>Mon, 02 Jan 2023 13:06:19 GMT</pubDate>
            <description><![CDATA[<p>역시 회고는 얼렁뚱땅 비둘기로 시작해야 제맛 😎
올해.. 아니 작년에 (왜 벌써 2022가 작년인지 알 수 없다 ,,, 가지마 내 24살) 여러 가지 일들이 많았기도 하고,
목표를 세우고 이뤄낸 것들은 좀 있지만 그 과정이 정말 얼레벌레였던 한 해였다.
상반기 회고를 쓰긴 했지만 작년을 전체적으로 뒤돌아보는 의미에서 1년 전체적으로 회고해 보는 시간을 가지려 한다 !</p>
</br>

<h2 id="🙂-전과-성공">🙂 전과 성공</h2>
<p>2021 회고 글 보니까 첫 대제목이 전과 실패였는데 이젠 이렇게 성공이라고 쓸 수 있게 되어서 매우매우 기쁘다 😃
42서울에서 악바리처럼 했던 공부들이 나한테 매우 큰 도움이 됐던 것 같다.
생각해 보면 이것저것 일 벌이는 거 진짜 잘 하긴 했어,, 자세한 내용은 <a href="https://velog.io/@welloff_jj/Looking-back-on-2021">2021 회고</a>에서 확인해주세용</p>
<p>솔직히 이번엔 전과 준비를 하면서 스스로 아 이건 되겠다 ..! 라고 생각하긴 했다 헤헷
42에서 했던 것들이랑 개인적으로 공부했던 것, 프로젝트 참여하면서 얻어갔던 것들을 전과 서류에 정리해서 냈는데 내가 봐도 오 이녀석 꽤 하는걸?싶은 느낌이었기 때문이다.
이쯤 되면 등산 전문가가 아닌가 싶다</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/7ea77d94-8b5e-415b-86c0-c3fc6a2f3fc5/image.png" alt=""></p>
<p><del>물론 우매함의 봉우리,,,</del>
암튼 성공했으니 된 거 아닐까 그만큼 노력하기도 했고 !</p>
<p>그렇게 전과 성공한 후엔 복학하고 나서의 미래에 대한 걱정+슬럼프로 당시에 참여하던 프로젝트에서 제대로 퍼포먼스를 보이지 못했고, 그러다가 복학해야 하는 때가 되어 프로젝트에서 하차하게 되었다.
이 부분은 아직도 아쉽고, 함께하던 팀원들에게 미안하다.
조금 더 프로젝트와 스스로의 일에 있어 책임감을 가져야겠다고 생각하는 계기가 된 사건이었다 💦</p>
</br>

<h2 id="🏫-1학기-학교생활">🏫 1학기 학교생활</h2>
<h3 id="💯-멋진-학점">💯 멋진 학점</h3>
<p>5전공과 1필수교양을 들었는데, 너무 중요한 전필들이라 정말정말 잘 듣고 정말정말 학점을 잘 받고 싶었다.
그리고 마침 전과하고 나서 친구도 한 명도 없었다,,
그래서 공부에 집중할 수 있었으니까 조은 걸까,,? 아무튼 시간 쪼개 가며 열심히 계획 세우고 5월 전까지는 진짜 열심히 살았던 것 같다.
왜 5월 전까지인지는 이 다음에 얘기할 건데 아무튼 그럼</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/6b07d75f-e6fb-4504-bca3-f76363edf9b8/image.png" alt=""></p>
<p>이렇게나 계획 열심히 세우며 살았던 나 (근데 이제 뒤로 갈수록 빈약해지는)
과제도 미리미리 하고 수업도 진짜 열심히 들었다 특히 컴구 컴네 ! 자신있게 말할 수 있음</p>
<p>그래서 결과적으로 1학기 전공평점도 전체평점도 목표 수치였던 4.0 이상을 받았다 ⭐️</p>
<p>기말고사 기간엔 많이 나태해지긴 했지만 그래도 나름 공부 열심히 했고, 내가 워낙 벼락치기 특화 인간이라 다행히 기말을 잘 봐서 운 좋게 받을 수 있었던 거니까 다음 학기에는 더 열심히 해야겠다 ! 라고 생각했었음
ㅋㅋ</p>
<h3 id="👯♀️-좋은-친구들">👯‍♀️ 좋은 친구들</h3>
<p>위에서 5월 전까지는 열심히 살았다고 했는데, 5월 이후로 내 계획이 얼레벌레가 되어버린 건에 대하여</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/6278a136-04a0-4944-8be5-4102029d0017/image.png" alt=""></p>
<p>저 이런 거 안 봐요 오해 노노</p>
<p>아무튼 소프트웨어학과 전과 이후로 친한 사람 아무도 없고 모든 수업을 독강하며 외로운 싸움을 하던 나는,
이대로는 안 되겠다 ! 친구를 만들어야겠다 ! 해서 본격적으로 친구 만들기 프로젝트를 시작했다.
애초부터 상반기 목표 중에 친구 사귀기가 있었기도 하고 🫠
그래서 이런저런 동아리에 많이 들어가서 행사를 기다리고 있었다.</p>
<p>그러다가 Do-it!이라는 웹개발 동아리에서 중간총회를 한다지 모야?
보통 중간총회는 잘 안 하는데 코로나가 슬슬 풀리던 와중이라 첫 오프라인 행사였다 !
두근두근하는 마음을 감추지 못한 채 당시엔 안경 걸이던 내가 무려 렌즈 끼고 풀메이크업 하고 신나서 감 ㅎ</p>
<p>18학번 주제에 2022년에 풀메하고 중총 가는 거 좀 주책이었던 듯
??: 가셔도 됩니다</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/0c8ff8ca-c10b-4483-b009-1495b26f8530/image.png" alt=""></p>
<p>그렇게 종총 갔는데 넘 재밌고 멋진 사람들 많이 만나버림 🙌🏻
좋은 사람들 많이 만났고, 그 중에 코살/코딩에서 살아남기/COSAL을 만난 건 올해 중 제일 잘한 일 같다
Shout out to 민태홍 송여경 이강민 정준호 (가나다순)
코살 사진 하나쯤 올리고 싶지만,, 혹시라도 초상권 침해로 고소당하면 안 그래도 최근에 자금난인데 탈탈 털릴 수 있어서 그냥 아무 짤 하나로 대체하겠다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/8bf6c545-1452-40f1-92d6-0e7d41134eb1/image.jpeg" alt=""></p>
<p>5월에 종총 후 친해진 사람들이랑 만나면서 신나는 학교생활 하다가, 축제 기점으로 코살이랑 너무 친해져서 냅다 열심히 놀아버림 휘휘
특히 6월 2-3일이 학교 축제였고 2주 뒤가 시험이었는데, 축제의 그 느낌 살려서 그대로 쭈욱 놀아버리는 바람에 기말고사 공부를 진짜 찐찐 벼락치기로 했다. 근데 어떻게 이게 되지 싶은 느낌</p>
<p>아무튼 넘 즐거운 상반기였다 ! 👯‍</p>
</br>

<h2 id="⛱️-여름방학">⛱️ 여름방학</h2>
<p>개인적으로 학기 말~여름방학 초 기간 내내 스스로 부족하다고 느낀 부분들 때문에 힘든 시기를 겪었다.
그래도 하고 있는 것들을 멈출 수 없기에 이겨내야겠다고 생각했고, 당장 학점 채우기가 중요한 이슈였기 때문에 방학 중에 계절학기를 들으며 뭔갈 하려고 노력했다.</p>
<p>여름 계절로는 실전코딩1이라는 과목을 들었다. Git, React.js, Node.js, SpringBoot, Maven, Jenkins 같은 실무에서 쓰이는 툴/프레임워크/라이브러리들을 다루는 과목이었다.
계절학기는 3주간 진행되는데 다룰 것들은 많다 보니 깊이 있는 공부는 못 했고 그냥 아 이런 게 있구나 ! 정도를 할 수 있었다. 그래도 나름 얻은 게 없진 않은 듯 !</p>
<p>그리고 계절학기 수강 중에 🎂생일🎂을 맞아 많은 사람들의 축하를 받기도 했다 🙂</p>
<h3 id="☄️-42서울-블랙홀">☄️ 42서울 블랙홀</h3>
<p>복학하고 나서도 카뎃(본과정 교육생)으로서의 자격을 유지하기 위해 틈틈이 과제를 해 왔다. <del>생명연장 프로젝트</del>
그렇지만 아무래도 42서울은 원래부터가 전일제/오프라인 교육과정이 모토이다 보니 학교 다니는 게 우선인 나에겐 결국 한계가 찾아왔고,,
설상가상으로 42서울 과제는 바깥 서클로 갈수록 볼륨이 커져서 시간 투자가 많이 필요한데, 나는 방학 때도 계절학기 수업을 듣느라 시간 투자를 많이 할 수 없었다 🥲
그래서 어쩔 수 없이 블랙홀에 빠지게 되었다.</p>
<p>작년 한 해를 42로 꽉 채웠던 나에게는 아쉬운 선택이었지만, 42를 통해 정말 많은 것을 얻었고 그것을 전과와 복학 후에도 너무 잘 써먹고 있어서 뒤돌아보니 지난 1년이 정말 뿌듯하다.
이젠 더 이상 카뎃은 아니지만 42에서 만난 좋은 사람들과는 여전히 교류하며 지내기도 하고 !</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/3b896bdb-c1b6-4d38-a727-1d9028175b8d/image.png" alt=""></p>
<p>42에서 얻은 것들을 바탕으로 앞으로 더 성장하는 hyeojung이 되어야겠다 :)</p>
<h3 id="👀-새로운-눈">👀 새로운 눈</h3>
<p>이건 진짜 너무 TMI라서 쓸까 말까 고민했는데 그냥 쓰기로 했다 ,,🙃
뭐냐면 바로바로 8월이 되자마자 라섹 함
라섹 후 눈을 모래로 긁는 듯한 통증과 멈추지 않는 눈물로 인해 꽤 고생했고, 여름이라 햇빛도 세서 꽤 오랫동안 선글라스를 쓰고 다녔다.
선글라스 진짜 눈 보호하려고 쓴 건데 주변 사람들이 컨셉충이냐고 뭐라고 함 흑흑</p>
<p>아무튼 그리고 나서 약 4개월 정도가 지난 지금까지는 만족도 100%
약간의 안구건조를 얻었지만 세상이 선명하게 보이는 건 너무 큰 행복이다 😚 지금은 너무 익숙해져서 전처럼 흐리게 보이면 세상이 무너진 줄 알 듯...</p>
<p>이외에는 자바 기본 문법을 익혀보겠다고 책을 좀 읽고 라섹 회복하고 그동안 못 만난 친구들을 만나며 쏘다니는 시간을 가졌다.</p>
</br>

<h2 id="🙌🏻-2학기-학교생활">🙌🏻 2학기 학교생활</h2>
<p>여름방학을 보내고, 나름대로 원대한 목표를 갖고 (하반기 계획 글 참고) 2학기를 시작했다.</p>
<h3 id="💦-그냥-학점">💦 그냥 학점</h3>
<p>2학기에 수강한 과목은 운영체제, 알고리즘, 기계학습, 인공지능, 데이터베이스, IT전문영어였다.
이번 학기에도 핵심적이고 잘 알아야 할 CS과목들이 많다 보니 쉽지 않을 것으로 예상되었고, 실제로 그랬다.
특히 꿀 빨려고 과제 덜 빡센 교수님 수업 신청했는데 강의에 집중을 도저히 못하겠어서 그냥 독학하고,, 어떤 교수님은 말 끝을 자꾸 흐리셔서 결국 중요한 내용은 제대로 못 들어서 독학하고,, 수업 시간에 안 다룬 내용 과제로 내주셔서 독학하고,, 원어 강의인데 교수님이 마스크 쓰고 계시느라 뭐라고 말씀하시는지 못 들어서 독학하고,, 그냥 독학하고,,
그래서 그런지 들어야 할 강의노트 분량은 자꾸 밀리는데 공부가 넘 하기 싫었다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/e9dbc581-3505-4b41-a364-2cd4e7468133/image.png" alt=""></p>
<p>그래서 그냥 안 함 🫠
이번 학기에는 과제도 너무 많아서 과제와 팀플에 치이다 보니까 막상 기본 개념 공부할 시간이 별로 없었다.
그래서 시험기간에만 맨날 벼락치기 공부했는데 다행히도 42서울에서 구르고 구르던 베이스가 있어서 그나마 이 정도 학점이 나온 것 같다 42 고마워 🙌🏻</p>
<h3 id="👩🏻💼-어학-성적-취득">👩🏻‍💼 어학 성적 취득</h3>
<p>졸업하려면 별 건 아닌 것 같은데 너무 귀찮고 근데 꼭 따야 하는 게 바로 어학성적이다.
사실 1학기에 따는 게 목표였는데 다른 일들이 너무 많아서 + 영어에 자신이 없어서 따지 못했고, 이번 학기엔 꼭 취득하겠다고 마음먹었었다.</p>
<p>토익은 솔직히 진짜 자신이 1도 없어서 토익스피킹과 오픽 중에 하나 선택하려고 했는데,
주변 사람들이 토익스피킹 엄청 쉽다고 해서 결국 토익스피킹 시험 등록하고 보러 다녀왔다.</p>
<p>따로 공부한 건 정말 없고 그냥 시험 전날 토익스피킹 30분 완성이라는 제목의 유튜브 영상을 본 게 다였는데, 너무 다행스럽고 감사하게도 IH가 나왔다 😎</p>
<h3 id="🎸-동아리-활동">🎸 동아리 활동</h3>
<p>인생에 예체능 한 스푼은 있어야 한다는 지론에 따라 어쿠스틱 기타 동아리<del>밴드 동아리</del>에서 활동했다.
코살 친구들이랑 같이 한 곡, 그냥 해보고 싶은 곡 한 곡 해서 총 두 곡 준비했는데 덕분에 바쁜 일주일에 두 시간은 힐링할 수 있었던 것 같다 😊</p>
<p>아 그리고 동아리 내에서 진행된 보컬레슨에도 참여했는데 이런저런 이론들도 많이 듣고 연습법도 알게 되어서 넘 유익했다 !
역시 인생엔 예체능 한 스푼은 필수 !</p>
<p>공연한 영상은 유튜브에 올라와 있는데 넘 부끄러우니 첨부 xx</p>
<p>코살 칭구들은 나 빼고 다들 천재라서 나는 그냥 앞에 서서 노래 불렀는데 애들이 다 해 주는 그런 공연이었다 !
<img src="https://velog.velcdn.com/images/welloff_jj/post/9e033561-7cea-4e73-b634-65b257542b2b/image.png" alt="">
<del>노래하는 감자 정도</del>
아무튼 이번 학기에도 성공적으로 예체능 한 스푼 완 👍</p>
<h3 id="💻-코딩트레이너-활동">💻 코딩트레이너 활동</h3>
<p>코딩트레이너는 선배가 후배의 코드를 첨삭해주며 프로그래밍적인 사고를 기르도록 도와주고, 교과 과목 외에도 진로 멘토링 등등을 진행하면서 말 그대로 선배 노릇을 하는 멘토링 활동이다.
이렇게 쓰니까 뭔가 멋진 일을 한 것 같지만 그건 아니고,, 멘토링 시간당 멘토링비 줘서 개꿀일 거 같아서 신청했는데 실제로 개꿀이었다 (?)</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/8d76e2a5-453e-4529-a60d-6cf511e9f43b/image.png" alt=""></p>
<p>열심히 산 척 하기 딱 조은 활동
그치만 개꿀이었던 활동
수민아 고맙다 ! 🙌</p>
<p>코딩트레이너로 활동하면서 엄청 많은 학생들에게 도움을 주진 못했지만, 적어도 내가 멘토링한 학생들에게 조금이라도 도움이 되었다면 정말 뿌듯할 것 같다 :)
다음 학기에도 할 수 있으면 꼭 하고 싶은 활동이다.</p>
<h3 id="링크인턴-합격">링크인턴 합격</h3>
<p>이건 추후에 인턴 후기로 돌아오겠음</p>
</br>

<h2 id="💬-정리">💬 정리</h2>
<p>전반적으로 휘몰아치는 1년을 보낸 것 같다,,
많이 놀기도 했지만 애초에 너무 나태할 수가 없는 환경이라서 결과적으로는 바쁘게 살았다. 그 결과로 성장한 부분도 많지만, 조금 더 잘 할 수 있지 않았을까? 하는 아쉬움이 남는 부분도 많다.</p>
<p>이제 더 달릴 일만 남았으니까 더 정신 바짝 차리고 열심히 해서 원하는 일 하며 살고 싶다 ! 정현지 화이팅 !
2023년 계획도 얼른 써야 하는데 ,,, 그건 또 언제 쓰지</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[상반기 회고 + 멋진 2022년 하반기를 위한 목표 🗓]]></title>
            <link>https://velog.io/@welloff_jj/2022-second-half-plan</link>
            <guid>https://velog.io/@welloff_jj/2022-second-half-plan</guid>
            <pubDate>Fri, 29 Jul 2022 05:46:31 GMT</pubDate>
            <description><![CDATA[<p>2022년 하반기가 된 지 벌써 한 달이나 지났다.
지금 쓰는 걸 하반기 계획이라고 불러도 되는 건지는 모르겠지만 아무튼 내가 하반기 계획이라고 하면 하반기 계획인 게 아닐까? 암튼 그럼,,</p>
<p>먼저 상반기 계획에 대해 스스로 평가해보고 그걸 토대로 하반기(방학 + 가을학기) 목표를 세워 봐야겠다 ,,!</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/a7ff5068-5449-4b19-b400-2d83d7dccd8f/image.png" alt=""></p>
<h1 id="✔️-상반기-회고">✔️ 상반기 회고</h1>
<ul>
<li>1학기 전공학점 4.0 이상
✅ 전공학점 4.31, 전체평점 4.34 !</li>
<li>친구 사귀기
✅ 생각보다 많이 사귀어서 그냥 마냥 행복한 사람 됨,,,</li>
<li>복학 전에 DYE 알파알파테스트 완료
❌ 이건 내가 넘 잘못한 부분인데 슬럼프 + 퍼포먼스 크게 하락 와서 생각보다 개발 속도가 늦어졌었다ㅜ</li>
<li>42서울 3서클 돌파하기
✅ 지금은 블랙홀에 풍덩 빠지긴 했지만,, 3서클은 돌파하고 죽었으니 목표 달성한 거 아닐까?</li>
<li>블로그 꾸준히 쓰기
❌ 말도 안되는 소리였다 !</li>
<li>집에서 공부하겠다는 말도 안 되는 소리 하지 않기
✅ 근데 밖에서 공부하겠단 말도 안 함</li>
<li>8시간 이상 자지 않기
✅ 노는 것도 하고 공부도 하려니까 수면빚이 잔뜩 생겨버렸다,, 그래서 지금 갚는 중,,</li>
<li>스크린타임 줄이기
❌ 스크린타임은 줄었지만 그만큼 맥북으로 카톡을 많이 하는 사람이 되어버렸다 !</li>
<li>수면 전후로 빠릿빠릿하게 움직이기
❌ 침대가 날 안 놔줘 🫥</li>
<li>개발 지식 쌓기
✅ 따로 프레임워크 공부를 하거나 한 건 아니지만 전반적으로 수업을 열심히 들으면서 CS 지식을 많이 쌓은 것 같다 ! 컴구 컴네 열심히 들은 보람이 있는 것 같음</li>
</ul>
<p>전반적으로 봤을 때 학교 공부 열심히 하면서 친구도 많이 만들고, 성적도 잘 챙긴 상반기였던 것 같다.
다음 학기에는 놀 때 놀고 공부할 때 공부하면서 (상반기에 안 그랬단 건 아님) 인생에 예체능 한 스푼 추가할 예정 😎</p>
<p>42 서울 카뎃이 더 이상 아니게 된 건 계획에 없긴 했지만,
8월부터 클러스터 출석 시간을 채워야 하는 것으로 지원금 지급 조건이 바뀌어서 어차피 더 이상 카뎃 신분을 유지할 수 없는 상황이라,,,
필연적인 일이었으니까 더 내 개인 공부에 집중하며 자기계발을 해 보려고 한다 !</p>
<br />

<h1 id="✔️-하반기-계획">✔️ 하반기 계획</h1>
<h2 id="✏️-2학기-전공학점-40-이상">✏️ 2학기 전공학점 4.0 이상</h2>
<p>다음 학기에 갑자기 6전공을 듣는 사람이 되어 버렸다. 왜냐하면 난 전과생이니까,,,
그치만 이번 학기에 했던 것 + 알파로 조금만 더 열심히 하고 좀더 체계적인 삶을 산다면 충분히 가능하지 않을까 ?!</p>
<p>비열하고 치졸하고 얍삽하게 살 각을 열심히 보면서 학점 잘 받아야겠다. 물론 얻어가는 게 많도록 공부 열심히 해야지,,!
다음 학기엔 운영체제 알고리즘 인공지능 기계학습 데이터베이스 IT전문영어 이렇게 들어야 하는데 일단 수강신청부터 성공해야겠다 휘휘</p>
<h2 id="🎶-인생에-예체능-한-스푼-끼얹기">🎶 인생에 예체능 한 스푼 끼얹기</h2>
<p>근데 진짜 딱 한 스푼만 !
공부 하다가 스트레스 받을 때 or 아닐 때 아무튼 노래 흥흥 부르면서 살아가고
공연도 몇 개 해야지,,, 무대 두 개 정도면 행복할 거 같다,,</p>
<h2 id="📱-스크린타임-줄이기">📱 스크린타임 줄이기</h2>
<p>어차피 맥북으로 카톡 할 거 다 하니까 스크린타임은 주 평균 4시간,, 으로 맞춰봐야겠다,,
제발,,</p>
<h2 id="🖥-학교-공부-이외에도-개발-공부하기">🖥 학교 공부 이외에도 개발 공부하기</h2>
<p>여러 가지 진로 경험해보고 취업 준비하는 게 목표니까 방학 땐 자바 공부하고 학기 중에 조금이나마 따로 스프링 공부 하기 !</p>
<p>여러모로 바쁜 한 학기가 될 것 같다 🫠</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/c03c0ecf-0437-4d53-b594-69c84a4a484b/image.png" alt=""></p>
<p>일단 이딴 계획을 세워 봤고 학습 후 내용을 벨로그에 정리해보려고 함,,</p>
<p>** ➡️ 계획 수정됨 **
방학 동안 &lt;혼자 공부하는 자바&gt; 책 다 읽긴 했는데 정리 하나도 안 했고 ㅋㅎ
이번 학기 내내 바쁠 것 같은데 학기 끝나고 인턴 하려면 프엔 공부를 더 하는 게 맞다는 생각 듦
구래서,,,,</p>
<h2 id="📚-리액트-스터디-하기">📚 리액트 스터디 하기</h2>
<p>머 암튼 하기</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/4930969d-50f2-4d33-90c1-8ac7759808cc/image.png" alt=""></p>
<p>하반기 목표도 대충 세워 봤는데 역시 하반기에도 할 일이 많다. 아 그리고 초과학기가 확정되어서 5-1까지 다니게 되었다,, 이게 맞냐,,
그래도 시간 정말 빠르고(왜 벌써 곧 8월..?) 특히 20대는 더 빠르게 지나가니까, 뭐 어쩌구저쩌구 아무튼 열심히 살아야겠다 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🐳 docker 🐳 도커 호구조사하기 (container, image)]]></title>
            <link>https://velog.io/@welloff_jj/introduce-docker</link>
            <guid>https://velog.io/@welloff_jj/introduce-docker</guid>
            <pubDate>Wed, 06 Jul 2022 10:42:40 GMT</pubDate>
            <description><![CDATA[<p>방학에 실전코딩1 과목을 들으며 제일 처음으로 마주친 도커,,,,
초면이라 좀 낯설어서 호구조사를 조금 해보며 친해지기로 했다.
구래서 도커가 왜 태어났는지, 그리고 머 하는 애인지 좀 대충 정리해보려고 한다 !</p>
<h2 id="docker의-탄생">docker의 탄생</h2>
<p>옛날에는 서버 관리라는 게 정말 어려운 문제였다고 한다.
왜냐하면 리눅스 배포판이 바뀌거나 업데이트되는 일이 상당히 많은데, 이에 맞추어 하나의 서버에 프로그램을 여러 개 설치하거나 동일한 포트를 사용하도록 설정하거나 프로그램에서 사용하는 라이브러리 버전이 다르거나 .. 등등 여러 가지 괴랄한 경우들이 있었기 때문이다.
그러면 이에 맞춰 서버 세팅을 다시 해야 하고... 아무튼 힘든 일이 많았다.
그런데 여기에 더해, 최근 DevOps의 등장으로 소프트웨어 개발 주기가 점점 더 짧아지면서 관리가 더 복잡해지게 되었다 🫥</p>
<p>기술이 점점 발전하여 새로운 툴은 계속 나오고 클라우드의 발전으로 세팅해야 할 서버가 미친 듯이 늘어나는 이런 상황에서 등장한 것이 바로 <strong>docker</strong>이다 🐳
도커의 등장 이후로 혁신이라 말할 수 있을 만큼 서버 관리 방식이 바뀌었다고 한다 !</p>
<h2 id="docker란">docker란?</h2>
<p>그렇다면 도커는 뭐하는 애일까?
도커란 <strong>&quot;컨테이너 기반의 오픈소스 가상화 플랫폼&quot;</strong> 이라고 한다.</p>
<p>여기에서 가장 중요한 개념이 바로 <strong>컨테이너</strong>인데, 컨테이너라고 하면 바로 아래 같은 물건을 떠올리기 쉽다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/31bda4e4-89ec-43d0-8f6c-076b948951a2/image.png" alt=""></p>
<p>컨테이너가 하는 일은 몰까? 바로 다양한 화물들을 규격화하여 쉽게 관리하고 옮길 수 있도록 하는 것이다.</p>
<p>서버에서의 컨테이너도 이와 비슷하다. 다양한 프로그램과 실행 환경을 컨테이너라는 단위로 추상화하여 프로그램의 관리 및 배포를 쉽게 할 수 있도록 도와준다.
어떤 프로그램도 컨테이너로 추상화할 수 있으며 어떤 환경에서도 실행할 수 있어 개쩌는 것이다,,,,</p>
<h3 id="container컨테이너란">Container컨테이너란?</h3>
<p>정리해서 말하자면 컨테이너란 격리된 공간에서 프로세스가 동작하는 기술이다.
가상화 기술의 한 종류이지만 기존의 방식과는 다르다.</p>
<p>뭐가 다르냐면 ! 기존 가상화 방식은 주로 OS 자체를 가상화하는 방식이었다고 한다.</p>
<p>기존의 VMware나 VirtualBox 같은 가상머신은 호스트OS 위에 게스트OS를 올리고 게스트OS 전체를 가상화하여 사용하는 방식이다.
이 방식은 OS 자체를 가상화하므로 여러 가지 OS를 사용할 수 있으며 사용법이 간단하다는 장점이 있다.
하지만 무겁고 매우 느려서 서버를 운영하는 데에는 적합하지 않다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/d80def15-1be8-4d9e-b5fa-05ff600bb2de/image.png" alt=""></p>
<p>이렇게 추가적인 게스트OS를 설치해 OS 자체를 가상화하는 방법은 성능 문제가 있어,
이를 개선하기 위해 나온 방식이 바로 <strong>프로세스를 격리</strong>하는 방식이다.</p>
<p>리눅스에서는 이 방식을 리눅스 컨테이너라고 한다. 프로세스를 격리하므로 빠르게 동작하며 CPU와 메모리는 프로세스가 필요한 만큼만 추가로 사용하여 성능적 손실도 거의 없다고 한다.</p>
<p>하나의 서버에 여러 컨테이너를 실행하면 OS 커널은 공유하면서 프로세스만을 격리하므로 서로 영향을 미치지 않고 독립적으로 실행된다.</p>
<blockquote>
<p>실행 중인 컨테이너에 접속해 명령어를 입력할 수도 있고, 패키지를 설치할 수 있으며 사용자 추가도 가능하고 여러 프로세스를 백그라운드에서 실행할 수 있다.
또한 CPU, 메모리 사용량을 제한할 수 있고 호스트 특정 포트와 연결하거나 호스트의 특정 디렉토리를 마치 내부 디렉토리인 것처럼 사용할 수도 있다.
거기다 심지어 컨테이너 생성 시간도 넘 짧아서 완전 최고최고,,,,</p>
</blockquote>
<p>도커는 이 컨테이너의 개념을 가져오고, 거기에 더해 이미지라는 개념을 사용해 프로그램 배포와 관리를 매우매우 쉽게 해준다고 한다 !</p>
<p>사실 쓰면서도 무슨 말인지 잘 모르겠는데 뭐 공부하다 보면 나아지겠거니 하는 중..</p>
<h3 id="image이미지란">image이미지란?</h3>
<p>도커의 핵심 개념 중 하나인 이미지에 대해 알아보자 !
잘 모르긴 한데 몬가 컨테이너랑 이미지 개념을 잘 이해하면 도커랑 좀 친해질 수 있을 거 같다는 생각이 든다.
그냥.. 그렇다고..
이번 짧대 재밌더라..</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/171b8798-e6d7-491c-9f4b-2fe1a0ae8655/image.png" alt=""></p>
<p>이미지는 <strong>컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는 것</strong>으로, 상태값을 가지지 않고 변하지 않는 Immutable한 것이다.
컨테이너는 이 이미지를 <code>실행한 상태</code>로 볼 수 있고, 추가되거나 변하는 값은 이미지가 아닌 컨테이너에 저장된다.
같은 이미지로 여러 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 삭제되더라도 이미지는 변하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/8699134c-c4a3-4c29-891e-ed280b0f5ae3/image.png" alt=""></p>
<p>예를 들면, MySQL 이미지는 debian을 기반으로 MySQL을 실행하기 위해 필요한 모든 파일과 실행 명령어, 포트 정보 등을 가지고 있다.
말 그대로 이미지는 컨테이너를 실행하기 위한 모<del>~</del>든 정보를 가지고 있으므로, 새로운 서버를 세팅할 때 그냥 미리 만들어져 있는 이미지를 다운받은 후 컨테이너를 생성만 하면 원하는 프로그램을 서버에서 돌릴 수 있는 것이다.
개쩌는듯</p>
<p>이런 도커 이미지는 Docker Hub에 등록하거나 Docker Registry 저장소를 직접 만들어 관리할 수 있다고 한다.
도커 허브에서 주로 다운받거나 배포하는 거 같은데 링크는 <a href="https://hub.docker.com/">요기</a>
참고로 로그인 안 해도 됨 그냥 검색하면 됨</p>
<h2 id="docker가-핫한-이유는-다음-글에">docker가 핫한 이유..는 다음 글에...</h2>
<p>이렇게 알아보고 나니 사실 도커는 이미 있던 기술들을 어케 잘 요리조리 해서 만들어놓은 짬뽕순두부인 것 같다.
근데 요즘 이렇게 도커가 핫걸인 이유가 뭘까?
는 좀 귀찮으니까 이다음 글에 쓰겠음 ,,,</p>
<p><a href="https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html">https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Philosophers] 식사하는 철학자 문제에 대한 고찰]]></title>
            <link>https://velog.io/@welloff_jj/Dining-Philosophers</link>
            <guid>https://velog.io/@welloff_jj/Dining-Philosophers</guid>
            <pubDate>Wed, 04 May 2022 07:51:45 GMT</pubDate>
            <description><![CDATA[<h1 id="식사하는-철학자-문제dining-philosophers-problem에서-고려해야-할-것">식사하는 철학자 문제(Dining Philosophers problem)에서 고려해야 할 것</h1>
<ol>
<li>Data Consistency</li>
<li>Deadlock</li>
<li>Starvation</li>
<li>Concurrency</li>
</ol>
<p>무슨 말인지 모르겠으니까 조금씩 이해해 보자 ,,,,</p>
<br />
<br />
<br />

<h1 id="process">Process</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/1d54f23b-0bff-4a77-8b93-70df558a0d17/image.png" alt=""></p>
<h2 id="사전적-의미">사전적 의미</h2>
<ul>
<li>컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램</li>
<li>메모리에 올라와 실행되고 있는 프로그램의 인스턴스(독립적 개체)</li>
<li>운영체제로부터 시스템 자원(CPU 시간/프로그램 운영에 필요한 메모리 공간/Code, Data, Stack, Heap의 구조로 되어 있는 독립된 메모리 영역)을 할당받는 작업의 단위</li>
</ul>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/c092fbb9-f514-4132-8400-518f90400141/image.png" alt=""></p>
<h2 id="특징">특징</h2>
<ul>
<li>프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap)을 가짐</li>
<li>각 프로세스가 별도의 메모리 공간에서 실행되므로, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없음<ul>
<li>다른 프로세스의 자원에 접근하고 싶다면 프로세스 간 통신을 사용해야 함(IPC, inter-process communication)</li>
</ul>
</li>
<li>기본적으로 프로세스당 최소 1개의 스레드를 가짐(메인 스레드)</li>
</ul>
<h2 id="context-switch">Context Switch</h2>
<p>운영체제에 의해 프로세스가 스케줄링되며, 운영체제 동작 환경이 단일 코어라고 가정했을 때 하나의 코어에는 하나의 작업만 존재할 수 있음 !
이때 모든 프로세스를 처리하려면 한 프로세스 처리 후 그 다음 프로세스를 처리하는 식으로 프로세스 간 전환이 요구. 이와 같이 처리되는 프로세스의 전환을 <strong>Context Switching</strong>이라고 함</p>
<p>그렇담 Context Switching은 언제 일어나는가?</p>
<ul>
<li>프로세스에게 할당된 Time Quantum(프로세스가 한 번에 처리될 수 있는 시간 총량)이 모두 소진된 경우</li>
<li>I/O 호출과 같은 Interrupt에 의해</li>
</ul>
<p>Context Switching이 발생하면 기존 수행 작업에서 새 작업으로 넘어가게 되므로, 새로운 작업을 불러올 뿐만 아니라 기존 수행 작업이 추후 이어서 수행되도록 저장할 수도 있어야 한다(Kernel의 Dispatcher에서 담당).</p>
<h2 id="kernel-mode와-user-mode-그리고-시스템-콜system-call">Kernel Mode와 User Mode, 그리고 시스템 콜(System Call)</h2>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/20db83e8-13b0-4dd0-a5f0-119bec05eecf/image.png" alt=""></p>
<p>기본적으로 프로세스에서 Instruction을 수행하기 위해 CPU를 사용할 때, 해당 프로세스가 Kernel Mode인지 User Mode인지에 따라 CPU 실행이 달라진다.</p>
<h3 id="kernel-mode">Kernel Mode</h3>
<p><strong>Kernel Mode</strong>의 프로세스는 Instruction에 대해 모든 권한을 가지고 있으며 대표적으로는 운영체제가 이에 해당된다. 이러한 프로세스는 I/O 장치 제어 등 시스템 상에서 처리해야 하는 모든 Instruction을 하드웨어에게 요구할 수 있다.</p>
<h3 id="user-mode">User Mode</h3>
<p><strong>User Mode</strong>의 프로세스는 대체로 사용자에 의해 구동된 어플리케이션으로, 범용적 권한만을 가진다.
따라서 User Mode의 프로세스가 Kernel Mode로만 가능한 작업을 수행하고 싶다면 대체로 운영체제에게 요청해 서비스를 제공받게 된다. 이를 실행 모드 전환(Execution Mode Switch)라고 한다.
➡️ 이때 운영체제가 해당 서비스들을 요청할 수 있도록 제공하는 도구가 바로 <strong>시스템 콜</strong>이다.</p>
<h3 id="시스템-콜">시스템 콜</h3>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/e6beeef1-e824-4646-b501-ac0e5e9d5b7b/image.png" alt=""></p>
<p>User Mode의 프로세스가 시스템 콜을 호출하면, 운영체제는 요청대로 작업을 수행한 뒤 User Mode로 복귀한다. 이와 같이 시스템 콜로 구현되어 있는 동작에는 <code>open</code>, <code>write</code>, <code>fork</code>, <code>pipe</code> 등이 있다.</p>
<br />
<br />
<br />

<h1 id="thread">Thread</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/9804522a-1557-4962-b48a-8bb4e931ad98/image.png" alt=""></p>
<h2 id="사전적-의미-1">사전적 의미</h2>
<ul>
<li>프로세스 내에서 실행되는 여러 흐름의 단위</li>
<li>프로세스의 특정한 수행 경로</li>
<li>프로세스가 할당받은 자원을 이용하는 실행의 단위</li>
</ul>
<h2 id="특징-1">특징</h2>
<ul>
<li>각 스레드는 프로세스 내에서 Stack만 따로 할당받고, Code, Data, Heap 영역은 공유</li>
<li>다시 말해 프로세스 내 주소 공간이나 자원을 스레드끼리 공유하며 실행됨!</li>
<li>각 스레드는 <strong>별도의 레지스터와 스택</strong>을 가지나 힙 메모리는 서로 읽고 쓸 수 있음 -&gt; 한 스레드가 프로세스 자원을 변경하면 다른 이웃 스레드(sibling thread)도 그 변경 결과를 즉시 볼 수 있음</li>
<li>프로세스는 운영체제에 의한 스케줄링의 단위라면, 스레드는 실제 처리 단위를 말함! 프로세스는 스레드 단위로 처리된닷</li>
</ul>
<h2 id="멀티-프로세스와-멀티-스레드의-차이점">멀티 프로세스와 멀티 스레드의 차이점</h2>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/4935162a-b869-4230-8227-b611dc860331/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/welloff_jj/post/2443ce5d-ffef-41b6-b6eb-02dc4a39091e/image.png" alt=""></p>
<h3 id="멀티-프로세싱">멀티 프로세싱</h3>
<ul>
<li>하나의 응용 프로그램을 여러 프로세스로 구성해 한 프로세스가 하나의 작업(Task)를 처리하도록 하는 것</li>
<li>장점: 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽고, 다른 영향이 확산되지 않음</li>
<li>단점<ol>
<li>Context Switching에서의 오버헤드: 캐쉬 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등 오버헤드가 발생하게 됨 (프로세스는 각각 독립된 메모리 영역을 할당받으므로 공유 메모리가 없어, Context Switching이 발생 시 캐쉬 데이터를 모두 리셋하고 다시 불러와야 함)</li>
<li>프로세스 사이 통신(IPC)이 어렵고 복잡함</li>
</ol>
</li>
</ul>
<h3 id="멀티-스레딩">멀티 스레딩</h3>
<ul>
<li>하나의 응용 프로그램을 여러 스레드로 구성해 한 스레드가 하나의 작업을 처리하게 하는 것</li>
<li>많은 운영체제(윈도우, 리눅스 등)가 멀티 프로세싱을 지원하긴 하나 멀티 스레딩을 기본으로 함</li>
<li>장점<ol>
<li>시스템 자원 소모 적음(자원의 효율적 사용): 프로세스를 생성해 자원을 할당하는 시스템 콜이 줄어들어 자원의 효율적 관리 및 사용 가능</li>
<li>시스템 처리량 증가(처리 비용 감소): 스레드 간 데이터를 주고받는 것이 간단해지므로 시스템 자원 소모가 줄어듦, 스레드 사이 작업량이 작아 Context Switching 빠름</li>
<li>스레드 간 통신 방법이 간단함</li>
</ol>
</li>
<li>단점<ul>
<li>디버깅이 까다로움 -&gt; 주의 깊은 설계 필요</li>
<li>단일 프로세스 시스템의 경우 효과 기대하기 어려움</li>
<li>다른 프로세스(프로세스 밖)에서 스레드 제어 불가</li>
<li>자원 공유 문제 발생</li>
<li>한 스레드에 문제 발생 시 전체 프로세스가 영향을 받음</li>
</ul>
</li>
</ul>
<h2 id="kernel-level과-user-level">Kernel-Level과 User-Level</h2>
<h3 id="kernel-level-thread">Kernel-Level Thread</h3>
<p>운영체제에서 스레딩을 지원하는 경우 이용할 수 있는 스레드로 Kernel 내에서 사용할 스레드를 의미한다.
주로 스케줄링 등을 관리하기 위해 사용된다.</p>
<h3 id="user-level-thread">User-Level Thread</h3>
<p>Kernel 위에서 지원되는 스레드로, 일반적으로 User-Level 라이브러리를 통해 구현된다.
사용자들이 대체적으로 사용하는 스레드가 바로 이것으로, 별도로 속성 설정을 하지 않은 채로 스레드를 생성하면 User-Level로 생성된다. (스레드 지원 주체에 따라 나뉨)
라이브러리를 통해 스레드가 생성되며 이렇게 생성된 스레드는 동일 메모리 영역을 공유한 채로 생성된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이전에 올렸던 글 중 js 기초 정리]]></title>
            <link>https://velog.io/@welloff_jj/js-summary</link>
            <guid>https://velog.io/@welloff_jj/js-summary</guid>
            <pubDate>Tue, 12 Apr 2022 07:40:39 GMT</pubDate>
            <description><![CDATA[<h2 id="html과-js의-만남">HTML과 JS의 만남</h2>
<h3 id="script-태그">script 태그</h3>
<ul>
<li>HTML의 태그 중 script 태그 안에 Javascript 코드를 쓸 수 있다.</li>
<li>HTML로 작성한 코드와 다른 점은, Javascript로 쓴 코드는 동적이라는 것이다.</li>
<li>웹페이지에 글씨를 출력할 땐 <code>document.write();</code>를 쓴다.<br>

</li>
</ul>
<h3 id="이벤트">이벤트</h3>
<p>: 웹브라우저 내에서 일어나는 사건</p>
<pre><code class="language-html">&lt;input type=&quot;button&quot; value=&quot;hi&quot; onclick=&quot;alert(&#39;hi&#39;)&quot;&gt;</code></pre>
<ul>
<li>onclick의 속성값으로는 반드시 JS 코드가 와야 한다.</li>
<li>onclick 속성의 속성값은 사용자가 클릭을 했을 때 JS의 문법에 따라 해석되어 웹브라우저에서 출력된다.<pre><code class="language-html">&lt;input type=&quot;text&quot; onchange=&quot;alert(&#39;changed&#39;)&quot;&gt;</code></pre>
</li>
<li>입력창에서 사용자가 키보드를 이용해 무언가 입력하여 내용이 바뀌는 사건이 일어났을 때</li>
<li>이외에도 다양한 이벤트들이 있다. ex) onkeydown, onmouseover 등<br>

</li>
</ul>
<h3 id="콘솔">콘솔</h3>
<ul>
<li>웹 브라우저에서 오른쪽 클릭 &gt; 검사 &gt; Console 
(Elements에서 Esc를 누르면 Console 창을 함께 볼 수 있다.)</li>
<li>파일을 만들지 않고 코드를 웹페이지에서 즉석으로 실행할 수 있다.</li>
<li>콘솔에서 실행시키는 JS는 웹페이지를 대상으로 실행된다.<pre><code class="language-javascript">alert(&#39;Hello, World!&#39;.length)</code></pre>
</li>
<li>위 코드를 콘솔에 입력해 실행시키면 바로 경고창이 뜨고 문자열의 길이를 알려준다.<br>

</li>
</ul>
<h2 id="js의-데이터-타입과-연산">JS의 데이터 타입과 연산</h2>
<ul>
<li>데이터 타입: Boolean, Null, Undefined, Number, String, Symbol</li>
<li>연산자와 메소드<ul>
<li>Number 타입 - 산술 연산자</li>
<li>String 타입<ul>
<li>.length 연산자<ul>
<li>str.toUpperCase(): 문자열의 모든 문자를 대문자로 변환</li>
<li>str.indexOf(&#39;hi&#39;): 문자열 내에서 hi 문자열이 앞에서부터 몇 번째 문자인지 알려줌</li>
<li>.trim(): 공백을 없애줌</li>
<li>&#39;1&#39;+&#39;1&#39;을 하면 결과는 &#39;11&#39;이 됨</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>변수와 대입 연산자<ul>
<li>var(variable)을 변수 이름 앞에 붙여주면 좋음! ex.<code>var x=1</code></li>
<li>대입 연산자 <code>=</code><br>

</li>
</ul>
</li>
</ul>
<h2 id="웹브라우저-제어">웹브라우저 제어</h2>
<pre><code class="language-javascript">document.querySelector(&quot;body&quot;)
documnet.querySelector(&quot;body&quot;).style.backgroundColor = &#39;black&#39;;

&lt;input type=&quot;button&quot; value=&quot;night&quot; onclick=
  &quot;documnet.querySelector(&#39;body&#39;).style.backgroundColor = &#39;black&#39;;&quot;&gt;</code></pre>
<ul>
<li><p>night 버튼을 클릭하면 <code>body</code> 태그를 선택하여 스타일 속성 중 backgroundColor을 black으로 변경하도록 한다.
<br><br><br></p>
</li>
<li><p>HTML: 프로그래밍 언어가 <strong>아님</strong>
HTML로 만든 웹페이지는 시간의 순서에 따라 실행되지 않고, 한 번 만들어지면 바뀌지 않기 때문</p>
</li>
<li><p>Javascript: 프로그래밍 언어가 <strong>맞음</strong>
사용자와 상호작용하고, 이를 위해서 시간에 따라 여러 기능이 실행되기 때문</p>
</li>
</ul>
<br>

<h2 id="조건문">조건문</h2>
<p>: 프로그램에서 조건에 따라 다른 기능들이 다른 순서에 따라서 실행되도록 만들어주는 것</p>
<ul>
<li>if-else 문
: if문의 괄호 안 불리언 데이터 타입이 true이면 if문의 중괄호 안의 코드가 실행되고, false이면 else문의 중괄호 안의 코드가 실행된다.<pre><code class="language-javascript">if(document.querySelector(&#39;#night_day&#39;).value === &#39;night&#39;) {
document.querySelector(&#39;body&#39;).style.backgroundColor = &#39;black&#39;;
document.querySelector(&#39;body&#39;).style.color = &#39;white&#39;;
document.querySelector(&#39;#night_day&#39;).value = &#39;day&#39;;
}
else {
document.querySelector(&#39;body&#39;).style.backgroundColor = &#39;white&#39;;
document.querySelector(&#39;body&#39;).style.color = &#39;black&#39;;
document.querySelector(&#39;#night_day&#39;).value = &#39;night&#39;;
}</code></pre>
<h3 id="비교-연산자">비교 연산자</h3>
</li>
<li>동등 비교 연산자 <code>===</code>: 이항 연산자로 좌우가 같으면 True, 다르면 False</li>
<li>비교 연산자 <code>&lt;</code>,<code>&gt;</code>: 이항 연산자로 좌우의 값을 비교하여 식이 옳으면 True, 옳지 않으면 False<ul>
<li>HTML에서는 태그를 나타낼 때 쓰이는 기호이므로 꺽쇠 기호 대신 <code>&amp;lt;</code>와 <code>&amp;rt;</code>를 쓴다.</li>
</ul>
</li>
</ul>
<p><br><br></p>
<h2 id="리팩토링-중복-제거">리팩토링 (중복 제거)</h2>
<p>: 비효율적인 코드를 효율적으로 만들어서 가독성을 높이고 유지보수가 쉽도록 만드는 것, 코드의 기능적인 측면에는 변화가 없어야 한다.</p>
<ul>
<li><strong><code>this</code></strong>: 자기 자신을 가리키기 위한 키워드</li>
<li>같은 부분이 계속 코드에서 반복된다면, 그 부분을 새로운 변수로 선언하여 코드의 길이를 줄일 수 있다.<pre><code class="language-javascript">var target = document.querySelector(&#39;body&#39;);
if(this.value === &#39;night&#39;) {
target.style.backgroundColor = &#39;black&#39;;
target.style.color = &#39;white&#39;;
this.value = &#39;day&#39;;
}
else {
target.style.backgroundColor = &#39;white&#39;;
target.style.color = &#39;black&#39;;
this.value = &#39;night&#39;;
}</code></pre>
<br><br></li>
</ul>
<h2 id="반복문과-배열">반복문과 배열</h2>
<h3 id="배열">배열</h3>
<ul>
<li><p>대괄호를 이용해 선언하고 각 요소들을 반점(,)으로 구분한다.</p>
</li>
<li><p>아래 제시된 기능들 외에도 다른 기능들이 많으니 찾아보자.</p>
<pre><code class="language-javascript">var fruits = [&quot;apple&quot;, &quot;banana&quot;];
document.write(fruits[0]); // 배열의 값에 접근
document.write(fruits.length); // 배열의 길이 출력, 이 경우에는 2
fruits.push(&quot;coconut&quot;); // 배열의 맨 뒤에 값 추가
fruits.splice(&quot;잘라낼 시작 위치&quot;, &quot;제거할 원소 개수(생략가능)&quot;, &quot;치환할 내용(생략가능)&quot;);</code></pre>
<h3 id="반복문">반복문</h3>
</li>
<li><p>while 문
: while문의 괄호 안이 true 값을 가지는 동안 중괄호 내의 코드가 반복적으로 실행됨, false인 경우 while문을 빠져나옴</p>
<pre><code class="language-javascript">var i = 0;
while (i &lt; fruits.length) {
document.write(&#39;&lt;li&gt;&#39;+fruits[i]+&#39;&lt;/li&gt;&#39;);
i = i + 1;
}</code></pre>
<h3 id="활용">활용</h3>
<p>querySelectorAll이 찾은 모든 a 태그를 배열 형태로 alist에 저장</p>
<pre><code class="language-javascript">var alist = document.querySelectorAll(&#39;a&#39;);</code></pre>
<p>문서 안의 모든 a 태그의 색깔을 powderblue로 변경</p>
<pre><code class="language-javascript">var i = 0;
while (i &lt; alist.length) {
alist[i].style.color = &#39;powderblue&#39;;
i = i + 1;
}</code></pre>
</li>
<li><p>) <code>console.log();</code>를 콘솔 창에서 쓰면 괄호 안이 가리키는 값이 콘솔 창에 출력된다.
<br><br><br></p>
</li>
<li><p>Ctrl + / 하면 드래그한 부분이 주석처리된다.</p>
<br>

</li>
</ul>
<h2 id="함수">함수</h2>
<ul>
<li>반복문을 쓸 수 없는 경우일 때 리팩토링에 유용하다.<pre><code class="language-javascript">document.write(&#39;2&#39;);
document.write(&#39;3&#39;);
document.write(&#39;4&#39;);
document.write(&#39;2&#39;);
document.write(&#39;3&#39;); // 이와 같은 코드를
</code></pre>
</li>
</ul>
<p>function two() {
  document.write(&#39;2&#39;);
  document.write(&#39;3&#39;);
} // 함수를 선언하여</p>
<p>document.write(&#39;1&#39;);
two();
document.write(&#39;4&#39;);
two(); // 더욱 간결하게 나타낼 수 있다.</p>
<pre><code>- **인자로 this 키워드를 전달받아 다양하게 활용 가능하다.**
- 함수를 정의하는 다양한 방법
```javascript
객체이름.func = function() {} // 객체의 메소드로 추가
var func = function() {}
function func = {}</code></pre><h3 id="매개변수parameter와-인자argument">매개변수(Parameter)와 인자(Argument)</h3>
<p>: 함수의 입력에 해당</p>
<pre><code class="language-javascript">function sum(left, right) {
  document.write(left + right);
} // left, right는 매개변수

sum(2,3); // 2, 3은 인자</code></pre>
<h3 id="리턴return">리턴(Return)</h3>
<p>: 함수의 출력에 해당</p>
<pre><code class="language-javascript">function sum(left, right) {
  return left + right;
} // 위의 함수가 값을 직접 출력하는 것이 아니라 값을 반환하도록 함</code></pre>
<p><br><br></p>
<h2 id="객체">객체</h2>
<ul>
<li>서로 연관된 함수와 변수가 아주 많아졌을 때 이를 정리하는 데 유용</li>
<li>객체에는 다양한 것들을 담을 수 있다. 함수도 담을 수 있음!<pre><code class="language-javascript">document.querySelector(&#39;body&#39;);</code></pre>
</li>
<li>위와 같은 코드에서 document는 객체, querySelector는 메소드이다.
즉 <strong>객체에 속해 있는 함수들은 메소드(Method)</strong>라고 부른다.<h3 id="객체의-읽기와-쓰기">객체의 읽기와 쓰기</h3>
</li>
<li>객체의 각 요소들은 이름과 값으로 이루어져 있으며, 객체를 만들 때는 배열과 달리 중괄호 <code>{}</code>를 사용한다.<pre><code class="language-javascript">var coworkers= {
&quot;programmer&quot;: &quot;egoing&quot;,
&quot;designer&quot;: &quot;leezche&quot;
};</code></pre>
</li>
<li>객체에 요소를 추가할 때는 다음과 같은 코드를 쓴다.<pre><code class="language-javascript">coworkers.bookkeeper = &quot;duru&quot;;
coworkers[&quot;bookkeeper&quot;] = &quot;duru&quot;;
// 객체 coworkers에 bookkeeper이라는 이름으로 duru라는 값을 넣는다.
// 이름에 공백이 포함된다면 두 번째 코드를 사용해야 한다.</code></pre>
</li>
<li>객체의 요소들을 꺼낼 때는 다음과 같은 코드를 쓴다.<pre><code class="language-javascript">document.write(coworkers.programmer)
document.write(coworkers[&quot;programmer&quot;])
// coworkers 객체 안에서 programmer이라는 이름을 가진 값을 가져와 출력
// 두 줄 모두 같은 결과 출력</code></pre>
<h3 id="순회">순회</h3>
: 객체의 모든 요소에 접근하기</li>
<li><strong>for in</strong>을 사용 - 이름과 값을 출력하는 법이 각각 다르니 주의</li>
<li>배열에서는 index를 쓰지만 객체에서는 key를 쓴다!
ex. <code>객체이름[&quot;key&quot;]</code>라고 쓰면 key라는 이름을 가진 값을 가리킨다.<pre><code class="language-javascript">for(var key in coworkers) {
document.write(key+&#39;&lt;br&gt;&#39;);
} //  coworkers에 있는 &quot;이름&quot;들을 하나씩 가져와 차례대로 key에 넣어 출력
</code></pre>
</li>
</ul>
<p>for(var key in coworkers) {
  document.write(coworkers[key]+&#39;<br>&#39;);
} // coworkers에 있는 이름들에 해당하는 &quot;값&quot;을 하나씩 출력</p>
<pre><code>### 프로퍼티(Property)와 메소드(Method)
- 프로퍼티(Property): 객체에 소속된 변수, 컴마로 구분
- 메소드(Method): 객체에 소속된 함수
&lt;br&gt;&lt;br&gt;&lt;br&gt;

## Javascript 활용
### 파일로 쪼개서 코드 정리하기
- 파일에 모든 페이지에서 공통적으로 사용되는 Javascript 코드를 넣고, 코드가 사용되는 태그의 src 속성에 파일 이름을 넣어서 바꾸면 된다.
```javascript
&lt;script src=&#39;colors.js&#39;&gt;&lt;/script&gt;</code></pre><ul>
<li><p>코드를 재사용할 수 있고, 동시에 코드를 수정할 수 있어서 유지보수가 편리</p>
</li>
<li><p>코드가 명확해지고 가독성이 좋아짐</p>
</li>
<li><p>파일을 한 번 다운로드해서 캐시에 저장해두면 다운로드 없이 사용할 수 있기 때문에 더 빨리 페이지를 표시 가능하므로 캐시 입장에서도 좋음</p>
<h3 id="라이브러리와-프레임워크">라이브러리와 프레임워크</h3>
</li>
<li><p><strong>라이브러리</strong>: 프로그램에 필요한 부품이 되는 소프트웨어가 정리되어 있는 것</p>
</li>
<li><p><strong>프레임워크</strong>: 만들고자 하는 프로그램의 종류에 따라서 공통적인 부분을 미리 만들어놓는 것</p>
</li>
<li><p>JQuery 라이브러리: 가장 유명한 Javascript 라이브러리 중 하나</p>
<ul>
<li>인터넷에서 jQuery를 다운로드해 사용 가능</li>
<li>CDN을 사용해 더 간편하게 사용 가능(jQuery 홈페이지에서 찾을 수 있음)<pre><code class="language-javascript">&lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js&quot;&gt;&lt;/script&gt;
// 구글 CDN, 이 한 줄을 head 태그에 추가하면 됨</code></pre>
</li>
</ul>
</li>
<li><p>라이브러리와 프레임워크를 이용하면 프로그래밍의 생산성을 크게 높일 수 있다. 문법 공부도 중요하지만 어떤 라이브러리가 있는지도 살펴볼 것
<br><br></p>
</li>
</ul>
<h2 id="웹-개발과-관련된-검색어">웹 개발과 관련된 검색어</h2>
<ul>
<li>document 객체: 태그를 삭제하거나 자식 태그를 추가하고 싶은 경우</li>
<li>그래도 찾을 수 없다면 DOM 객체</li>
<li>windows 객체: 웹브라우저 자체를 제어해야 하는 경우, 예를 들면 웹페이지의 주소를 알아낸다거나 창을 열거나 해야 하는 경우</li>
<li>ajax: 웹페이지를 새로고침하지 않고도 정보를 변경하고 싶다면</li>
<li>cookie: 웹페이지가 새로고침되어도 현재 상태를 유지하도록 만들고 싶으면</li>
<li>offline web application: 인터넷이 끊겨도 동작하는 웹페이지를 위해</li>
<li>webRTC: 화상 통신 웹 앱을 만들고 싶을 때</li>
<li>speech로 시작되는 API: 음성을 인식하거나 음성과 관련된 것을 처리하고 싶을 때</li>
<li>webGL: 3차원 그래픽을 이용하고 싶다면</li>
<li>webVR: 가상현실에 대해서 알아보고 싶다면
<br><br><br></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[이전에 올렸던 글 중 html/css 정리]]></title>
            <link>https://velog.io/@welloff_jj/html-css-summary</link>
            <guid>https://velog.io/@welloff_jj/html-css-summary</guid>
            <pubDate>Tue, 12 Apr 2022 07:38:14 GMT</pubDate>
            <description><![CDATA[<h2 id="html-태그와-친해지기">html 태그와 친해지기</h2>
<p>Heading 태그: <code>&lt;h1&gt;&lt;/h1&gt; 등, h6까지 있음</code><br>
Paragraph 태그: <code>&lt;p&gt;&lt;/p&gt;</code><br>
Linebreak 태그: <code>&lt;br&gt; (빈 태그)</code><br>
텍스트 표현 태그: <code>굵게 &lt;b&gt;</code> <code>기울여서 &lt;i&gt;</code> <code>밑줄 &lt;u&gt;</code> <code>중간선 &lt;s&gt;</code>
.　　　　　　　　주의! <code>&lt;i&gt;</code>태그는 html5 에서 의미를 가지는 태그로 변경됨<br>
Anchor 태그: <code>&lt;a href=&quot;&quot;&gt;&lt;/a&gt;</code>, target 속성도 자주 쓰임
의미가 없는 컨테이너 요소: <code>&lt;div&gt;&lt;/div&gt; (블록)</code>, <code>&lt;span&gt;&lt;/span&gt; (인라인)</code><br>
List 요소: <code>&lt;ul&gt;&lt;/ul&gt; (순서x, li를 자식 태그로 가짐)</code>, <code>&lt;ol&gt;&lt;/ol&gt; (순서o, li를 자식 태그로 가짐)</code>, <code>&lt;dl&gt;&lt;/dl&gt; (dd, dt의 쌍을 자식 태그로 가짐)</code><br>
Image 요소: <code>&lt;image src=&quot;&quot; alt=&quot;&quot;&gt;</code>, width, height 속성을 사용하기도 함<br>
Table 요소 </p>
<ul>
<li><code>&lt;table&gt;</code> : 표를 나타내는 태그 
<code>&lt;tr&gt;</code> : 행 
<code>&lt;th&gt;</code> : 제목 셀 
<code>&lt;td&gt;</code> : 셀</li>
<li>표를 구조적으로 파악하기 위해 사용하는 태그: 
<code>&lt;caption&gt;</code>: 표의 제목 
<code>&lt;thead&gt;</code>: 제목 행 그룹화 
<code>&lt;tbody&gt;</code>: 본문 행 그룹화 
<code>&lt;tfoot&gt;</code>: 바닥 행 그룹화</li>
<li><code>rowspan=&quot;&quot;</code> : 행 병합, <code>colspan=&quot;&quot;</code> : 열 병합<br></li>
</ul>
<p>Form 요소</p>
<ul>
<li>input type=&quot;&quot;에 들어갈 다양한 타입들
<code>text</code>: 단순 텍스트 입력, placeholder 속성 사용 가능
<code>password</code>: 공개할 수 없는 텍스트 입력, placeholder 속성 사용 가능
<code>radio</code>: 중복 선택 불가한 라디오 버튼-name 속성으로 그룹화, checked
<code>checkbox</code>: 중복 선택 가능한 박스-name 속성으로 그룹화, checked
<code>file</code>: 파일을 업로드할 때 사용
<code>submit</code>: form 값 전송
<code>reset</code>: form 값 초기화
<code>image</code>: submit과 동작은 동일, 이미지 삽입 가능-src, alt 속성 필요
<code>button</code>: 아무 기능이 없는 버튼</li>
<li>폼 요소로 쓰이는 태그들 중 input을 받는 태그들
<code>&lt;select&gt;</code>: 선택 목록 상자, 내부에서 <option>으로 항목 나타냄, selected
<code>&lt;textarea&gt;</code>: 텍스트 여러 줄 입력 시 사용, rows(줄 수), cols(글자 수) 속성과 함께 사용 가능
<code>&lt;button&gt;</code>: select, reset, button 총 세 가지 타입</li>
<li>form 요소들을 구조화하고 명시적으로 연결시키기 위해 사용하는 태그들
<code>&lt;fieldset&gt;</code>: 여러 개의 폼 요소를 그룹화하여 구조적으로 만듦, 보통 form의 성격에 따라 구분
<code>&lt;legend&gt;</code>: 폼 요소의 제목으로, 반드시 <code>&lt;fieldset&gt;</code>의 자식으로 최상단에 위치해야 함
<code>&lt;label&gt;</code>: form 요소의 이름과 form 요소를 명시적으로 연결, form 요소의 id 속성값과 <label>의 for 속성값을 같게 적어야 함</li>
<li><code>&lt;form&gt;</code> 태그:  form 요소들을 모두 감싸는 태그, 데이터를 묶어서 실제 서버로 전송<ul>
<li>action 속성: 데이터를 처리하기 위한 서버의 주소<ul>
<li>method 속성: 데이터를 전송하는 방식 - get(데이터 노출), post</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br><br></p>
<h2 id="콘텐츠-모델">콘텐츠 모델</h2>
<p><img src="https://images.velog.io/images/welloff_jj/post/ce385a3d-b0ed-466a-96c6-734cb2d8249d/image.png" alt=""></p>
<ul>
<li><p><strong>Metadata</strong>: 콘텐츠의 style(표현), script(동작)을 설정하거나 다른 문서와의 관계 등의 정보를 포함하는 요소</p>
<ul>
<li>base, link, meta, noscript, script, style, title 등 주로 <code>&lt;head&gt;</code> 태그 내에 들어가는 태그들</li>
</ul>
</li>
<li><p><strong>Flow</strong>: 문서에 사용되는 대부분의 요소. 태그 대부분이 여기에 해당되며 일부 <strong>Metadata</strong> 태그들은 미포함</p>
</li>
<li><p><strong>Sectioning</strong>: 헤딩과 푸터의 범위를 결정하는 요소, 아웃라인이 있음</p>
<ul>
<li>article, aside, nav, section 등 모두 html5에서 새로 생긴 태그</li>
</ul>
</li>
<li><p><strong>Heading</strong>: 섹션의 헤더를 정의하는 요소. <code>&lt;h1&gt;~&lt;h6&gt;</code></p>
</li>
<li><p><strong>Phrasing</strong>: 문서의 텍스트이며 문단 내부 레벨로 마크업하는 요소</p>
<ul>
<li>b, i, br, a 태그 등등</li>
</ul>
</li>
<li><p><strong>Embedded</strong>: 이미지, 비디오, 플래시 등 외부 컨텐츠를 문서 내에 표현하는 요소</p>
<ul>
<li>audio, canvas, embed, iframe, img, math, object, svg, video 등</li>
</ul>
</li>
<li><p><strong>Interactive</strong>: 사용자와 상호작용을 하는 요소. 대표적으로 폼 요소들이 해당됨</p>
<br>
### 시멘틱 마크업
: 브라우저가 잘 이해할 수 있도록 코딩하는 것을 말함. 
마크업을 할 때는 의미에 맞는 태그, 요소를 사용하는 것이고 문서를 표현할 때는 구조화를 잘 해주는 것</li>
<li><p><code>&lt;b&gt;굵은&lt;/b&gt;</code> <b><strong>굵은</strong></b> vs <code>&lt;strong&gt;중요한&lt;/strong&gt;</code> <strong>중요한</strong></p>
</li>
<li><p><code>&lt;i&gt;기울어진&lt;/i&gt;</code> <i>기울어진</i> vs <code>&lt;em&gt;강조하는&lt;/em&gt;</code> <em>강조하는</em></p>
</li>
<li><p><code>&lt;u&gt;밑줄친&lt;/u&gt;</code> <u>밑줄친</u> vs <code>&lt;ins&gt;새롭게 추가된&lt;/ins&gt;</code> <ins>새롭게 추가된</ins></p>
</li>
<li><p><code>&lt;s&gt;중간선이 있는&lt;/s&gt;</code> <s>중간선이 있는</s> vs <code>&lt;del&gt;삭제된&lt;/del&gt;</code> <del>삭제된</del></p>
</li>
<li><p>html5에서 새로 생긴 Semantic 요소들</p>
<ul>
<li><code>&lt;article&gt; &lt;aside&gt; &lt;figcaption&gt; &lt;figure&gt; &lt;footer&gt; &lt;header&gt; &lt;main&gt; &lt;mark&gt; &lt;nav&gt; &lt;section&gt; &lt;time&gt;</code> 등등...<br>

</li>
</ul>
</li>
</ul>
<h3 id="block--inline">Block &amp; Inline</h3>
<ul>
<li>블록 레벨 요소<ul>
<li>부모 요소의 가로 영역에 맞게 꽉 채워져 표현<ul>
<li>양옆으로 다른 요소가 배치되지 않게 박스를 생성</li>
<li>일반적인 모든 블록, 인라인 요소들을 포함할 수 있음</li>
</ul>
</li>
</ul>
</li>
<li>인라인 레벨 요소<ul>
<li>하나의 라인 안에서 자신의 내용만큼의 박스를 생성<ul>
<li>라인의 흐름을 끊지 않으며 요소 앞뒤로 줄바꿈이 생기지 않음</li>
<li>인라인 요소는 블록 레벨 요소를 포함할 수 없음</li>
<li><strong>예외</strong>로 <code>&lt;a&gt;</code>: 인라인 요소이지만 자식으로 블록 레벨 요소를 가질 수 있음
<br><br><br></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="css의-소개-문법과-적용">CSS의 소개, 문법과 적용</h2>
<h3 id="소개">소개</h3>
<ul>
<li>CSS: Cascading Style Sheets로, HTML(마크업 언어)를 꾸며주는 언어이다.</li>
<li>HTML이 웹페이지의 정보를 표현한다면 CSS는 HTML을 보기 좋게 디자인한다.
마크업 문서가 존재하지 않으면 CSS는 무용지물이나 마찬가지!<h3 id="문법">문법</h3>
<code>h1 { color: yellow; font-size: 2em; }</code></li>
<li><strong>선택자(selector)</strong>: 어떤 요소를 꾸밀지 선택하는 부분, 위 코드에서는 <code>h1</code></li>
<li><strong>선언(declaration)</strong>: <strong>속성(property)</strong>과 <strong>값(value)</strong>를 묶어 하나의 선언이라고 함. 위 코드에서는 <code>color: yellow;</code> 와 <code>font-size: 2em;</code>이며 마지막 선언에는 <code>;</code>를 붙이지 않아도 됨<ul>
<li>HTML에서의 속성과 CSS에서의 속성의 비교
: HTML-&gt;attribute, CSS-&gt;property</li>
</ul>
</li>
<li><strong>선언부(declaration block)</strong>: 중괄호까지를 모두 포함하는 부분으로, 위의 코드에서는 <code>{ color: yellow; font-size: 2em; }</code></li>
<li><strong>규칙(rule set)</strong>: 선택자까지를 모두 포함하는 부분으로 위 코드 전체를 가리킴</li>
<li><strong>주석(comment tags)</strong>: <code>/* 내용 */</code>, 여러 줄로도 작성 가능<h3 id="적용">적용</h3>
</li>
<li><strong>Inline 스타일 방식</strong>: 해당 요소에 직접 스타일 속성을 넣어 선언, 선택자 X</li>
</ul>
<pre><code class="language-html">    &lt;div style=&quot;...&quot;&gt;&lt;/div&gt;</code></pre>
<ul>
<li><strong>Internal 스타일 방식</strong>: <code>&lt;head&gt;</code>태그 내에 <code>&lt;style&gt;</code>태그를 선언, 선택자 O</li>
</ul>
<pre><code class="language-html">    &lt;style&gt;...&lt;/style&gt;</code></pre>
<ul>
<li><strong>External 스타일 방식</strong>: 규칙들을 별도의 CSS 파일(.css)에 저장, 원하는 CSS 파일을 <code>&lt;link&gt;</code> 태그를 통해(<code>&lt;head&gt;</code> 태그 내에 선언) 불러와 스타일을 적용</li>
</ul>
<pre><code class="language-html">    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/style.css&quot;&gt;</code></pre>
<ul>
<li>import 스타일 방식: 스타일 시트 내에서 다른 스타일 시트 파일을 불러오는 방식, 내부 상단이나 외부 스타일 시트 파일 상단에 선언. <u>성능상 좋지 않아 거의 쓰이지 않는다.</u></li>
</ul>
<pre><code class="language-css">    @import url(&quot;css/style.css&quot;);</code></pre>
<p><br><br></p>
<h2 id="선택자">선택자</h2>
<h3 id="그룹핑grouping">그룹핑(Grouping)</h3>
<ul>
<li>쉼표를 이용해 선택자들을 나열:    <code>h1, h2, h3 { color: yellow; }</code></li>
<li>전체 선택자: <code>* { color: yellow; }</code>, <u>사용을 가급적 지양</u><h3 id="class-선택자">class 선택자</h3>
: HTML의 글로벌 속성인 class 속성을 활용</li>
</ul>
<ol>
<li>HTML 코드의 class 속성에 원하는 값을 넣고,<pre><code class="language-html"> &lt;p class=&quot;foo bar&quot;&gt;...&lt;/p&gt; </code></pre>
</li>
<li>CSS 코드에서 class 속성값을 선택자로 사용. 온점<code>.</code> 기호를 사용한다.<pre><code class="language-css"> .foo { font-size: 30px; text-decoration: underline; }
     .bar { color: blue; }
     /* 이와 같이 하면 html 코드에 두 class의 스타일이 다 적용됨 */</code></pre>
</li>
</ol>
<h3 id="id-선택자">id 선택자</h3>
<p>: class 선택자와 유사한 방식으로 사용</p>
<ol>
<li><p>HTML 코드의 id 속성에 원하는 값을 넣고,</p>
<pre><code class="language-html"> &lt;p id=&quot;bar&quot;&gt;...&lt;/p&gt;</code></pre>
</li>
<li><p>CSS 코드에서 id 속성값을 선택자로 사용. 값 앞에 해시 기호(#)을 씀</p>
<pre><code class="language-css"> #bar { background-color: yellow; }</code></pre>
</li>
</ol>
<ul>
<li>class 속성과의 차이</li>
<li><em>id는 문서 내에서 유일해야 함.*</em> 즉 id 속성은 무분별하게 사용해서는 안된다!
구체성 면에서도 다른데 이건 다음 강의에서 더 자세히 나온다!</li>
</ul>
<h3 id="선택자의-조합">선택자의 조합</h3>
<pre><code class="language-css">/* 요소+class */ p.foo {...}
/* 다중 class */ .foo.bar {...}
/* id+class */ #foo.bar {...}</code></pre>
<h3 id="속성-선택자">속성 선택자</h3>
<ul>
<li>단순 속성으로 선택: 지정 속성이 있는 요소에 모두 적용<pre><code class="language-css">p[class] { color: silver; }
p[class][id] { font-size: 20px; }</code></pre>
</li>
<li>정확한 속성값으로 선택: 지정 속성의 속성값이 있는 요소에 적용<pre><code class="language-css">p[class=&quot;foo&quot;] { color: yellow; }
p[id=&quot;title&quot;] { text-decoration: underline; }</code></pre>
</li>
<li>부분 속성값으로 선택<ul>
<li><code>[class~=&quot;bar&quot;]</code> : class 속성의 값이 공백으로 구분한 &quot;bar&quot; 단어가 포함되는 요소 선택</li>
<li><code>[class^=&quot;bar&quot;]</code> : class 속성의 값이 &quot;bar&quot;로 시작하는 요소 선택</li>
<li><code>[class$=&quot;bar&quot;]</code> : class 속성의 값이 &quot;bar&quot;로 끝나는 요소 선택</li>
<li><code>[class*=&quot;bar&quot;]</code> : class 속성의 값이 &quot;bar&quot; 문자가 포함되는 요소 선택</li>
</ul>
</li>
</ul>
<h3 id="문서-구조의-이해">문서 구조의 이해</h3>
<ul>
<li>부모와 자식<ul>
<li>부모 요소: 그 요소를 포함하는 가장 가까운 상위 요소로, 그 요소의 부모 요소는 단 하나뿐이다.<ul>
<li>자식 요소: 부모 요소와 반대이며, 자식 요소는 여러 개일 수 있다.</li>
</ul>
</li>
</ul>
</li>
<li>조상과 자손<ul>
<li>조상 요소: 그 요소를 포함하는 모든 요소로, 부모 요소를 포함하여 여러 개일 수 있다.<ul>
<li>자손 요소: 그 요소가 포함하고 있는 모든 요소로 여러 개일 수 있다.</li>
</ul>
</li>
</ul>
</li>
<li>형제: 같은 부모를 가지고 있는 모든 요소</li>
</ul>
<h3 id="문서-구조-관련-선택자">문서 구조 관련 선택자</h3>
<ul>
<li><strong>자손 선택자</strong>: 선택자 사이를 공백으로만 구분한다. 다음 예시는 <code>&lt;div&gt;</code>의 자손 요소인 <code>&lt;span&gt;</code> 요소를 선택하는 선택자이다.<pre><code class="language-css">  div span { color: red; }</code></pre>
</li>
<li><strong>자식 선택자</strong>: 선택자 사이에 <code>&gt;</code> 기호를 넣는다. 다음 예시는 <code>&lt;div&gt;</code>의 자식 요소인 <code>&lt;h1&gt;</code> 요소를 선택하는 선택자이다.<pre><code class="language-css">  div &gt; h1 { color: red; }</code></pre>
</li>
<li><strong>인접 형제 선택자</strong>: 형제 관계이면서 _바로 뒤에 인접해 있는 요소_를 선택할 때 사용한다. 선택자 사이에 <code>+</code> 기호를 넣는다. 다음 예시는 <code>&lt;div&gt;</code>의 형제 요소인 <code>&lt;p&gt;</code> 요소를 선택하는 선택자이다.<pre><code class="language-css">  div + p { color: red; }</code></pre>
</li>
<li>문서 구조 관련 선택자의 조합: 아무리 복잡하게 나열되어 있더라도, 실제 선택되는 요소는 가장 우측에 있는 요소라는 점을 기억하자.<pre><code class="language-css">  body &gt; div table + ul { ... }</code></pre>
<br><br><h2 id="가상-선택자">가상 선택자</h2>
<h3 id="가상-클래스-선택자">가상 클래스 선택자</h3>
</li>
<li><strong>가상 클래스(pseudo class)</strong>: 미리 정의해놓은 상황에 적용되도록 약속된 보이지 않는 클래스로, HTML과 CSS는 정적인 언어이므로 필요하다.<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/Pseudo-classes">https://developer.mozilla.org/ko/docs/Web/CSS/Pseudo-classes</a> 에서 많은 가상 클래스들을 볼 수 있다!</li>
<li>아래 예시처럼 콜론<code>:</code> 기호를 사용하여 나타낸다.</li>
</ul>
</li>
</ul>
<pre><code class="language-css">      :pseudo-class { property: value; }</code></pre>
<ul>
<li><strong>문서 구조와 관련된 가상 클래스</strong><ul>
<li><code>:first-child</code>: 첫 번째 자식 요소 선택<ul>
<li><code>:last-child</code>: 마지막 자식 요소 선택<pre><code class="language-css">li:fitst-child {...} 
li:last-child {...}</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>앵커 요소와 관련된 가상 클래스</strong><ul>
<li><code>:link</code>: 하이퍼링크(앵커 내에 <code>href</code> 속성이 있는 것)이면서 아직 방문하지 않은 앵커<ul>
<li><code>:visited</code>: 이미 방문한 하이퍼링크<pre><code class="language-css">a:link { color: blue; }
a:visited { color: gray; }</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>사용자 동작과 관련된 가상 클래스</strong><ul>
<li><code>:focus</code>: 현재 입력 초점을 가진 요소에 적용<ul>
<li><code>:hover</code>: 마우스 커서가 있는 요소에 적용</li>
<li><code>:active</code>: 사용자 입력으로 활성화된 요소에 적용(순간적, ex 클릭)<pre><code class="language-css">a:focus { background-color: yellow; }
a:hover { font-weight: bold; }
a:active { color: red; }</code></pre>
<h3 id="가상-요소-선택자">가상 요소 선택자</h3>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>가상 요소</strong>: 미리 정해놓은 위치에 삽입되도록 약속된 보이지 않는 요소<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/Pseudo-elements">https://developer.mozilla.org/ko/docs/Web/CSS/Pseudo-elements</a>  에서 다양한 가상 요소를 볼 수 있다!</li>
<li>가상 클래스와 구분하기 위해 CSS3부터 더블 콜론<code>::</code> 기호를 사용한다.</li>
</ul>
</li>
<li>대표적인 가상 요소들<ul>
<li><code>::before</code>: 가장 앞에 요소를 삽입 (<code>content</code> 속성을 사용해 내용 입력) </li>
<li><code>::after</code> : 가장 뒤에 요소를 삽입 (<code>content</code> 속성을 사용해 내용 입력)</li>
<li><code>::first-line</code> : 요소의 첫 번째 줄에 있는 텍스트를 감싸는 요소 생성</li>
<li><code>::first-letter</code> : 블록 레벨 요소의 첫 번째 문자를 감싸는 요소 생성<pre><code class="language-css">p::before { content: &quot;###&quot; }
p::after { content: &quot;!!!&quot; }
p::first-line { ... }
p::first-letter { ... }</code></pre>
<br><br><h2 id="구체성">구체성</h2>
<h3 id="구체성의-정의와-계산">구체성의 정의와 계산</h3>
</li>
</ul>
</li>
<li>선택자로 지정한 스타일이 상반되는 경우, 어떤 규칙이 우선적으로 적용되어야 하는지에 대해 정해진 규칙, Cascading 규칙 중 하나</li>
<li>선택자를 얼마나 명시적으로 선언했는지를 수치화한 것으로, 값이 클수록 우선적으로 적용</li>
<li>다음과 같이 4개의 숫자 값으로 이루어진다.<pre><code>  0, 0, 0, 0</code></pre></li>
<li>값을 비교할 때에는 좌측 숫자부터 비교하며, _좌측 부분의 숫자가 클수록 높은 구체성_을 가진다. 구체성은 다음 규칙대로 계산된다.<pre><code>0, 1, 0, 0 : 선택자에 있는 모든 id 속성값
0, 0, 1, 0 : 선택자에 있는 모든 class 속성값, 기타 속성, 가상 클래스
0, 0, 0, 1 : 선택자에 있는 모든 요소, 가상 요소
조합자는 구체성에 영향을 주지 않는다. (&gt;, + 등)
전체 선택자는 0, 0, 0, 0을 가진다.</code></pre></li>
</ul>
<h3 id="인라인-스타일">인라인 스타일</h3>
<ul>
<li>인라인 스타일의 구체성 값은 <code>1, 0, 0, 0</code>으로 규칙들 중 가장 큰 구체성을 갖는다.</li>
</ul>
<h3 id="important-키워드">important 키워드</h3>
<ul>
<li>별도의 구체성 값은 가지지 않으나, 모든 구체성을 무시하고 우선권을 갖는다.</li>
<li>속성값 뒤 한 칸 공백 후 느낌표와 같이 사용한다.<pre><code class="language-css">  p#page { color: red !important; }</code></pre>
<br><br><h2 id="상속">상속</h2>
</li>
<li><strong>상속되는 속성</strong>: 보통 상식적으로 구분될 만한 속성들이며, 박스 모델 속성들은 상속되지 않는다(margin, padding, background, border 등)</li>
<li><strong>상속되는 속성의 구체성</strong>: <em>상속된 속성은 구체성을 가지지 않는다.</em> 그러므로 스타일이 충돌할 경우 상속된 속성 외의 속성이 우선적으로 적용된다.</li>
</ul>
<p><br><br></p>
<h2 id="캐스케이딩-cascading">캐스케이딩 Cascading</h2>
<ul>
<li>스타일 규칙들이 어떠한 기준으로 요소에 적용되는지를 정한 규칙</li>
<li>모든 스타일 규칙들은 Cascading의 단계적인 규칙에 따라 요소에 적용<h3 id="캐스케이딩-규칙">캐스케이딩 규칙</h3>
</li>
</ul>
<ol>
<li>중요도(!important)와 출처<ul>
<li>출처는 CSS 출처를 의미하며, 제작자와 사용자, 사용자 에이전트(user agent) 순서대로 규칙을 적용한다.</li>
</ul>
</li>
<li>구체성</li>
<li>선언 순서</li>
</ol>
<ul>
<li>-&gt; 중요도가 명시적으로 선언되었는지 -&gt; 출처에 따라 분류 </li>
<li><blockquote>
<p>구체성에 따라 분류 -&gt; 뒤에 선언된 규칙일수록 우선적으로 적용
<br><br><br></p>
</blockquote>
</li>
</ul>
<h2 id="다양한-속성의-정의와-구분">다양한 속성의 정의와 구분</h2>
<ul>
<li><p>실무자들이 많이 참고하는 사이트</p>
<ul>
<li><a href="https://www.w3.org/">https://www.w3.org/</a> - 깊이 있는 원리에 대해 알고 싶을 때<ul>
<li><a href="https://www.w3schools.com/">https://www.w3schools.com/</a> - 속성의 간단한 스펙과 예제 확인</li>
<li><a href="https://developer.mozilla.org/ko/">https://developer.mozilla.org/ko/</a> - 개발적 버그나 추가적 스펙 확인</li>
</ul>
</li>
</ul>
</li>
<li><p>위 사이트에 접속하면 CSS 속성명이 나열되어 있고 예제와 사용방법, 브라우저 지원, CSS 문법, 속성값들과 관련 페이지를 확인할 수 있다.</p>
</li>
<li><p>기본값: 모든 속성에는 기본값이 적용되어 있다.</p>
</li>
<li><p>상속: 부모의 값을 상속받을 수 있는지 여부</p>
</li>
<li><p>애니메이션이 가능한지의 여부</p>
</li>
<li><p>CSS 버전: 굉장히 중요. CSS 버전에 따라 브라우저 지원율이 달라지기 때문</p>
</li>
<li><p>syntax(문법): 속성은 다양한 값들로 선언 가능</p>
</li>
<li><p>) 대부분의 속성들은 initial, inherit로 선언할 수 있다.</p>
<ul>
<li>initial: 속성의 기본값으로 초기화; 인터넷 익스플로러에서는 지원하지 않음<ul>
<li>inherit: 부모 요소의 해당 속성값을 상속; 상속 가능한 속성만 가능
<br><br><h2 id="단위">단위</h2>
</li>
</ul>
</li>
</ul>
</li>
<li><p>단위도 다른 속성들과 마찬가지로 버전에 따라 지원 범위가 다르므로, 자신이 작업해야 하는 프로젝트의 지원율을 확인 후 사용할 것!</p>
<h3 id="절대-길이">절대 길이</h3>
</li>
<li><p><strong>px(pixels)</strong> ( 1px = 1/96th of 1 inch )</p>
<ul>
<li>절대 길이이므로 다른 요소의 영향을 받지 않아 화면에서 고정된 크기를 가지지만, 장치의 해상도에 따라 상대적</li>
<li>브라우저 호환성에 장점을 가지므로 디자인 환경이 많이 반영된 웹사이트의 경우 픽셀 사용을 권장</li>
</ul>
<ul>
<li><strong>pt(points)</strong> ( 1pt - 1/72 of 1 inch )<ul>
<li>인쇄물이나 워드프로세서 프로그램에서 사용되어 온 가장 작은 표준 인쇄 단위</li>
<li>인쇄용 문서를 위한 스타일을 정의할 때 유용</li>
<li>장치의 해상도에 따라 상대적 -&gt; 웹 개발 시 <em>권장되지는 않음</em></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="상대-길이">상대 길이</h3>
<ul>
<li><strong>%(Persentage)</strong>: 기본 글꼴 크기에 대해 상대적인 % 값</li>
<li><strong>em</strong>: font-size에 대해 상대적. 1em은 현재 크기, 2em은 200% 크기를 말함<ul>
<li>소수점 3자리까지 선언 가능</li>
</ul>
</li>
<li>이외 <strong>rem</strong>, <strong>vw</strong>와 같은 단위들도 상황에 따라 사용됨(개인 공부)
<br><br><h2 id="색상">색상</h2>
<h3 id="color-속성">Color 속성</h3>
: 폰트의 색상 값을 적용할 때 사용 <pre><code class="language-css">h1 { color: 색상 값; }</code></pre>
</li>
</ul>
<h3 id="색상-값-선언-방식">색상 값 선언 방식</h3>
<pre><code class="language-css">body { color:black }; /* By color names */
body { color:#000000 }; /* Hexademical colors */
body { color:#000 }; /* Hexademical -&gt; 두 자리씩 같으면 축약 가능 */
body { color:rgb(0, 0, 0) }; /* As RGB values(R,G,B / 0~255) */
body { color:rgba(0, 0, 0, 1) }; /* (alpha / 0~1, 투명도) */
/* 이외에도 HSL values, HWB values 등 다양한 방식으로 선언 가능 */</code></pre>
<p><br><br></p>
<h2 id="background">Background</h2>
<p>: 요소의 배경을 컬러나 이미지로 적용할 때 사용</p>
<ul>
<li><p>background-color</p>
<ul>
<li>기본값: transparent</li>
<li>background의 색상을 지정</li>
</ul>
</li>
<li><p>background-image</p>
<ul>
<li>기본값: none</li>
<li>배경으로 사용할 이미지의 경로를 지정<ul>
<li>절대 경로와 상대 경로 모두 사용 가능</li>
</ul>
</li>
</ul>
</li>
<li><p>background-repeat</p>
<ul>
<li>기본값: repeat</li>
<li>이미지의 반복 여부와 방향을 지정</li>
<li>속성값</li>
<li><strong>repeat</strong>: x, y 방향으로 모두 반복</li>
<li><strong>repeat-x</strong>: x 방향으로만 반복</li>
<li><strong>repeat-y</strong>: y 방향으로만 반복</li>
<li><strong>no-repeat</strong>: 반복하지 않음</li>
</ul>
</li>
<li><p>background-position</p>
<ul>
<li>기본값: 0% 0%, <em>left top 값이 기준</em></li>
<li>요소에서 배경 이미지의 위치를 지정</li>
<li>속성값</li>
<li><strong>%</strong>: 기준으로부터 % 만큼 떨어진 지점과 이미지의 % 지점이 일치하는 곳에 위치</li>
<li><strong>px</strong>: 기준으로부터 px 만큼 떨어진 지점과 이미지의 (0,0) 지점이 일치하는 곳에 위치</li>
<li><strong>키워드</strong>: top, left, right, bottom, center 키워드<ul>
<li>left, right는 x축 기준 / top, bottom은 y축 기준</li>
</ul>
</li>
</ul>
</li>
<li><p>background-attachment</p>
<ul>
<li>기본값: scroll</li>
<li>화면 스크롤에 따른 배경 이미지의 움직임 여부를 지정</li>
<li>브라우저 성능에 영향을 미치므로 자주 사용되지는 않음</li>
<li>속성값</li>
<li><strong>scroll</strong>: 배경 이미지가 요소 자체를 기준으로 고정되어 있으며 내용과 함께 스크롤되지 않음</li>
<li><strong>fixed</strong>: 배경 이미지가 뷰포트(사용자가 시각적으로 볼 수 있는 웹페이지 영역) 기준으로 고정되어 있으며 스크롤에 영향을 받지 않음</li>
<li><strong>local</strong>: 배경 이미지가 요소의 내용을 기준으로 고정되어 있으며 내용과 함께 스크롤됨</li>
</ul>
</li>
<li><p>background 축약형</p>
<pre><code class="language-css">background: color image repeat attachment position;</code></pre>
<p><br><br></p>
<h2 id="❗-box-model-❗">❗ Box Model ❗</h2>
<p><img src="https://images.velog.io/images/welloff_jj/post/c7ddec24-99ad-4892-ad03-fc3ef5ac2b08/image.png" alt=""></p>
<h3 id="content-영역">content 영역</h3>
<p>: 요소의 실제 내용을 포함하는 영역, 크기는 내용의 너비 밑 높이</p>
</li>
<li><p><strong>width</strong> </p>
<ul>
<li>기본값: 0</li>
<li>요소의 가로 크기를 지정</li>
<li>속성값<ul>
<li><strong>auto</strong>: 브라우저에 의해 자동으로 계산되어 적용<ul>
<li><strong>length</strong>: 고정값으로 지정 (ex. px, em, ...)</li>
<li><strong>percent</strong>: 부모 요소의 width 값에 상대적인 크기 지정</li>
</ul>
</li>
</ul>
</li>
<li>width 값을 auto가 아닌 다른 값으로 선언하여 사용하면, 그 크기는 box model에서 margin 영역을 제외한 모든 영역에 대해 영향을 받는다.</li>
<li><blockquote>
<p>_<u>전체 박스 width = content + (padding × 2) + (border × 2)</u>_</p>
</blockquote>
</li>
</ul>
</li>
<li><p><strong>height</strong></p>
<ul>
<li>기본값: 0</li>
<li>요소의 세로 크기를 지정</li>
<li>속성값<ul>
<li><strong>auto</strong>: 브라우저에 의해 자동으로 계산되어 적용
기본적으로 content 영역의 내용만큼의 높이를 가짐<ul>
<li><strong>length</strong>: 고정값으로 지정 (ex. px, em, ...)</li>
<li><strong>percent</strong>: 부모 요소의 height 값에 상대적인 크기 지정
<em>!! 단, 부모 요소가 명시적인 height 값을 가지고 있어야 적용됨 !!</em></li>
</ul>
</li>
</ul>
</li>
<li>height 값을 auto가 아닌 다른 값으로 선언하여 사용하면, 그 크기는 box model에서 margin 영역을 제외한 모든 영역에 대해 영향을 받는다.</li>
<li><blockquote>
<p>_<u>전체 박스 height = content + (padding × 2) + (border × 2)</u>_</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h3 id="border-영역">border 영역</h3>
<p>: content 영역을 감싸는 테두리 선
: 속성과 속성값에 대하여 정의하지 않으면 _<strong>모두 기본값이 적용</strong>_된다.</p>
<ul>
<li><strong>border-width</strong><ul>
<li>기본값: medium</li>
<li>선의 굵기를 지정</li>
<li>border-top-width, border-bottom-width, border-right-width, border-left-width를 이용해 상하좌우 선의 굵기를 다르게 설정 가능, 축약 가능</li>
<li>속성값
: <em>키워드</em>(thin, medium, thick), <em>단위</em>(px, em, ..)(%, 정수 단위 사용불가)<pre><code class="language-css">border-width: 6px 6px 3px 3px; /* top right bottom left */
  border-width: 6px 3px; /* top&amp;bottom right&amp;left */
  border-width: thin;</code></pre>
</li>
</ul>
</li>
<li><strong>border-style</strong><ul>
<li>기본값: none</li>
<li>선의 모양을 지정</li>
<li>border-top-style, border-bottom-style, border-right-style, border-left-style를 이용해 상하좌우 선의 모양을 다르게 설정 가능, 축약 가능</li>
<li>속성값<ul>
<li><strong>none</strong>: border를 표시하지 않음<ul>
<li><strong>solid</strong>: border를 실선으로 나타냄</li>
<li><strong>double</strong>: border를 이중 실선으로 나타냄</li>
<li><strong>dotted</strong>: border를 점선으로 나타냄</li>
<li>이 밖에도 다양한 속성들이 존재한다.<pre><code class="language-css">border-style: none solid double dotted; /* top right bottom left */
border-style: solid none; /* top&amp;bottom right&amp;left */
border-style: dotted;</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>border-color</strong><ul>
<li>기본값: correntColor</li>
<li>선의 색상을 지정</li>
<li>border-top-color, border-bottom-color, border-right-color, border-left-color를 이용해 상하좌우 선의 색상을 다르게 표현 가능, 축약 가능<pre><code class="language-css">border-color: red green yellow pink; /* top right bottom left */
  border-color: blue black; /* top&amp;bottom right&amp;left */
  border-color: orange;</code></pre>
</li>
</ul>
</li>
<li><strong>border 축약형</strong><ul>
<li>정의되지 않은 속성은 기본값이 적용된다.<pre><code class="language-css">border: width style color;</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="padding-영역">padding 영역</h3>
<p>: content 영역과 테두리 사이의 여백, content 영역에 배경, 색 또는 이미지가 있을 때 이 영역까지 영향을 미치므로 content의 연장으로 볼 수도 있음
: 정의하지 않은 속성과 속성값의 경우에 바로 기본값이 적용되지 않고, 상하 좌우의 값이 같을 경우 합쳐서 적용할 수 있다.</p>
<ul>
<li>기본값: 0</li>
</ul>
<p>+) <strong>CSS에서는 0 값에 대해 따로 단위를 적지 않는다!</strong></p>
<ul>
<li>속성값<ul>
<li><strong>length</strong>: 고정값으로 지정 (px, em, ..)</li>
<li><strong>percent</strong>: 요소의 width에 상대적으로 크기 지정</li>
<li>padding-top, padding-right, padding-bottom, padding-left를 이용해 content 영역을 기준으로 상하좌우 여백을 다르게 지정 가능, 축약 가능</li>
</ul>
</li>
<li><strong>padding 축약형</strong><pre><code class="language-css">padding: [-top] [-right] [-bottom] [-left];
         0      10px     20px      30px   /* 상, 우, 하, 좌 다름 */
         0      10px     20px             /* 좌, 우 같음 */
         0      10px                      /* 상, 하 같음 &amp; 좌, 우 같음 */
         0                                /* 상, 우, 하, 좌 모두 같음 */
         /* 시계 방향 순서대로 적용한다고 생각하기! */</code></pre>
</li>
</ul>
<h3 id="margin-영역">margin 영역</h3>
<p>: border 바깥쪽 영역,  주변 요소와의 여백을 지정할 수 있음</p>
<ul>
<li>기본값: 0, 상속되지 않는 속성</li>
<li>속성값<ul>
<li><strong>length</strong>: 고정값으로 지정 (px, em, ..)</li>
<li><strong>percent</strong>: 요소의 width에 상대적으로 크기 지정</li>
<li><strong>auto</strong>: 브라우저에 의해 자동으로 계산된 값이 적용<ul>
<li>대부분의 경우 기본값(0) 또는 요소의 해당 측면에서 사용 가능한 공간과 같은 값을 가짐<ul>
<li>이를 이용해 <strong><em>수평 중앙 정렬 가능</em></strong>! 
단 요소의<strong>_ width 값이 반드시 필요_</strong>!! - width가 auto이면 기준이 없기 때문
<code>margin-left: auto; margin-right:auto;</code></li>
</ul>
</li>
</ul>
</li>
<li>padding 영역에서 했던 것처럼 margin-top, -bottom, -right, -left를 이용해 border 영역을 기준으로 상하좌우 여백을 다르게 지정 가능, 축약 가능</li>
<li>padding과 다르게 <em>음수 값을 지정할 수 있음</em></li>
</ul>
</li>
<li><strong>margin 축약형</strong> - padding과 동일한 형태<pre><code class="language-css">margin: [-top] [-right] [-bottom] [-left];
         0      10px     20px      30px   /* 상, 우, 하, 좌 다름 */
         0      10px     20px             /* 좌, 우 같음 */
         0      10px                      /* 상, 하 같음 &amp; 좌, 우 같음 */
         0                                /* 상, 우, 하, 좌 모두 같음 */
         /* 시계 방향 순서대로 적용한다고 생각하기! */</code></pre>
<h4 id="margin-collapse-마진-병합"><strong>margin collapse 마진 병합</strong></h4>
: 인접한 두 개 이상의 수직 방향 박스의 마진이 하나로 합쳐지는 것<ul>
<li>다음 세 가지 경우에 발생</li>
</ul>
</li>
</ul>
<ol>
<li><em><strong>두 요소가 상하로 인접한 경우</strong></em> - 위 요소 하단 마진 + 아래 요소 상단 마진</li>
<li><em><strong>부모 요소와 첫 번째 자식 요소 또는 마지막 자식 요소</strong></em><ul>
<li>부모 요소의 상단 마진 + 첫 번째 자식 요소의 상단 마진</li>
<li>부모 요소의 하단 마진 + 마지막 자식 요소의 하단 마진</li>
</ul>
</li>
<li><em><strong>내용이 없는 빈 요소의 경우</strong></em> - 해당 요소 상단 마진 + 위 요소 하단 마진</li>
</ol>
<ul>
<li>마진 병합은 수직 방향에 대해서만 이루어지며 좌우에서는 일어나지 않는다.</li>
<li>마진 병합은 마진이 맞닿아야만 발생하므로 2, 3번째 경우에서는 padding 및 border가 없어야 한다.</li>
<li>절대 위치나 상대 위치가 주어진 요소에서는 발생하지 않는다.</li>
</ul>
<h3 id="margin과-padding의-비교">margin과 padding의 비교</h3>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">+</th>
<th align="center">-</th>
<th align="center">auto</th>
<th align="center">단위</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>margin</strong></td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">px, %, ...</td>
</tr>
<tr>
<td align="center"><strong>padding</strong></td>
<td align="center">O</td>
<td align="center">X</td>
<td align="center">X</td>
<td align="center">px, %, ...</td>
</tr>
</tbody></table>
<h4 id="margin과-padding에서--값의-사용과-기준점">margin과 padding에서 % 값의 사용과 기준점</h4>
<ul>
<li>%는 요소의 크기를 기준으로 상대적 크기를 결정한다.</li>
<li>일반적으로 생각했을 때 상하는 height, 좌우는 width 값에 의해 결정될 것 같지만 사실은 방향에 관계없이 <strong>상하좌우 모두 width 값에 의해 결정</strong>된다.
<br><br><br></li>
</ul>
<h2 id="typography">Typography</h2>
<p><img src="https://images.velog.io/images/welloff_jj/post/398a8569-97cb-44c8-ad04-fcbaf1a711e9/image.png" alt=""></p>
<ul>
<li>Baseline: 영문 소문자 x를 기준으로 밑의 기준점 라인</li>
<li>ex: 해당 폰트의 소문자 x의 높이</li>
<li>Descender: 소문자에서 baseline 아래로 쳐지는 영역</li>
<li>Ascender: 소문자 x의 상단 라인 위로 넘어가는 영역</li>
<li>em: 폰트의 전체 높이
<br><br></li>
</ul>
<h2 id="font-family">font-family</h2>
<ul>
<li><code>family-name</code>과 <code>generic-family</code>로 구성</li>
<li><strong><code>generic-family</code></strong> - 중요!
: <code>family-name</code>으로 지정한 폰트가 사용자의 컴퓨터에 없을 때 다른 적절한 폰트를 선택할 수 있도록 몇 가지 유형의 폰트를 같이 선언해주는 것<ul>
<li><code>family-name</code>를 선언할 때 꼭 세트로 함께 선언해주어야 한다! (특히 자식 요소에서 재선언했을 때 빼먹으면 X<pre><code class="language-css">/* 맨 마지막 선언된 폰트는 generic-family */
/* family-name은 선언 순서로 우선순위가 결정 */
font-family: Helvetica, Dotum, &#39;돋움&#39;, sans-serif;</code></pre>
</li>
</ul>
</li>
<li>다양한 <code>generic-family</code> 예시<ul>
<li>serif: 명조(삐침 있는)</li>
<li>sans-serif: 돋움(삐침 없는)</li>
<li>monospace: 모든 글자가 같은 width 값을 갖는 폰트</li>
<li>cursive, fantasy: 꾸밈이 있는 폰트</li>
</ul>
</li>
<li>상속되는 속성이다.
<br><br></li>
</ul>
<h2 id="line-height">line-height</h2>
<p>: 줄간격을 의미하며 행간을 제어할 때 사용
<img src="https://images.velog.io/images/welloff_jj/post/5d27f955-0d57-48fe-a5ad-8133613b622a/image.png" alt=""></p>
<ul>
<li>기본값: normal</li>
<li>줄 사이 간격이 아니라, typography에서 배웠던 em + 상하단 여백을 의미</li>
<li>속성값<ul>
<li><strong>normal</strong>: 기본값으로 주로 브라우저 기본 속성을 따르며, 대부분 1.2 정도로 설정되어 있음(폰트 기준 1.2배라는 뜻)</li>
<li><strong>number</strong>: font-size를 기준으로 설정한 숫자만큼 배율로 적용</li>
<li><strong>length</strong>: px, em 등 고정 수치 적용</li>
<li><strong>%</strong>: font-size를 기준으로 설정한 퍼센트만큼의 배율을 적용
<br><br></li>
</ul>
</li>
</ul>
<h2 id="font-size">font-size</h2>
<p>: 글꼴의 크기를 지정하는 속성</p>
<ul>
<li>기본값: medium</li>
<li>속성값<ul>
<li><strong>keyword</strong><ul>
<li><em>absolute size</em> : 기본값 medium에 대한 상대 크기로, 브라우저마다 사이즈가 다르게 정의되어 있음(xx-small ~ xx-large)</li>
<li><em>relative size</em> : 부모 요소의 font-size에 대한 상대 크기로, smaller는 0.8배, larger는 1.2배이다.</li>
</ul>
</li>
<li><strong>length</strong>: px, em 등 고정 수치로 지정</li>
<li><strong>%</strong>: 부모 요소의 font-size를 기준으로 배율 적용</li>
<li>viewport units: vw(뷰포트 width의 1%), vh(뷰포트 height의 1%) 단위로 뷰포트 기준
<br><br></li>
</ul>
</li>
</ul>
<h2 id="font-weight">font-weight</h2>
<p>: 글꼴의 굵기를 지정하는 속성</p>
<ul>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong>: 기본값(400)</li>
<li><strong>bold</strong>: 굵게(700)</li>
<li><strong>bolder</strong>: 부모 요소보다 굵게(실무에서 자주 사용 X)</li>
<li><strong>lighter</strong>: 부모 요소보다 얇게(실무에서 자주 사용 X)</li>
<li><strong>number</strong>: 100~900까지 100 단위로 값을 지정해 사용</li>
</ul>
</li>
<li>수치를 이용한 font-weight는 폰트 자체에서 지원을 해야 표현 가능</li>
<li>normal과 bold만 지원하는 폰트일 경우에는 100<del>500까지는 normal로, 600</del>900까지는 bold로 표현
<br><br></li>
</ul>
<h2 id="font-style">font-style</h2>
<p>: 글꼴의 스타일을 지정하는 속성</p>
<ul>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong>: font-family 내에 분류된 기본 값</li>
<li><strong>italic</strong>: italic 스타일</li>
<li><strong>oblique</strong>: oblique 스타일 
<code>font-weight oblique &lt;각도&gt;;</code>를 이용해 각도를 추가로 지정 가능 - 유효한 값은 -90 ~ 90도이며, 따로 각도를 지정하지 않으면 14도 
(브라우저 지원율에 따라 사용 불가능할 수도 있음)
<br><br></li>
</ul>
</li>
</ul>
<h2 id="font-variant">font-variant</h2>
<p>: 글꼴의 형태를 변환하는 속성으로, 소문자를 작은 대문자로 변환 가능</p>
<ul>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong>: 기본 값</li>
<li><strong>small-caps</strong>: 소문자를 작은 대문자로 변환
<br><br></li>
</ul>
</li>
</ul>
<h2 id="font">font</h2>
<p>: font와 관련된 다양한 값을 한 번에 선언 가능한 축약형 속성</p>
<ul>
<li>기본값: 각 속성들의 기본값<pre><code class="language-css">font: font-style font-variant font-weight font-size/line-height font-family | initial | inherit;</code></pre>
</li>
<li>각 속성의 선언 순서를 지켜야 함</li>
<li>font-size와 font-family는 반드시 선언해주어야 함 (이외 속성 중 빠진 속성이 있을 경우 기본값이 적용됨)</li>
<li>이러한 제약으로 인해 실무에서는 자주 사용되지 않음
<br><br></li>
</ul>
<h2 id="webfont-font-face">webfont (@font-face)</h2>
<h3 id="실무에서-폰트-관련해-주로-사용하는-명칭들">실무에서 폰트 관련해 주로 사용하는 명칭들</h3>
<ul>
<li>시스템 폰트:  font-family로 선언한 글꼴이 사용자 시스템에 기본으로 설치되어 있어 사용할 수 있는 경우</li>
<li>이미지 폰트: 특정 글꼴을 사용하는 것 X, 글꼴 대신 이미지를 이용해서 표현하는 경우(이미지 폰트가 아니라 이미지)</li>
<li>웹 폰트: 서버에 저장해(클라이언트 단에서, 포털에서) 제공하거나, 웹 경로를 통해 사용하는 폰트<h3 id="font-face">@font-face</h3>
: 웹에 있는 글꼴을 사용자의 로컬 환경(컴퓨터)으로 다운로드하여 적용하는 속성</li>
<li>기본값: 없음</li>
<li>속성값<ul>
<li><strong>font-family(필수)</strong></li>
<li><strong>src(필수)</strong>: 다운로드받을 글꼴의 경로</li>
<li><strong>font-style</strong>: 기본값은 normal</li>
<li><strong>font-weight</strong>: 기본값은 normal</li>
</ul>
</li>
<li>웹폰트의 확장자마다 브라우저 지원율이 다름
<br><br></li>
</ul>
<h2 id="vertical-align">vertical-align</h2>
<p>: 인라인 요소의 수직 정렬을 지정하는 속성</p>
<ul>
<li>기본값: baseline</li>
<li>속성값 - 예시 코드로 설명<pre><code class="language-css">/* keyword values */
vertical-align: baseline; /* 부모 기본값 */
vertical-align: sub; /* 부모 아래 첨자 기준선 */
vertical-align: super; /* 부모 위 첨자 기준선 */
vertical-align: text-top; /* 부모 텍스트의 맨 위(Ascender 제외) */
vertical-align: text-bottom; /* 부모 텍스트의 맨 아래(Descender 제외) */
vertical-align: middle; /* 부모의 중앙에 위치 */
vertical-align: top; /* 부모의 맨 위 위치 */
vertical-align: bottom; /* 부모의 맨 아래 위치 */
</code></pre>
</li>
</ul>
<p>/* length values - 음수 값도 사용 가능 */
vertical-align: 10em;
vertical-align: 4px;</p>
<p>/* percent(%) value - line-height를 기준, 음수 값 사용 가능 */</p>
<pre><code>- block 요소가 아닌 inline 또는 inline-block(테이블 셀 등)에서만 사용 가능
- 주로 부모 요소를 기준으로 정렬
&lt;br&gt;&lt;br&gt;

## text-align
: 인라인 요소의 수평 정렬을 지정하는 속성
(선언은 블록 레벨에 하더라도 인라인 레벨에 적용됨)
- 기본값: left (left to right 언어일 경우 right)
- 속성값
    - **left**: 왼쪽 정렬
    - **right**: 오른쪽 정렬
    - **center**: 중앙 정렬
    - **justify**: 양쪽 정렬(마지막 라인은 정렬하지 않음)
- block 요소가 아닌 inline 또는 inline-block(테이블 셀 등)에서만 사용 가능
+) block 요소를 가운데 정렬하려면?  boxmodel margin의 auto 값을 이용
&lt;br&gt;&lt;br&gt;

## text-indent
: 텍스트의 들여쓰기를 지정하는 속성
- 기본값: 0
- 속성값
    - **length**: px, em 등 고정 수치로 지정, 음수 허용
    - **%**: 부모의 width를 기준으로 배율 적용
- 상속되는 속성이다.
&lt;br&gt;&lt;br&gt;

## text-decoration
: 텍스트의 꾸밈을 지정하는 속성
- 기본값: none   currentColor   solid
```css
text-decoration: text-decoration-line text-decoration-color text-decoration-style | initial | inherit;</code></pre><ul>
<li>속성값<ul>
<li><strong>text-decoration-line</strong>: 텍스트 꾸밈 선의 종류를 지정하는 속성 (멀티로도 선언 가능)<ul>
<li>기본값: none<ul>
<li>속성값: none(꾸밈 X), underline, overline, line-through</li>
<li>text에 의존적이므로 선의 위치는 임의로 조정 불가능</li>
</ul>
</li>
</ul>
</li>
<li><strong>text-decoration-color</strong>: 텍스트 꾸밈의 색상을 지정하는 속성<ul>
<li>기본값: currentColor<ul>
<li>색상 값을 사용해 원하는 색상으로 지정 가능</li>
</ul>
</li>
</ul>
</li>
<li><strong>text-decoration-style</strong>: 텍스트 꾸밈 선의 스타일을 지정하는 속성<ul>
<li>기본값: solid<ul>
<li>속성값: solid, double, dotted, dashed, wavy
<br><br></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="단어-관련-속성">단어 관련 속성</h2>
<h3 id="white-space">white-space</h3>
<p>: 요소 내의 공백을 어떻게 처리할지 지정하는 속성</p>
<ul>
<li>기본값: normal</li>
<li>속성값</li>
</ul>
<table>
<thead>
<tr>
<th align="center">속성값</th>
<th align="center">공백</th>
<th align="center">개행</th>
<th align="center">자동 줄바꿈</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>normal</strong></td>
<td align="center">무시</td>
<td align="center">무시</td>
<td align="center">필요한 경우</td>
</tr>
<tr>
<td align="center"><strong>nowrap</strong></td>
<td align="center">무시</td>
<td align="center">무시</td>
<td align="center">x</td>
</tr>
<tr>
<td align="center"><strong>pre</strong></td>
<td align="center">표현</td>
<td align="center">표현</td>
<td align="center">x</td>
</tr>
<tr>
<td align="center"><strong>pre-line</strong></td>
<td align="center">무시</td>
<td align="center">표현</td>
<td align="center">필요한 경우</td>
</tr>
<tr>
<td align="center"><strong>pre-wrap</strong></td>
<td align="center">표현</td>
<td align="center">무시</td>
<td align="center">필요한 경우</td>
</tr>
<tr>
<td align="center"><br></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h3 id="letter-spacing">letter-spacing</h3>
<p>: 자간을 지정하는 속성</p>
<ul>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong></li>
<li><strong>length</strong>: px, em 등 고정 수치로 지정, 음수 허용<br>
### word-spacing
: 단어 사이의 간격을 지정하는 속성</li>
</ul>
</li>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong></li>
<li><strong>length</strong>: px, em 등 고정 수치로 지정, 음수 허용<br>
### word-break
: 단어가 라인 끝에 나올 경우 어떻게 처리할지 중단점을 지정하는 속성</li>
</ul>
</li>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong>: 공백이나 하이픈을 중단점으로 함(CJK는 음절)</li>
<li><strong>break-all</strong>: 음절을 중단점으로 함, 모든 글자가 요소를 벗어나지 않고 개행</li>
<li><strong>keep-all</strong>: 공백이나 하이픈을 중단점으로 함(CJK는 그 외 기호도 포함)</li>
</ul>
</li>
<li>CJK: 중국어, 일본어, 한국어 등 아시아권 언어<br>
### word-wrap
: 요소를 벗어난 단어의 줄바꿈(중단점)을 지정하는 속성</li>
<li>기본값: normal</li>
<li>속성값<ul>
<li><strong>normal</strong>: 중단점에서 개행</li>
<li><strong>break-word</strong>: 모든 글자가 요소를 벗어나지 않고 강제로 개행
<br><br><br></li>
</ul>
</li>
</ul>
<h2 id="display">display</h2>
<p>: 요소의 렌더링 박스 유형을 결정하는 속성</p>
<ul>
<li>기본값: - (요소마다 다름)</li>
<li>속성값<ul>
<li><strong>none</strong>: 요소가 렌더링 되지 않음</li>
<li><strong>inline</strong>: inline level 요소처럼 렌더링</li>
<li><strong>block</strong>: block level 요소처럼 렌더링</li>
<li><strong>inline-block</strong>: inline level 요소처럼 렌더링, block level의 성질을 가짐</li>
<li>이외에도 다양한 값 존재!</li>
</ul>
</li>
<li>inline level 요소 사이의 공백과 개행 처리
: inline 요소에서 공백과 개행은 하나의 여백으로 받아들여진다.</li>
<li><blockquote>
<p>inline, inline-block에서 태그 사이에 공백이나 개행이 있을 경우 약 4px의 여백이 발생한다.</p>
</blockquote>
</li>
<li><strong>display와 box model의 관계</strong></li>
</ul>
<table>
<thead>
<tr>
<th align="center"><strong>display</strong></th>
<th align="center"><strong>width</strong></th>
<th align="center"><strong>height</strong></th>
<th align="center"><strong>margin</strong></th>
<th align="center"><strong>padding</strong></th>
<th align="center"><strong>border</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>block</strong></td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
</tr>
<tr>
<td align="center"><strong>inline</strong></td>
<td align="center">X</td>
<td align="center">X</td>
<td align="center">좌우</td>
<td align="center">O (설명)</td>
<td align="center">O (설명)</td>
</tr>
<tr>
<td align="center"><strong>inline-block</strong></td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">O</td>
</tr>
</tbody></table>
<p>사실 inline 요소의 padding과 border는 상하좌우 모두 적용된다.
하지만 상하 padding, border는 line-box에는 영향을 주지 못하므로 부모 요소의 박스에 반영되지 않고 인접한 다른 line-box에도 반영되지 않아, 콘텐츠가 겹칠 수 있기 때문에 <u>실무에서는 잘 사용되지 않는다.</u>
<br><br></p>
<h2 id="visibility">visibility</h2>
<p>: 요소의 화면 표시 여부를 지정하는 속성</p>
<ul>
<li>기본값: visible</li>
<li>속성값<ul>
<li><strong>visible</strong>: 화면에 표시</li>
<li><strong>hidden</strong>: 화면에 표시되지 않으나 공간 차지(box 영역 유지)</li>
<li><strong>collapse</strong>: 셀 간 경계를 무시하고 숨김(table 요소에만 지정 가능)</li>
</ul>
</li>
<li><strong><code>visibility: hidden;</code>과 <code>display: none;</code>의 차이점</strong>
: <code>display: none;</code>은 요소가 아예 렌더링되지 않으므로 웹페이지가 그 요소와 관련된 정보를 제공하지 않으나, <code>visibility: hidden;</code>은 요소가 보이지는 않지만 렌더링되어 화면에 공간을 차지하고 있다.
<br><br></li>
</ul>
<h2 id="float">float</h2>
<p>: 요소를 float(보통의 흐름에서 벗어나게 함) 시킬지 지정하는 속성</p>
<ul>
<li>특징<ul>
<li>요소를 보통의 흐름에서 벗어나 띄워지게 함</li>
<li>주변 텍스트나 인라인 요소가 주위를 감싸는 특징이 있음</li>
<li>대부분 요소의 display 값을 block으로 변경함 (예외: inline-table, flex 등)</li>
</ul>
</li>
<li>기본값: none</li>
<li>속성값<ul>
<li><strong>none</strong>: float시키지 않음</li>
<li><strong>left</strong>: 왼쪽으로 float</li>
<li><strong>right</strong>: 오른쪽으로 float
<br><br></li>
</ul>
</li>
</ul>
<h2 id="clear">clear</h2>
<p>: 요소를 floating 된 요소의 영향에서 벗어나게 하는 속성</p>
<ul>
<li>기본값: none</li>
<li>속성값<ul>
<li><strong>none</strong>: 양쪽으로 floating 요소 <code>허용</code></li>
<li><strong>left</strong>: 왼쪽으로 floating 요소 <code>비허용</code></li>
<li><strong>right</strong>: 오른쪽으로 floating 요소 <code>비허용</code></li>
<li><strong>both</strong>: 양쪽으로 floating 요소 <code>비허용</code></li>
</ul>
</li>
<li><strong>block-level 요소에만 적용 가능</strong>
<br><br></li>
</ul>
<h2 id="position--offset">position &amp; offset</h2>
<p>: 요소의 위치를 원하는 곳으로 지정할 때 사용하는 속성</p>
<h3 id="position">position</h3>
<ul>
<li>기본값: static</li>
<li>속성값<ul>
<li><strong>static</strong>: Normal-flow에 따라 배치되며 offset 값 적용 X</li>
<li><strong>absolute</strong><ul>
<li>부모 요소의 위치를 기준으로 offset에 따라 배치<ul>
<li>부모가 position 값(static 제외)을 가질 경우: offset 값의 시작점이 됨 - 부모의 content 영역을 기준으로 가짐(padding까지)</li>
<li>부모의 position 값이 static인 경우: 조상의 position 값이 static이 아닐 때까지 거슬러 올라감</li>
<li>block-level 요소가 아닐 경우 display 값이 block으로 변경됨</li>
<li>Normal-flow의 흐름에서 벗어난다.</li>
</ul>
</li>
</ul>
</li>
<li><strong>fixed</strong><ul>
<li>뷰포트(브라우저의 창)를 기준으로 offset에 따라 배치
즉, 화면 스크롤에 관계없이 항상 화면의 정해진 위치에 나타남<ul>
<li>부모의 위치에 영향을 받지 않음</li>
<li>block-level 요소가 아닐 경우 display 값이 block으로 변경됨</li>
</ul>
</li>
</ul>
</li>
<li><strong>relative</strong><ul>
<li>자신이 원래 있어야 할 위치를 기준으로 offset 에 따라 배치<ul>
<li>부모의 position 속성에 영향을 받지 않음</li>
<li>Normal-flow의 흐름에 따른다.</li>
<li>주변 요소에 영향을 주지 않으면서 offset 값으로 이동</li>
</ul>
</li>
</ul>
</li>
<li><strong>sticky</strong>: 브라우저 지원율이 낮아 실무에서 많이 사용 못하는 중...<h3 id="offset">offset</h3>
</li>
</ul>
</li>
<li><code>top</code>/<code>bottom</code>/<code>left</code>/<code>right</code> 속성으로 사용 가능</li>
<li><strong>position 값이 static이 아닐 경우</strong>에만 작동</li>
<li>속성값: auto 혹은 length
(% 단위도 사용 가능 - 상하는 height, 좌우는 width를 기준으로 함)
<br><br></li>
</ul>
<h2 id="z-index">z-index</h2>
<p>: 요소가 겹치는 순서(쌓임 순서 또는 stack order)를 지정하는 속성</p>
<ul>
<li>기본값: auto</li>
<li>속성값<ul>
<li><strong>auto</strong>: 쌓임 순서를 부모와 동일하게 설정</li>
<li><strong>number</strong>: 해당 수치로 쌓임 순서를 설정(음수 허용)</li>
</ul>
</li>
<li>특징<ul>
<li>position 값이 static이 아닌 경우 작동</li>
<li>순서 값이 없을 경우 코드상 순서에 따라 쌓임</li>
<li>부모가 z-index 값이 있을 경우 부모 안에서만 의미 있음</li>
<li>값이 클수록 가장 위에 위치</li>
</ul>
</li>
</ul>
<br>

<h2 id="htmlcss의-유효성-테스트">HTML/CSS의 유효성 테스트</h2>
<p>: <a href="https://validator.w3.org/">https://validator.w3.org/</a>
<br><br><br><br><br></p>
<h2 id="미디어쿼리-media-queries">미디어쿼리 Media Queries</h2>
<p>: 각 미디어 매체에 따라 다른 스타일 시트를 적용할 수 있게 만드는 것
( 미디어 매체: 모니터와 같은 스크린 매체, 프린트, 스크린 리더기 등등 )
<br></p>
<h3 id="mediaat-media">@media(at media)</h3>
<pre><code class="language-css">@media mediaqueries { /* style rules  */ }</code></pre>
<ul>
<li>위와 같은 방법으로 선언하며, 위 코드의 <code>mediaqueries</code>를 미디어 쿼리 구문이라고 한다.</li>
<li>미디어쿼리 구문이 참이면 뒤에 나오는 스타일 규칙이 적용되고, 거짓이면 무시된다.</li>
<li>미디어 쿼리 구문은 <strong>미디어 타입(Media Types)</strong>과 <strong>미디어 특성(Media Features)</strong>으로 구성되어 있다.<h3 id="미디어-타입">미디어 타입</h3>
</li>
<li><strong>all</strong>, braille, embossed, handheld, <strong>print</strong>, projection, <strong>screen</strong>, speech, tty, tv 등</li>
<li>화면을 출력하는 디스플레이가 있는 미디어들은 전부 screen에 속함</li>
<li>곧 상용화될 미디어 쿼리 level 4에서 미디어 타입 대부분이 폐기 예정<h3 id="미디어-특성">미디어 특성</h3>
</li>
<li><strong>width</strong>, height, device-width, device-height, <strong>orientation</strong>, aspect-ratio, device-aspect-ratio, color, color-index, monochrome, resolution, scan, grid 등</li>
<li><strong>width</strong>는 스크린의 너비가 아니라 뷰포트(브라우저 창)의 너비를 뜻한다.</li>
<li><strong>orientation</strong>은 width와 height 특성의 값을 비교하여 세로/가로모드를 판별한다. 세로모드에서는 portrait, 가로모드에서는 landscape 키워드와 매칭된다.</li>
<li>곧 상용화될 미디어 쿼리 level 4에서 미디어 특성 중 일부 속성 폐기 예정<br>
### 미디어쿼리 Syntax</li>
<li>[ a ] : a가 나올 수도 있고 나오지 않을 수도 있다.</li>
<li>a | b : a 또는 b 둘 중에 하나를 선택</li>
<li>a? :  a가 0번 나오거나 1번만 나올 수 있음</li>
<li>a* : a가 0번 나오거나 그 이상 계속 나올 수 있음</li>
<li>media_type : all, screen, print 등 미디어 타입</li>
<li>media_feature : width, orientation 등 미디어 특성<pre><code class="language-css">media_query_list
: S* [media_query [ &#39;,&#39; S* media_query ]* ]?
; /* 여러 개의 미디어 쿼리로 이루어진 리스트로 작성 가능하며, 쉼표로 구분 */
media_query
: [ONLY | NOT]? S* media_type S* [ AND S* expression ]*
| expression [ AND S* expression ]*
; /* A형태 - 미디어 타입에 and 키워드로 표현식 붙일 수 있음(생략 가능) 
      미디어 타입 앞에 only, not 키워드가 올 수 있다.
    B형태 - 미디어 타입 없이 미디어 표현식이 바로 나올 수 있고
            and 키워드로 계속 나올 수 있다.
              (미디어 타입이 명시되지 않으면 all로 간주) */
expression
: &#39;(&#39; S* media_feature S* [ &#39;:&#39; S* expr ]? &#39;)&#39; S*
; /* 괄호로 감싸야 하며, 특성 이름과 해당 값으로 이루어진다.
   특성 이름과 값을 : 기호로 연결하며 특성 이름만 사용하는 것도 가능 */</code></pre>
</li>
<li>예제 코드<pre><code class="language-css">@media screen { ... }
  /* 미디어 타입이 screen이면 적용 */
</code></pre>
</li>
</ul>
<p>@media screen and (min-width: 768px) { ... }
    /* 미디어 타입이 screen이고 width가 768px 이상이면 적용 */</p>
<p>@media (min-width: 768px) and (max-width: 1024px) { ... }
    /* and로 연결된 모든 표현식이 참이면 적용 */</p>
<p>@media (color-index)
    /* 미디어 장치가 color-index를 지원하면 적용 */</p>
<p>@media screen and (min-width: 768px), screen and (orientation: portrait), ...
    /* 쉼표로 연결된 미디어 쿼리 중 하나라도 참이면 적용(and와 반대) */</p>
<p>@media not screen and (min-width: 768px)
    /* not 키워드는 하나의 media_query 전체를 부정
     (not screen) and (min-width: 768px) X
     not (screen and (min-width: 768px)) O */</p>
<p>@media not screen and (min-width: 768px), print
     /* 첫 번째 미디어 쿼리에만 not 키워드 적용 */</p>
<pre><code>- min-/max- 접두사: 범위를 지정하여 간결하게 반응형 사이트를 제작할 수 있음
    - 특성의 값으로 숫자 형태가 들어가는 속성에는 모두 사용 가능
    - orientation (portrait, landscape 키워드), grid, scan 이 세 가지 특성은 값으로 특정 키워드가 들어가므로 프리픽스 사용 불가
    - 현재 유력 표준안에서는 이러한 접두사 대신 부등호 사용 가능

&lt;br&gt;

### 미디어쿼리 선언 방법
- `@media screen and (color)`
  : CSS 파일 내부 또는 `&lt;style&gt;` 태그 내부에 사용 가능, **가장 보편적**
- `&lt;link rel=&quot;stylesheet&quot; media=&quot;screen and (color)&quot; href=&quot;example.css&quot;&gt;`
   : `&lt;link&gt;` 태그의 media 속성에 미디어 쿼리 선언, 미디어 쿼리가 참이면 뒤의 css 파일 규칙 적용
- `@import url(example.css) screen and (color);`
   : CSS 파일 내부 또는 `&lt;style&gt;` 태그 내부에 사용 가능, @import문 뒤에 미디어 쿼리 선언
- 꼭 실습해보자 !
&lt;br&gt;&lt;br&gt;

## 뷰포트 Viewport
: 브라우저가 화면을 나타내는 가상의 화면 사이즈
- 뷰포트 설정: `&lt;head&gt;` 태그 내에 위치하는 `&lt;meta&gt;` 태그에 선언
```html
&lt;meta name=&quot;viewport&quot; content=&quot; 뷰포트의 설정 값&quot; &gt;

&lt;!-- 대부분의 모바일 웹 사이트의 뷰포트 설정 --&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</code></pre><ul>
<li>설정값<ul>
<li><strong>width/height</strong>: 뷰포트의 가로/세로 크기 지정
대부분 특수 키워드 <strong>device-width(height)</strong> 사용</li>
<li>initial-scale: 페이지가 처음 나타날 때 초기 줌 레벨 값(소수)</li>
<li>user-scalable: 사용자의 확대/축소 기능 설정
<br><br><br></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CRA로 만든 React TypeScript 프로젝트에 절대경로 적용하기 with Craco]]></title>
            <link>https://velog.io/@welloff_jj/Applying-Absolute-Path-with-Craco-to-React-Project-made-with-CRA</link>
            <guid>https://velog.io/@welloff_jj/Applying-Absolute-Path-with-Craco-to-React-Project-made-with-CRA</guid>
            <pubDate>Thu, 20 Jan 2022 06:18:12 GMT</pubDate>
            <description><![CDATA[<p>이번 포스팅에서는 CRA로 생성한 React 프로젝트에서 절대경로 import를 하는 방법에 대해 다뤄 보려 한다. 그런데 약간의 삽질을 곁들인...</p>
<p>사건의 발단은 지난주 수요일에 했던 코드 리뷰였다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/26264479-5ae6-46e4-8f6b-f5d01315ad36/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.50.41.png" alt=""></p>
<p>나의 <strong>지옥의 상대경로 import</strong>를 본 한 팀원이 나에게 절대경로를 지정해 사용해 보는 건 어떻겠냐는 의견을 내 주었고, 나도 마침 이번주 task로 넣을 생각을 하고 있던 이슈라서 바로 OK했다.</p>
<p>그리고 드디어 이번 스프린트가 시작되고, 절대경로를 적용해보려 열심히 구글링을 해보았다.</p>
<br>

<h2 id="🛠-절대경로-한번-적용해보려고-한-온갖-삽질들">🛠 절대경로 한번 적용해보려고 한 온갖 삽질들</h2>
<p>구글링하면서 찾다 보니 정말 여러 가지 방법이 있었다.</p>
<p>웹팩이랑 바벨에 대해 무지했던 과거의 내가 벌인 실수라서 좀 부끄럽지만 혹시나 찾으시는 분들이 있을까 해서 간단하게나마 정리해보려고 한다 😛</p>
<h3 id="🔨-webpackconfigjs-설정">🔨 webpack.config.js 설정</h3>
<pre><code class="language-js">// webpack.config.js

resolve: {
    modules: [
        path.join(__dirname, &quot;src&quot;),
        &quot;node_modules&quot;
      ]
}</code></pre>
<p>뭣도 모르고 파일을 생성해서 해보려 했지만 설정 파일을 건드린 게 아니라서 어림없게 실패 !</p>
<h3 id="🔨-env-파일에-node_pathsrc-설정-및-tsconfigjson-설정">🔨 .env 파일에 NODE_PATH=src/ 설정 및 tsconfig.json 설정</h3>
<p>.env 파일에 <code>NODE_PATH=src/</code>를 추가하고, tsconfig.json에 다음과 같이 써줬다.</p>
<p>앗 참고로 tsconfig.json 파일에 대한 내용은 이전 포스팅 <a href="https://velog.io/@welloff_jj/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TypeScript%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-with-CRA-ESLint-Prettier-%EC%A0%81%EC%9A%A9">React 프로젝트 TypeScript로 설정하기 with CRA (+ ESLint, Prettier 적용)</a>에 있으니 참고 😉</p>
<pre><code class="language-javascript">// tsconfig.json

{
    &quot;compilerOptions&quot;: {
              ...
        &quot;baseUrl&quot;: &quot;.&quot;,
        &quot;paths&quot;: {
            &quot;*&quot;: [
                       &quot;*&quot;,
                    &quot;src/*&quot;
                  ]
        },
    },
          ...
}</code></pre>
<p>그치만 이렇게 한 다음에 <code>import Box from &quot;components/atoms/Box&quot;</code>로 임포트해도 전혀 인식하지 못하더라..
CRA로 만들어진 프로젝트에서 .env에 환경변수를 입력할 때 <code>REACT_APP_</code>으로 시작해야 하기도 하고, 빌드 설정을 건드리지 않기 때문에 당연히 실패!</p>
<h3 id="🔨-tsconfigjson에서-baseurl-및-path-지정">🔨 tsconfig.json에서 baseUrl 및 path 지정</h3>
<pre><code class="language-javascript">// tsconfig.json

{
    &quot;compilerOptions&quot;: {
              ...
        &quot;baseUrl&quot;: &quot;.&quot;,
        &quot;paths&quot;: {
            &quot;@assets/*&quot;: [&quot;src/components/assets/*&quot;],
            &quot;@atoms/*&quot;: [&quot;src/components/atoms/*&quot;],
            &quot;@molecules/*&quot;: [&quot;src/components/molecules/*&quot;],
            &quot;@organisms/*&quot;: [&quot;src/components/organisms/*&quot;],
            &quot;@pages/*&quot;: [&quot;src/components/pages/*&quot;],
        },
    },
          ...
}</code></pre>
<p>이런 식으로 tsconfig.json에 baseUrl과 path를 지정하면 <code>&quot;@assets/image&quot;</code> 이렇게 import가 가능하다고 해서 해봤다.
근데 안되더라 🥲 왜 그런가 했더니 webpack 설정도 건드려 줘야 하는데 그걸 빼먹어서 그렇다고 한다.
tsconfig.json만 수정하면 <code>yarn start</code>를 했을 때 강제로 작성한 path가 사라진다나 뭐라나..</p>
<p>CRA로 만든 프로젝트는 webpack 설정이 숨겨져 있어 이걸 바꿔주려면 <code>yarn eject</code>를 통해 설정 파일을 꺼내 건드려줘야 한다.
하지만 이렇게 해버리면 내가 프로젝트를 CRA로 만든 장점이 사라져버리기도 하고 한번 eject 하면 되돌릴 수 없기 때문에 이 방법은 fail ...</p>
<br>

<h2 id="❤️-craco와-함께-절대경로-설정하기">❤️ Craco와 함께 절대경로 설정하기</h2>
<p>위의 삽질들 +알파를 거친 후에야 오 이거 괜찮은데? 싶은 방법을 발견했다.
그건 바로 craco-alias를 사용해 간편하게 tsconfig 옵션들을 적용하는 것이다!</p>
<h3 id="❓-craco가-뭔데">❓ Craco가 뭔데?</h3>
<p>Craco는 <code>Create React App Configuration Override</code>의 약자로, Create-React-App 즉 CRA를 쉽게 설정하기 위해 만들어졌다고 한다.</p>
<p>craco 모듈을 설치한 뒤 root 폴더에 <strong>craco.config.js</strong> 파일을 작성하고 여기에 이것저것 설정을 해주면 eject를 할 필요 없이 tsconfig.json에 작성한 내용을 빌드 과정에서 적용할 수 있고, webpack이나 babel 설정도 건드릴 수 있다고 하니 참 편리한 모듈인 듯 ✨</p>
<h3 id="💾-craco-설치하기">💾 Craco 설치하기</h3>
<p>우리는 Craco 모듈과, 내가 작성한 tsconfig 옵션들을 적용하기 위한 플러그인인 craco-alias를 설치할 것이다.</p>
<p>명령어는 다음과 같다.</p>
<pre><code class="language-cmd">$ yarn add @craco/craco
$ yarn add --dev craco-alias</code></pre>
<p>위 명령어를 이용하면 craco는 전역으로, craco-alias는 현재 프로젝트에 설치할 수 있다.</p>
<h3 id="✔️-packagejson-수정하기">✔️ package.json 수정하기</h3>
<p>먼저 craco를 통해 프로젝트를 빌드하도록 package.json을 수정한다.</p>
<pre><code class="language-js">// package.json

&quot;scripts&quot;: {
        &quot;start&quot;: &quot;craco start&quot;,
        &quot;build&quot;: &quot;craco build&quot;,
        &quot;test&quot;: &quot;craco test&quot;,
        &quot;eject&quot;: &quot;react-scripts eject&quot;
}</code></pre>
<h3 id="✔️-tsconfigjson---tsconfigpathsjson-파일-설정">✔️ tsconfig.json &amp;  tsconfig.paths.json 파일 설정</h3>
<p>다음으로 javascript를 사용한다면 jsconfig.json을, typescript를 사용한다면 tsconfig.json 파일에 extends로 추가할 path 전용 설정 파일인 <code>tsconfig.paths.json</code>을 root에 생성한다.</p>
<p>tsconfig.json 파일에 바로 작성해도 되지만 craco-alias에서 옵션으로 path 파일을 필요로 하기도 하고, 이렇게 따로 분리하면 관리에 용이하다는 장점이 있다고 한다.</p>
<p>아무튼 파일을 생성하고 입맛에 맞게 baseUrl과 paths를 설정해 주면 된다 🙂</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/6f2a52a6-b1e9-44b1-aa15-f13e2391bfe3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-20%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.07.25.png" alt=""></p>
<p>나의 경우 프로젝트 src 폴더 구조가 위의 사진처럼 생겼기 때문에 paths를 내 입맛에 맞게 폴더별로 지정해주었다.</p>
<pre><code class="language-javascript">// tsconfig.paths.json

{
    &quot;compilerOptions&quot;: {
        &quot;baseUrl&quot;: &quot;.&quot;,
        &quot;paths&quot;: {
            &quot;@assets/*&quot;: [&quot;src/components/assets/*&quot;],
            &quot;@atoms/*&quot;: [&quot;src/components/atoms/*&quot;],
            &quot;@molecules/*&quot;: [&quot;src/components/molecules/*&quot;],
            &quot;@organisms/*&quot;: [&quot;src/components/organisms/*&quot;],
            &quot;@pages/*&quot;: [&quot;src/components/pages/*&quot;]
        }
    }
}</code></pre>
<blockquote>
<p>⚠️ 주의할 점</p>
</blockquote>
<p>맨 마지막 요소에 <code>,(콤마)</code>가 붙어 있으면 craco가 .json 파일을 parsing하지 못한다는 에러 메시지를 볼 수 있다.
그러므로 마지막 요소에 습관적으로 <code>,</code>를 붙였다면 꼭 ! 지워 주어야 한다 😎</p>
<p>이렇게 tsconfig.paths.json 파일 작성을 마쳤다면 tsconfig.json에 이 파일을 extends로 등록해 준다.</p>
<pre><code class="language-javascript">// tsconfig.json

{
    &quot;extends&quot;: &quot;./tsconfig.paths.json&quot;,
    &quot;compilerOptions&quot;: {
            ...
    },
        ...
}</code></pre>
<h3 id="✔️-cracoconfigjs-작성하기">✔️ craco.config.js 작성하기</h3>
<p><code>craco.config.js</code> 파일은 적용하고 싶은 craco 설정들을 작성하는 파일이다.
우리는 craco-alias 플러그인을 적용해 아까 작성했던 paths를 절대경로로 사용할 것이므로 다음과 같이 적어주면 된다.</p>
<pre><code class="language-js">// craco.config.js

const CracoAlias = require(&quot;craco-alias&quot;);

module.exports = {
    plugins: [
        {
            plugin: CracoAlias,
            options: {
                source: &quot;tsconfig&quot;,
                tsConfigPath: &quot;tsconfig.paths.json&quot;,
            },
        },
    ],
};</code></pre>
<blockquote>
<p>💡 더 알아보기: options에 대해</p>
</blockquote>
<ul>
<li><code>source</code>: default는 <code>options</code>이고, 프로젝트 구성에 따라 <code>jsconfig</code>, <code>tsconfig</code> 선택 가능</li>
<li><code>baseUrl</code>: default는 <code>./</code>로 root 폴더를 가리킴 (여기에선 default 값 그대로 사용)</li>
<li><code>aliases</code>: alias 이름과 경로를 의미하며 default는 <code>{}</code></li>
<li><code>tsConfigPath</code>: <code>source</code>가 <code>tsconfig</code>인 경우 해당 파일 이름 작성</li>
<li><code>debug</code>: default는 false이고, 만약 버그가 생긴다면 값을 true로 수정해 console로 내용 확인 가능</li>
</ul>
<h3 id="✔️-tsconfigjson에-extends-추가하기">✔️ tsconfig.json에 extends 추가하기</h3>
<p>craco.config.js를 추가해준다.</p>
<pre><code class="language-javascript">// tsconfig.json

{
    &quot;extends&quot;: &quot;./tsconfig.paths.json&quot;,
    &quot;compilerOptions&quot;: {
            ...
    },
        ...
        &quot;include&quot;: [
        &quot;src&quot;,
        &quot;craco.config.js&quot;
    ],
}</code></pre>
<h3 id="✔️-적용해보기">✔️ 적용해보기</h3>
<p><img src="https://images.velog.io/images/welloff_jj/post/1520a840-de78-408f-8b98-b095d7d62b5e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-20%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.34.28.png" alt=""></p>
<p>드디어 절대경로를 통해 컴포넌트를 import할 수 있게 되었다 ❤️</p>
<p>CRA를 사용하지 않고 프로젝트를 만들었다면 바로 설정 파일을 만들거나 수정해 절대 경로 사용이 가능했겠지만, CRA를 사용하다 보니 설정을 직접 건드릴 수 없어 삽질을 꽤 오래 했다.</p>
<p>부디 같은 문제로 헤매던 분들 중 한 분에게라도 내 글이 도움이 되기를 ... 🙏🏻</p>
<br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://velog.io/@shin6403/React-Typescript-%EC%A0%88%EB%8C%80%EA%B2%BD%EB%A1%9C-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0feat.React-CRA#4-tsconfigjson-%ED%8C%8C%EC%9D%BC%EC%97%90-extends%EB%A5%BC-%EC%B6%94%EA%B0%80%ED%95%9C%EB%8B%A4">React Typescript | 절대경로 적용하기(feat.React-CRA)</a>
<a href="https://bgradecoding.tistory.com/14">[React] 상대경로 지옥에서 벗어나기 (craco)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)]]></title>
            <link>https://velog.io/@welloff_jj/Javascript-Shallow-Copy-Deep-Copy</link>
            <guid>https://velog.io/@welloff_jj/Javascript-Shallow-Copy-Deep-Copy</guid>
            <pubDate>Mon, 17 Jan 2022 08:46:21 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 하다 배열을 복사해서 써야 할 일이 생겼다.
그래서 그냥 아무 생각 없이 일반 변수처럼 대입해서 쓰면 되겠지! 라고 생각하며 다음과 같이 썼다.</p>
<pre><code class="language-javascript">
// 복사할 객체
const src = [ val1, val2, val3, ...];

// 이렇게 복사하면 안 되는 거였냐구 ㅜㅜ
const dest = src;</code></pre>
<p>그런데 이렇게 복사하고 나서 dest의 값을 임시로 변경했더니 src의 값까지 변경되어, 원본 데이터를 잃어버리는 매우매우 끔찍한 상황이 발생했다.</p>
<p>왜 이런 일이 일어난 걸까?</p>
<br>

<h2 id="👀-원시-타입과-참조-타입">👀 원시 타입과 참조 타입</h2>
<blockquote>
<p>💡 참고: 이전 포스팅 <a href="https://velog.io/@welloff_jj/Javascript-Primitive-Type-Reference-Type">원시 타입(Primitive Type)과 참조 타입(Reference Type)</a></p>
</blockquote>
<p>결론부터 얘기하자면 위와 같은 일이 일어난 이유는 src가 참조 타입이기 때문이다.
원시 타입과 참조 타입에 대한 자세한 내용은 위 링크 참고 😊</p>
<blockquote>
<p>참조 타입의 변수들은 데이터 복사가 일어날 때 값이 담긴 주솟값을 바로 복사하지 않고, <strong>값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복사</strong>한다.</p>
</blockquote>
<p>그렇다면 참조 타입 데이터를 완벽하게(?) 복사해, 복사된 값을 바꾸어도 원본이 변경되지 않게 할 수는 없는 걸까?</p>
<br>

<h2 id="💡-얕은-복사shallow-copy와-깊은-복사deep-copy">💡 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)</h2>
<p>위 질문에 대한 답은 <code>당연히 할 수 있다!</code>이다.
그렇다면 어떻게 복사해야 하는 걸까..? 이에 대해 알아보기 전에 먼저 javascript에서 값이 복사되는 두 가지 방식에 대해 알아보자.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/9b88eda6-a7f5-4a1d-be5d-d708fd13758e/image.png" alt="참조형 데이터의 얕은 복사와 깊은 복사"></p>
<h3 id="✔️-얕은-복사-shallow-copy">✔️ 얕은 복사 (Shallow Copy)</h3>
<p>➡️ 바로 아래 단계의 값만 복사. 즉 참조형 데이터인 객체(Object)의 경우 객체가 가리키는 값들의 묶음을 가리키는 주솟값만 복사 !</p>
<p>얕은 복사로 데이터를 복사 후 복사본에서 프로퍼티 값을 바꾸면,
<strong>복사본과 원본은 모두 같은 객체를 바라보고 있는 상태</strong>에서 프로퍼티가 변경되는 것이므로 원본의 값도 변하게 된다.</p>
<p>원시 타입 데이터의 경우 <strong>값이 담긴 데이터 공간의 주소가 변수 공간에 바로 저장</strong>되어 있기 때문에,
값을 복사한 후 복사본의 값을 바꾸면 복사본이 새로운 값의 주소를 저장하게 되므로 원본은 변하지 않는다.
다시 말해 원시 타입 데이터는 얕은 복사와 깊은 복사의 결과가 동일하다. 고려할 필요 xx</p>
<h3 id="✔️-깊은-복사-deep-copy">✔️ 깊은 복사 (Deep Copy)</h3>
<p>➡️ 내부의 모든 값들을 하나하나 찾아 전부 복사. 객체 안에 객체가 있을 경우에도 내부 프로퍼티들을 모두 순회하여 얕은 복사가 이루어지지 않도록 해야 함</p>
<p>이 경우 원본과 복사본이 서로 다른 객체를 가리키게 되므로 복사본의 프로퍼티가 변경되어도 원본이 변경되지 않는다.</p>
<p>예를 들어 보자.</p>
<pre><code class="language-javascript">var copyObjectDeep = function(target) {
  var result = {};
  if (typeof target === &#39;object&#39; &amp;&amp; target !== null) {
    for (var prop in target) {
      result[prop] = copyObjectDeep(target[prop]);
    }
  } else {
    result = target;
  }
  return result;
}</code></pre>
<p>위 코드는 매개변수로 들어온 target이 null이 아닌 객체일 경우 깊은 복사를 수행해주는 함수이다.
만약 target의 프로퍼티가 객체인 경우 (중첩 객체) 재귀를 통해 깊은 복사를 수행한다.</p>
<p>이를 실행해 보면,</p>
<pre><code class="language-javascript">var obj1 = {
  a: 1,
  b: {
    c: null,
    d: [1, 2]
  }
};

var obj2 = copyObjectDeep(obj1);

console.log(obj1 === obj2); // false
console.log(obj1); // { a: 1, b: { c: null, d: [1, 2] } }
console.log(obj2); // { a: 1, b: { c: null, d: { 0: 1, 1: 2 } }</code></pre>
<h3 id="✔️-참조형-데이터의-깊은-복사-방법">✔️ 참조형 데이터의 깊은 복사 방법</h3>
<ol>
<li>사용자 정의 함수 만들기 (위의 예시 참조)</li>
<li>배열의 복사: <code>Array.prototype.slice()</code> 활용<ul>
<li>배열 내에 참조형 요소가 있다면 얕은 복사를 수행하니 주의!</li>
</ul>
</li>
<li>JSON.parse, JSON.stringify를 통한 복사<ul>
<li>객체를 json 문자열로 변환해 참조를 모두 끊은 후, 다시 객체로 변환하는 방법</li>
<li>json으로 변환할 수 없는 프로퍼티는 무시되며 속도가 매우 느리다고 함</li>
</ul>
</li>
<li><code>lodash</code> 라이브러리 사용</li>
</ol>
<br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://bbaktaeho-95.tistory.com/37">[Javascript] 얕은 복사, 깊은 복사 (배열 복사, 객체 복사, shallow copy, deep copy, slice, JSON.parse, JSON.stringify)</a>
<a href="https://velog.io/@th0566/Javascript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC">[Javascript] 얕은 복사, 깊은 복사</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] 원시 타입(Primitive Type)과 참조 타입(Reference Type)]]></title>
            <link>https://velog.io/@welloff_jj/Javascript-Primitive-Type-Reference-Type</link>
            <guid>https://velog.io/@welloff_jj/Javascript-Primitive-Type-Reference-Type</guid>
            <pubDate>Sun, 16 Jan 2022 13:57:19 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트는 동적 타입(dynamic typed) 언어 혹은 느슨한 타입(loosely typed) 언어이며 구문 작성이 자유롭고 느슨하다고 <a href="https://velog.io/@welloff_jj/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TypeScript%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-with-CRA-ESLint-Prettier-%EC%A0%81%EC%9A%A9">전 포스팅</a>에서 한 번 언급한 적이 있다. 예를 들면 이런 식이다.</p>
<pre><code class="language-javascript">const a = 12;
const b = &quot;12&quot;;</code></pre>
<p>위와 같이 코드를 작성했을 때, 따로 변수에 자료형을 지정해주지 않았지만 자바스크립트는 자동으로 a는 <code>number</code> 타입으로, b는 <code>string</code> 타입으로 인식한다.
그리고 이런 것도 가능하다.</p>
<pre><code class="language-javascript">console.log(a == b); // true
console.log(a === b); // false</code></pre>
<p>첫번째 줄에서는 a와 b를 비교할 때 먼저 형변환을 통해 두 값의 자료형을 일치시킨 뒤 비교하는 <strong>동등 연산자(==, equality operator)</strong>를 사용했기 때문에 a와 b가 같다는 결과가 나온다.
하지만 두번째 줄에서는 데이터 타입의 변환 없이 비교하여, 타입의 동등 여부까지 검사하는 <strong>일치 연산자(===, strict equality operator)</strong>를 사용했기 때문에 a와 b가 다르다는 결과가 나온다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/7c8eba4d-019b-43e7-8564-4ca66f8310ac/image.png" alt=""></p>
<p>이처럼 Javascript는 다른 언어(C, Java 등)들에 비해 자료형 즉 타입에 비교적 너그럽다.
이런 Javascript의 특성은 코드를 짤 때는 행복하게 느껴질 수도 있지만, 코드에서 오류가 발생했을 땐 지옥의 디버깅을 겪게 하는 악마로 느껴질 수도 있다.</p>
<p>그러므로 자바스크립트 내부에서 변수들의 타입이 어떻게 다루어지는지 이해하고 Typescript를 이용한 정적 타이핑을 한다면 보다 더 슬기로운 코딩생활을 할 수 있겠지? 🙂</p>
<p>그래서 이번 포스팅에서는 슬기로운 코딩생활을 위해 자바스크립트의 데이터 타입에 대해 알아보려고 한다 🙌🏻</p>
<br/>

<h2 id="🧩-원시-타입-primitive-type">🧩 원시 타입 (Primitive Type)</h2>
<p>원시 타입에 속하는 데이터 타입에는 <strong>숫자(Number &amp; Bigint), 문자열(String), 논리형(Boolean), null, undefined, 심볼(Symbol)</strong>이 있다.</p>
<p>참고로 NaN은 Not a Number라는 뜻으로 숫자에 속한다. null, undefined, NaN이 어떻게 다른지는 나중에 따로 포스팅해보도록 하겠다 !</p>
<h3 id="✔️-원시-타입의-불변성-immutable">✔️ 원시 타입의 불변성 (immutable)</h3>
<p>자바스크립트에서 원시 타입은 변수에 할당될 때 메모리에 고정 크기로 원시 값을 저장하고 그 값을 변수가 직접 가리키는 형태를 띈다.</p>
<p>즉 데이터를 저장하기 위한 별도의 데이터 공간을 확보해 값을 저장하고, 그 공간을 변수 영역에 저장한다.
➡️ <strong>변수 영역과 데이터 영역이 존재</strong></p>
<p>이렇게 할당된 값은 <strong>불변성(immutable)</strong>을 갖는다.
즉 메모리에 할당된 원시 타입의 값은 그 자체가 변경될 수 없다.</p>
<p>이에 대해 조금 더 자세히 설명해 보자면, 변수에 값을 재할당할 때 기존 값이 변하는 것처럼 보이지만 사실은 새로운 메모리에 재할당한 값이 저장되고 변수가 가리키는 메모리가 달라지는 것이다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/1e16751f-57dd-4e62-a911-676392567415/image.png" alt=""></p>
<p>위 사진을 통해, str에 &quot;문자열&quot;이라는 값을 할당한 후 &quot;문자열2&quot;라는 값을 재할당하면 새로운 메모리에 재할당한 값인 &quot;문자열2&quot;가 저장되고 변수가 그 메모리를 가리키게 되는 것을 알 수 있다.</p>
<h3 id="✔️-원시-타입의-값-복사하기">✔️ 원시 타입의 값 복사하기</h3>
<p>원시 타입의 변수들은 데이터 복사가 일어날 때 <strong>값이 담긴 주솟값을 바로 복사</strong>한다 ✨</p>
<pre><code class="language-javascript">var str1 = &quot;hello&quot;;
var str2 = str1;

str1 = &quot;world&quot;;

console.log(str1); // world
console.log(str2); // hello</code></pre>
<p>위의 코드를 보면 알 수 있듯 원본 변수에 값을 재할당해도 복사본의 값은 변하지 않는다.</p>
<p>이것은 새로운 변수 str2에 str1을 복사할 때 str1의 값이 저장되어 있는 메모리 공간을 변수가 가리키도록 하기 때문이다.
그리고 str1에 다른 값인 &quot;world&quot;를 재할당하면 메모리 공간에 &quot;world&quot;가 새로 할당되고, str1은 &quot;world&quot;가 저장되어 있는 공간을 가리키게 된다.</p>
<p>즉 원시 타입의 값은 한 번 만들면 바꿀 수 없다. 이미 만들어진 값은 가비지 컬렉팅을 당하지 않는 이상 사라지지 않는다 !</p>
<br/>

<h2 id="🧩-참조-타입-reference-type">🧩 참조 타입 (Reference Type)</h2>
<p>자바스크립트에서 원시 타입을 제외한 나머지는 참조 타입<strong>(객체, Object)</strong>이라 할 수 있다.
객체의 하위 분류에 속하는 데이터 타입에는 <strong>배열(Array), 함수(Function), 날짜(Date), 정규표현식(RegExp) 등</strong>이 있다.</p>
<h3 id="✔️-참조-타입과-원시-타입의-차이점">✔️ 참조 타입과 원시 타입의 차이점</h3>
<p>참조 타입과 원시 타입의 가장 큰 차이점은, <strong>객체의 변수(프로퍼티) 영역이 추가로 존재</strong>한다는 것이다.</p>
<p>예를 들어,</p>
<pre><code class="language-javascript">var obj1 = {
  a: 1,
  b: &quot;bbb&quot;
};</code></pre>
<p><img src="https://images.velog.io/images/welloff_jj/post/b29f29f4-7ec2-432d-bb26-b18cf7fa4706/image.png" alt=""></p>
<p>이렇게 생긴 객체를 선언 및 초기화할 때 생기는 일에 대해 알아보자.</p>
<ol>
<li>먼저 변수 영역의 빈 공간(@1002)을 확보하고 주소의 이름을 obj1로 지정한다.</li>
<li>임의의 데이터 저장 공간(@5001)에 데이터를 저장하려니 여러 프로퍼티로 이루어진 데이터 그룹이므로, 그룹 내부 프로퍼티들을 저장하기 위한 별도의 변수 영역을 마련하고 그 영역의 주소(@7103~)를 @5001에 저장한다.</li>
<li>@7103과 @7104에 각각 a, b라는 프로퍼티 이름을 지정한다.</li>
<li>데이터 영역에서 1을 검색하고, 없으므로 임의로 @5003에 저장한 뒤 이 주소를 a가 가리키도록 @7103에 저장한다. &quot;bbb&quot;도 이와 같은 과정을 거친다.</li>
</ol>
<p>위로부터 알 수 있듯 데이터 영역에 저장된 값들은 모두 불변값이지만, 객체가 별도로 할애한 영역은 &quot;변수 영역&quot;이고 여기에는 얼마든지 다른 값을 대입할 수 있다.</p>
<p>이 때문에 참조형 데이터는 불변하지 않는 값, 즉 가변값이라고 한다.</p>
<h3 id="✔️-참조-타입의-값-복사하기">✔️ 참조 타입의 값 복사하기</h3>
<p>참조 타입의 변수들은 데이터 복사가 일어날 때 값이 담긴 주솟값을 바로 복사하지 않고, 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복사한다.</p>
<pre><code class="language-javascript">var obj1 = {
  a: 1,
  b: &quot;bbb&quot;
};
var obj2 = obj1;

obj2.a = 20;

console.log(obj1.a); // 20</code></pre>
<p>위의 코드에서, obj2는 obj1이 가리키는 데이터 묶음의 주소를 복사한다. (같은 객체를 보고 있음)
그러므로 obj2에서 프로퍼티의 값을 변경하면, 같은 객체의 주소를 가지고 있는 obj1에서도 값이 변하게 되는 것이다.</p>
<p>하지만,</p>
<pre><code class="language-javascript">var obj1 = {
  a: 1,
  b: &quot;bbb&quot;
};
var obj2 = obj1;

obj2 = {
  a: 20,
  b: &quot;cc&quot;
};

console.log(obj1.a); // 1</code></pre>
<p>이처럼 복사 후 obj2에 새로운 객체를 할당해 주게 되면 메모리 데이터 영역의 새 공간에 새로운 객체가 저장되고 그 주소를 변수 영역의 obj2에 저장하게 된다!
즉 obj1과 obj2가 다른 객체를 가리키게 되므로 obj1이 가리키는 값은 달라지지 않는다.</p>
<p>이로부터 알 수 있는 점은, 참조형 데이터를 가변값이라 할 때의 &quot;가변&quot;은 참조형 데이터 자체를 변경할 때(두 번째 경우)가 아니라 <strong>그 내부의 프로퍼티를 변경할 때</strong>(첫 번째 경우)에만 성립한다는 것이다.</p>
<br/>


<h2 id="참고자료">참고자료</h2>
<p>코어 자바스크립트(위키북스, 정재남)
<a href="https://velog.io/@nomadhash/Java-Script-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC%EC%99%80-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC">[Java Script] 원시타입과 참조타입 👀</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[멋진 2022년 상반기를 위한 신년 계획 🗓]]></title>
            <link>https://velog.io/@welloff_jj/2022-first-half-plan</link>
            <guid>https://velog.io/@welloff_jj/2022-first-half-plan</guid>
            <pubDate>Mon, 10 Jan 2022 06:54:27 GMT</pubDate>
            <description><![CDATA[<p>2022년 새해가 밝았다 🌄
사실 새해가 되고 벌써 10일이나 지났지만,, 아무튼 아직 1월 초반이니까 이건 신년 계획이 맞다. 암튼 그럼.</p>
<p>2021년 회고를 쓰면서 나 그래도 꽤 성장했구나라는 걸 느꼈는데, 2022년은 거기에서 더욱 도약하는 한해가 되도록 목표를 몇 가지 설정해보려고 한다!</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/17036263-d9a5-40fe-b7f1-7014ddf0d752/image.png" alt=""></p>
<br>

<h2 id="✏️-1학기-전공학점-40-이상">✏️ 1학기 전공학점 4.0 이상</h2>
<p>올해 드디어 복학을 하게 되었다. 학교 다니는 거 다 까먹어서 두렵지만 그동안 배운 것들을 기반으로 열심히 공부한다면 학점 잘 받을 수 있지 않을까?!
이번 학기엔 특히 전공 중에서도 기초 과목들을 듣는 만큼 신경 써서 학점 잘 받고 얻어가는 게 많도록 노력해봐야겠다.</p>
<p>아직 전과(화공 -&gt; 소프트웨어) 확정 알림이 나진 않았지만, 성공 여부에 상관없이 소프트웨어 전공 과목을 들을 생각이다. 제발 전과 성공하게 해주세요 🙏🏻</p>
<p>다음 학기에 들을 전공과목은 객체지향프로그래밍및실습, 자료구조, 디지털회로, 컴퓨터네트워크, 운영체제이다. 일단은 이렇게 계획 세워 놨는데 수강신청 결과에 따라 바뀔 수도 있다 ,,,</p>
<br>

<h2 id="👯♀️-친구-사귀기">👯‍♀️ 친구 사귀기</h2>
<p>소프트웨어 전과하려는 주제에 소프트웨어학과에 아는 사람 한명도 없다 실화냐,,?
다음 학기는 all 대면이니까 복학하고 전공 과목 들으면서 수업당 한명씩은 아는 사람 만드는 걸 올해 상반기 목표로 잡아야겠다. 그래도 그전 학기들 다 비대면이라 사람들 서로 모를 것 같으니까 자연스럽게 끼어들어서 친해져야지 ,,! 라고 화석🦖이 말했습니다 ,,</p>
<br>

<h2 id="🍚-복학-전에-dye-알파알파테스트-완료">🍚 복학 전에 DYE 알파알파테스트 완료</h2>
<p>현재 진행중인 프로젝트에서 만드는 서비스 가제가 &quot;밥은먹었니?&quot;이고, 약어로 DYE라고 부르고 있어서 이렇게 적었다.</p>
<p>알파테스트 전 단계를 알파알파테스트라고 부르기로 우리끼리 정했는데, mvp 개발을 끝내고 기술적인 테스트들을 완료하는 것을 의미한다. 복학하기 전 2월까지 해서 이 단계는 꼭 마무리하고 싶다.</p>
<p>이후 알파테스트, 베타테스트를 거쳐 릴리즈될 때까지 잘 붙잡고 가볼 예정이다. 구체적인 계획이 추가된다면 여기 더 적도록 하겠다.</p>
<h2 id="👽-42서울-3서클-돌파하기-수명연장-프로젝트">👽 42서울 3서클 돌파하기 (수명연장 프로젝트)</h2>
<p>지금 42서울 카뎃으로서도 과제를 나름,, 정말 나름 꾸준히(?) 하고 있는데, 1월 10일 현재 블랙홀이 107일 남은 상태이다.</p>
<p>107이면 넉넉하지 않나? 라는 생각이 들 수도 있지만 앞으로 복학 + 프로젝트 + 42서울 병행할 생각 하면 생각만 해도 아찔하다 ,, 수업 듣고 과제 내고 프로젝트도 하는 와중에 꼭 42서울 과제도 틈틈이 챙겨서 상반기까지 3서클 돌파를 목표로 해야겠다.</p>
<p>2서클 pipex / 3서클 Philosophers &amp; minishell 이렇게 세 개의 과제가 남았는데, 꼭 끝내자..! 제발..! 좋은 동료들과 멘토님들과 하반기에도 꼭 함께할 수 있었으면 좋겠다.</p>
<br>

<h2 id="✔️-블로그-꾸준히-쓰기">✔️ 블로그 꾸준히 쓰기</h2>
<p>지금도 블로그 쓰기 스터디를 하며 노력하고 있지만 굳이 스터디가 아니더라도 꾸준히 블로깅을 하려고 한다.
적어도 기술 주제 관련 포스팅을 주에 1~2회 정도는 써야겠다 !</p>
<br>

<h2 id="⏰-생활패턴-관련-계획">⏰ 생활패턴 관련 계획</h2>
<p>생활패턴은 고칠 점이 너무 많아서 쪼개 보았다..ㅎ</p>
<h3 id="🏠-집에서-공부하겠다는-말도-안되는-소리-하지-않기">🏠 집에서 공부하겠다는 말도 안되는 소리 하지 않기</h3>
<p>방역패스 때문이라든지 하는 구체적인 이유 없이는 집에 처박혀있지 말자!
집에 있으면 공부 안 하는 거 나 스스로 너무 잘 앎</p>
<h3 id="🛏-8시간-이상-자지-않기">🛏 8시간 이상 자지 않기</h3>
<p>솔직히 8시간도 많이 자는 건데 이것보다 더 많이 자는 건 에바지,,,
일하자 정현지! 너 올해 상반기 많이 바쁘다,, 할 일 많아 😭</p>
<h3 id="📱-스크린타임-줄이기">📱 스크린타임 줄이기</h3>
<p>바쁘니까 sns랑 유튜브 보는 시간 줄이기. 보더라도 자기 전에 침대에서 뒹굴거리면서 보는 건 자제하자..!</p>
<h3 id="💤-수면-전후로-빠릿빠릿하게-움직이기">💤 수면 전후로 빠릿빠릿하게 움직이기</h3>
<p>자기 전에 폰 보다가 늦게 자지 않기, 일어나서 폰 보면서 뒹굴거리다가 늦게 일어나지 않기
수면 전후로 폰 보는 시간 30분으로 제한해 보자. 물론 자신은 없지만,,,</p>
<br>

<h2 id="🖥-개발-지식-쌓기">🖥 개발 지식 쌓기</h2>
<p>적어도 나 이건 다뤄본 적 있다! 꽤 할 줄 안다! 라고 말할 수 있을 정도의 경험과 지식 쌓기
아마 js &amp; react가 될 것 같긴 함</p>
<p><br><br></p>
<p><img src="https://images.velog.io/images/welloff_jj/post/33605816-e94f-4a09-87aa-6e511e54256e/image.png" alt=""></p>
<p>계획을 대충 세워 봤는데 올해 상반기 정말 할 일이 많다. 전과 한다고 해도 학점 채우려면 막학기까지 학점 꽉꽉 채워 들으며 살아야 하더라,,
그래도 위 짤처럼 시간 정말 빠르고 특히 20대는 더 빠르게 지나가니까, 젊을 때 열심히 살아서 나의 가치를 높여야겠다! 난 멋진 사람이니까 말이야
2022년 상반기의 정현지 파이팅 💪🏻💪🏻</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[복잡도(Complexity): 시간 복잡도와 공간 복잡도, 그리고 빅오(Big-O) 표기법]]></title>
            <link>https://velog.io/@welloff_jj/Complexity-and-Big-O-notation</link>
            <guid>https://velog.io/@welloff_jj/Complexity-and-Big-O-notation</guid>
            <pubDate>Fri, 07 Jan 2022 15:32:58 GMT</pubDate>
            <description><![CDATA[<p>자료구조와 알고리즘 공부를 하다 보면 마주치게 되는 복잡도(Complexity)와 빅오 표기법(Big-O notation) ,, 하지만 아무리 백준 문제를 풀어도 나에게 복잡도란 너무 추상적인 개념이었다 🥲
앞으로도 복잡도를 고려해 코딩하는 멋진 개발자가 되고 싶기에 한 번쯤 정리할 필요를 느껴 포스팅해본다.</p>
<br>
<br>

<h2 id="🧩-복잡도complexity와-마주하기">🧩 복잡도(Complexity)와 마주하기</h2>
<p>복잡도란,</p>
<ol>
<li>알고리즘의 성능, 효율성을 나타내는 척도</li>
<li>크게 시간 복잡도(Time Complexity)와 공간 복잡도(Space Complexity)로 나눌 수 있다.</li>
<li>각 알고리즘이 주어진 특정 크기의 입력(n)을 기준으로 수행시간(연산) 혹은 사용공간이 얼마나 되는지 객관적으로 비교할 수 있는 기준을 제시한다.</li>
<li>복잡도를 나타내는 방법으로는 점근 표기법으로 O(빅오), Ω(오메가), Θ(세타) 등이 있고, 주로 빅오와 세타 표기법이 많이 사용된다.</li>
</ol>
<p>다시 말해, 복잡도라고 말하면 이름 그대로 정말 복잡해 보이지만 그냥 <code>어떤 알고리즘이 효율적인지를 판단하는 척도</code>라고 생각하면 된다!</p>
<p>알고리즘을 평가할 때 주로 수행 시간과 메모리 사용량을 기준으로 두는데, 이 중 수행 시간에 해당하는 것이 <span style="color: rgb(32, 201, 151); font-weight: 700;">시간 복잡도</span>이고 메모리 사용량에 해당하는 것이 <span style="color: rgb(32, 201, 151); font-weight: 700;">공간 복잡도</span>이다.</p>
<br>

<h3 id="⏰-시간-복잡도-time-complexity">⏰ 시간 복잡도 (Time Complexity)</h3>
<p>시간 복잡도란 <strong>특정 크기의 입력을 기준으로 할 때 필요한 연산의 횟수</strong>를 나타낸다.</p>
<p>이름은 <code>시간 복잡도</code>이지만 실행 시간이 아닌 연산 횟수를 세는 이유는 다음과 같다.</p>
<ul>
<li>모든 OS, IDE, 플랫폼에서 동일한 결과가 나오지 않는다.</li>
<li>실행 시간 측정을 위한 또다른 방법이 필요하다.</li>
</ul>
<blockquote>
<p>💡 <span style="font-size: 18px; font-weight: 600;">더 알아보기: 알고리즘의 성능 평가 Case</span></p>
</blockquote>
<ul>
<li>최선의 경우 (Best Case)
  최적의 입력을 한 상태에서, 작업을 완료하는 데 가장 연산 횟수가 적은 경우</li>
<li>최악의 경우 (Worst Case)
  최악의 입력을 한 상태에서, 작업을 완료하는 데 가장 연산 횟수가 많은 경우</li>
<li>평균의 경우 (Average Case)
  여러 경우의 수를 고려하여, 총 연산 횟수를 계산하고 시행 횟수로 나눈 경우<blockquote>
<p>➡️ 알고리즘 분석 시 평균의 경우와 최악의 경우가 가장 많이 활용되며, 알고리즘이 복잡해질수록 평균을 구하기 어려워져 <strong>최악의 경우</strong>로 알고리즘 성능을 파악한다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="⭐️-공간-복잡도-space-complexity">⭐️ 공간 복잡도 (Space Complexity)</h3>
<p>공간 복잡도란 <strong>프로그램 실행과 완료에 얼마나 많은 공간(메모리)가 필요한지</strong>를 나타낸다.</p>
<p>알고리즘을 실행시키기 위해 필요한 공간(space)는 두 가지로 나눌 수 있다.</p>
<ol>
<li><p>알고리즘과 무관한 공간, 즉 <strong>고정 공간</strong></p>
<ul>
<li>코드가 저장되는 공간, 알고리즘 실행을 위해 시스템이 필요로 하는 공간 등</li>
</ul>
</li>
<li><p>알고리즘과 밀접한 공간, 즉 <strong>가변 공간</strong></p>
<ul>
<li>문제를 해결하기 위해 알고리즘이 필요로 하는 공간. 변수를 저장하는 공간, 순환 프로그램일 경우 순환 스택(recursion stack) 등</li>
</ul>
</li>
</ol>
<br>

<h3 id="👊🏻-시간-복잡도-vs-공간-복잡도">👊🏻 시간 복잡도 vs 공간 복잡도</h3>
<p>시간 복잡도는 얼마나 빠르게 실행되는지, 공간 복잡도는 얼마나 많은 자원(메모리 공간)이 필요한지를 판단한다.</p>
<p>시간 복잡도와 공간 복잡도는 반비례하는 경향이 있어, 보통 알고리즘의 성능을 판단할 때는 <code>시간 복잡도</code>를 위주로 판단한다.</p>
<br>
<br>

<h2 id="🅾️-빅오-표기법-big-o-notation">🅾️ 빅오 표기법 (Big-O notation)</h2>
<p>빅오 표기법(Big-O notation)은 복잡도를 나타내는 점근 표기법 중 가장 많이 사용되는 표기법이다.</p>
<p>빅오 표기법이 가장 많이 사용되는 이유는 알고리즘 효율성을 <strong>상한선 기준</strong>으로 표기하기 때문이다.
다시 말해 <strong>최악의 경우</strong>를 고려하는 데 가장 좋은 표기법이다! (알고리즘 효율성은 값이 클수록, 즉 그래프가 위로 향할수록 비효율적임을 의미)</p>
<p>첨언하자면 빅오메가는 하한선을 기준으로, 빅세타는 상한선과 하한선 사이를 기준으로 표기한다.</p>
<br>

<h3 id="📈-빅오-표기법의-수학적-정의">📈 빅오 표기법의 수학적 정의</h3>
<p>빅오 표기법의 수학적 정의는 다음과 같다.</p>
<p><span style="font-weight: 700; font-size: 18px;">O(g(n)) = {f(n) : there exist positive constants c and $ n_0 $ such that 0≤f(n)≤cg(n) for all n≥$ n_0 $}</span></p>
<p><img src="https://images.velog.io/images/welloff_jj/post/fb8c0b08-05d2-4527-9571-fb975ccb145b/image.png" alt=""></p>
<p>n0를 기준으로 n0보다 오른쪽에 있는 모든 n 값에 대해 함수 f(n)은 함수 cg(n)보다 같거나 작다는 의미이다. - 점근적 상한선</p>
<p>즉 빅오 표기법에서는 주어진 알고리즘이 아무리 나빠도 비교하는 함수와 같거나 좋다!
그래프가 아래에 있을수록 수행시간이 짧으므로 성능이 좋은 것이다.</p>
<br>

<h3 id="✏️-빅오-표기법의-특징">✏️ 빅오 표기법의 특징</h3>
<ol>
<li>상수항 무시<ul>
<li>빅오 표기법은 n이 충분히 크다고 가정하고 있고, 알고리즘의 효율성은 n의 크기에 영향을 받으므로 상수항 같은 사소한 부분은 무시한다.
➡️ O(2n)은 O(n)으로 간주</li>
</ul>
</li>
<li>영향력 없는 항 무시<ul>
<li>빅오 표기법은 n의 크기에 영향을 받으므로 가장 영향력이 큰 항 이외에 영향력이 없는 항은 무시한다.
➡️ O(n^2 + 2n + 1)은 O(n^2)으로 간주</li>
</ul>
</li>
</ol>
<br>

<h3 id="📕-시간-복잡도와-빅오-표기법">📕 시간 복잡도와 빅오 표기법</h3>
<p>시간 복잡도는 특정 크기의 입력(n)을 기준으로 실행하는 연산의 횟수이다. 다시 말해 연산의 횟수를 세면 된다.</p>
<p>그렇다면 알고리즘이 실행될 때의 모든 연산의 횟수를 세어야 하는가?
답은 <code>아니다</code>. 알고리즘에서 핵심이 되는 연산의 횟수만 세면 된다.</p>
<p>시간 복잡도를 구하는 알고리즘 예제는 <a href="https://servertrix.com/880">여기</a>와 <a href="https://ledgku.tistory.com/33">여기</a>에서 한번 보면 이해가 잘 되니 한번쯤 읽어봐야겠다. 물론 내가...</p>
<p>위의 링크에 더해, 빅오 표기법으로 시간 복잡도를 구하는 과정을 잘 정리해주신 글이 있어 가져왔다.
<a href="https://velog.io/@cksal5911/%EB%B9%85%EC%98%A4%ED%91%9C%EA%B8%B0%EB%B2%95-%EC%A0%95%EB%A6%AC-with-JS">빅오표기법 정리 - with JS</a>
포스팅 하고 나서 풀어봐야겠다.</p>
<p>시간 복잡도와 그 예시를 나열해 보면 다음과 같다.</p>
<table>
<thead>
<tr>
<th>복잡도</th>
<th>소요 시간</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>O(1)</td>
<td>상수 시간</td>
<td>스택에서 Push, Pop</td>
</tr>
<tr>
<td>O(log n)</td>
<td>로그 시간</td>
<td>이진 트리</td>
</tr>
<tr>
<td>O(n)</td>
<td>직선적 시간</td>
<td>for 문</td>
</tr>
<tr>
<td>O(n log n)</td>
<td>선형 로그 시간</td>
<td>퀵 정렬(quick sort), 병합 정렬(merge sort), 힙 정렬(heap sort)</td>
</tr>
<tr>
<td>O(n^2)</td>
<td>2차 시간</td>
<td>이중 for 문, 삽입 정렬(insertion sort), 거품 정렬(bubble sort), 선택 정렬(selection sort)</td>
</tr>
<tr>
<td>O(C^n)</td>
<td>지수 시간</td>
<td>피보나치 수열</td>
</tr>
</tbody></table>
<p><img src="https://images.velog.io/images/welloff_jj/post/f503e580-c11e-4170-bba3-5e6dd6e21c14/image.png" alt=""></p>
<p>상수함수 &lt; 로그함수 &lt; 선형함수 &lt; 다항함수 &lt; 지수함수
왼쪽에서 오른쪽으로 갈수록 성능이 떨어지며, 시간 복잡도가 좋지 않은 알고리즘이다.</p>
<blockquote>
<p>💡 <span style="font-size: 18px; font-weight: 600;">더 알아보기: 시간 복잡도를 구하는 요령</span></p>
</blockquote>
<ul>
<li>하나의 루프를 사용하여 단일 요소 집합을 반복하는 경우: O(n)</li>
<li>컬렉션의 절반 이상을 반복하는 경우: O(n / 2) -&gt; O(n)</li>
<li>두 개의 다른 루프를 사용하여 두 개의 개별 콜렉션을 반복하는 경우: O(n + m) -&gt; O(n)</li>
<li>두 개의 중첩 루프를 사용하여 단일 컬렉션을 반복하는 경우: O(n²)</li>
<li>두 개의 중첩 루프를 사용하여 두 개의 다른 콜렉션을 반복하는 경우: O(n * m) -&gt; O(n²)</li>
<li>컬렉션 정렬을 사용하는 경우: O(n*log(n))</li>
</ul>
<br>

<h3 id="📗-공간-복잡도와-빅오-표기법">📗 공간 복잡도와 빅오 표기법</h3>
<p>공간 복잡도는 알고리즘 실행에 메모리가 얼마나 사용되는지를 계산하면 된다.</p>
<p>예를 들어 크기가 n인 배열을 입력으로 주었을 때, 알고리즘이 n * n의 이차원 배열을 생성한다면 이 알고리즘의 공간 복잡도는 n^2이다.</p>
<p>알고리즘의 공간 복잡도를 계산한 후 상수항과 영향력 없는 항을 무시해 나타내면 빅오 표기법이 된다. 참 쉽죠? 😜</p>
<p>공간 복잡도는 보통 중요하게 생각하지 않는 경우가 많지만, 많은 데이터를 다루는 경우 공간 복잡도가 커지게 되면 프로그램이 메모리에 올라가지 않아 실행할 수 없게 될 수도 있다.
따라서 알고리즘 작성 시 공간 복잡도도 어느 정도 신경 써서 작성하는 것이 좋다 !!</p>
<br>

<h3 id="📘-big-o-표기법으로-나타낸-자료구조별-시간-복잡도">📘 Big-O 표기법으로 나타낸 자료구조별 시간 복잡도</h3>
<p><img src="https://images.velog.io/images/welloff_jj/post/9616633f-8462-4315-a3fd-e6a53becf48a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-08%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.29.00.png" alt=""></p>
<br>

<h3 id="📙-big-o-표기법으로-나타낸-정렬-알고리즘별-복잡도">📙 Big-O 표기법으로 나타낸 정렬 알고리즘별 복잡도</h3>
<p><img src="https://images.velog.io/images/welloff_jj/post/acac088f-45a9-4d36-94b3-f73436a17b4a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-08%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.29.50.png" alt=""></p>
<br>
<br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://ledgku.tistory.com/33">[컴퓨터 알고리즘 성능분석] 시간 복잡도 vs 공간 복잡도</a>
<a href="https://velog.io/@cksal5911/%EB%B9%85%EC%98%A4%ED%91%9C%EA%B8%B0%EB%B2%95-%EC%A0%95%EB%A6%AC-with-JS">빅오표기법 정리 - with JS</a>
<a href="https://coding-factory.tistory.com/609">[Algorithm] 알고리즘 공간복잡도에 대하여</a>
<a href="https://servertrix.com/880">시간 복잡도, 공간 복잡도</a>
<a href="https://blog.chulgil.me/algorithm/">알고리즘의 시간 복잡도와 Big-O 쉽게 이해하기</a>
<a href="https://velog.io/@leobit/%EB%B3%B5%EC%9E%A1%EB%8F%84Complexity">복잡도(Complexity) : 시간 복잡도</a>
<a href="https://noahlogs.tistory.com/27">빅오 표기법 (big-O notation) 이란</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[push_swap] 내맘대로 한 푸쉬스왑 정리해 봄]]></title>
            <link>https://velog.io/@welloff_jj/push-swap-typeup</link>
            <guid>https://velog.io/@welloff_jj/push-swap-typeup</guid>
            <pubDate>Mon, 03 Jan 2022 04:13:58 GMT</pubDate>
            <description><![CDATA[<h2 id="0-서론">0. 서론</h2>
<p>글을 시작하기에 앞서 이번 푸쉬스왑을 함께한 seunpark님(<a href="https://github.com/KOREAparksh">깃헙</a>)님께 감사의 인사를 드리고 싶다.
깐부코딩 그거 괜찮더라,,, 괜히 42가 동료학습 동료학습 하는 게 아니라는 생각이 들었다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/8191d963-5573-4d65-9b91-470900ca9690/image.png" alt=""></p>
<p>그리고 다른 가이드 글이나 코드는 거의 참고하지 않았지만 정말 유용하게 쓴 테스터는 하나 있는데 이걸 만들어주신 제작자분께도 감사,,
테스터 링크는 <a href="https://github.com/minckim42/push_swap_tester">여기</a></p>
<p>아 그리고 들어가기 전에 주의할 점이 있는데, 여기 작성되어 있는 알고리즘은 과제 기준으로 만점을 받은 건 아니라는 점이다. 만약 100점으로 통과하고 싶다면 여기 있는 알고리즘을 그대로 차용하지 말고 조금 더 생각해보고 최적화해보길 권한다.</p>
<br/>

<h2 id="1-push_swap-뭐하는-과제인가">1. push_swap 뭐하는 과제인가?</h2>
<ol>
<li>A와 B라는 두 개의 스택이 주어진다.</li>
<li>스택 A에는 임의의 개수의 정수들이 중복 없이 채워져 있다.</li>
<li>스택 B는 비어 있다.</li>
<li>스택 A와 B, 그리고 적절한 &quot;연산&quot;을 통해 A의 숫자들을 오름차순으로 정렬해야 한다.</li>
<li>과제에서 사용할 수 있는 연산은 다음과 같다.<ul>
<li><code>sa</code>: A의 가장 위에 있는 두 원소(혹은 첫 번째 원소와 두 번째 원소)의 위치를 서로 바꾼다.</li>
<li><code>sb</code>: B의 가장 위에 있는 두 원소(혹은 첫 번째 원소와 두 번째 원소)의 위치를 서로 바꾼다.</li>
<li><code>ss</code>: <code>sa</code>와 <code>sb</code>를 동시에 실행한다.</li>
<li><code>pa</code>: B에서 가장 위(탑)에 있는 원소를 가져와서 A의 맨 위(탑)에 넣는다. B가 비어 있으면 아무 것도 하지 않는다.</li>
<li><code>pb</code>: A에서 가장 위(탑)에 있는 원소를 가져와서 B의 맨 위(탑)에 넣는다. A가 비어 있으면 아무 것도 하지 않는다.</li>
<li><code>ra</code>: A의 모든 원소들을 위로 1 인덱스만큼 올린다. 첫 번째 원소(탑)는 마지막 원소(바텀)가 된다.</li>
<li><code>rb</code>: B의 모든 원소들을 위로 1 인덱스만큼 올린다. 첫 번째 원소(탑)는 마지막 원소(바텀)가 된다.</li>
<li><code>rr</code>: <code>ra</code>와 <code>rb</code>를 동시에 실행한다.</li>
<li><code>rra</code>: A의 모든 원소들을 아래로 1 인덱스만큼 내린다. 마지막 원소(바텀)는 첫 번째 원소(탑)가 된다.</li>
<li><code>rrb</code>: B의 모든 원소들을 아래로 1 인덱스만큼 내린다. 마지막 원소(바텀)는 첫 번째 원소(탑)가 된다.</li>
<li><code>rrr</code>: <code>rra</code>와 <code>rrb</code>를 동시에 실행한다.</li>
</ul>
</li>
<li><strong>최소한의 연산만을 사용</strong>해 A의 숫자들을 정렬해보자!</li>
</ol>
<br/>

<h2 id="2-복잡도complexity를-고려해-알고리즘-선택하기">2. 복잡도(Complexity)를 고려해 알고리즘 선택하기</h2>
<blockquote>
<p><strong>Sorting values is simple.</strong>
<strong>To sort them the fastest way possible is less simple</strong>, especially because from one integers configuration to another, the most efficient sorting algorithm can differ.</p>
</blockquote>
<p>값 정렬은 간단하다. 가능한 한 가장 빠르게 값을 정렬하는 것은 덜 간단하다. 특히 정수 구성마다 가장 효율적인 정렬 알고리즘이 다를 수 있기 때문이다.</p>
<blockquote>
</blockquote>
<p><em>push_swap 서브젝트로부터</em></p>
<p>복잡도(Complexity)라는 개념은 알고리즘의 효율성을 나타내는 지표로, 개발자에게 매우 중요한 개념이다.
우리는 push_swap에서 최소한의 연산만을 사용해 스택 A의 숫자들을 정렬해야 하므로 복잡도라는 개념에 대해 먼저 알아보고 이를 고려해 알고리즘을 설계해야 한다 !!</p>
<p>+) 복잡도에 대해 조금 더 자세히 알고 싶다면 이다음 포스팅인 <a href="https://velog.io/@welloff_jj/Complexity-and-Big-O-notation">복잡도(Complexity): 시간 복잡도와 공간 복잡도, 그리고 빅오(Big-O) 표기법</a>을 읽어보시길 권한다. push_swap 과제 했는데 이 정도는 알아야겠다 싶어서 열심히 정리함,,,</p>
<h3 id="⏰-정렬-알고리즘별-시간-복잡도">⏰ 정렬 알고리즘별 시간 복잡도</h3>
<p><img src="https://images.velog.io/images/welloff_jj/post/7727c3e0-c6a9-4d19-b7aa-a33ac4c858c8/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/welloff_jj/post/6c9e0839-9e52-444e-b05c-0f2535c49a7b/image.png" alt=""></p>
<p>위의 표와 부등식(오른쪽으로 갈수록 효율이 나쁨)을 보았을 때,
평균의 경우를 고려하면 가장 효율이 좋은 알고리즘은 <strong>O(n log n)</strong>인 Heap Sort, Merge Sort, Quick Sort, Smooth Sort임을 알 수 있다.</p>
<p>물론 정렬 알고리즘 그대로를 문제 해결에 적용할 수는 없지만(사용할 수 있는 연산이 정해져 있어서🥲) 어떤 정렬 알고리즘을 기반으로 나만의 알고리즘을 설계할 것인지 생각해 두는 것이 좋다.</p>
<h3 id="🤖-알고리즘-선택하기">🤖 알고리즘 선택하기</h3>
<p>평균의 경우를 고려했을 때 Heap Sort, Merge Sort, Quick Sort, Smooth Sort가 O(n log n)으로 가장 효율이 좋음을 위에서 확인했다.
그리고 내가 선택한 정렬 알고리즘은 이 넷 중 바로바로 <strong>Quick Sort</strong>이다 ⭐️</p>
<blockquote>
<p>💡 <span style="font-size: 20px; font-weight: 600;">Quick Sort를 선택한 이유</span></p>
</blockquote>
<ol>
<li>스택 2개만 사용할 수 있다는 제약이 있어 트리로 구현해야 하는 Heap Sort, Smooth Sort는 제외했다.</li>
<li>Merge Sort와 비교했을 때 pivot이라는 기준이 되는 값이 있어 구현이 쉽다.</li>
<li>pivot 기준으로 값을 비교하여 정렬하기에, pivot을 효율적으로 선택하면 알고리즘 효율을 개선할 수 있을 것 같았다! ➡️ 그런데 그것이 실제로 일어났습니다. <a href="https://ghd5262.tistory.com/25">피벗정렬에 따른 퀵정렬의 속도</a></li>
</ol>
<p>어떤 알고리즘으로 정렬할지 결정했다면 반은 끝난 것이다. 이제 노가다 그리고 노가다를 하면 된다!</p>
<br>

<h2 id="3-전처리-작업-🔨-스택-구현-인자-파싱-예외처리">3. 전처리 작업 🔨 (스택 구현, 인자 파싱, 예외처리)</h2>
<p><del>노가다의 시작</del>
알고리즘대로 값을 정렬하기 전에 먼저 해주어야 할 일들이 있다.
해야 할 일들을 나열해 보면 다음과 같다.</p>
<ol>
<li><p>과제 설명은 스택 A와 B가 이미 있는 상태에서의 일들을 설명하고 있지만 사실 우리에겐 아무것도 없으므로 스택 먼저 구현해야 한다.</p>
</li>
<li><p>구현한 스택을 사용하기 위해 Push, Pop 등의 기본 함수를 구현해야 한다.</p>
</li>
<li><p>우리가 작성한 프로그램이 인자(argv)를 받을 때 여러 개의 인자가 들어오는 경우 (인자가 없는 경우 예외처리 필요), 하나의 문자열에 여러 개의 값이 포함되어 있는 경우를 고려해 파싱하는 함수를 만들어야 한다. 예를 들면:</p>
<pre><code> $ ./push_swap &quot;1 3 7 2&quot; &quot;3 9&quot;
 $ ./push_swap 8 2 &quot;1 5&quot; 63 &quot;70 12 3&quot;</code></pre></li>
<li><p>파싱한 인자들을 검사하여 예외처리를 해야 한다. (정수가 아닌 경우, 중복이 있는 경우 등)</p>
</li>
<li><p>인자들을 스택 A에 순서대로 Push해야 한다.</p>
</li>
</ol>
<p>나는 이렇게 했다는 것일 뿐 꼭 이 순서대로 수행할 필요는 없다. 하지만 예외처리 같은 경우 서브젝트에 예시가 나와 있으니 꼭 꼼꼼하게 처리해주자 !!</p>
<h3 id="💽-스택-구현-및-스택-관련-함수-작성">💽 스택 구현 및 스택 관련 함수 작성</h3>
<p>스택을 어떤 자료구조로 구현해야 하는지에 대한 고민이 있었다 🤔</p>
<ol>
<li><p>배열
: 어차피 전체 스택의 크기는 처음 인자를 파싱할 때 알 수 있으니 (받은 인자를 따로 저장해두고 크기를 세면 될 거 같다는 생각) 배열로 구현해도 되지 않을까?!
➡️ 스택의 최대 크기는 정해져 있지만, 스택에서 원소를 Push/Pop 하면 다른 원소들을 한 칸씩 이동시켜주어야 한다는 귀찮음이 있어 기각</p>
</li>
<li><p>단방향 연결리스트
: 스택 크기만큼 node를 할당해 값을 넣어주면 되고, Push/Pop도 node를 free해주거나 생성해서 연결해주면 되니까 이거 괜찮을 거 같다!
➡️ 단방향으로 구현했을 시 node의 오른쪽 값밖에 볼 수 없어 값 비교나 타 연산에 제약이 생기므로 기각</p>
</li>
<li><p><strong>양방향 연결리스트</strong>
: 공간 복잡도가 단방향 연결리스트에 비해 크지만, 연산에 제약이 줄고 알고리즘 설계할 때 편하므로 채택 !!</p>
</li>
</ol>
<p>위와 같은 이유로 양방향 연결리스트로 스택을 구현하기로 했고, 헤더 파일에 다음과 같이 코드를 작성했다.</p>
<pre><code class="language-c">// push_swap.h

typedef struct s_node
{
    int                val;
    struct s_node    *left;
    struct s_node    *right;
}    t_node;

typedef struct s_stack
{
    struct s_node    *top;
    struct s_node    *bottom;
}    t_stack;</code></pre>
<p>stack 구조체에서 top과 bottom은 의미 없는 임의의 값을 가진 node로, 스택의 top과 bottom을 가리킨다. 스택 순회를 조금 더 간편하게 하기 위해 넣어 주었다.</p>
<p>그리고 스택 관련 함수들을 작성했다.</p>
<pre><code class="language-c">// push_swap.h

/*util_stack.c*/
t_node        *get_new_node(int num);
void        init_stack(t_var *var);
void        push_top(t_stack *stack, t_node *new_node);
void        push_bottom(t_stack *stack, t_node *new_node);
t_node        *pop_top(t_stack *stack);
t_node        *pop_bottom(t_stack *stack);</code></pre>
<p><img src="https://images.velog.io/images/welloff_jj/post/afbf8050-0935-41aa-a2d5-4f235e432ed7/image.png" alt=""></p>
<p>스택은 큐와 다르게 후입선출이지만, push_swap에서는 정해진 연산을 사용해 스택을 정렬하므로 연산 사용의 편의성을 위해 push, pop을 top과 bottom에서 둘다 가능하도록 했다.</p>
<h3 id="🥸-인자-파싱-및-예외-처리">🥸 인자 파싱 및 예외 처리</h3>
<pre><code>$ ./push_swap &quot;1 3 7 2&quot; &quot;3 9&quot;        -&gt;    1 3 7 2 3 9
$ ./push_swap 8 2 &quot;1 5&quot; 63 &quot;70 12 3&quot;    -&gt;    8 2 1 5 63 70 12 3</code></pre><p>어떻게 하면 멋지게 argv를 파싱해 정수값을 스택에 넣을 수 있을까?
나는 argv에서 해답을 찾았다. 각 인자 하나하나(문자열)에 대해 정수값을 찾아주면 된다고 생각했다.</p>
<p>그래서 생각한 전처리 로직을 간단하게 작성해 보면 다음과 같다.</p>
<pre><code class="language-c">i = 0; // 첫 인자는 프로그램의 이름이므로 그 다음 인자부터
while (++i &lt; argc)
{
    j = -1;
    while argv[i][++j]가 널 문자가 아닌 경우
    {
        if argv[i][j]가 널 문자가 아니고 공백 문자도 아닌 경우, 즉 숫자나 문자인 경우
        {
            from = argv[i][j];
            while argv[i][j]가 숫자나 문자인 경우
                j++; // 다음 공백 문자를 찾기 위함
            to = argv[i][j]; // 널 문자 혹은 공백 문자를 가리킴
            ft_atoi(from, to); // atoi 함수로 정수로 변환
            변환한 정수의 개수를 count
            변환한 정수를 스택에 push
        }
    }
}</code></pre>
<p>들어온 값이 숫자가 아닌 경우의 예외 처리는 atoi 함수 내에서 해줘도 되고, atoi 함수의 반환값을 이용해 바깥에서 해도 된다.
INT_MAX, INT_MIN의 경우도 예외처리해야 하니 주의할 것!
중복 검사는 스택에 모든 값들을 다 push한 후 스택을 순회하며 수행했다.</p>
<h3 id="☑️-pivot을-선택하기-위해-정렬된-배열-만들기">☑️ pivot을 선택하기 위해 정렬된 배열 만들기</h3>
<p>아까 위에서 잠깐 언급했듯 Quick Sort는 pivot 설정에 따라 효율이 달라질 수 있다.
그 중에서도 pivot을 중앙값으로 설정할 경우 가장 효율적으로 정렬할 수 있기에 pivot을 똑똑하게 선택할 수 있도록 하고 싶었다.</p>
<p>고민해 본 결과, 내가 그렇게 하기 위해 선택한 방법은 <strong>스택 이외 다른 메모리 공간에 같은 값들을 저장</strong>하고, <strong>이 값들을 정렬해 가지고 있도록</strong> 하는 것이었다. 스택의 값들을 배열에 복사하고, 이 배열에 있는 값들을 퀵정렬 함수를 이용해(여기에서는 어떤 정렬 알고리즘을 사용해도 상관없다) 정렬해 스택이 들어 있는 구조체에 넣어 주었다.</p>
<p>참고로 스택이 들어 있는 구조체는 아래와 같이 생겼다.</p>
<pre><code class="language-c">// push_swap.h

typedef struct s_var
{
    int                max_size;
    int                *pivot_arr; // pivot을 뽑기 위해 정렬해 둔 배열
    struct s_stack    *stack_a;
    struct s_stack    *stack_b;
    struct s_list    *list;
    int                a_size;
    int                b_size;
}    t_var;</code></pre>
<p>tmi를 하나 덧붙이자면 원래는 배열 정렬할 때 기수정렬 적용하려다가 음수까지 한 번에 처리하는 게 안 된다는 사실을 알게 되어 퀵정렬로 바꿨다,,,</p>
<p>아무튼 여기까지 했다면 이제 스택을 정렬하기 위한 준비는 완료되었다.
이제 주어진 연산들을 이용해 스택 A를 정렬하면 된다!</p>
<br>

<h2 id="4-스택-정렬하기">4. 스택 정렬하기</h2>
<p>자료구조와 정렬할 때 사용할 수 있는 연산이 정해져 있다. 즉 제약이 제법 많다..!</p>
<p>이 제약들 안에서 내가 선택한 알고리즘을 어떻게 적용하여 나만의 알고리즘을 만들지 생각해보아야 한다.</p>
<blockquote>
<p>⚠️ 주의! 이 뒤의 내용에는 글쓴이의 주관적인 알고리즘이 담겨 있습니다.</p>
</blockquote>
<p>나는 Quick Sort를 사용하기로 결정했고, 내가 접해 본 퀵소트는 단 하나의 피벗을 사용하는 <strong>Single Pivot Quick Sort</strong>였기에 이것을 적용해보기로 마음먹었다. 다시 말하지만 내 주관적인 알고리즘이고 나는 100점을 받지는 못했다는 점을 기억해 주시길 바란다 ,,,!!</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/cb4bfa76-a17c-4512-ad04-1808e0df5ea4/image.png" alt=""></p>
<p>일반적인 퀵소트는 피벗을 설정할 때 랜덤으로 설정하지만, 내가 하려는 퀵소트에서는 피벗을 중앙값으로 설정하므로 위 그림과 같다. 위 그림과 다른 점은, 나는 피벗을 기준으로 절반은 다른 스택에 보내고 나머지 절반에서 다시 피벗을 잡아 정렬한다는 점?!</p>
<h3 id="💬-pseudo-code">💬 Pseudo Code</h3>
<p>전체적으로는 재귀함수를 사용해 A를 정렬한 뒤 B를 정렬하고 B에서 A로 원소를 보내주는 방식이다.
pseudo code로 나타내 보면 다음과 같다.</p>
<pre><code class="language-c">re(재귀에 필요한 파라미터) // 최초로 재귀함수를 호출하는 함수
{
    if (현재 스택의 가변 크기가 일정 크기 이하)
            정렬하고 return ;
        reA(재귀에 필요한 파라미터); // A를 정렬하는 재귀함수
        reB(재귀에 필요한 파라미터); // B를 정렬하는 재귀함수
          while (B에서 A로 보내야 할 원소의 수--)
            pb();
}</code></pre>
<h3 id="🎨-도식화해보기">🎨 도식화해보기</h3>
<ol>
<li>정렬하기 전 상태</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/4fef6b2c-8949-454f-8a9c-2286f7123604/image.png" alt=""></p>
<ol start="2">
<li>피벗을 잡아 절반을 다른 스택으로 보냄<ul>
<li>나의 경우 피벗보다 같거나 작은 값은 B에서 내림차순 정렬, 큰 값은 A에서 오름차순 정렬함 - 마지막에 스택 B에서 pb 명령어로 원소들을 스택 A에 보내줄 때 용이하도록</li>
<li>피벗보다 같거나 작은 값은 pb로 B에 보내고, 큰 값은 ra로 뒤로 넘겨줌</li>
</ul>
</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/6c36bd9b-82cb-4166-9bfa-829c7a686292/image.png" alt=""></p>
<ol start="3">
<li>현재 스택의 가변 크기가 일정 크기 이하일 때까지(여기에서는 2) 재귀함수 안으로 들어가며 절반을 다른 스택으로 보냄</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/5f2482be-644f-4c8e-b1a7-be6362e69f88/image.png" alt=""></p>
<ol start="4">
<li><p>현재 스택의 가변 크기가 일정 크기 이하가 되면 정렬, 위의 경우 A가 이미 오름차순 정렬되어 있으므로 생략</p>
</li>
<li><p>정렬 완료했다면 다른 스택으로 넘어감, 마찬가지로 가변 크기가 일정 크기 이하이면 정렬</p>
</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/76f36e14-42c0-4694-85b8-4297d838e4dc/image.png" alt=""></p>
<ol start="6">
<li>정렬 완료 후 현재 스택이 B였다면 정렬 완료된 원소들을 A로 보냄</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/fae29567-5708-4c77-84f6-6cbd776c06de/image.png" alt=""></p>
<ol start="7">
<li>크기 4일 때 A의 정렬은 완료되었으므로, 다시 B로 넘어와 피벗을 잡아 절반을 다른 스택으로 보냄</li>
</ol>
<p><img src="https://images.velog.io/images/welloff_jj/post/22d16ef4-e3b1-42a2-9227-635911c8cece/image.png" alt=""></p>
<ol start="8">
<li>위와 비슷하게 잘 반복</li>
</ol>
<p>이런 식으로 정렬했다. 나름 열심히 정리해 봤지만 그래도 혹시 이해가 잘 안 되신다면 댓글 남겨주세요 ..!</p>
<h3 id="🤔-몇-개까지-쪼갠-후-정렬할-것인가">🤔 몇 개까지 쪼갠 후 정렬할 것인가?</h3>
<p>이 부분은 많은 분들에게 조언을 얻어 본 결과 보통 5개부터 정렬을 하드코딩으로 처리하시는 것 같았다.
그치만 나는 4개부터 처리했고, 그나마도 하드코딩으로 했을 때 확실히 명령어가 더 적게 나오는 경우에만 따로 정렬해 주었다. 3개 이하부터는 무조건 하드코딩으로 처리했다.</p>
<p>이 부분은 아무래도 직접 해보면서 최적화하는 게 가장 좋은 것 같다.</p>
<br>

<h2 id="5-사용한-연산명령어-최적화하기">5. 사용한 연산(명령어) 최적화하기</h2>
<p>push_swap 과제를 진행하면서 내가 마지막으로 한 일은 바로 스택을 정렬하기 위해 사용한 연산들을 (물론 최소한의 연산을 사용하기 위해 노력했지만) 최적화해보는 것이었다.</p>
<p>리마인드해보자면 스택을 정렬하기 위해 우리에게 주어진 연산은 다음과 같았다.</p>
<blockquote>
</blockquote>
<ul>
<li><code>sa</code>: A의 가장 위에 있는 두 원소(혹은 첫 번째 원소와 두 번째 원소)의 위치를 서로 바꾼다.</li>
<li><code>sb</code>: B의 가장 위에 있는 두 원소(혹은 첫 번째 원소와 두 번째 원소)의 위치를 서로 바꾼다.</li>
<li><code>ss</code>: <code>sa</code>와 <code>sb</code>를 동시에 실행한다.</li>
<li><code>pa</code>: B에서 가장 위(탑)에 있는 원소를 가져와서 A의 맨 위(탑)에 넣는다. B가 비어 있으면 아무 것도 하지 않는다.</li>
<li><code>pb</code>: A에서 가장 위(탑)에 있는 원소를 가져와서 B의 맨 위(탑)에 넣는다. A가 비어 있으면 아무 것도 하지 않는다.</li>
<li><code>ra</code>: A의 모든 원소들을 위로 1 인덱스만큼 올린다. 첫 번째 원소(탑)는 마지막 원소(바텀)가 된다.</li>
<li><code>rb</code>: B의 모든 원소들을 위로 1 인덱스만큼 올린다. 첫 번째 원소(탑)는 마지막 원소(바텀)가 된다.</li>
<li><code>rr</code>: <code>ra</code>와 <code>rb</code>를 동시에 실행한다.</li>
<li><code>rra</code>: A의 모든 원소들을 아래로 1 인덱스만큼 내린다. 마지막 원소(바텀)는 첫 번째 원소(탑)가 된다.</li>
<li><code>rrb</code>: B의 모든 원소들을 아래로 1 인덱스만큼 내린다. 마지막 원소(바텀)는 첫 번째 원소(탑)가 된다.</li>
<li><code>rrr</code>: <code>rra</code>와 <code>rrb</code>를 동시에 실행한다.</li>
</ul>
<p>예를 들면 <code>sa</code>를 수행하고 이후에 바로 <code>sb</code>를 수행했다면, 이 두 명령어는 <code>ss</code>라는 명령어 하나로 압축될 수 있다.
또 다른 예를 들면 <code>ra</code>를 수행하고 이후에 바로 <code>rra</code>를 수행했을 경우에는 두 명령어가 상쇄되므로 삭제할 수 있다.</p>
<p>이런 경우의 수들을 잘 생각해 보고 상황에 맞게 잘 최적화해주면 연산 최종 개수가 정말 많이 줄어드는 것을 확인할 수 있다. 단, 이렇게 최적화를 하려면 연산을 하나 수행할 때마다 바로바로 명령어를 출력해서는 안 된다. 나의 경우에는 메모리 공간 어딘가에 명령어 리스트를 잘 저장해 뒀다가 스택 정렬이 끝나고 나서 리스트를 최적화해 한꺼번에 출력하였다.</p>
<p>명령어 리스트는 다음과 같이 구현했다.</p>
<pre><code class="language-c">// push_swap.h

typedef struct s_list_node
{
    char                *val;
    struct s_list_node    *left;
    struct s_list_node    *right;
}    t_list_node;

typedef struct s_list
{
    struct s_list_node    *top;
}    t_list;</code></pre>
<p>이 또한 스택을 구현했을 때처럼 노드 탐색에 용이하도록 양방향 연결리스트로 구현하였다.</p>
<br>

<h2 id="6-마치며">6. 마치며</h2>
<p>push_swap 마치고 평가 받은 지는 꽤 됐는데 막상 글로 정리하려니 힘들어서 생각보다 오래 걸렸다 😝</p>
<p>다시 한 번 강조하지만 내가 여기에 쓴 알고리즘으로는 평가표 기준 100점을 받을 수 없다,,, 
다만 나는 알고리즘을 뜯어 고치려면 다시 처음부터 해야 하다 보니 엄두가 안 나서 그냥 제출한 것일 뿐,,,</p>
<p>그러니 이 글을 읽으시는 분들은 100점을 받고 보너스까지 하고 싶으시다면 꼭 자신만의 알고리즘을 잘 생각해보시고 최적화도 열심히 해보셨으면 좋겠다...!! 예를 들면,</p>
<ul>
<li>피벗 기준으로 값을 보내거나 뒤로 돌릴 때, 이미 보내야 할 값들이 다 보내졌다면 더이상 돌리지 않도록 최적화하면 더 명령어 개수를 줄일 수 있을 것 같다.</li>
<li>피벗 기준으로 값을 다 보내고 뒤로 돌린 원소들을 다시 앞으로 가져올 때, 아래에 고정되어 있는 원소들이 없다면 굳이 앞으로 가져오는 명령어를 쓰지 않게 하면 더 줄일 수 있을 것 같다.</li>
</ul>
<p>이런 식으로 많은 생각들을 해보시면서 자신만의 push_swap을 멋지게 만들어 보셨으면 좋겠다!
모든 42서울 카뎃 화이팅 💪🏻💪🏻</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도전의 연속이었던 2021년 회고하기 ✨]]></title>
            <link>https://velog.io/@welloff_jj/Looking-back-on-2021</link>
            <guid>https://velog.io/@welloff_jj/Looking-back-on-2021</guid>
            <pubDate>Fri, 31 Dec 2021 09:15:37 GMT</pubDate>
            <description><![CDATA[<p>회고를 시작하기 앞서 올해를 정말 잘 표현할 수 있는 짤을 가져와봤다.
개발자라면 모두 알고 있을 바로 그 짤 😎</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/e26dad74-f079-407c-803c-e9134d64a4d0/image.png" alt=""></p>
<p>이 짤을 쓴 이유는,
올해 일을 시작할 때 계획을 세우고 시작하기보단 그냥 얼레벌레 시작한 일들이 많았는데
그렇게 시작한 일들이 어쨌든 나에게 경험이 되고 밑거름이 되었기 때문..
심지어 과정도 순탄치는 않았지만 아무튼 지나고 보니 의도한 대로 됐다 이말이야 😏</p>
<p>처음으로 한 해를 회고하는 글을 쓰려 하니 매우 어색하고 뭘 써야 할지 모르겠는 관계로
시간순으로 한 해를 되돌아보며 생각나는 대로 글을 써보려 한다 !</p>
<br/>

<h2 id="🥲-전과-실패">🥲 전과 실패</h2>
<p>2020년 원래 전공이었던 화학공학과에서 소프트웨어학과로 전과를 결심했다.
그리고 2020-2학기에 소프트웨어학과 전공 과목들을 들은 후 <del>(공부 열심히 함ㅎ)</del> 전과 신청을 해서 2021년 1월에 전입 면접을 봤다.
잔뜩 부푼 맘으로 기다렸지만 결과는 실패 💩</p>
<p>이유는 전입 면접 때 학과장님이 말씀하셨던 것에서 찾을 수 있었다. 학과장님은 요렇게 말씀하셨다:
<code>전공 몇 개 들었다고 이 분야에 적응을 잘 할 수 있는 게 아니다. 전공 과목을 몇 개 더 듣고 다시 신청해라.</code></p>
<p>근데 뭐 이유야 어찌 됐건 실패는 실패고,,, 내심 붙을 줄 알았기도 해서,,,
결과 나온 후로 잠시 동안은 번아웃 + 무력감 때문에 좀 쉽지 않은 시기를 보냈다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/325a93c3-0780-4d92-89d9-47fa6b3240cc/image.png" alt=""></p>
<p>회고 쓰려고 짤 찾다 보니 당시의 나와 비슷해보이는 걸 찾아서 들고 왔는데, ㄹㅇ루 하루종일 침대에 누워있었음
누워서 유튜브 보고 게임 좀 하면 하루 뚝딱..ㅋㅎ</p>
<br/>

<h2 id="🚀-42서울-카뎃이-되기까지">🚀 42서울 카뎃이 되기까지</h2>
<h3 id="🙋🏻♀️-42서울-라피신la-piscine-과정에-지원하다">🙋🏻‍♀️ 42서울 라피신(La Piscine) 과정에 지원하다</h3>
<p>그렇게 나름대로 힘든 시기를 보내면서 전과 후기 찾아보고 에브리타임(대학생 커뮤니티) 어플을 껐다켰다 하던 와중에 에브리타임에 42서울 광고 배너가 뜬 걸 보게 되었다.</p>
<blockquote>
<p><strong>42서울이 대체 뭔가요?</strong></p>
</blockquote>
<p>그렇게 물으신다면 대답해 드리는 게 인지상정!
<code>(재)이노베이션 아카데미의 소프트웨어 개발자 양성 프로그램입니다. 교수, 교재, 학비가 없는 3무 교육 프로그램.</code> 이라고 홈페이지 소개에 써 있다.</p>
<blockquote>
</blockquote>
<p>3무 교육 프로그램이다 보니 동료학습을 지향하고, 전액 무료로 교육과정이 운영되며 과기부에서 지원을 받고 있어 본과정 교육생의 경우 2년간 한 달에 세전 100만원씩을 받으며 공부할 수 있다.
혜택이 있는 만큼 선발 과정이 나름 빡센데, 한 달간의 라피신(La Piscine)이라 불리는 선발과정에 합격해야 본과정에 올 수 있다. 합격/불합격의 기준은 밝혀진 바 없다.</p>
<blockquote>
</blockquote>
<p>더 궁금한 점이 있다면 <a href="https://whitepaper.innovationacademy.kr/">이노베이션 아카데미 백서</a>를 참고하면 좋을 것 같다.</p>
<p><strong>내가 진짜 이 분야로 진로를 바꿔도 될까?</strong> 에 대한 확신이 없던 상황에서 그 배너를 보니, 42서울 선발 과정인 라피신이 나에게 그 확신을 줄지도 모른다는 생각이 들었다. 결과야 어떻게 되든 <strong>치열하게 코딩하는 경험</strong>을 한번쯤 해봐야겠다는 생각도 강하게 들었고.</p>
<p>그래서 친구 진짜 없는데 여기저기 선착순 뚫는거 도와달라고 연락해서 결국 체크인 뚫고 라피신 뚫어서 신청 성공 🎉 이때 라피신 신청 도와준 친구한테 아직도 종종 고마워하며 지내는 중이다.
이건 tmi긴 한데 그 친구는 지금 군인이다. 회고 글만 쓰고 인편(인터넷편지) 하나 써야겠다,,,</p>
<h3 id="🌊-라피신la-piscine을-겪으며-">🌊 라피신(La Piscine)을 겪으며 ..</h3>
<p>치열한 선착순을 뚫고 신청한 라피신... 참고로 나는 4기 1차였고, 라피신 끝나자마자 쓴 후기글은 <a href="https://velog.io/@welloff_jj/42seoul-4%EA%B8%B0-1%EC%B0%A8-La-Piscine-%ED%9B%84%EA%B8%B0">여기</a> 있다.
<del>근데 지금 보니까 많이 부실하네</del></p>
<p>이런저런 일들을 많이 겪었지만 아무튼 42의 <strong>동료학습</strong>에 나는 매료되었고 정말정말 본과정에 가고 싶다는 생각에 치열하게 매일 코딩하며 살았던 것 같다.
라피신이 프랑스어로 수영장이라는 뜻이라고 했던 것 같은데, 진짜 수영장에 던져놓고 알아서 수영해라 ! 이런 느낌이라 처음엔 많이 생소했지만 그냥 그런 점들마저도 난 즐거웠다. <del><strong>안 힘들었단 건 아님</strong></del></p>
<p><img src="https://images.velog.io/images/welloff_jj/post/8a69879e-b031-421c-98dd-e38ec9fdca51/image.png" alt=""></p>
<p>인상적이었던 점을 요약해보자면</p>
<ul>
<li>동료의 학습 내용을 평가하며 나도 얻어가는 게 많다는 점</li>
<li>혼자 하는 것보다 깐부가 있는 게 좋구나 ...! (심적인 쪽에서도 개발 쪽에서도 의지가 많이 됨)</li>
<li>열심히 하면 뭐라도 된다. 맨 위 짤 참조</li>
</ul>
<p>이 정도인 것 같다.
과제 관련 이야기도 하고 싶지만 그건 유출하면 소송 당할 수도 있어서 아쉽지만 언급하지 않겠다.
그치만 이거 하나는 말할 수 있을 것 같다. <strong>내 인생에서 젤 공부 열심히 하던 한 달이었다는 거 ・ ・ ・</strong>
격일제 출석이었음에도 동료들과 스터디를 만들어 클러스터에 못 가는 날은 따로 스터디룸 잡고 모여서 열심히 코딩했고, 시험 전날엔 밤 새고 다음날 아침에 맥도날드 가서 맥모닝 먹고 시험 보러 갔는데 증말 피곤해서 시험장에서 졸면서 시험봤던 기억이 난다 😏</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/c0bfa169-9fa1-4312-a657-b80697f3eeb2/KakaoTalk_Photo_2021-12-31-16-07-59.jpeg" alt=""></p>
<p>밤 새는데 도저히 아예 안 잘 수 없어서 빈백에서 누워서 자던 불쌍한 내 사진,,,
저때 같이 공부하던 동료들이 너 왜그렇게 불쌍하게 자냐고 슬퍼해줬던 기억이 난다.
그치만 후회는 없다 왜냐하면 그 결과로 이렇게!</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/977904e6-55c8-4088-a173-9dffc2c1ae60/image.png" alt=""></p>
<p>합격 메일을 받을 수 있었기 때문 ✨</p>
<br/>

<h2 id="🖥-42서울-본과정-카뎃으로서의-삶">🖥 42서울 본과정: 카뎃으로서의 삶</h2>
<p>위에는 바로 합격 메일 받은 것처럼 썼지만 사실 뻥이다. (?)
실제로 합격/불합격 여부를 알게 된 건 라피신 끝나고 한 달쯤 후였다. 난 4기 1차인데 4기 2차 라피신이 끝난 후 한 번에 결과 메일이 발송되기 때문에, 결과 알기 전 한 달 동안은 결과를 기다리면서 최선을 다해 쉬고 열심히 노는 시간을 보냈다.</p>
<p>그러다 라피신 합격 메일을 받은 게 4월 23일이고 (받은 시간 보니까 4시 43분이었다. 4:42에 보내시려다가 딜레이 생긴 것 같은데,,, 아무튼 42에 과몰입한 사람들 너무 많다 🤦🏻‍♀️) 본과정 정식 입과일은 5월 3일이었다.
사실 합격의 기쁨 + 한 달 동안 열심히 공부했던 것의 반작용으로 이후 몇 달간 과제 설렁설렁 하고 띵가띵가 놀면서 시간을 보냈다. 쉴 땐 시간 정말 잘 가더라 ・ ・ ・
<del>(대충 아무것도 안하고 있지만 더 격렬하게 아무것도 안하고 싶다 짤)</del></p>
<p>그래도 나름 열심히 살아보겠다고 자료구조 스터디도 하고 -&gt; 벨로그에 쌓인 수많은 백준 문제 풀이 글들
본과정 과제도 혼자 하면 안 하니까 동료들과 스터디 하면서 끝내보기도 하고 -&gt; 벨로그에 존재하는 42서울 관련 글들
그렇게 살았다.</p>
<h3 id="👩🏻💻-python-django로-웹이랑-인사하기">👩🏻‍💻 Python-Django로 웹이랑 인사하기</h3>
<p>시간 순서가 약간 안 맞지만, 중간에 42서울 본과정의 웹 피신 과정에 등록해서 Python-Django로 처음으로 웹 프로그래밍을 접할 기회가 있었다.</p>
<p>방금 커밋 날짜 확인해보니까 7월 말부터 시작한 것 같다. 전에 Python을 제대로 해본 적도 없는데 달려들었던 거다 보니 빠르게 따라갈 순 없었고 얼레벌레 웹 피신이 마무리되었지만 나에게 <code>오.. 이거 좀 재밌는데?</code> 라는 감상을 주는 과정이었다.
이때 했던 과제들의 결과물은 내 깃헙에 소중하게 올라가있다. 하지만 너무 기초적이라 부끄러우니 링크는 걸지 않겠다 !!!!
그나마 덜 부끄러운 <a href="https://github.com/gghotted/moviemon">팀과제</a> 하나만 걸어놔야지 ,,,</p>
<h3 id="👩🏻💻-javascript로-웹이랑-친해지기">👩🏻‍💻 JavaScript로 웹이랑 친해지기</h3>
<p>Python-Django 웹 피신을 하면서 웹한테 약간 호감이 생긴 상태에서, 어쩌다 슬랙에 올라온 42JS 피신이 열린다는 공지를 보게 되었고 재밌어 보이길래 바로 신청했다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/0b8c8f0b-bc3a-4df9-b2e9-c13d09918195/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.45.17.png" alt=""></p>
<p>개인적으로 Python-Django 웹피신을 하면서 느꼈던 것 중 하나가 <strong>front-end와 back-end가 강하게 결합되어 있는 것 같다</strong>는 것이었는데, 호불호가 있겠지만 나에게는 불호였다. 굉장히 경직된 느낌이었달까..?
<em>코딩알못이라 정확한 비교는 당연히 불가하다 그냥 나한테 그런 느낌이었다는 것 😓</em></p>
<p>그런 와중에 접한 <strong>JavaScript</strong>는 굉장히 신기한 언어였다. 특히 라피신과 본과정을 거치면서 C언어에 찌들어버린 나에겐 너무 융통성 있고 nice한 언어로 느껴졌다. 이때의 충격(?) 때문에 아직까지 React를 사용하고 있다 ㅋㅎ (근데 이젠 TypeScript를 써서 그런지 그때의 나이스함은 못 느끼는 중)</p>
<p>JavaScript의 J 자도 몰랐던 내가 비동기가 뭔지 알게 되고, 리액트로 간단한 웹 프론트를 만들 수 있게 되고, 노드로 정말정말 티끌같지만 아무튼 api를 작성할 수 있게 되고, 팀과제로 이상하게 작동하는 (글 맨 첫번째 짤 참조) 웹사이트를 얼레벌레 만들 수 있게 되었다.</p>
<p>이때 했던 과제물들은 <a href="https://github.com/Hyeonji-Jung/piscine">깃허브 레포</a>에 있고,
팀과제는 <a href="https://github.com/from97/piscine-rush00">동작하지 않는 무언가</a>에 있다. 근데 퀄리티가 0에 수렴하는..</p>
<p>열심히 하면 뭔가 되긴 하더라!(글 맨 첫번째 짤 참조)라는 인생의 진리를 다시 한 번 깨닫는 시간이었다.
이렇게저렇게 하다 보니 피신을 완주해서 아래와 같은 수료증(?)도 발급받았다. 되게 예쁨</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/9c779abd-efd9-45f0-ae7c-7f3694edec17/hyeojung.svg" alt=""></p>
<p>참고로 내가 참여한 42JS 피신은 베타 버전이었고 깃허브에 아카이빙되어있다.
링크: <a href="https://github.com/42js/js-piscine-beta-2021-08">과제</a> <a href="https://github.com/42js/js-piscine-beta-2021-08-rush00">팀과제1</a> <a href="https://github.com/42js/js-piscine-beta-2021-08-rush01">팀과제2</a></p>
<h3 id="🏃🏻♀️-토이프로젝트를-해보려던-나날들">🏃🏻‍♀️ 토이프로젝트를 해보려던 나날들</h3>
<p>JavaScript를 하면서 웹이랑 나름 친해진 것 같아 더 진지한 관계로 발전시켜 보고 싶다는 마음이 들었다.
그래서 라피신부터 본과정, 그리고 42JS 피신까지 같이한 한 동료분과 42GG라는 토이프로젝트를 기획했다.</p>
<p>깃허브 링크는 <a href="https://github.com/nfl1ryxditimo12/42GG/tree/develop">여기</a></p>
<p>대충 소개해 보자면 <a href="https://www.op.gg/">op.gg</a>처럼 42서울 카뎃들의 현재 상태, 랭킹, 통계 등을 보여주는 웹 사이트였다.
하지만 설계 단계에서 김수보 멘토님의 가감없는 멘토링을 받고,, 엄청난 고민 끝에 프로젝트 진행을 하지 않기로 했다.</p>
<p>이유는 다음과 같았다.</p>
<ul>
<li>기술보다는 노가다가 필요한 게시판형 프로젝트이다. 즉 투자하는 시간 대비 얻을 수 있는 것이 많지 않다.</li>
<li>기획이 추상적이다.</li>
<li>직접 작성하는 API가 아닌 외부 API에 의존해야 하고, 외부 API가 불안정하다.</li>
</ul>
<p>그렇게 처음으로 설계하고 진행하려 했던 프로젝트를 엎었고 나름 괜찮은 아이디어라 생각했기에 조금 슬펐다.
이 경험을 통해 가장 크게 느낀 점은</p>
<blockquote>
<p>나는 나를 정말 <strong>긍정적</strong>으로 평가하는구나 ..!</p>
</blockquote>
<p>였다.
자기애가 너무 넘친 나머지 내가 설계한 건 다 좋아 보이고 예뻐 보이는 병에 걸리고 말았던 것이다..
이후로 프로젝트 기획을 할 때는 많은 경우의 수를 생각해보려 노력하고 있다.</p>
<h3 id="👾-we-make-a-piscine-해커톤">👾 &quot;We make a Piscine&quot; 해커톤</h3>
<p>토이프로젝트를 엎고 다음은 뭐 하지..? 라는 생각이 들 때쯤 42서울 슬랙 announcement 채널에 해커톤 관련 공지가 올라왔다. 보통 해커톤이라 하면 코딩해서 열심히 뭔갈 만드는 걸 상상하겠지만, 이번 해커톤 주제는 <strong>&quot;We make a Piscine&quot;</strong> 이었다. 지정된 기간 동안 주제에 대해 강의, 교재, 교수 없이 동료학습만을 통해 빡세게 학습할 수 있도록 서브젝트를 만들면 되는 고런 것,,</p>
<p>나는 ulee(<a href="https://github.com/usanglee">깃허브</a>), seonkim(<a href="https://seongsu.me/">블로그</a>)님과 팀을 이루었고 우리 팀 주제는 <strong>창업</strong>이었다.
감사하게도 창업 정부지원 관련해 심사위원으로 계시는 노정인 멘토님을 매칭받아 멘토링을 받으며 해커톤을 진행할 수 있었다.</p>
<p>두괄식 기법을 좋아해서 결과물을 먼저 요약하자면 아래와 같다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/e911f228-1fb4-4dae-805f-ae751722a79f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.29.38.png" alt=""></p>
<p>그리고 다음은 서브젝트 맛보기 😉</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/10b25871-d89c-42bb-8e6e-8433b36aa0db/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.30.26.png" alt=""></p>
<p>해커톤을 시작하며 처음 기획한 것과는 상당히 다른 결과물이 나왔는데, 구체적으로 어떤 점이 다르냐면:</p>
<ol>
<li>피시너들이 기획, 개발, 판매를 모두 겪어볼 수 있게 하자 -&gt; 기획 및 사업계획서 작성을 제대로 배울 수 있게 하자</li>
<li>방향을 제시하되, 세부적인 사항은 피시너들의 자유로 두자 -&gt; 가이드라인을 제시하자</li>
</ol>
<p>1번의 경우 사실 기획, 개발, 판매는 따로 가는 게 아니라 같이 가야 하는데 (노정인 멘토님의 말씀) 이걸 단계별로 나누고 학습한다는 것 자체가 조금 이상하기 때문 + 사업기획서 작성을 위해 우리 팀이 직접 사업계획서 작성을 해본 결과 개발자가 처음부터 사업계획서 작성을 하면 개판인 결과물이 나온다는 걸 알았기 때문이었다.</p>
<p>2번은 1번과 비슷한데, 우리가 만든 서브젝트를 수정하기 위해 직접 수행해본 결과 창업을 위해 필요한 것들을 제대로 학습하지 못하고 그냥 대충대충 하고 문서화도 제대로 하지 않는다는 걸 알게 되었기 때문이었다.</p>
<p>이 과정을 통해 배운 점을 요약하자면,</p>
<blockquote>
<ol>
<li>개발자들끼리만 있다 보니 개발자적 마인드에 갇혀 사업이 어떻게 이루어지는지 파악하기 힘들군. (개발 != 사업)</li>
<li>개발자들은 제법 문서화를 귀찮아하는군.</li>
<li>개발자들은 인포그래픽을 만드는 데 약하군. (보기 좋게 텍스트나 수치를 가공하는 걸 잘 못함)</li>
<li>개발자들은 수치화에 약하군.</li>
</ol>
</blockquote>
<p>위와 같다. 이런 점들을 알게 되었다는 것 자체가 해커톤을 통해 얻은 큰 수확인 것 같다.
그리고 위에는 &#39;개발자들은&#39;이라고 썼지만 그건 사실 나라는 점,,도 알게 되었다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/690b8148-63c7-42e0-a3e0-8b4d5e67a42b/image.png" alt=""></p>
<p>올라운더가 되기 위해, 특히 PM을 꿈꾸는 나로서는 내가 바라는 모습으로 성장하기 위해 내 단점들을 보완할 필요를 느낄 수 있어 보람된 해커톤이었다.</p>
<p>해커톤 결과물은 <a href="https://github.com/usanglee/Painkiller">여기</a>
노션에 이것저것 정리하면서 서브젝트 만들었는데, 그건 <del>너무 더럽고</del> 비공개라서 미리보기 이미지만 첨부한다. 직접 만든 서브젝트 내용을 수행해보려고 노력한 흔적들도 있다.
<img src="https://images.velog.io/images/welloff_jj/post/1bdc286e-1c9f-41aa-8bd9-919d94da55b5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.46.36.png" alt=""></p>
<br/>

<h2 id="✨-그리고-지금">✨ 그리고 지금</h2>
<p>지금은 해커톤을 하면서 만난 seunpark(<a href="https://github.com/KOREAparksh">깃허브</a>)님과 seonkim님(<a href="https://seongsu.me/">블로그</a>)과 함께 프로젝트를 하나 해보는 중이다.
물론 아직까지도 친한 React와 함께 ... ❤️</p>
<h3 id="🍚-진행중인-프로젝트">🍚 진행중인 프로젝트</h3>
<p><img src="https://images.velog.io/images/welloff_jj/post/f116840b-5649-47d2-b6e9-6814d0d72d40/image.png" alt=""></p>
<p>지금 진행중인 프로젝트 <code>밥은먹었니?</code>는 반찬 구독 플랫폼이다.
seunpark님은 <code>Mobile</code>, seonkim님은 <code>Back-end</code>, 나는 <code>Front-end &amp; PM</code>를 맡아 참여하고 있다.
그리고 지금 많은 도움을 주시고 계신 제5의 멤버 이광헌 멘토님도 계신다. (그저 빛 ✨)</p>
<p>이광헌 멘토님의 도움을 받아 Jira와 Confluence를 협업에 적극 활용하며 애자일이란 뭔지 몸소 체험하고 프로젝트에 적용해보고 있다.</p>
<p>사실 내가 PM이라 하기 민망한 게, 이미 사업기획이 다 되어 있는 상태에서 나중에 합류하게 된 거라 우리 프로덕트에 대해 나보다 다른 분이 더 잘 알고 계신다 ,,ㅎ
그리고 프론트엔드 개발만 하기에도 바빠서 직무 유기 중이다. 내가 할 일 여기저기로 던지는 중 ^^!
그치만 팀원들에게 적당한 Task를 배분하는 것도 PM의 역할 아닐까?라고 합리화 중 ~! 😎</p>
<p>최근 내가 올린 블로그 글들을 보면 알 수 있지만 나는 아직 개발 초기 단계에 서있다,,
앞으로 정말정말 힘내서 빠르게 개발을 마칠 수 있으면 좋겠다. 달리자 달려🏃🏻‍♀️🏃🏻‍♀️</p>
<br/>

<h2 id="💬-세줄요약-">💬 세줄요약 (?)</h2>
<ol>
<li>올해 뭔가 하긴 했다. 그치만 얼레벌레 했다.</li>
<li>내년에 복학해야함</li>
<li>올해의 나 수고했고 내년엔 더 구르자..!!!</li>
</ol>
<p>+) 내년 계획은 내년에 써야징
+) 도움 주신 많은 분들 정말 감사합니다 사......사골곰탕</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React TypeScript 프로젝트에 Storybook 도입하기 📚]]></title>
            <link>https://velog.io/@welloff_jj/React-TypeScript-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-Storybook-%EB%8F%84%EC%9E%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@welloff_jj/React-TypeScript-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-Storybook-%EB%8F%84%EC%9E%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 30 Dec 2021 06:48:42 GMT</pubDate>
            <description><![CDATA[<h2 id="🤷🏻♀️-제발-생각이란-걸-하자-">🤷🏻‍♀️ 제발 생각이란 걸 하자 ..!</h2>
<p>원래 잔뜩 중구난방으로 코드를 싸던 (쓰던인데 오타난거 아님 제대로 쓴거 맞음) 나,,,</p>
<p>생각없이 코딩을 하다 보니 정말 근본없는 디렉토리 구조를 마주하게 되었다 🥲</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/1bb7275f-435b-403b-8179-ca7fd4b00f82/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.45.04.png" alt=""></p>
<p>이렇게 보면 그냥 그래 보이지만 저 안에 서브디렉토리는 하나도 없고, pages와 views의 경계는 모호했으며, 비즈니스 로직은 어느 단위의 컴포넌트와 결합되어 있는지도 정해져 있지 않은 상태였다.
( = 개판이라는 뜻)</p>
<p>이거,, 어떻게 뜯어고쳐야 할까,,,?
아니 뜯어고칠 순 있는 걸까,,,?</p>
<br/>

<h2 id="🚀-가보자고-">🚀 가보자고 ~!</h2>
<p><img src="https://images.velog.io/images/welloff_jj/post/c0a6fbbd-d7ba-4b3d-a2f3-51f07c04f036/image.png" alt=""></p>
<p>정말정말 그러고 싶진 않았지만, 다른 레퍼런스들과 깃헙을 열심히 참고하면서 생각해본 결론은 <code>이거 지금이라도 갈아엎는 게 낫겠다^^,,</code>였다.
프로젝트를 빨리 끝내는 것도 물론 중요하지만, 유지보수를 염두에 두지 않고 막 코딩하는 건 프로젝트에도 미래의 나에게도 도움이 되지 않을 것이라는 생각이었다.</p>
<h3 id="디자인-패턴-정하기-design-pattern-정하기">디자인 패턴 정하기 (Design Pattern) 정하기</h3>
<p>이번 프로젝트에서 내가 구현해야 할 웹 어플리케이션의 특징은 다음과 같다.</p>
<blockquote>
</blockquote>
<ol>
<li>재사용되는 컴포넌트들이 매우 많다.</li>
<li>기본적으로 Base가 되는 컴포넌트가 있고, 그 컴포넌트의 Children으로 다른 컴포넌트들이 렌더링된다.</li>
<li>호출해야 하는 api가 많지 않다.</li>
</ol>
<p>이런 특징들을 고려해 어떻게 컴포넌트를 분리하고 상태관리를 할지 고민해보았고, 결국 그렇게 선택한 디자인 패턴은..!
이전에 다른 포스트에서 다룬 바 있는 <strong>Atomic Design Pattern</strong>이다.</p>
<h3 id="왜-atomic-design-pattern인가">왜 Atomic Design Pattern인가?</h3>
<ul>
<li>컴포넌트 재사용이 매우 많으므로 컴포넌트들을 Atom 단위로 분리하여 작성해 놓는다면 재사용성이 더욱 높아지고 스타일 등의 관리에도 용이할 것이라고 생각</li>
<li>호출하는 api의 종류(?)가 다양하지 않아 비즈니스 로직 분리와 관리가 쉬울 것이다.</li>
<li>관심사의 분리가 잘 되어 있다면 다른 사람에게 내 코드를 설명하기 좋고 내가 내 코드 유지보수 할 때도 좋을 듯</li>
<li>하나 덧붙이자면 ... 디자인 패턴 이름이 멋있어서 ...?ㅎ</li>
</ul>
<br/>

<h2 id="📚-드디어-storybook-도입하기">📚 드디어 Storybook 도입하기</h2>
<p>도입할 디자인 패턴까지 정한 나. 이제 앞으로 술술 풀릴 일만 남은 줄 알았다.
그치만 곧 컴포넌트 어떻게 쪼개고 어떻게 관리하고 어떻게 수정해야 할지 감을 잡지 못하고 헤매게 되었다 🥲</p>
<p>그렇게 구글링의 늪에 빠져 살다가 발견한 키워드, <strong>Storybook</strong> !
근데 스토리북 그게 뭔데,,,?</p>
<h3 id="storybook-그게-뭔데">Storybook 그게 뭔데?</h3>
<p>Storybook은 간단하게 말하면 UI 컴포넌트 개발 도구이다.
공식 문서에 따르면 독립된 환경에서 UI 컴포넌트를 개발하고 디자인하는 데 도움이 된다고 한다.</p>
<p>공식 문서는 <a href="https://storybook.js.org/tutorials/intro-to-storybook">여기</a> 있으니 혹시 이 글을 읽으시는 분이 계시다면 참고하시면 좋을 것 같당</p>
<p>암튼 좀 더 쉽게 말하자면 컴포넌트들을 <strong><em>각 컴포넌트별로</em></strong> 보고 관리할 수 있게 해주는 고런 도구이다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/f796df36-999b-4c35-ac9d-28b3e7fde184/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.30.50.png" alt=""></p>
<p>요런 느낌으로 별도의 storybook 서버에서 개발자가 설정한 stories를 통해 UI 컴포넌트들을 렌더링해볼 수 있고, 아래 옵션들을 보면 알 수 있듯 스토리북에서 데이터나 옵션을 변경해 가며 관리해볼 수도 있다.</p>
<p> +) addon이라는 추가 모듈들을 설치해 더 파워풀한 기능들을 사용할 수도 있다!</p>
<h3 id="storybook-설치하고-적용하기">Storybook 설치하고 적용하기</h3>
<p> 다음 명령어를 입력한다.</p>
<pre><code>$ npx -p @storybook/cli sb init --type react_scripts</code></pre><p>요즘 넘 세상이 조아져서(응애 나 23살) 위 명령어만 입력해주면 다른 필요한 모듈들도 다 설치해준다.
init이 끝나고 나면 <code>프로젝트 루트 디렉토리에 .storybook 폴더</code>와, <code>src 디렉토리에 stories 폴더</code>가 생성된다.</p>
<p>그 중 stories 폴더는 사용 예제들이 담겨있는 폴더이므로 삭제해도 상관없다.</p>
<p>Storybook을 실행하고 싶다면 다음 명령어를 입력하면 된다.</p>
<pre><code>$ npm run storybook // 또는
$ yarn run storybook</code></pre><h3 id="storybook-활용하기">Storybook 활용하기</h3>
<p>요건 다음 포스팅에.... 😉</p>
<br/>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://jbee.io/tool/storybook-intro/">고통없는 UI 개발을 위한 Storybook</a>
<a href="https://toby2009.tistory.com/40">cra + typescript + storybook 프로젝트 만들기</a>
<a href="https://benjaminwoojang.medium.com/storybook%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-react-test-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-65bbe6c453b5">Storybook을 이용한 React Test 환경 구축하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 프로젝트 TypeScript로 설정하기 with CRA (+ ESLint, Prettier 적용)]]></title>
            <link>https://velog.io/@welloff_jj/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TypeScript%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-with-CRA-ESLint-Prettier-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@welloff_jj/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TypeScript%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-with-CRA-ESLint-Prettier-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Wed, 29 Dec 2021 07:17:00 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 정말 기초적인, 아주 기본적인 내용을 다룬다.
그치만 아직도 프로젝트 처음 생성하고 설정할 때 꼭 구글링을 해야 하는 내가 보기 위해 조촐하게 글을 싸본다 ,, 💩 (써본다인데 오타 난 거 아님 싼다고 쓴 거 맞음)</p>
<br/>

<h2 id="❓-왜-typescript인가">❓ 왜 typescript인가?</h2>
<p>기본적으로 자바스크립트는 동적 타입(dynamic typed) 언어 혹은 느슨한 타입(loosely typed) 언어로 구문 작성이 자유롭고 느슨하다는 점이 특징이다.</p>
<p>하지만 자유로움엔 책임이 따른다고 했던가 ... 🤷🏻‍♀️ 이 자유로움은 개발 과정에서 개발자를 혼란스럽게 하기도 하고 분명 오류가 나야 할 구문에서도 코드가 작동하는 등 여러 변수를 가지고 있어 디버깅을 어렵게 하는 요인이 되기도 한다.</p>
<p>그래서 이같은 자바스크립트의 문제점을 극복하고자 자바스크립트의 대체 언어가 등장하기 시작했고, <strong>TypeScript</strong>는 이 중 하나로서 자바스크립트(ES5)의 상위확장(Superset)이다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/3a87c018-d26d-4797-87a4-8bba4ff2783b/image.png" alt="TypeScript Superset"></p>
<p>타입스크립트에서는 기존 자바스크립트 문법을 그대로 사용할 수 있으며, <strong>정적 타이핑</strong>을 지원하고 ES6의 <strong>클래스, 모듈</strong> 등과 ES7의 <strong>Decorator</strong> 등을 지원한다.
(사실 ES5, ES6이 기능 차이가 뚜렷하다고 하는데 난 응애라 잘 모르겠다 😅)
그리고 이후에도 ES 업그레이드에 따른 새로운 기능을 계속 추가할 예정이라고 한다.</p>
<p>나의 경우 정적 타이핑을 지원하는 것만으로도 TypeScript를 사용할 이유가 충분하다고 생각되어 이번 리액트 프로젝트에 TypeScript를 도입하기로 결정했다.</p>
<br/>

<h2 id="📝-react-프로젝트-typescript로-설정하기">📝 React 프로젝트 TypeScript로 설정하기</h2>
<p>리액트 프로젝트를 생성하기 전에 먼저 Node.js가 로컬에 설치되어 있어야 한다.
Node.js 버전은 원하는 것을 써도 상관없지만, 나의 경우 <strong>nvm를 사용해 LTS 버전을 설치</strong>했다.
설치 방법은 매우 간단한데, 아래 명령어를 terminal에 입력하기만 하면 된다.
물론 Node.js 홈페이지에서 파일을 다운받아 설치해도 된다 😎</p>
<pre><code>$ nvm install --lts</code></pre><p>위 명령어를 사용하기 전, nvm이 설치되어 있지 않다면 Homebrew를 이용해 먼저 설치해 주면 된다.</p>
<pre><code>$ brew install nvm</code></pre><h3 id="react-프로젝트-생성하기">React 프로젝트 생성하기</h3>
<p>리액트 프로젝트를 생성하는 방법은 여러 가지이지만, 나는 가장 손쉽고 보편적인 <code>CRA(create-react-app)</code> 사용을 선택했다.
먼저 CRA를 전역으로 설치한다. 사용하는 패키지 매니저에 맞는 명령어를 입력한다.
Node.js를 설치했다면 기본적으로 npm도 같이 설치되므로 처음 설치하시는 분들은 npm을 사용하시면 될 것 같다.</p>
<pre><code>$ npm install -g create-react-app
$ yarn global add create-react-app</code></pre><p>CRA를 설치했다면 이제 리액트 프로젝트를 타입스크립트로 설정해 생성해보자 !!</p>
<pre><code>$ npx create-react-app &lt;프로젝트명&gt; --template typescript</code></pre><p>여기에서 혹시 npm, yarn은 알겠는데 npx는 도대체 뭔가 싶다면 <a href="https://webruden.tistory.com/275">여기</a>를 참조해보자. 사실 내가 몰라서 링크 첨부함
요약하자면 npx는 새로운 패키지 관리 모듈이 아니라 npm에서 제공하는 도구다 ,, 요정도 ㅋㅎ</p>
<p>아무튼 여기까지 마쳤다면 멋진 CRA 😎가 자동으로 리액트 프로젝트를 TypeScript로 생성해주고, tsconfig.json 파일도 자동 생성 및 설정을 해줬을 것이다.</p>
<p>CRA는 강력하지만 커스텀이 조금 힘들다는 단점이 있는데, 만약 설정이 궁금하거나 수정하고 싶다면</p>
<pre><code>$ yarn eject</code></pre><p>를 실행하면 된다. 이 명령어를 실행하면
<img src="https://images.velog.io/images/welloff_jj/post/23729894-b85d-4587-8aca-e90213915e3a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.10.27.png" alt=""></p>
<p>요렇게 경고 문구가 뜨고, &#39;y&#39;를 입력하면 config, scripts 폴더가 생기면서 설정 파일들이 보이게 된다.</p>
<h3 id="tsconfigjson-수정하기">tsconfig.json 수정하기</h3>
<p>CRA가 생성해준 tsconfig.json 파일에서 strict 옵션을 꺼준다.
Lint 설정까지 하면 코딩할 때 나를 정말 힘들게 하는 옵션이기 때문 ... 😓</p>
<pre><code class="language-js">//.tsconfig.json

{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;es5&quot;,
    &quot;lib&quot;: [
      &quot;dom&quot;,
      &quot;dom.iterable&quot;,
      &quot;esnext&quot;
    ],
    &quot;allowJs&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;allowSyntheticDefaultImports&quot;: true,
    // &quot;strict&quot;: true,
    &quot;forceConsistentCasingInFileNames&quot;: true,
    &quot;noFallthroughCasesInSwitch&quot;: true,
    &quot;module&quot;: &quot;esnext&quot;,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;resolveJsonModule&quot;: true,
    &quot;isolatedModules&quot;: true,
    &quot;noEmit&quot;: true,
    &quot;jsx&quot;: &quot;react-jsx&quot;
  },
  &quot;include&quot;: [
    &quot;src&quot;
  ]
}</code></pre>
<p>여기까지 완료했다면 기초적인 프로젝트 생성은 끝난 것이다 👏🏻
하지만 나는 조금 더 규약에 맞춘, 보기 좋은 코드를 짜고 싶었기에 ESLint와 Prettier를 추가적으로 사용했다 !</p>
<br/>

<h2 id="📝-eslint-설정하고-적용하기">📝 ESLint 설정하고 적용하기</h2>
<p><img src="https://images.velog.io/images/welloff_jj/post/fc57b492-00a8-41c2-964b-7807806a736a/image.png" alt=""></p>
<p>쉬어가는 의미에서 대충 TypeScript 짤,,,,
참고로 이 뒤의 내용은 모두 VScode 기준으로 작성되었습니닷</p>
<h3 id="🙋🏻♀️-eslint가-뭘까">🙋🏻‍♀️ ESLint가 뭘까?</h3>
<p>Lint, 혹은 Linter는 소스 코드를 분석해 프로그램 오류, 버그, 스타일 오류 등을 표시하는 도구들을 가리킨다.
그 중에서도 ESLint는 JavaScript와 JSX를 위한 정적 분석 도구로, 오픈 소스 프로젝트이다.</p>
<h3 id="eslint-설치-및-초기-설정하기">ESLint 설치 및 초기 설정하기</h3>
<p>설치는 앞서 했던 것처럼 npm 또는 yarn을 이용해 하면 된다. <code>-g</code> 옵션이나 <code>global</code> 을 붙여 전역으로 설치할 수도 있지만, ESLint에서는 권장하지 않는다.</p>
<pre><code>npm install eslint --save-dev
yarn add eslint --dev</code></pre><p>나의 경우 VScode를 사용하므로, ESLint 익스텐션을 설치했다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/f2ecd721-ffe0-40e2-b0b7-95f451895cfc/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.38.png" alt=""></p>
<p>설치가 완료되었다면 구성 파일을 설정한다. 다음 명령어를 입력한다.</p>
<pre><code>$ npx eslint --init</code></pre><p>그러면 다음과 같은 질문들이 뜨고, 답변에 따라 <code>.eslintrc.&lt;선택한 파일 확장자&gt;</code> 가 생성된다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/59ada8bc-7ef5-4410-8253-7109ba372e37/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.42.46.png" alt=""></p>
<p>이렇게 생성된 설정 파일을 열어보면 옵션들이 기본으로 설정되어 있고, 이 파일을 입맛대로 잘 요리해서 프로젝트에 살살 뿌리면 된다!
<a href="https://eslint.org/">여기</a> 공식문서도 존재하니 잘 보고 멋진 설정 파일 만드시길 .... 👩🏻‍🍳</p>
<h3 id="eslint-plugin-적용하기">ESLint Plugin 적용하기</h3>
<p>물론 ESLint의 기본 규칙도 충분히 강력하지만, 나는 커스텀되어있는 많은 ESLint Style Guide 중에서도 Airbnb Style Guide를 추가적으로 사용하기로 했다.
왜냐하면 자세하고 + 보편적이고 + 읽기 쉬운 코드를 만들 수 있게 해주기 때문 ..</p>
<p>Airbnb ESLint에는 _eslint-config-airbnb_와 _eslint-config-airbnb-base_가 있다. 둘의 차이점은 base의 경우 리액트 관련 규칙을 포함하지 않는다는 것 ..!
만약 base로 설치하고 싶다면, 아래 명령어에 뒤에 <code>-base</code>를 붙이면 된다.</p>
<pre><code>$ npx install-peerdeps --dev eslint-config-airbnb</code></pre><p>그리고 <code>.eslintrc</code> 파일에 <code>&quot;extends&quot;: &quot;airbnb&quot;</code>를 추가하면 끝 !</p>
</br>

<h2 id="📝-prettier-설정하고-적용하기">📝 Prettier 설정하고 적용하기</h2>
<h3 id="🙋🏻♀️-prettier가-뭘까">🙋🏻‍♀️ Prettier가 뭘까?</h3>
<p>Prettier는 코드 포매터(Code Formatter)이다. 자동으로 코드를 포맷팅해주는 역할을 하지만, 코드 품질이나 문법 등은 잡아주지 않기 때문에 ESLint와 통합해 사용하는 경우가 많다.</p>
<h3 id="prettier-설치-및-초기-설정하기">Prettier 설치 및 초기 설정하기</h3>
<p>VScode의 경우 Prettier 익스텐션을 설치해준다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/03274e4d-4be2-46b8-bfed-f7dd05adc26f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.57.00.png" alt=""></p>
<p>그리고 프리티어를 사용하면 코드 스타일의 경우 ESLint와 부딪히는 부분이 있을 수 있는데, 이 부분을 무시하기 위해 _eslint-config-prettier_를 설치한다.</p>
<pre><code>$ npm install --save-dev eslint-config-prettier
$ yarn add --dev eslint-config-prettier</code></pre><p>그리고 프로젝트 루트 디렉토리에 <code>.prettier.json</code> 또는 <code>.prettier.js</code> 파일을 생성하고,
아래처럼 설정해주면 된다. 여기저기 찾아보니까 프리티어 국룰 설정이라고 함 !</p>
<pre><code class="language-js">//.prettierrc.js

module.exports = {
  singleQuote: true,
  semi: true,
  useTabs: false,
  tabWidth: 2,
  trailingComma: &#39;all&#39;,
  printWidth: 80,
  arrowParens: &#39;avoid&#39;,
};</code></pre>
<p>그치만 나의 경우 설정 파일을 마음대로 건드려서 입맛대로 요리해 사용했다.
<a href="https://prettier.io/">여기</a> 공식문서가 있으니 참고해서 설정하면 될 것 같다 😏</p>
<h3 id="auto-formatting-설정하기">Auto Formatting 설정하기</h3>
<p>이건 VScode 설정에서 뭔갈 만져주면 됐던 걸로 기억하는데 나중에 추가하게씀
블로그 글 쓰는 거 생각보다 힘들다 ,,, 🥲</p>
</br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://poiemaweb.com/typescript-introduction">TypeScript의 소개와 개발 환경 구축</a>
<a href="https://velog.io/@miiunii/CRACreate-React-App%EC%9C%BC%EB%A1%9C-Typescript-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0">CRA(Create-React-App)으로 Typescript 설정하기</a>
<a href="https://ingg.dev/eslint/">[JS] ESLint 적용하기</a>
<a href="https://velog.io/@_jouz_ryul/ESLint-Prettier-Airbnb-Style-Guide%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0">ESLint &amp; Prettier, Airbnb Style Guide로 설정하기</a>
<a href="https://tech.kakao.com/2019/12/05/make-better-use-of-eslint/">ESLint 조금 더 잘 활용하기</a>
<a href="https://velog.io/@yrnana/prettier%EC%99%80-eslint%EB%A5%BC-%EA%B5%AC%EB%B6%84%ED%95%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90">prettier와 eslint를 구분해서 사용하자</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🎨 React Design Pattern : Presentational and Container & Atomic Design]]></title>
            <link>https://velog.io/@welloff_jj/React-Design-Pattern-Presentational-and-Container-Atomic-Design</link>
            <guid>https://velog.io/@welloff_jj/React-Design-Pattern-Presentational-and-Container-Atomic-Design</guid>
            <pubDate>Mon, 27 Dec 2021 08:49:12 GMT</pubDate>
            <description><![CDATA[<h2 id="🧩-presentational-and-container-pattern">🧩 Presentational and Container Pattern</h2>
<h3 id="❓-presentational-and-container-패턴이란">❓ Presentational and Container 패턴이란?</h3>
<p>➡️ Presentational 컴포넌트와 Container 컴포넌트를 따로 사용함으로써 데이터 처리와 데이터 출력을 분리하는 패턴</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/68dc26e1-d684-45ca-b485-bfb357eb0594/image.png" alt=""></p>
<h3 id="📚-container-component">📚 Container Component</h3>
<ul>
<li>주로 데이터 fetch가 이루어진다. Redux를 사용해 상태 관리를 할 경우 <code>dispatch</code></li>
<li>behavior 로직을 관리하는 컴포넌트로, DOM Markup이나 CSS가 없다.</li>
<li>렌더링되어야 할 데이터 또는 callback 함수를 Presentation이나 또다른 Container 컴포넌트에 <code>props</code>로 전달한다.</li>
<li>연관 있는 서브 컴포넌트를 렌더링한다.</li>
</ul>
<h3 id="📚-presentational-component">📚 Presentational Component</h3>
<ul>
<li>데이터 처리 능력이 없고, CC(Container Component)로부터 props를 받는다.</li>
<li>View, 즉 DOM Markup과 Style(CSS)를 담당한다.</li>
<li>기본적으로는 state를 직접 조작하지 않고 CC가 내려준 props의 함수로 state를 변경한다.</li>
<li>View에 필요한 state는 가질 수 있다.</li>
</ul>
</br>

<h3 id="😀-장점">😀 장점</h3>
<ul>
<li>앱의 기능과 ui의 구분이 쉽다.</li>
<li>로직 수행과 Markup이 분리되어 있어 유지보수가 쉽고 재사용성이 뛰어나다.</li>
<li>Markup 변경에 유연하게 대처할 수 있다.</li>
</ul>
<h3 id="😅-단점">😅 단점</h3>
<ul>
<li>컨테이너의 범위를 크게 잡는 경우 FC에 전달할 props가 많아지고, 코드가 길어질 수 있다.</li>
<li>컨테이너의 범위를 작게 잡는 경우 숙련도가 낮다면 분리하는 데 시간이 많이 들 수 있다.</li>
</ul>
</br>
</br>

<h2 id="🧩-atomic-design-pattern">🧩 Atomic Design Pattern</h2>
<h3 id="❓-atomic-design-패턴이란">❓ Atomic Design 패턴이란?</h3>
<p>➡️ 가장 작은 컴포넌트 단위를 <strong>원자(Atoms)</strong> 로 설정하고, 이를 바탕으로 상위 컴포넌트를 만들어 코드 재사용을 최대화하는 패턴
➡️ 상위 컴포넌트는 순서대로 <strong>분자(Molecules)</strong>, <strong>유기체(Organisms)</strong>, <strong>템플릿(Templates)</strong>, <strong>페이지(Pages)</strong> 가 된다.</p>
<p><img src="https://images.velog.io/images/welloff_jj/post/741ca110-2390-4d0b-b385-cea42ebab048/image.png" alt=""></p>
<h3 id="📚-원자-atoms">📚 원자 (Atoms)</h3>
<ul>
<li>button, title, input과 같은 basic html elements를 포함하는 가장 작은 구성 컴포넌트</li>
<li>상위 컴포넌트에서 재사용해야 하므로 다른 곳에 영향을 미치지 않는 최소한의 기능만을 포함하도록 제작해야 한다.</li>
<li>레이블(Label), 텍스트(Text), 버튼(Button) 등</li>
</ul>
<h3 id="📚-분자-molecules">📚 분자 (Molecules)</h3>
<ul>
<li>2개 이상의 원자로 구성되어 있는, 하나의 단위로 함께 동작하는 그룹</li>
<li>입력 폼(Input forms), 네비게이션(Navigation), 카드(Card) 등</li>
</ul>
<h3 id="📚-유기체-organisms">📚 유기체 (Organisms)</h3>
<ul>
<li>분자, 원자, 또는 다른 유기체로 구성된 비교적 복잡한 그룹</li>
<li>인터페이스의 개별적인 영역을 형성한다.</li>
<li>이 단위에서 상태 관리를 수행하기도 한다. (진리의 케바케 ,,,)</li>
</ul>
<h3 id="📚-템플릿-templates">📚 템플릿 (Templates)</h3>
<ul>
<li>분자, 원자, 유기체 컴포넌트들을 배치하고 설계 구조를 보여주는 그룹. 즉 스타일링에 집중한 단위</li>
<li>실제 컴포넌트가 없을 경우 페이지가 어떻게 보이는지에 대한 골격 구조 (와이어프레임 같은 느낌 !!)</li>
</ul>
<h3 id="📚-페이지-pages">📚 페이지 (Pages)</h3>
<ul>
<li>실제 컨텐츠들을 배치한 UI를 보여주는, 템플릿이 구체화된 그룹</li>
<li>분자, 원자, 유기체를 포함한다.</li>
<li>보통 이 단위에서 <strong>어플리케이션 상태 관리</strong> (Redux 등)가 이루어진다. but 분자, 유기체, 템플릿 단위에서 컴포넌트 동작을 위한 상태관리는 가능 &gt;&lt;</li>
</ul>
<p><img src="https://images.velog.io/images/welloff_jj/post/279a21ea-2f12-4996-aa3e-8b2dac63596c/atomic%20design.gif" alt=""></p>
</br>

<h3 id="😀-장점-1">😀 장점</h3>
<ul>
<li>어플리케이션에서 컴포넌트를 분리하여 개발하고 테스트할 수 있다.</li>
<li>패턴이 확립되면 컴포넌트의 계층 구조를 알아보기 쉬우며 설계 변경이 필요할 시 더 빠르고 유연성 있게 대처할 수 있다.</li>
<li>모든 디자인 요소에 대한 변경을 컴포넌트 스타일 변경으로 한 번에 처리할 수 있고, styles를 최소로 구현할 수 있어 style 레거시가 줄어든다.</li>
<li>기본적으로 컴포넌트를 재사용하므로 컴포넌트가 쌓일수록 작업 속도가 빨라진다.</li>
</ul>
<h3 id="😅-단점-1">😅 단점</h3>
<ul>
<li>숙련도가 부족해 컴포넌트를 잘 분리하지 못한다면 오히려 컴포넌트 간 의존성과 복잡도가 까다로워져 유지보수가 어려워진다.</li>
<li>컴포넌트 간 의존성이 상하로 발생하므로 하위 컴포넌트의 에러가 상위 컴포넌트에도 영향을 미친다.<ul>
<li>원자 단위를 보수적으로 관리하고, 이벤트 핸들링은 수동적으로 관리할 필요가 있음</li>
</ul>
</li>
<li>컴포넌트가 분리되어 있고 상위 컨테이너 컴포넌트의 사이즈를 결정할 수 없을 경우 미디어쿼리를 사용하기 어렵다.<ul>
<li>flex, grid와 같은 CSS 속성을 구현한 레이아웃 컴포넌트를 도입해 해결할 수 있음</li>
</ul>
</li>
</ul>
</br>
</br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://velog.io/@te-ing/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4">디자인패턴의 정의 (feat MVC, 옵저버패턴)</a>
<a href="https://kyounghwan01.github.io/blog/React/container-presenter-dessign-pattern/#presentational-container-%E1%84%83%E1%85%B5%E1%84%8C%E1%85%A1%E1%84%8B%E1%85%B5%E1%86%AB-%E1%84%91%E1%85%A2%E1%84%90%E1%85%A5%E1%86%AB%E1%84%8B%E1%85%B5%E1%84%85%E1%85%A1%E1%86%AB">presentational &amp; container 디자인 패턴</a>
<a href="https://jeffgukang.github.io/react-native-tutorial/docs/state-tutorial/redux-tutorial/04-container-and-presentational/container-and-presentational-kr.html">Container 컴포넌트와 Presentational 컴포넌트</a>
<a href="https://velopert.gitbooks.io/react-redux/content/5-2-app-refactory.html">App 컴포넌트 정리하기</a>
<a href="https://vallista.kr/2020/03/29/Component-%EB%B6%84%EB%A6%AC%EC%9D%98-%EB%AF%B8%ED%95%99">컴포넌트 분리의 미학</a>
<a href="https://brunch.co.kr/@skykamja24/580">아토믹(Atomic) 컴포넌트 디자인 개발 패턴</a>
<a href="https://ui.toast.com/weekly-pick/ko_20200213">리액트 어플리케이션 구조 - 아토믹 디자인</a>
<a href="https://velog.io/@holim0/React-Design-Pattern#-atomic-design-pattern">React Design Pattern 🎨</a></p>
<br/>

<p>+) Atomic 디자인 패턴 관련 글들 읽으면서, 멋있지만 저거 언제 적용하지 싶었는데 막상 깃헙 찾아보니 이 패턴 적용하신 분들이 꽤 많더라 그래서 나도 적용해보려 함 근데 언제 하지 ,,,?
+) 이다음 글은 내 프로젝트에 Atomic 디자인 적용하는 걸로 해야겠다 근데 부실함을 곁들인</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[210702_TIL]]></title>
            <link>https://velog.io/@welloff_jj/210702TIL</link>
            <guid>https://velog.io/@welloff_jj/210702TIL</guid>
            <pubDate>Fri, 02 Jul 2021 06:13:51 GMT</pubDate>
            <description><![CDATA[<p>gnl 리팩토링해서 통과하고, 방금 막 넷왓도 통과했다 !
이제 본투비루트랑 프엪 남았다,,,,,
본투비루트 평가 받는 거랑 프엪 코드짜기 둘 중 뭘 먼저 할지 고민 중</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[210626_TIL]]></title>
            <link>https://velog.io/@welloff_jj/210626TIL</link>
            <guid>https://velog.io/@welloff_jj/210626TIL</guid>
            <pubDate>Sat, 26 Jun 2021 10:50:57 GMT</pubDate>
            <description><![CDATA[<h2 id="gnl">gnl</h2>
<p>미루고 미루던 gnl 평가를 드디어 받았다. 그런데,,, 하위 함수에서는 malloc 오류 처리를 해줘놓고 상위 함수(get_next_line)에서는 그 값을 제대로 처리해주는 부분을 안 만드는 바람에 리트를 해야 하게 되었다,,,,</p>
<p>상당히 슬픈 일이지만 그래도 예외처리의 중요성을 다시 한 번 알게 되었다,,,</p>
<h2 id="그-외">그 외</h2>
<p>그동안 til을 안써서 공부를 안 한 것 같지만 그런 건 절대 아니고(사실 좀 많이 놀긴 했음) 알고리즘 스터디도 하고 본투비뤁도 하고 방금 넷왓 시험도 보았다,,
평가 받을 때마다 심장이 너무 쫄리는데 이게 바로 평가 공포증이란 걸까,,? 쫄리지 않고 야수의 심장으로 평가 받을 수 있도록 디펜스 준비를 더 단단히 해주어야겠다,,,,,</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[210620_TIL]]></title>
            <link>https://velog.io/@welloff_jj/210620TIL</link>
            <guid>https://velog.io/@welloff_jj/210620TIL</guid>
            <pubDate>Sun, 20 Jun 2021 14:00:00 GMT</pubDate>
            <description><![CDATA[<p>오랜만에 쓰는 TIL 같지만 사실 매일매일 born2beroot 과제를 위해 공부하고 있었다...</p>
<p><a href="https://velog.io/@dogfootbirdfoot/Born2beRoot">https://velog.io/@dogfootbirdfoot/Born2beRoot</a>
<a href="https://velog.io/@dogfootbirdfoot/Born2beRoot2">https://velog.io/@dogfootbirdfoot/Born2beRoot2</a>
<a href="https://linuxize.com/post/how-to-change-ssh-port-in-linux/">https://linuxize.com/post/how-to-change-ssh-port-in-linux/</a>
<a href="https://m.blog.naver.com/PostView.naver?blogId=jodi999&amp;logNo=221334854192&amp;proxyReferer=https:%2F%2Fwww.google.com%2F">https://m.blog.naver.com/PostView.naver?blogId=jodi999&amp;logNo=221334854192&amp;proxyReferer=https:%2F%2Fwww.google.com%2F</a>
<a href="https://opentutorials.org/course/2598/14470">https://opentutorials.org/course/2598/14470</a>
<a href="https://thebook.io/006718/part02/ch05/01/01/">https://thebook.io/006718/part02/ch05/01/01/</a>
<a href="https://funarock.tistory.com/m/907?category=675956">https://funarock.tistory.com/m/907?category=675956</a>
<a href="https://www.notion.so/vertual-box-SSH-0924f2a572f64fd491da7c85bd956114">https://www.notion.so/vertual-box-SSH-0924f2a572f64fd491da7c85bd956114</a>
<a href="https://www.notion.so/born2beroot-2601b9306b8b4d2187a41f561811052e">https://www.notion.so/born2beroot-2601b9306b8b4d2187a41f561811052e</a>
<a href="https://www.notion.so/9568b5dd3f004c0e9b81e468809cd246">https://www.notion.so/9568b5dd3f004c0e9b81e468809cd246</a></p>
<p>호스트 이름 에러
<a href="https://noota.tistory.com/entry/Error-sudo-unable-to-resolve-host">https://noota.tistory.com/entry/Error-sudo-unable-to-resolve-host</a></p>
<p><a href="https://velog.io/@taeskim/Born2beroot#1-project-overview">https://velog.io/@taeskim/Born2beroot#1-project-overview</a>
<a href="https://www.notion.so/checklists-71dbe69d8ced4b36874d559820cdc9a9">https://www.notion.so/checklists-71dbe69d8ced4b36874d559820cdc9a9</a>
<a href="https://www.notion.so/vertual-box-SSH-0924f2a572f64fd491da7c85bd956114">https://www.notion.so/vertual-box-SSH-0924f2a572f64fd491da7c85bd956114</a></p>
]]></description>
        </item>
    </channel>
</rss>