블로그

볼드 UX

[인프런 워밍업 스터디 1기 디자인] 오리엔테이션 준비하기

 안녕하세요! 지식공유자 볼드입니다. 최근에 인프런 워밍업 스터디 클럽 1기에서 프로덕트 디자인 코치로 참여하게 되었어요.준비 과정이 꽤 새로웠고, 많은 것을 배우는 시간이었습니다. 오늘은 제가 어떻게 러너분들과 첫 만남을 위해 준비를 하였는지 알려드리고자 해요.   첫 만남을 미리 계획하다저는 4주 전부터는 0기 코치님들이 남겨둔 자료들을 보며 어떻게 하면 더 좋은 오리엔테이션을 만들 수 있을지 고민했어요. 구조부터 차근차근 짜고, 내용을 채워 넣어서 빠르게 프레젠테이션을 완성했습니다. 첫만남인 만큼 어떻게 하면 더 재미있고, 참여자들과 적극적으로 소통할 수 있을까 고민을 많이 했어요. 그래서 피그잼을 사용한 워크샵 형태로 진행하기로 결정하고, 세 가지 큰 원칙을 세웠습니다:많은 정보를 빠르게 명확하게 전달하기최대한 재미있고 인터랙티브하게 이야기가 살아있는 컨셉 유지하기 다행히 ‘러너’라는 주제가 이미 있어서 그걸로 컨셉을 잡았고, 다음과 같은 여정으로 구성해 보았어요.🚀 출발: 워밍업 클럽을 시작하게 된 이유🗺 코스: 워밍업 클럽의 미션들🎯 도착: 워밍업 클럽을 마치고 받게 되는 혜택들    OT 시작 전에는 새 직장에서 바쁠 것 같아서 미리 인프런 담당자 셰리님과 자료를 공유하고 점검하는 시간을 가졌어요.그리고 막상 OT 주간이 되니, 예상대로 정신 없었습니다. OT 당일에는 반차를 내고, 오전에 교회에서 성경공부를 마치고 집에 돌아와 커피 한 잔 마시며 마지막 준비를 했죠.    러너 분들과 드디어 만나다영국시간으로 12시에 시작했어요.(한국 시간으로는 오후 8시), 제가 먼저 짧게 발표를 먼저 진행하고 러너 분들은 질문에 따라 각자 글을 작성하셨어요.  작성 후에는 서로의 글을 보며 하트를 남기는 시간을 가졌는데, 이게 생각보다 더 재미있었던 것 같아요.  미리 준비한 탭으로 미션 정보를 빠르게 효과적으로 보여드리고, 원래 OT 전까지 블로그 글을 쓰지 못했는데 셰리님의 빠른 대처로 발자국 미션 시연을 성공적으로 마칠 수 있었어요.  OT 끝나고 난후워크샵이 끝난 후, 참가자분들의 피드백을 부탁드렸어요. 피드백을 보고 나니 제가 준비한 만큼 결과도 좋았다는 생각이 들더군요.(아래는 제가 몇개 선정한 감사한 피드백!)  2기에도 제가 참여할지는 아직 모르겠지만 2기에도 오리엔테이션 준비 경험을 살리거나 또 다른 코치님들이 사용할 수 있도록 이 피그잼 보드를 템플릿화하면 좋을 것 같아요. 또한, 이 방식을 다른 온라인 강의에서도 활용할 수 있을 것 같아요. (필요하신 분들은 알려주세요. 무료 나눔해드릴게요!) 마지막으로 인프런 워밍업 클럽 이전에 제가 진행한 인증샷 스터디에서 수강생과 교류가 있으면 좋을 것 같다는 의견이 있었어요. 처음엔 이걸 어떻게 개선해야할지 막막했는데, 인프런 워밍업 클럽을 참여하면서 이 문제를 해결할 수 있었어요. 그리고 셰리님을 포함한 인프런 팀이 없었다면 이 모든 게 불가능했을 거예요. 정말 감사드립니다! 인프런팀 만세! 앞으로 남은 세 번의 특강, 워크샵을 어떻게 준비할지 계획 중인데, 라이브 튜토리얼과 프레젠테이션을 어떻게 잘 조합할지, 함께 만들어가는 워크샵 과정이 어떨지 기대되네요. 인프런 워밍업 클럽 1기에 참여하신 모든 러너분들 다같이 파이팅해요 🔥     

UX/UI워밍업클럽디자인시스템피그마

대롱대롱

[인프런 워밍업클럽 CS 2기] 3주차 발자국

드디어 스터디의 마지막 발자국을 작성하는 날이 왔습니다. - 이번주에 공부한 내용의 키워드 - 운영체제컴파일과 프로세스메모리-레지스터, 캐시, 메인메모리, 보조저장장치절대주소/상대주소가변분할/고정분할가상메모리동적주소변환세크멘테이션 분할방식/페이징 분할 방식스레싱/워킹셋여러가지 주변장치(입출력 디바이스와 저장장치)하드디스크파일과 파일시스템디렉토리디스크 자료구조와 알고리즘버블/선택/삽입/병합/퀵 정렬동적 프로그래밍(메모이제이션/타뷸레이션) - 이번주에 공부한 내용 요약 - 운영체제메모리는 가장 빠른 레지스터, 데이터 임시 저장하는 캐시, RAM이라 불리는 메인메모리, 그리고 보조기억장치가 있습니다. 물리주소는 말 그대로 물리적인 메모리 주소이고 논리주소는 사용자 관점에서 본 상대적 주소입니다. 메모리 할당방식으로는 가변분할방식과 고정분할방식이 있습니다. 현대에서는 두 가지 방식을 모두 사용하여 단점을 최소화하는 버디시스템을 사용합니다.가상메모리는 컴퓨터의 물리적 메모리의 크기를 확장하기 위해 사용되는 기술입니다. 동적주소변환은 메모리관리자가 가상메모리의 논리주소를 물리주소로 변환하는 것을 의미합니다.논리주소를 물리주소로 변환할 때 세그멘테이션 분할 방식은 메모리 관리자가 논리주소를 세그멘테이션 테이블을 이용해 물리주소를 찾고, 페이징 분할 방식은 논리주소를 페이지 테이블을 이용해 물리주소를 찾습니다.프로세스가 가상메모리에 접근요청 했을 때 물리메모리에 데이터가 없다면 페이지 폴터라는 인터럽트가 발생합니다. 이 때 HDD의 스왑영역에 있는 데이터를 메모리에 올리는 작업이 수행됩니다.스레싱은 페이지폴트가 발생해서 CPU사용률이 0에 가깝게 떨어지게 되는 현상을 의미합니다. 워킹셋은 메모리에 올라온 페이지를 하나의 세트로 묶어 메모리에 올리는 것을 의미합니다.주변장치들은 메인보드에 있는 버스로 연결되어 있으며 두 개의 채널과 두개의 버스로 구분합니다.파일관리자는 운영체제가 파일을 관리하기 위해 필요한 존재입니다. HDD나 flash memory는 블록 디바이스로 전송단위가 블록이지만 사용자는 바이트 단위로 파일에 접근해야 해서 파일관리자가 중간에서 관리해야합니다.파일은 순차파일구조, 직접파일구조, 인덱스파일구조가 있습니다.관련있는 파일을 모아두기 위해 필요한 것이 디렉토리입니다. 자료구조와 알고리즘정렬에는 크게 5가지 방식이 있습니다간단해서 구현은 쉽지만 성능은 좋지 못한 버블, 선택, 삽입 정렬과 이들보다 상대적으로 성능이 좋은 병합정렬과 퀵정렬이 있습니다.동적프로그래밍 방식으로 메모이제시녀과 타뷸레이션이 있습니다.메모이제이션은 계산결과를 기억하며 재귀를 사용합니다. 하향식 계산방식입니다.타뷸레이션은 계산에 필요한 모든 값을 계산하여 테이블에 저장하고 상향식 계산방식입니다.- 이번 주 회고 겸 스터디 회고 - 눈 깜짝할 사이에 스터디 마지막이 되었습니다. 완주를 위해 달려왔는데 목적했던 바를 이루어서 뿌듯합니다. 개인적으로 따로 다른 분들과 스터디를 했는데 운이 좋게도 열정적이고 좋은 분들을 만나 복습과 완강을 함께 할 수 있었습니다. 일주일에 세번씩 꾸준하게 디스코드 상에서 스터디를 했는데 아주 만족스러웠습니다. 덕분에 허물뿐인 완강이 아니라 제대로 공부하면서 완강을 하게 되었어요.이번주에는 중간점검도 있었는데 그 때 감자님께서 회고를 읽어보신다는 것을 알았습니다. 그동안 너무 주저리주저리 길게 쓰는 것은 지양해야겠다고 생각했는데 그냥 길~게 쓸걸 하는 아쉬움이 있습니다. 짧아서 심심하셨겠다는 생각이 드네요. 이번주 회고는 마지막인만큼 좀 분량 있게 써보겠습니다. 일단 이 CS스터디를 신청한 이유는 '그래도 개발의 길을 걷는 사람이 CS지식도 모르다니! 이럴 수는 없다!'는 마음이 있었기 때문입니다. 기본 지식은 쌓아야 한다는 생각이 강했어요(제가 운영체제 과목을 들은 적이 없습니다..^^;;). 그래서 제가 자주 하는 '일단 신청하자'를 시전했습니다. 왜 하필 이 강의를 선택했냐고 물으신다면 답은 하나입니다. 재미있어 보여서요. 저는 도파민중독자입니다. 일단 재미가 있어야 뭔가를 시작합니다. 감자님 강의를 보는데 애니메이션으로 설명하는 것이 너무 재미있어 보였어요. 이전에 '아 지금 공부하는 게 눈으로 보이면 좋겠다...'라는 생각을 했는데 이 강의가 딱 이 생각에 맞아버린 것이죠. 애니메이션으로 공부하니 재미있고 재미있으니 더 공부하고 싶고... 이런 선순환이 반복되어 어느덧 완강이라는 종착지에 다다르게 된 것입니다. 스터디원들과 스터디를 하다보니 발표자료도 만들게 되었는데 발표자료 만드는 것도 많은 정성을 기울였습니다. 남에게 보여야 하는 것인데 허접하게 만들 수는 없잖아요. 처음에는 노트앱에 기본으로 있는 템플릿을 썼는데 그 템플릿이 너무 마음에 들지 않았어요. 맘에 안들면 제가 만들면 됩니다(자급자족 라이프!). 그래서 만들어진 것이 '감자전용 템플릿'입니다. 귀엽게 디자인이 뽑혔고 이렇게 만든 템플릿 덕분에 스터디를 재미있게 할 수 있었던 것 같습니다. 강의 들으면서 1차적으로 적은 야생의 거친 필기를 이 템플릿으로 더 잘 정리하려는 마음에 한 파트 정리하는데 시간이 좀 많이 걸린다는 소소한 단점이 있기는 합니다... 그렇지만 이렇게 정리한 것이 나중에 복습할 때 도움이 크게 될 것이라 믿어 의심치 않습니다.적다보니 길어졌네요. 스터디가 끝나니 아쉬움이 남기는 합니다. 다음에도 이런 스터디가 또 열렸으면 좋겠어요. 저번에 들어보니 컴퓨터구조 강의도 준비하신다던데.... 그때 한번 또 스터디가 열렸으면 하는 소소한 바램이 있습니다. 이번에 들은 내용들 복습하면서 더 심화적인 내용도 개인적으로 공부해야겠습니다. 좋은 강의 감사하고 다음에 또 뵐 기회가 있으면 좋겠습니다.

운영체제자료구조CS워밍업클럽스터디

장서윤

[인프런 워밍업 클럽 0기] 2주차 발자국 👣

이번 발자국은 과제 진행 과정을 작성해 볼 예정이다. 목차는 다음과 같다.1. 기능 목록 작성2. 공통 컴포넌트 구현3. 결과물4. 고민했던 부분 ✅️ 1. 기능 목록 작성1. 항목 추가/수정할 수 있다.지출 항목 + 비용을 입력받는다 (조건을 만족할 때까지)지출 항목은 문자열이여야 한다.비용은 숫자여야 한다.지출 항목 + 비용 모두 입력되어야 한다. (공백 제외)  조건을 만족할 경우, 버튼이 enable 된다. 추가/수정을 완료했을 경우, toast 메시지를 띄워준다. 2. 항목 리스트를 보여준다. (테이블 형식)각 항목(row) 마다 수정/삭제 버튼이 존재한다.수정 버튼을 누른 경우[ 기능목록 1. 항목 추가/수정할 수 있다 ] 로 이동한다.삭제 버튼을 누른 경우항목이 삭제되며, toast 메시지를 띄워준다. 총 지출 금액을 보여준다.항목 리스트가 없을 경우, '존재하지 않습니다' 를 보여준다.   3. 모든 항목을 삭제할 수 있다.목록 지우기 버튼을 누른 경우모든 항목이 삭제되며, toast 메시지를 띄워준다. ✅ 2. 공통 컴포넌트 구현MUI와 같은 UI 라이브러리를 쓰지 않고, tailwind css로만 구현할 것이기에, 필요한 컴포넌트는 직접 만들어야한다. 먼저 공통된 디자인을 위해 rounded만을 사용하고자 했다. ( 컴포넌트마다 rounded를 다 다르게 사용하지 않는다)색상은 emerald + slate 만을 최대한 사용했다. 그렇게 해서 필요한 컴포넌트는 다음과 같다. Outlined Input시간을 투자한 부분이다. 기본 html의 input은 굉장히 단순하기에 커스텀이 필요했다.focus 했을 때, label 을 input 박스 위로 가게 하고, 부드러운 애니메이션을 넣고자 했다.Contained Button + Text Button배경을 채운 Contained Button오직 text 만 존재하는 Text ButtonTable기본 table에 css만 추가했다.Toast 메시지 success : 초록색 체크 아이콘추가, 수정, 삭제가 성공적으로 완료되었음을 표시한다. warn : 노란색 경고 아이콘입력값의 유효성검사가 일치하지 않을때 표시한다.  ✅ 3. 결과물 ✅ 4. 고민했던 부분 지출 항목이 문자여야하는데, 이를 어떻게 판별하는가? 이다.애매한 부분이 지출 항목이 "맥북 pro 16" 처럼 오직 문자 type으로 이뤄지지 않고, 여러 type이 같이 존재할 수 있다. 그래서 이걸 어떻게 예외처리 해줄지 고민했었는데, 일단은 지출 항목을 절대 숫자로만 이뤄지지는 않을 것 같아서, isNaN()만을 판별했다. 이 부분은 고민이 더 필요할 것 같다.. toast 메시지의 색상을 어떻게 할 것인가? 이다.상품을 "삭제" 했을 경우, toast 메시지의 아이콘 색상을 고민했었다.빨간색 -> 부정적 의미 -> 삭제와 연관된다! -> 그러나 error 와도 연관됨 -> 사용자 입장에서 "에러가 났다..!" 로 혼동할 수 있음.초록색 -> 삭제가 완료되었다! 에 의미를 둠-> 그러나, 추가, 수정, 삭제도 어쨌든 완료이기에, 다른 기능임에도 아이콘 색상이 같아서 구별이 어렵다는 문제가 존재함.고민 끝에 error와 연관되는 빨간색보다는 초록색으로 가되, "추가", "수정", "삭제" text 를 크고 두껍게 처리해주는 것으로 합의를 보았다!후기UI 라이브러리만 사용하다가, tailwind css로 직접 컴포넌트를 만드니까, 생각보다 시간이 오래 걸렸다. 중간에 계속 애니메이션도 적용된 라이브러리를 사용하고 싶었지만, 이를 css로(비록 tailwind css지만) 직접 완성시켰을때 상당히 뿌듯했다!또한, 기능목록을 제대로 작성한건지 모르겠다. 조금 더 깔끔하게 작성하고 싶은데, 어디까지 자세하게 적어야하는지, ui 부분도 자세하게 적어야하는지(버튼 색깔이 바뀐다거나)를 잘 모르겠다. 더 공부해봐야겠다!  

웹 개발프론트FE워밍업클럽

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 2 발자국

발자국워밍업 스터디 클럽이 2주 차에 접어들었습니다. 해당 발자국은 따라 하며 배우는 리액트 A-Z (섹션 0-5) 중심으로 작성되었습니다.요약React를 사용하려면 Node.js가 필요하다. Node.js를 설치하면 NPM도 같이 설치되니 꼭 Node.js를 설치하자. Node.js 공식 홈페이지에 접속하면 2개의 Node 버전이 있는데, 그중에서 안정적인 버전인 LTS를 설치하면 된다. Section 01. React[ React란? ]리액트는 사용자 인터페이스(user interface, UI)를 만들기 위해서 사용되는 자바스크립트의 라이브러리다. 리액트는 인터렉션이 많은 웹 앱을 개발하기 위해서 주로 사용된다. 이렇게 사용자 인터페이스를 만들기 위해 도움을 주는 TOOL로는 리액트 말고도 Vue.js와 Angular.js가 있다.React: 라이브러리Angular, Vue: 프레임워크[ Framework vs Library ]프레임워크와 라이브러리를 대략 설명하자면 다음과 같다.Framework : 어떠한 앱을 만들기 위해 필요한 대부분의 것을 가지고 있다.Library : 어떠한 특정 기능을 모듈화 해 놓은 것이다.프레임워크는 앱을 만드는데 필요한 대부분의 라이브러리를 가지고 있으며, 라이브러리들은 특정 기능을 위해 모듈화 되어있다.리액트는 라이브러리이다. 왜냐? 리액트는 전적으로 UI를 렌더링 하는 데 관여하기 때문이다. 리액트는 여러 모듈을 사용하며 앱을 관리한다.라우팅: react-router-dom …상태관리: redux, mobx …빌드: webpack, npm …테스팅: Eslint, Mocha …[ React Component ]리액트를 공부하다보면 무조건 마주치는 단어가 있다. 바로 컴포넌트이다. 리액트는 컴포넌트 기반이라고 하는데, 이 컴포넌트는 무엇을 말하는 것일까?컴포넌트(Component): React로 만들어진 웹/앱을 이루는 최소한의 단위리액트는 이 컴포넌트를 통해서 웹/앱을 개발하게 된다.리액트는 여러 컴포넌트 조각으로 되어있다. 이것은 블록같다고 생각하면 된다. 여러 블록 조각을 맞추고 쌓아 올려 하나의 블록 작품을 완성하는 것. 리액트도 마찬가지로 컴포넌트를 이리저리 조합하고 쌓아올려 하나의 웹 페이지를 구성하게 된다.리액트 컴포넌트에는 2가지가 있다.클래스형 컴포넌트함수형 컴포넌트React는 여러 컴포넌트 조각으로 구성된다.개인적인 설명을 덧 붙이자면 리액트는 레고 블럭과 같다고 생각한다. 레고 블럭들을 하나 둘 씩 쌓아 올려 하나의 완성된 레고 작품을 만드는 것이다.[ Component 종류 ]React는 2개의 컴포넌트 종류가 있다.클래스형 컴포넌트(Class Components)class App extends Component { render() { return <h1>Hello, ReactJS!</h1>; } }함수형 컴포넌트(Functioanl Components)function App() { return <h1>Hello, ReactJS!</h1>; }💡 현재 함수형 컴포넌트를 HOOK이랑 해서 많이 사용한다.💡 참고로 컴포넌트를 작성할 때 반드시 대문자 시작을 해야 한다. 소문자 시작 시 body, h1, p 같은 DOM 태그로 인식해 버린다.[ 브라우저가 그려지는 원리와 가상 돔 ]React의 가장 큰 특징은 가상 돔(Virtual DOM)이다. 이것을 사용하는 이유는 인터렉션 때문이다. 이 인터렉션에 의해 DOM에 변화가 발생하면 다시 DOM을 재구성하기 시작한다.JS 발자국에도 남겼었지만 웹 브라우저의 경우 다음과 같은 과정을 겪고 이 과정은 비용이 꽤 든다.Critical Render Path (웹 페이지 렌더링 과정): 데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ PaintDOM을 재구성 한다는 것은 위 렌더링 과정을 다시 반복한다는 것이다. 즉, 인터렉션이 일어날때마다 위 과정을 다시 한다. 이것을 보완하기 위해서 나온 것이 가상 돔이다.가상돔 과정을 살펴보자..!데이터가 바뀌면 가상 돔에 렌더링 되고, 이전에 생긴 가상 돔과 비교를 해서 바뀐 부분만 실제 돔에 적용 시킨다.바뀐 부분을 찾는 과정을 Diffing이라고 부른다.바뀐 부분만 실제 돔에 적용 시키는 것을 Reconciliation(재 조정)이라고 부른다.[ Create React App 을 이용해서 리액트 설치하기 ]create-react-app 을 통해서 원하는 위치에 리액트를 설치할 수 있다. 이 때, Webpack과 Babel이 함께 설치가 된다. 따라서 React 앱 생성 전에 Webpack과 Babel에 대해서 간단히 알고 가자.Webpack정의: Webpack: 웹팩은 오픈 소스 자바스크립트 모듈 번들러써 여러 개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축고 최적화하는 라이브러리이다.장점여러 파일의 자바스크립트 코드를 압축하여 최적화할 수 있기 때문에 로딩 줄일 수 있. (네트워크 비용 줄음)모듈 단위로 개발이 가능하여 가독성과 유지 보수가 쉽다.Babel정의: 최신 자바스크립트 문법을 지원하지 않는 브라우저들을 위해서 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 변환 시켜주는 라이브러리이다.⇒ 이러한 Webpack과 Babel은 개발자가 React 개발 시 알아서 설정 해야 하지만 Create-React-App을 사용해서 React 앱을 생성하면 Babel이나 Webpack 설정이 이미 되어있기 때문에 준비 시간이 단축된다.[ Create-React-App ]프로젝트를 진행할 폴더 생성VSC에서 해당 프로젝트 폴더 열기Termial에 npx create-react-app 생성할파일명 입력강의에서는 npx create-react-app ./을 입력하였다../는 현재 위치를 뜻한다.[ npx create-react-app 에 대하여 ]npx: 노드 패키지 실행을 도와주는 도구이다.npx create-react-app이란 npm 레지스트리에 잇는 패키지를 ./에 실행시켜서 React를 설치해 주는 것이다.실행하는 방법실행하고자 하는 리액트 파일 위치에서 npm run start 입력(강의에서는 npm run start방법만 소개시켜 주셧는데 npm start도 가능하다.)🤔 개인적으로 요즘 vite에 관한 이야기가 보이는데 이도 조사해 보아야겠다… Section 2. 간단한 To-Do 앱 만들며 리액트 익히기[ create react app ]create-react-app으로 리액트를 설치하면 여러 파일이 등장하는데, 이 중에서 절대로 이름을 수정해서는 안되는 파일이 존재한다.public/index.html: 페이지 템플릿src/index.js: 자바스크립트 시작 점조심하자!💡그리고 우리가 새로 js, jsx, css 등 직접 생성할 파일들은 src 폴더에서 하면 된다. Webpack이 src/ 부분에만 작동하기 때문이라고 한다.[ package.json ]해당 프로젝트에 대한 정보들이 들어있다. 프로젝트 이름, 버전, 필요한 라이브러리와 라이브러리들의 버전이 명시되어 잇다.[ 싱글 페이지 애플리케이션(single-page application, SPA) ]싱글 페이지 애플리케이션(single-page application, SPA)은 서버로부터 완전한 새로운 페이지를 불러오지 않고 현재의 페이지를 동적으로 다시 작성함으로써 사용자와 소통하는 웹 애플리케이션이나 웹사이트를 말한다.위키백과React.js는 SPA이다. 즉, 어떠한 데이터에 관한 교체 이벤트가 발생했을 때, 서버로부터 페이지를 새롭게(html 파) 받아와 구성하는 것이 아니라 content를 바꿔치기 한다. 이는 HTML 5의 History API를사용해서 가능하게 만든다.[ History API ]전통적인 웹 사이트는 a page에서 b page로 이동할 때 a.html을 보여주다가 b.html을 보여주면 되었지만 SPA의 경우 오직 1개의 HTML(index.html)이 존재한다. 따라서 페이징 전환을 하기 위해서 HTML 5 History API를 이용한다.History.back(): 세션 기록의 바로 뒤 페이지로 이동하는 비동기 메서드History.forward(): 세션 기록의 바로 앞 페이지로 이동하는 비동기 메서드History.go(): 특정한 세션 기록으로 이동하게 해 주는 비동기 메서드History.pushState(): 주어진 데이터를 세션 기록 스택에 넣어준다.History.replaceState(): 최근 세션 기록 스택의 내용을 주어진 데이터로 교체한다.생성했던 React 프로젝트에서 public/index.js를 살펴보면 <div id="rood"></div>가 있다.그리고 src/index.js 코드에는 document.getElementById('root')라는 코드가 있다.자바스크립트 파일의 시작 점인 src/index.js에서 id값이 rood인 요소를 찾아 그곳에 해당 요소들을 렌더링하는 것이다. 즉, div라는 최상위 루트 노드 아래에 직접 정의한 요소를 더해 화면을 꾸며나가는 것이다!![ JSX ]JSX는 Javascript Syntax Extension의 약자로 자바스크립트의 확장 문법이다.리액트에서는 이 JSX를 이용해서 화면에서 UI가 보이는 모습을 나타내준다.JSX 사용이 필수는 아니나 사용하면 가독성이 너무 좋아서 필수 아닌 필수이다. (애초에 리액트 개발자들 대부분이 JSX를 사용한다고 한다.)JSX는 createElement를 쉽게 사용하기 위해서 사용한다.모든 UI를 만들때 마다 createElement를 사용해서 컴포넌트를 만들 수 없다.Ract는 React.crateElemnt API를 사용해서 엘리먼트를 생성한 후에 이 엘리먼트를 In-Memory에 저장한다. 그리고 RaectDOM.render 함수를 통해 웹 브라우저에 그린다.JSX를 사용하면 Babel이 사용한 문법을 crateElemnt로 자동 변환해준다. 따라서 그냥 개발자는 자유롭게 JSX 사용하면 된다.단, JSX는 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸줘야 한다.// 안된다. // 자식 요소가 여러 개 라면 부모 요소로 감싸줘라. function hello() { return ( <div>Hello, Raect!</div> <div>Hello, Wrold!</div> ); } // 이렇게 말이다. function hello() { return <div> <div>Hello, Raect!</div> <div>Hello, Wrold!</div> </div>; }💡 만약 JSX에서 JS 코드를 사용하고 싶다면 { } 내부에 작성해주면 된다.[ React와 Key ]map()을 사용한다면 언제나 명심해야 하는 것. KEY. 이것을 넣지 않는다면 에러가 발생한다.React에서 요소의 리스트를 나열할 때는 Key를 넣어줘야 한다. Key는 React가 변경, 추가 또는 제거된 항목을 식별하는 데 도움이 된다.추가적으로, 이 Key에 지정하는 값은 순회하고자 하는 목록의 아이템에 대한 ID 값이면 된다. 즉, 고유한 값이여야 한다. 정 없으면 index 넣어도 되지만 index 값은 권장하지 않는다.리액트는 가상 돔을 이용해서 바뀐 부분만 실제 돔에 적용한다. 그렇다면 리스트를 나열할 때 바뀐 부분만 어떻게 찾을까? 바로 이 key를 이용해서 어떠한 부분이 바뀌었는 인식하는 것이다.[ state ]정말 정말 중요한 개념!!!리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서 React State를 사용한다. State란 무엇일까?간단히 말해서 변수이다.단, 이 변수의 값이 변경되면 컴포넌트들이 재렌더링 된다.state에는 리액트의 흐름에 관한 데이터와 관련이 있다. Section 3. To-Do 앱 최적화 하기[ React HOOK ]엄청나게 중요하다. 이 HOOK은 클래스형 컴포넌트처럼 함수형 컴포넌트에서도 state와 생명주기 메서드를 사용할 수 있도록 해주는 메서드이다.클래스 형 컴포넌트에서는 Mounting, Updating, Unmounting 3단계 따라서 생명주기 메서드를 제공한다.Mounting: componentDidMount()Updating: componentDidUpdateUnmounting: componentWillUnmount()함수형 컴포넌트에서는 이를 위해 HOOK을 사용한다.[ HOC(Higher Order Component) ]화면에서 재사용 가능한 로직만을 분리해서 component로 만들고, 재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법이다.HOC는 HOOK이 나오기 전에 사용했던 부분이다.Wrapper가 많아지면 흐름 파악이 어려워서 이제 잘 안 쓴다.HOC를 만들고 싶으면 Custom HOOK을 사용하자.[ HOOK ]기본적으로 알고 있어야 할 HOOK은 다음과 같다.useState()리액트의 유동적인 데이터들은 state에 담아 사용하기 위해 이용하는 HOOK클래스형 컴포넌트의 setState와 같이 state 객체에 대한 업데이트 실행단!!! state 변경 시 재 렌더링이 일어남useEffect()사이드 이팩트 처리 HOOK클래스형 컴포넌트의 생명 주기 함수 역할 수행useMemo()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 지정한 함수를 실행하여 해당 반환 값을 반환useCallback()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 함수를 반환useRef()요소의 참조를 위해 사용하는 HOOK[ Props ]Props는 Properties의 줄임말상위 컴포넌트에서 하위 컴포넌트로 데이터를 전송하고 싶을 경우 사용읽기 전용으로 자녀 컴포넌트에서 강제로 이 값을 변경할 수 없다.전달 받은 props가 state고 이 값을 바꾸고 싶다면 props로 set함수를 넘기고 이것을 이[ TailWindCSS ]HTML 안에서 CSS 스타일을 할 수 있게 해주는 CSS 프레임워크빠른 스타일 작업 가능id 혹은 class 명을 작성하기 위해 머리를 혹사 시키지 않아도 된다.class에 특정 키워드를 넣어서 CSS 조작정해진 속성 키워드가 워낙 많으니 공식 홈페이지 검색 필수다[ 리액트 불변성 ]불변성을 지키며 개발을 하자!참조 타입에서 객체나 배열의 값이 변할 때 원본 데이터가 변경되면 예상치 못한 오류가 발생할 수 있다.불변성을 지킬 수 있는 참조 관련 메서드:spread operator, map, filter, slice, reduce불변성을 해치는 참조 관련 메서드:splice, push[ React.memo ]React.memo는 Higher-Order Components(HOC)이다. 불필요한 컴포넌트 렌더링을 방지할 수 있게해준다. (일종의 최적화 용 HOC) Section 4-5. Netflix 앱 만들기주로 실습 내용 이었다. 정리할 이론만 추려내 보겠다.[ Styled Component ]자바스크립트 파일 안에서 CSS를 처리할 수 있게 해주는 라이브러리[ React Router Dom ]React Router DOM을 이용하면 웹/앱에서 동적 라우팅을 구현할 수 있다. 라우팅이 실행 중인 앱 외부의 구성에서 처리되는 기존 라우팅 아키텍처와 달리 React Router DOM은 앱 및 플랫폼의 요구 사항에 따라 컴포넌트 기반 라우팅을 용이하게 한다.React Router DOM을 사용하기 위해서는 몇 가지 설정을 해야한다.index.js에서 BrowerRouter로 루트 컴폰너트를 감싸준다.BrowserRouter은 HTML 5 History API를 사용하여 UI를 URL과 동기화 된 상태로 유지해준다.import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter > <App /> </BrowserRouter> </React.StrictMode> ); 여러 컴포넌트 생성 및 라우트를 정의한다.Routes와 Route를 사용한다.Routes: 앱에서 생성될 모든 개별 경로에 대한 컨테이너 상위 역할을 한다.Route: 단일 경로를 만드는 데 사용된다.path 속성: 원하는 컴포넌트의 URL 경로를 지정한다.element 속성: 경로에 맞게 렌더링 되어야 하는 컴포넌트를 지정한다.import { Routes, Route } from "react-router-dom"; function App() { return ( <div className="app"> <Routes> <Route path="/" element={<Home />}> <Route path="about" element={<About />} /> <Route path="contact" element={<Contact />} /> </Route> </Routes> </div> ); } +) <Link />를 통해 경로 이동하기Link 구성 요소는 HTML의 a 태그와 유사하다.to 속성은 링크가 유저를 데려가는 경로를 지정한다.앱 구성 요소에 나열된 경로 이름을 생성했기 때문에 링크를 클릭하면 경로를 살펴보고 해당 경로 이름으로 구성 요소를 렌더링한다.import { Link } from "react-router-dom"; function Home() { return ( <div> <h1>홈페이지</h1> <Link to="about">About 페이지를 보여주기</Link> <Link to="contact">Contact 페이지를 보여주기</Link> </div> ); } [ 중첩 라우팅 ]라우팅은 중첩 처리가 가능하다.[ Outlet ]자식 경로 요소를 렌더링하려면 부모 경로 요소에서 Outlet를 사용해야한다.하위 경로가 렌더링될 때 중첩된 UI가 표시될 수 있다.부모 라우트가 정확히 일치하면 자식 인덱스 라우트를 덴더링하거나 인덱스 라우트가 없으면 아무것도 렌더링하지 않는다.[ useNavigate ]경로를 바꿔준다.naviate(”/home”) ⇒ localhost:3000[ useParams ]:style 문법을 path 경로에 사용했다면 useParams()로 읽을 수 있다.function test() { return ( <Routes> <Route path="invoices/:invoiceId" element={<Invoice />} /> </Routes> ); } function Invoice() { let params = useParams(); return <h1>Invoice {params.invoiceId}</h1>; } [ useLocation ]현재 위치의 객체를 반환현재 위치가 변경될 때마다 일부 side effect를 수행하려는 경우 유용하다.[ useRoutes ]<Routes>와 기능적으로 동일하나 <Route> 요소 대신 자바스크립트 객체를 사용하여 경로를 정의한다.일반 <Route> 요소와 동일한 속성을 갖지만 JSX가 필요하지 않는다.[ Custom HOOK ]개발자가 정의하는 HOOK이다.HOOK의 이름은 use로 시작해야 한다.참고로 HOOK은 함수형 컴포넌트 또는 커스텀 HOOK에서만 호출이 가능하다.따라서 커스텀 HOOK도, 함수용 컴포넌트 또는 HOOK 내부에서 호출되어야 한다.강의에서는 useDebounce과 useOnClickOutside HOOK을 만들었다.useDebounce: input 요소에서 데이터 입력이 발생하면 설정한 set함수 때문에 매번 state 값이 바뀌고 재 렌더링이 일어난다. 따라서 keyup 이벤트의 처리를 지연시키는 커스텀 HOOK이다. (코드는 강의를 참고하자!)useOnClickOutside HOOK: 모달 창 밖의 부분을 클릭하면 해당 모달 창이 꺼지는 기능을 수행하는 HOOK이다. (코드는 강의를 참고하자!)이런 식으로 HOOK을 만들고 활용하는구나 싶었다…미션과제 총 합본 https://www.inflearn.com/blogs/7021 JS 미션 03. 퀴즈 앱[ 구현 해야하는 기능 ]1. 퀴즈 문제, 문제에 해당 하는 선택지 (선택지의 갯수가 매번 다름)2. 답 선택 시, 정답 여부에 따라 배경의 색상이 변경되어야 함문제는 data.json을 직접 작성하여 동적 생성했습니다. JS 복습 겸으로 해당 주제로 퀴즈 앱을 간단하게 만들어 봤습니다. 미션을 진행하며 문제는 없었습니다. JS 미션 04. 책 나열 앱[ 구현 해야하는 기능 ]1. 책 이름 입력 란2. 책 저자 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함4. 제출된 데이터는 책 리스트에 출력 됨아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 책 이름, 저자5-2. 각 아이템에는 삭제 기능이 있어야 함 구현하는데 문제가 없었습니다. REACT 01. 예산 계산기[ 구현 해야하는 기능 ]1. 지출 항목 입력 란2. 지출 비용 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 지출 항목, 지출 비용5-2. 각 아이템에는 수정 및 삭제 기능이 있어야 함수정 버튼 클릭 시 수정 모드로 변경전체 삭제 기능이 있어야 함정말 막힘 없이 진행되다 딱 한 군데에서 문제를 맞았습니다. 상황에 맞게 알림을 띄우는 기능이었는데, JS에서는 아무런 문제 없이 해결했던 이 기능을 React에서 구현 하려고 하니 이상한 문제가 발생하더군요. 여러 동작을 해서 메시지가 많이 발생할 경우, 메시지가 예시처럼 모두 생성되는 것이 아니라 같은 자리에서 텍스트만 바뀌어서 출력이 되었습니다. 물론 잘 해결해서 과제를 마쳤습니다.회고워밍업 스터디의 2주 차에 진입하며 자바스크립트 공부를 마치고 새롭게 React 공부를 진행하며 React의 다양한 기술을 접하게 되었습니다. 특히 state, props, hook, 그리고 라우팅 부분은 처음에는 이해하기가 어려웠습니다. 그러나 부족한 이해를 보완하기 위해서 강의 내용을 정리하고, 추가적인 학습 자료를 찾아가며 개념을 확실히 파악하려고 노력했습니다.React 학습을 마치고 시작한 미션도 초반에는 막막함을 느꼈지만 코드를 작성해 나가며 수업 때 배운 내용을 적용해 가며 문제를 해결해 나갔습니다.워밍업 스터디도 이제 끝을 향해 가네요. 마무리되는 날까지 열심히 학습에 참여하고 미션 해결을 위해 도전해 보겠습니다. 

프론트엔드워밍업클럽FE

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 1 발자국

들어가기 앞서...2024년의 첫 해가 밝으며, 지금까지는 단순히 관심만 갖고 있었던 웹 개발에 대한 공부를 시작해보기로 결심했습니다. 먼저 HTML과 CSS의 공부를 마치니 운이 좋게 인프런에서 JS와 ReactJS 스터디를 진행한다는 소식을 듣게 되었습니다. 이런 좋은 기회를 놓치지 않겠다고 생각하고, 워밍업 클럽에 참여하게 되었습니다.발자국OT를 참가한지 엊그제 같은데 시간은 정말 순식간에 지나가는 것 같습니다. 벌써 스터디가 시작된 지 1주차가 되었습니다. 이제 그 동안의 강의 내용을 간단하게 요약하고, 회고를 남겨 보려고 합니다. 이번 주 강의는 따라하며 배우는 자바스크립트 A-Z (섹션 0~8) 부분을 진행하였습니다.요약Section 01. 자바스크립트 기초[ Console 객체 ]자바스크립트의 console 객체는 코드를 작성하고 테스트를 할 때, 사용하기 좋은 함수를 제공해준다. 다음은 강의에서 소개한 주요 Console 객체의 함수들이다.console.log(): console에 메시지를 출력한다. console.table(): console에 배열이나 객체의 데이터를 테이블 형태로 출력한다. console.error(): console에 에러 메시지를 출력한다. console.warn(); console에 경고 메시지를 출력한다. console.time(), console.timeEnd(): 세트로 사용되며, 두 함수 사이의 코드 실행 시간을 측정한다. [ var, let, const과 스코프 ]변수/상수를 선언할 때 let, const 그리고 var 키워들 사용한다. let과 const는 ES6에 새롭게 추가된 키워드이다. var 키워드는 오래된 선언 키워드로 let과 const 사용을 권장하고 있다.let: 변수 키워드, 재선언 X, 재할당O const: 상수 키워드, 재선언 X, 재할당Xvar: 재선언 O, 재할당 O 그리고 사용한 let/const와 var 키워드에 따라 스코프가 다르게 처리된다. 스코프(scope, 유효/참조 범위)란 어떠한 변수를 참조하려고 할 때, 그 변수에 접근 가능한 유효 범위이다.let/const: 모든 코드 블록 { } 내부에서 선언된 변수는 코드 블록 내에서만 유효. var: 함수 내에서 선언된 var 변수는 함수 내에서만 유효하며, 함수 내에서 블록 내·외부에 관계없이 접근 가능. [ 호이스팅 ]코드가 실행되기 전에 변수 및 함수 선언을 로컬 범위(유효 범위)의 맨 위로 끌어 올려지는 경우를 말한다.[ 자바스크립트 타입과 타입 변환 ]자바스크립트의 데이터 타입(자료형)은 다음과 같다.원시 타입: Boolean, String, Number, null, undefined, Symbol고정된 크기로 Call Stack 메모리에 저장실제 데이터가 변수에 할당참조 타입: Object, Array데이터 크기가 정해지지 않고 Call Stack 메모리에 저장데이터의 값이 Heap에 저장되며 메모리의 주소 값이 할당 자바스크립트 변수에 저장된 값은 다른 데이터 유형으로 변환될 수 있다.명시적 데이터 변환(개발자가 직접 함수를 사용해서 변환)자동 데이터 변환(자바스크립트 자체에 의해 자동으로 변환) [ 연산 및 Math ]자바스크립트에서는 기본적인 산술 연산자, 논리 연산자, 비교 연산자를 제공한다.Math를 통해 더 많은 연산을 이용할 수 있다. [ Template Literals]Backtick(`)을 사용하여 문자열을 표현한 것을 템플릿 리터럴이라고 한다. 템플릿 리터럴을 이용하면 다음과 같은 이점이 있다.줄 바꿈이 쉽다.${}을 사용하여 내부에 표현식을 포함할 수 있게 한다. [ Loops ]for: 초기식, 조건식, 증감식을 포함하는 반복문으로 주어진 조건이 참일 경우 블록 안의 코드를 반복 실행for/in: 객체의 열거 간으한 속성들을 반복하는데 사용.while: 주어진 조건이 true일 동안 코드 블록을 계속해서 실행.do/while: 먼저 코드 블록을 실행한 후, 조건을 확인한다. 그러고 나서 조건이 true일 동안 반복 실행한다. Section 02. Window 객체 및 DOM[ Window 객체 ]브라우저에 의해 자동으로 생성된다. (자바스크립트 객체 X, 브라우저에서 제공 O)이 window 객체는 다음과 같은 역할을 수행한다.브라우저에 접근 및 조작 가능자바스크립트 코드의 전역 객체 역할 [ DOM ]문서 객체 모델(Document Object Model, DOM)요소로 이루어진 HTML 파일을 Tree 구조로 표현한 객체 모델최상단에는 document 노드가 위치해 있으며, 이를 통해 DOM 접근 및 조작 가능Critical Render Path (웹 페이지 렌더링 콰정)데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ Paint +) 강의에서 수 많은 Property 및 Method를 소개해 주셨지만 너무 많은 관계로 생략... Section 03. Event[ Event ]만약 인프런에서 로그인 버튼을 누르면 무엇이 일어날까? 당연히 로그인 페이지로 이동할 것이다. 이렇게 웹 페이지에서 발생하는 사용자의 행동에 대응하여 브라우저에서 일어나는 특정 사건을 "이벤트"라고 한다. 자바스크립트에서는 다음과 같은 이벤트가 존재한다.UI 이벤트load, change, resize, scroll, error 키보드 이벤트keydown, keyup, keypress마우스 이벤트click, dblclick, mousedown, mouseout, mouseover, mousemove, mouseup포커스 이벤트focus, blur폼 이벤트input, change, select, reset, submit, cut/copy/paste 이벤트를 등록하기 위해서는 addEventListener()를 사용하면 된다. 또한 이벤트 흐름에는 이벤트 bubbling과 Capturing라는 2가지의 기본 모델이 존재한다.[ Event Bubbling과 Event Capturing ]이벤트 bubbling은 가장 깊게 중첩된 요소에 이벤트가 발생했을 때, 이벤트가 위로 전달 되는 것을 의미한다. 이벤트 bubbling은 target 이벤트에서 시작해서 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 만약 bubbling 중단을 원한다면 event.stopPropagation()을 호출하면 된다.event.stopPropagation()DOM Tree를 통한 이벤트 흐름 중지 가능브라우저 기본 동작은 취소 X 이벤트 Capturing은 bubbling과 다르게 제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것을 말한다.[ Event Delegation ]이벤트 bubbling과 이벤트 Capturing을 통해서 이벤트 위임을 이해할 수 있다. 이 이벤트 위임은 '하위 요소의 이벤트를 상위 요소에 위임하는 것'이다. Section 04. 자바스크립트 중급[ this]Method의 this: 해당 객체를 가리킨다.함수에서 this: window 객체를 가리킨다.constructor의 this: 빈 객체를 가리킨다. [ bind, call, apply]call():함수를 호출하는 함수.첫 번째 인자 값으로 어떠한 것을 전달해 주면 호출되는 함수의 this가 인자 값으로 지정apply(): call()과 유사하나 인수 부분에 배열을 넣어줘야함.bind(): 해당 함수가 지정한 인자 값을 가리키도록 하지만 call(), apply()와 다르게 직접 함수 실행 X [ 삼항 연산자 ]다음과 같은 구문을 갖는다.조건 ? true이면 반환 : false이면 반환 [ Event Loop]자바스크립트는 동기 언어이다. 하지만 가끔 비동기로 작동하는 setTimeout()를 사용하는 예시를 볼 수 있다. 자바스크립트는 비동기 코드를 작성하기 위해서 자바스크립트 이외의 도움을 받는다.[ Closure ]다른 함수 내부에 정의된 함수가 있는 경우, 외부 함수가 실행을 완료하고 해당 변수가 해당 함수의 외부에서 더 이상 엑세스할 수 없는 경우에도, 해당 내부 함수는 외부 함수의 변수 및 액세스가 가능하다. 이 기능을 Closure라고 부른다.[ 구조 분해 할당 ]배열이나 객체의 속성을 해제하여 그 값을 개별 변수에 담을 수 있게 해주는 표현 식이다.[ Map, Filter, Reduce ]Map, Filter, Reduce은 배열 메서드의 대표적인 예시이다.map(): 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출하고 나온 결과를 모아 새로운 배열로 만들어 반환한다.filter(): 주어진 함수의 필터를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.reduce(): 배열의 각 요소에 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결괏값을 반환한다.[ 얕은 비교 VS 깊은 비교 ]숫자, 문자열 등 원시 자료형은 값을 비교하게 된다. 하지만 배열, 객체 등의 참조 자료형은 참조되는 위치를 비교하게 된다. 얕은 비교를 하게 되면 원시 값의 경우 문제가 없지만 참조 값의 경우 실제 값이 아닌 저장된 위치(참조 값)이 비교되기 때문에 문제가 된다.깊은 비교를 사용하게 되면 참조 자료형도 실제 값으로 비교할 수 있게 된댜ㅏ.객체 depth가 깊지 않은 경우: JSON.stringify() 사용객체 depth가 깊은 경우: lodash 라이브러리의 isEqual() 사용[ 얕은 복사 VS 깊은 복사 ]위에서 정리한 내용처럼 복사에도 문제가 발생하게 된다. 따라서 참조 자료형의 값의 경우 깊은 복사를 사용하면 된다.JSON.stringify()lodash 라이브러리의 deepCopy[ 함수 표현식, 함수 선언문 ]함수 선언문: 함수 선언은 함수를 만들고 이름을 지정하는 것이다.일반적인 함수 선언 방식으로 function 키워드와 식별자를 표기하여 사용한다.함수 표현식은 함수를 만들고; 변수에 할당하는 것이다.익명 함수(function 키워드는 사용했으나 식별자 X), 화살표 함수 사용 Section 05. OOP[ OOP ]OOP(Object-Oriented Programming, 객체 지향 프로그래밍)란 Java 및 C를 비롯한 많은 프로그래밍 언어의 기본이 되는 프로그래밍 패러다임이다. 완전 간단하게 말하자면 객체 지향 프로그래밍은 객체들의 모임이라고 할 수 있다.OOP 특징으로는 다음과 같다.추상화:불필요한 정보는 숨기고 중요한 정보 만을 표현함으로써 프로그램을 간단히 만드는 것.상속:새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있도록 해주는 것.기존 클래스: 부모 클래스, 상위 클래스새로운 클래스: 자식 클래스, 하위 클래스다형성: 하나의 틀을 가지고 여러 개의 다양한 형태를 만드는 것이다.overriding을 통하여 다형성 구현 일반적인 코드를 재사용하고 작성할 수 있다.캡슐화:클래스 안에 있는 Method, 변수 등을 하나로 묶어준다. [ class와 constructor ]class에서는 constructor라는 특별한 메서드를 제공한다. 이 constructor는 생성자로, 인스턴스화된 객체에서 다른 메서드를 호출하기 전에 수행해야 하는 사용자 지정 초기화를 할 수 있게 해준다.클래스를 new 키워드를 붙여 인스턴스 객체로 생성하면 넘겨 받은 인자 값과 함께 constructor가 가장 먼저 실행이 된다. 따라서 이 곳에 초기화를 해야 하는 작업을 수행한다.[ Super]자바스크립트에서 super는 다음과 같은 역할을 수행한다.자식 클래스 내에서 부모 클래스의 생성자를 호출할 때 사용한다.자식 클래스 내에서 부모 클래스의 메소드를 호출할 때 사용한다. Section 06. 비동기[ 동기와 비동기 ]동기(Synchronous)코드를 순차적으로 실행하는 것. 즉, 한 작업이 끝나기를 기다렸다가 끝나면 다음 작업을 수행한다.각 작업이 완료될 때까지 다음 작업이 실행되지 않는다.비동기(Asynchronous)작업이 종료되지 않아도 다음 작업을 진행할 수 있는 방식비동기적인 코드는 특정 작업을 기다리지 않고 다음 작업을 계속 수행한다. [ Callbacks, ES6 Promise, ES7 Async / Await ]callbacks콜백 함수는 특정 함수에 매개변수로 전달된 함수를 의미한다.콜백 함수는 함수를 전달 받은 함수 내부에서 호출된다.단, 콜백 지옥을 맛볼 수 있다.Promise자바스크립트 비동기 처리에 사용되는 객체이다.new 키워드와 생성자를 사용해서 만들며, 생성자의 매개변수로 실행 함수를 전달한다.new Promise(실행함수) 실행 함수의 1번째 매개변수 resolve는 비동기 작업 성공 값이다.실행 함수의 2번째 매개변수 reject는 작업 실패 값이다.Promise는 다음 중 하나의 대기 상태를 갖는다.대기, 이행, 거부단, 체인 지옥이 시작된다...Async / Await비동기 코드를 마치 동기 코드처럼 작성할 수 있도록 해준다.Promise에서 than 체인 형식으로 호출하는 것보다 가독성이 좋다.await는 async 함수에서만 사용 가능하다.동기식 코드에서 사용하는 try...catch 문을 사용할 수 있다. Section 07. Symbol, Iterator, Generator[ Symbol ]ES6에 새롭게 추가된 원시 타입으로, 유니크한 식별자를 만들기 위해서 사용.단, for...in과 getOwnPropertyNames에서 제외 된다.Symbol 사용 시 기본적으로 Property가 숨겨진다. (찾을 수 있는 방법 有)따라서 for...in과 getOwnPropertyNames에서 symbol로 만든 Property가 안보인다.[ Iterator, Generator ]Iterator대표적인 예시로 배열이 있다.반복 가능한 것을 Iterable하다고 한다. for…of를 이용할 수 있다.[Symbol.iterator()] 값을 가지고 있다.Generator사용자의 요구에 따라 일시적으로 정지할 수 있고, 다시 시작할 수 있는 특별한 기능을 가지고 있다.function다음에 Asterisk (애스터리스크)를 붙인 형태로 사용한다.function*yield 키워드를 이용한다: 제너레이터 함수의 실행을 일시적으로 정지시킴. Section 08. Design Pattern[ 디자인 패턴 ]디자인 패턴은 개발자가 응용 프로그래밍나 시스템을 디자인할 때 일반적인 문제를 히결하는 데 사용할 수 있는 공식화된 모범 사례이다.- 위키 피디아다음과 같은 장점이 있다.최고의 솔루션재사용성풍부한 표현력향상된 의사 소통필요없는 코드 리팩토링코드베이스 크기 감소[ 디자인 패턴 종류 ]Singleton Pattern: 클래스의 인스턴스화를 객체 1개로 제한하는 디자인 패턴Factory Pattern: 비슷한 객체를 반복적으로 쉽게 생성하게 해주는 디자인 패턴Mediator Pattern(중재자 패턴): 객체 그룹에 대한 중앙 권한을 제공해주는 디자인 패턴Observer Pattern: event-driven 시스템을 이용하는 디자인 패턴Module Pattern: 코드를 더 작고 재사용 가능한 조각으로 분할하게 해주는 디자인 패턴 미션완벽히 해결한 미션은 다음과 같습니다.음식 메뉴 앱음식 메뉴 앱 미션은 주어진 카테고리에 해당되는 메뉴를 출력하는 웹을 구현하는 것이었습니다. 저는 카페 메뉴를 주제로 해당 웹을 구현했습니다. 다만 출력할 아이템에 대한 DB가 없어서 직접 data.json을 작성하여 처리했습니다. 미션을 해결하면서 기능 구현에는 특별한 문제가 없었으나 기능 구현보다 데이터 파일 생성이 더 오래 걸린 미션이었습니다... (출력되는 메뉴 이미지는 스타벅스 이미지를 활용했습니다.) 가위 바위 보 앱플레이어와 컴퓨터가 가위 바위 보를 하는 게임을 구현하는 미션입니다. 총 10번의 기회가 주어지며 게임에 대한 스코어 제공 및 승패 결과를 제공해야 했습니다. UI를 어떻게 구현할까 고민하다가 이미지를 추가적으로 더 넣어 구성했습니다. 컴퓨터의 가위 바위 보 선택지는 Math.random()을 이용해 처리했으며, 기능 구현에는 특별한 문제는 없었습니다.회고자바스크립트 강의를 들으며 기초를 다지고 그 지식을 바탕으로 주어진 미션을 해결하는 한 주를 보냈습니다. 특히 웹 개발이 처음이라서 미션을 해결해 나가는 시간이 정말 흥미로웠습니다. 앞으로 워밍업 클럽 Study를 진행하며 제가 얼만큼 발전할 수 있는지 궁금해지기도 합니다. 남은 기간 최선을 다해서 임해보겠습니다!

프론트엔드워밍업클럽

대롱대롱

인프런 워밍업 클럽 2기 CS 후기 및 오프라인 수료식 후기

인프런 워밍업 클럽이 끝났습니다한달간의 여정이 끝났네요오프라인으로 수료식을 한다기에 냉큼 달려갔습니다어떤 분들과 같이 스터디를 했는지 궁금했기 때문이죠 이번에 판교를 처음 가봤습니다지하철로 판교역까지 가서 한 20분 걸으면 목적지가 나옵니다판교 구경도 할 겸 좀 걸어봤습니다 판교테크노스타트업캠퍼스 3층 인프랩에 도착해서 이름표 받고 들어갔습니다올 때까지는 조용했는데 인프랩에 들어가고 나니 와글와글 하더라구요많은 분들이 오셨는데 저는 아는 얼굴도 없고 파워I라서 일단 조용히 앉아있었습니다(사람 많은 곳을 갔을 때 흔한 I의 모습) 간단한 식사로 피자와 음료가 제공되었어요알콜/논알콜 음료로 구분되었는데 저는 알콜 음료를 집었습니다이때 아니면 회사에서 언제 알콜을 마셔보겠습니까ㅎㅎㅎ스터디 종류에 따라 회의실에 모여서 네트워킹을 진행했어요저는 CS스터디를 들었기 때문에 CS 스터디원들이 모인 곳으로 갔습니다회의실 이름이 볼드모트인가... 암튼 그랬습니다저 혼자 알콜 먹나 했는데 한 분 더 있어서 서로 위안이 되었습니다먼저 간단하게 자기소개부터 시작했는데 백엔드와 프론트엔드 분들이 많더군요AI는 저 혼자더라구요... AI스터디로 열어줘요....현업에 계신 분들도 많아서 오 신기하다하고 그분들이 얘기를 들었죠고등학생 분도 있었는데 벌써 진로를 정하고 움직이다니 대단하다고 생각했습니다 네트워킹 이후에는 온라인 접속자들과 함께하는 Q&A 시간이 진행되었습니다질문들 중에서 주요 질문 5개만 감자님이 뽑아서 답변을 해주셨습니다 Q&A까지 마치고 다시 모든 참여자들이 한자리에 모였어요코치분들 소개가 진행된 후 스터디별로 우수러너 시상이 진행되었어요CS스터디가 가장 마지막 발표라서 옆에 앉은 분이랑 이런저런 이야기하고 있었는데 놀랍게도 옆에 분과 제가 우수러너로 발표되었어요되면 좋겠는데... 안되면 슬프겠지만 어쩔 수 없지...의 마인드였는데 받으니까 좋았습니다우수러너 혜택으로 인프런 한정판 굿즈와 1:1멘토링권이 주어졌어요에코백 안에 유리컵이랑 우산이랑 미니미한 뱃지가 들어있었는데 굉장히 귀엽습니다우수러너가 되길 너무 잘한 것 같아요(초록초록한 캐릭터 너무 귀엽습니다)(가슴팍에 새겨진 깨알같은 인프런 워밍업클럽. 이런 디테일을 제가 아주 좋아합니다) 아무튼 이렇게 인프런 워밍업 스터디가 진짜 끝났습니다뭔가 시원섭섭하고 그러네요다음번에는 어떤 스터디가 열릴지 기대됩니다AI 스터디도 열렸으면 하는 바램이 있습니다^^수료식 준비하신 스탭분들과 코치님들 모두 고생많으셨습니다다음에 기회가 되면 또 만나요~~      

워밍업클럽CS스터디수료식

김예지

[인프런 워밍업 스터디 클럽 2기 FE] 오프라인 수료식 후기

 오프라인 수료식 후기 퇴근하고 판교까지 늦지 않게 갈 수 있을까 걱정했는데 다행히 여유 있게 도착해서 이름표를 받았다.안으로 들어가니 이미 많은 분들이 일찍 도착해 계셨다.  코치님이랑 다른 러너분들이랑 자기소개도 하고 피자 먹으면서 자유 네트워킹 시간을 가졌다. 발자국을 남길 때 봤던 분들을 직접 만나게 되어서 좋았다. 다들 좋으신 분들이라 오프라인 수료식에 갈지 말지 고민했던 게 무색하게 재밌던 시간이 되어서 오길 잘했다는 생각이 들었다. 잠깐의 쉬는 시간이 지나고 시작된 Q&A 시간도 좋았다. 코치님께서 하나하나 해주시는 답변들이 정말 큰 도움이 되었다. 메모를 조금 하고 싶었는데 필기도구도 안 챙겼고.. 핸드폰에 쓰면 딴짓하는 사람처럼 보일까 봐 최대한 기억만 했다.그리고 하고 싶었던 질문이 있어서 할까 말까 고민하고 있었는데 마침 다른 분이 물어봐 주셔서 내 궁금증도 같이 해소가 되었다. 다른 분들은 어떤 고민을 하고 어떤 생각을 하시는지 들을 수 있는 점도 좋았다.궁금했던 부분도 해결하고 모르는 것들도 많이 알게 되어서 유익한 시간이었다. 자유 네트워킹, Q&A 시간이 너무 빠르게 지나간 것 같아서 아쉽다는 생각이 들었다. 다른 분들이랑 얘기를 더 나누고 싶었다.  이번에 워밍업클럽 신청하길 잘한 것 같다. 3주동안 열심히 했던 만큼 성장한 부분이 있다고 생각한다.      귀여운 인프런 굿즈가 생겼다 ✌  

워밍업클럽

강지원

[인프런 워밍업 스터디 클럽 2기 FE] 강지원 오프라인 수료식 후기

인프런 워밍업 클럽 2기 오프라인 수료식 후기 처음으로 같이 스터디를 한 분들을 만나는 자리라 떨리는 마음으로 출발했다.판교역에 도착해서 버스를 기다리는데 정류장에 이런 문구가 붙어있었다.정류장에서도 코딩에 관련한 글을 읽을 수 있다니 '이 곳은 정말 코딩에 진심인 사람들이 있는 동네구나' 라는 생각이 들어서 신기하기도 하고 재밌는 마음으로 버스를 기다렸다. 시간에 딱 맞게 도착해서 거의 바로 프론트엔드 팀과 같이 앉는 시간이 되었는데 처음부터 다들 편하게 대해주셔서 많이 긴장했던 것이 풀려갔다. 자기 소개 시간에 들어보니 다른 분들은 거의 취직을 한 상태에서 이 스터디에 참여하셨다. 아직 취직을 하지 못해서 상대적으로 시간이 많던 나도 따라가기가 벅찰 분량의 스터디였는데 본업을 하면서 스터디까지 하신 모습에 감탄하면서 더 열심히 해야겠다고 마음을 다짐했다. 코치님과 피자를 먹으며 대화를 나누고, Q&A시간을 가지면서 개발자 인생에 도움이 되는 이야기를 정말 많이 들을 수 있었다. 한창 힘들 때였는데 응원을 많이 해주셔서 정말 감사하고 힘이 됐다. 질문에 대한 대답도 하나하나 적어오셔서 알려주신 것이 감동이었다. 이 시간이 더 길었으면 좋았을텐데 아쉽게 느껴졌다. 피자는 아주 맛있었다!  가장 걱정했던 시간이었던 것이 무색하게도 순식간에 끝난 네트워킹 시간이 끝나고 드디어 우수러너 발표 시간이 왔다. 우수러너가 되지 못하더라도 할 수 있는 최선을 다했으니 그것에 만족하자고 생각하면서 왔는데 막상 시상식이 시작되니 기대감이 커지기 시작했다. 그렇게 두근두근 하고 있는데 거짓말처럼 내 이름이 불렸다. 오랜만에 정말 큰 기쁨과 성취감을 느껴본 것 같다. 정말 갖고 싶었던 인프런 굿즈도 받고 코치님과 사진도 찍었다. 나와 같이 우수러너가 되신 분의 블로그를 보며 감탄할 때가 많았는데 그 분과 함께 받을 수 있어서 더 기분이 좋았다. 인프런 스터디를 통해서 실력도 멘탈도 많이 성장했다. 이번 스터디에 참가하기를 정말 잘한 것 같다ㅎㅎ 오프라인 수료식은 현장 분위기가 정말 좋았고, 코치님, 다른 개발자 분들과 함께 얘기를 나눠볼 수 있는 점도 정말 좋았다. 만약 3기에 오프라인 수료식을 고민하고 있는 사람이 있다면 무조건 가는 것을 추천한다. 수료식이 끝나고 저녁에 먹고 남은 피자를 들고 가고 있는데 피자가 많이 남았다면서 한판씩 더 주셔서 감사했다ㅎㅎ 앞으로 인프런에서의 좋은 기억을 가지고 더 열심히 살아야겠다.

인프런워밍업클럽오프라인수료식후기

빠타박스

[인프런 워밍업 클럽 2기 - CS] 지난 3주간의 여정 속에서 - 완주 후기

처음 이걸 왜 들었을까?이 과정을 듣기 2일쯤 됬던가. 벤처 게임회사에 면접을 보았다.그 회사의 면접은 그냥 말아먹었다.그 이유는 역시 기초 지식이다.  공부한지 어연 5년이 다된간다. 이쯤되면 게임개발이라는 것을 포기할만도 했다...어떻게 해야할까 하는 찰나에 인프런에 들어와 여느때 처럼 그냥 공부를 하고자 한숨을 내쉬며 들어왔는데바로 보이는... CS 이게 무슨일이지 하면서 한번 볼까? 무료라고?아.. 근데 아니였다... 기본적으로 할인을 해주나 로드맵에 있는 수강내역을 구매해야만 참가가 가능했다.나는 좀 아쉬웠다.. 가뜩이나 백수 5년째 거금을 들이기가 선뜻 겁이 났다... 그렇게 많은 돈은 아닐 수 있었지만... 나에게는 식비와 공과금을 충당해야만 하는 비용이였기 때문이다.하지만 면접에서 탈탈 털린 나로써는 CS지식이 시급했다... 나에겐 여러 장애물이 있었다...자격증 시험이였다... 항상 내 발목을 묶는 장애물이였다.이 과정을 진행하면서 실기일이 얼마 남지 않은 상태였다... 그럼에도 불구하고 CS 지식을 터득하자. 하지만 가볍게 보고 다음에 다시 보도록 하자는 마인드였다.(내가 반복하는 걸 싫어하다 보니까... 이게 참 문제다... )그렇게 그냥 열심히 했다...그냥 할 수 있는 만큼...  공부는 어떻게 해야 하죠? 난 솔직히 아직도 개발 공부란 것을 어떻게 해야할 지 모르겠다...그냥 받아적고 천천히 느리게 한다. 하나 볼때 최대한 이해하려고 다 적는다.하지만 남는게 별로 없다...반복학습이 생명인 것을 알겠다..ADHD를 겪고 있던 나로써 반복학습은 정말 지겨웠다.. 그래도 반드시 해내자 라는 마인드로 임했다...그렇게 공부한 것들을 필기하고 요약하려고 하였지만 쉽지 않았고, 최대한 가볍게 이해하려고 했다. 가장 어려웠던건 알고리즘 부분이였다... javascript로 하다보니 C++로 변환하려니까. 뭔가 비슷은 한데 헷갈리는 부분이 많았다... 안되던 것도 있었고,,,... 쉽지 않았다... 정처기 얼마 남지 않았는데 계속 붙들고 있는 경우도 발생했다그게 1주차 때이다. 그냥 무작정 하라는 대로 하였다. 최대한 깊어보이면서 간결하게다른 사람들이 쓴 것도 보았으면 좋았겠지만. 쓰고 바로 정보처리기사 공부를 해야만 했다. 18일 금요일 모든 과정이 종료 되었고, 이제 수료식만을 남겨둔채 나는 정보처리기사 공부를 집중했다.10월 20일 일요일 정보처리기사 D-Day...,..실기는 매우 어려웠었고 조졌다.... 그렇게 돌아와 낙심에 빠졌다... 그리 며칠 가지 않아서하.. CS 관련해서 심화적으로 봐야만 한다는 것을 어떻게 할까 하다가.최대한 쿠폰을 사용해서.. 보고 싶은데 해서 결국 구매를 강행했다..아직 보진 않았다. 왜냐하면 이전꺼도 다시한번 봐야만한다.다시 반복학습을 해야만 하니까. 이 과정이 끝나고 정말 운수 좋은날인가... 아는 분을 통해 일자리를 얻게 되었다...처음에는 어리둥절했다... 뭔지도 모르고 뭘 시킬지도 모르는데... 게임개발만 3년 정도를 팠다....언리얼엔진....갔더니 대표님이 언리얼엔진에 대한 이전 문제 때문에 나를 궁금해 하셨고 그일을 나에게 맡기셨다..부담스럽기도 하고 기회다 하며 재밌겠다 하며 그 기회를 붙잡았다...11월 4일 부로 출근하게 되었다. 그래서 언리얼엔진 심화 및 기초에 대한 내용을 공부하고 있어서 해당 자료구조를 못보고 있었다.  수료식그렇게 11월 1일(금)원래대로면 오프라인에 참석해야 하나.. 나의 직업군인시절 후유증으로 인해...갑자기 도져서 가지 못한다고 말하게 되었다...시작된 워밍업 클럽 수료식 과정중 코치님 감자 강사님께서 나오셔서 질의 응답 시간을 가졌다.유익한 시간이였고 좋은 정보도 얻었다. 추천 받은 책 : CODE (컴퓨터 구조에 대한 내용 밑바닥?)https://elfmfl.tistory.com/33 (펌 정보) 난 아직도 많은 공부를 해야만한다는 것을 느꼈다. 저곳에 모인 사람들 중에 분명 나보다더 대단한 사람도있고젊고 파릇파릇한 분들도 있을테고 여럿 사람들이 모였었을 것이다.부러웠다.. 저 자리에 위치할 수 있어서...하지만 또 나름 나의 시간을 아끼며 공부를 했다. 그렇게 질의응답시간이 끝나고 수료식의 대망의 수상 발표이다. 응?뭐지.. 적어도 26~30명 정도 CS 과정을 들었던거 같은데.. 우수러너에 뽑히게 되었다....다들 수상을 하고 있을 때 그저 축하해주기 위해서 남아있었는데.내가 수상하게 될 줄 은 꿈에도 몰랐다. 그래서 이 감사를 어떻게 해야 할지 바로 누군가에게 자랑을 했다. ㅎㅎ;;감사한 하루였다. 앞으로 어떤 과정이 또 생길지 모르겠다.하지만 이제 일을 시작했고, 이 일을 완벽히 하기 위해 더더욱 기초가 다져져야 한다.이 과정과 고난의 길 위를 즐기자. 기쁨으로 하루를 살아가자 이 과정을 겪을 수 있어서 감사합니다.인프런을 통해 많은 청년들이 새 꿈을 이룰 수 있게 해줬으면 좋겠다. " 모든 것의 가장 빠른 배움은 부딪히는 것이다. 그게 밑바닥이 되었든.가장 좋은것은 프로젝트를 하고 현업처럼 부딪히는 것 "     이제 다가올 2025년도를 위해인프런 공부를 하며 여러 사건과 여러 정치적인 이슈들이 있었다.우리는 내일을 위해 무언가를 지켜야 하고 싸워야 하는 경우가 생길 것이다.그저 지금 편안하게 우리가 공부할 수 있는 것은 누군가 희생되고 있음을 깨달아야 한다. "모든 일에는 당연한 것이 없다" 누군가의 배품, 누군가의 선함, 누군가의 악행,모든 것에는 이유가 있다. 포괄적차별금지법북한군파병이스라엘과 하마스 및 헤즈볼라윤모의 자금 횡령 및 국가비상금 빼돌림 여러 이슈들이 존재 한다. 우리는 공부하면서 깨어있어야 한다. 우리 미래가 결정되고우리 후대의 미래가 결정된다.해외 부자들 CEO들이 우리나라의 급격한 인구가 줄어드는 것을 바라보고 있다..대책이 없다... 그저 장막 안에서 보호를 받으면서 공부를 하는것도 그렇지만. 나라가 없어지면..공부도 무의미 하다... 깨어있는 공부를 하자. 부디 25년도에는 많은 것들이 청렴해지고 나아지길 바란다. 끝없이 성장하는 개발자가 되고생존하자. 버티며 끝까지 임하자 최선을 다하자. 내일 죽는한이 있더라도 자신의 위치에서 최선을다하자

알고리즘 · 자료구조인프런인프런워밍업클럽스터디2기자료구조알고리즘감자워밍업클럽

f1rstf1y9

[인프런 워밍업클럽 CS 2기] 2주차 발자국👣

2주차 학습 내용운영체제CPU 스케줄링 알고리즘 - SJF(Shortest Job First)Burst Time이 짧은 프로세스를 먼저 실행하는 알고리즘이론적으론 FIFO보다 성능이 좋지만, 구현에 문제가 발생할 수 있음어떤 프로세스가 얼마나 실행될지 예측 어려움Burst Time이 긴 프로세스는 아주 오랫동안 실행되지 않을 수도 있음CPU 스케줄링 알고리즘 - Round Robin한 프로세스에게 일정 시간만큼 CPU를 할당하고, 할당 시간이 지나면 강제로 다른 프로세스에게 일정 시만큼 CPU를 할당하는 알고리즘프로세스에게 할당하는 일정 시간 => 타임 슬라이스, 타임 퀀텀타임 슬라이스의 값에 따라 RR 알고리즘의 성능이 크게 바뀜타임 슬라이스가 큰 경우(무한대라고 가정)먼저 들어온 프로세스의 작업이 종료될 때까지 실행 => FIFO 알고리즘이 됨타임 슬라이스가 작은 경우(1ms라고 가정)컨텍스트 스위칭이 너무 자주 일어남프로세스 처리량보다 컨텍스트 스위칭을 처리하는 양이 더 커짐 => 오버헤드가 너무 큼최적의 타임 슬라이스 : 사용자가 느끼기에 여러 프로세스가 버벅거리지 않고, 동시에 실행되는 것처럼 느껴지면서 오버헤드가 너무 크지 않는 값Windows는 20ms, Unix는 100ms 정도 CPU 스케줄링 알고리즘 - MLFQ(Multi Level Feedback Queue)오늘날 운영체제에서 가장 일반적으로 쓰이는 CPU 스케줄링 기법기본적으로 CPU 사용률과 I/O 사용률이 좋게 나오는 작은 크기의 타임 슬라이스를 선택하되, CPU Bound Process들에게는 타임 슬라이스를 크게 줌CPU를 사용하는 프로세스가 스스로 CPU를 반납하면 I/O Bound Process일 확률이 높고, 실행 도중 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황이 발생하면 CPU Bound Process일 확률이 높음우선순위 큐를 여러 개 준비하여, 우선순위가 높으면 타임 슬라이스 크기가 작고, 우선순위가 낮으면 타임 슬라이스 크기가 커짐처음엔 타임 슬라이스가 작게 할당되어있다가, CPU가 강제로 뺏기면 좀 더 큰 타임 슬라이스를 할당받게 됨프로세스 간 통신프로세스는 독립적으로 실행되기도 하지만, 다른 프로세스와 데이터를 주고받으며 통신을 하는 경우도 있음한 컴퓨터 내에서 프로세스 간 통신하는 방법파일을 이용하는 방법통신하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프를 이용하는 방법운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법한 프로세스 내에서 쓰레드 간 통신하는 방법데이터 영역의 전역 변수나 힙을 이용해 통신네트워크를 이용한 방법운영체제가 제공하는 소켓통신이나 다른 컴퓨터에 있는 함수를 호출하는 RPC(원격 프로시저 호출)를 이용해 통신공유자원과 임계구역공유자원프로세스가 통신할 때 공동으로 이용하는 변수, 파일 등여러 프로세스가 공유하고 있기 때문에 각 프로세스의 접근 순서에 따라 결과가 달라질 수 있음임계 구역(Critical Section)여러 프로세스가 동시에 사용하면 안되는 영역경쟁 조건(Race Condition) : 공유 자원을 서로 사용하기 위해 경쟁하는 것임계 구역 문제를 해결하기 위한 조건상호 배제(Mutual Exclusion) 메커니즘 필요임계 구역엔 주어진 시간에 항상 하나의 프로세스만 접근할 수 있어야 한다동시에 여러 개의 요청이 있더라도 하나의 프로세스의 접근만 허용한다.임계 구역에 들어간 프로세스는 빠르게 나와야 한다.세마포어프로세스들은 대기 큐에서 공유 자원을 사용하기 위해 대기하고, 운영 체제가 관리하는 열쇠를 가진 프로세스만 공유 자원을 사용할 수 있음 => 이때 이 열쇠를 세마포어(정수형 변수)라고 함공유 자원의 개수에 따라 세마포어의 값 또한 달라짐wait() : 열쇠를 요청해서 열쇠를 받고 문을 잠금. 열쇠가 없으면 기다림signal() : 방에서 나와 문지키는 직원에게 열쇠 반납단점 : wait() 함수, signal() 함수의 순서를 이상하게 호출해서 세마포어를 잘 못 사용할 가능성이 있음 => 모니터로 해결!모니터운영체제가 처리하는 것이 아닌, 프로그래밍 언어 차원에서 지원하는 방법Java에서 synchronized라는 키워드가 붙으면, 이 키워드가 붙은 함수들은 동시에 여러 프로세스에서 실행시킬 수 없음 = 상호배제가 완벽하게 이루어짐만약 프로세스 A에서 increase() 함수를 실행하면, 프로세스 B는 synchronized 키워드가 붙은 decrease() 함수도 실행할 수 없음교착상태(데드락)여러 프로세스가 서로 다른 프로세스의 작업이 끝나길 기다리다가 아무도 작업을 진행하지 못하는 상태교착상태의 필요 조건 (한가지라도 충족하지 않으면 교착상태 발생 X)상호배제 : 어떤 프로세스가 한 리소스를 점유했다면, 그 리소스는 다른 프로세스에게 공유되면 안됨 비선점 : 프로세스 A가 리소스를 점유하고 있는데 프로세스 B가 리소스를 빼앗을 수 없어야 함 점유와 대기 : 어떤 프로세스가 리소스A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야 함 원형 대기 : 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있어야 함 교착 상태의 네가지 조건을 이용해서 교착상태를 예방하는 방법을 연구해보고자 했으나, 제약이 많고 비효율적이라 해결하는 방법을 연구함교착상태 회피(Deadlock avoidance)프로세스들에게 자원을 할당할 때 어느정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 수준의 자원 할당을 함전체 자원의 수와 할당된 자원의 수를 기준으로 안정 상태, 불안정 상태로 나눔운영체제는 최대한 안정 상태를 유지하려고 자원할당 함불안정 상태에 있더라도 무조건 교착 상태에 빠지는 것이 아닌, 교착 상태에 빠질 확률이 높아짐운영체제에서 은행원 알고리즘 구현하기안정상태은행원 알고리즘은 각 프로세스가 현재 요구할 수 있는 요청이 예상되는 자원을 구함  P1에서 4개를 요청하면 현재 사용 가능 자원이 2개뿐이므로 거절P2에서 2개를 요청하면 2개 모두 P2에 할당, P2는 작업을 마치고 6개를 반납사용 가능한 자원이 6개가 되어, P1, P3 모두에 필요한 만큼 할당 가능불안정 상태사용 가능한 자원이 1개현재 사용 가능한 자원 개수로는 P1, P2, P3가 요청할 수 있는 최대 요청인 2개를 충족하지 못함 => 불안정 상태모든 프로세스가 최대 자원을 요청하지 않는다면 교착 상태에 빠지지 않을 수도 있지만, 불안정상태에 빠지지 않도록 유지하는게 좋음교착상태의 검출 방식가벼운 교착 상태 검출프로세스가 일정 시간 동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주해결 방법 : 일정 시점마다 체크포인트를 만들어 작업을 저장하고 타임아웃으로 교착 상태가 발생했다면 마지막으로 저장했던 체크포인트로 롤백무거운 교착 상태 검출자원 할당 그래프 이용현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착 상태가 발생했다면 해결그래프에 순환 구조가 생긴다면 교착 상태가 생긴 그래프교착 상태를 검출하면 교착 상태를 일으킨 프로세스를 강제 종료시키고, 다시 실행시킬 때 체크포인트로 롤백단점 : 운영체제가 지속적으로 자원할당그래프를 유지하고 검사해야하므로 오버헤드가 발생장점 : 가벼운 교착상태에서 발생하는 억울하게 종료되는 프로세스는 발생하지 않음메모리 종류레지스터가장 빠른 기억장소, CPU 내에 존재휘발성 메모리 - 컴퓨터의 전원이 꺼지면 데이터가 사라짐CPU를 구분할 때 말하는 32bit, 64bit는 레지스터의 크기를 말함CPU는 계산을 할 때, 메인메모리에 있는 값을 레지스터로 가져와 계산하고, 결과는 메인메모리에 저장캐시휘발성 메모리레지스터는 굉장히 빠르고, 메인메모리는 너무 느림 => 메인 메모리에 있는 값을 레지스터로 옮기려면 한참 걸리므로 필요할 것 같은 데이터를 미리 가져와서 캐시에 저장성능의 이유로 여러개를 둠메인메모리(RAM)실제 운영체제와 다른 프로세스들이 올라가는 공간전원이 공급되지 않으면 데이터가 지워지므로 휘발성 메모리하드디스크나 SSD보다 속도는 빠르지만, 가격이 비싸므로 데이터를 저장하기 보다는 실행 중인 프로그램만 올림 보조저장장치(HDD, SSD)사무용 프로그램, 게임, 작업한 파일 등을 저장할 필요가 있는데, 비싸고, 휘발성인 메모리에 저장할 순 없음가격이 저렴하고 전원이 공급되지 않아도 데이터가 지워지지 않는 비휘발성 메모리를 만듦 메인메모리오늘날의 컴퓨터 구조인 폰 노이만 구조는 모든 프로그램을 메모리에 올려 실행시킴운영체제는 메모리를 관리하기 위해 1바이트 크기로 구역을 나누고 숫자를 매김 => 이 숫자는 "주소"라고 부름물리 주소와 논리 주소물리 주소 : 메모리를 컴퓨터에 연결하면 0x0번지부터 시작하는 주소 공간논리 주소 : 사용자 관점에서 바라본 주소 공간사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있음경계 레지스터메모리에는 수많은 프로세스가 올라오는데, 운영체제를 위한 공간은 따로 마련해둠. 이때,하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 경계 레지스터를 만듦메모리 할당 방식유니 프로그래밍메모리 오버레이유니프로그램 방식에서 메모리보다 더 큰 프로그램을 실행시키는 방법큰 프로그램을 메모리에 올릴 수 있도록 잘라서 당장 실행시켜야 할 부분만 메모리에 올리고 나머지는 용량이 큰 하드디스크의 스왑 영역에 저장하는 기법멀티프로그래밍가변 분할 방식(세그멘테이션)프로세스의 크기에 따라 메모리를 나누는 방식장점 : 내부 단편화 없음단점 : 외부 단편화 발생고정 분할 방식(페이징)프로세스의 크기와 상관 없이 메모리를 정해진 크기로 나누는 방식 장점 : 구현이 간단하며 오버헤드가 적음단점 : 작은 프로세스도 큰 영역에 할당돼서 공간이 낭비되는 내부 단편화 발생버디 시스템오늘날 가변 분할 방식과 고정 분할 방식을 혼합하여 단점을 줄인 방식2의 승수로 메모리를 분할해 메모리를 할당하는 방식가변 분할 방식처럼 프로세스 크기에 따라 할당되는 메모리 크기가 달라지고, 외부 단편화를 방지하기 위해 메모리 공간을 확보하는 것이 간단함고정 분할 방식처럼 내부 단편화가 발생하긴 하지만 많은 낭비가 발생하진 않음알고리즘재귀(recursion)어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀 함수탈출 조건이 없으면 콜스택이라는 메모리 공간이 가득차서 자동으로 종료언제 종료될지 예측할 수 있게 하기 위해 탈출 조건, 즉 기저 조건이 반드시 필콜스택함수가 호출되면서 올라가는 메모리 영역, 스택이라고도 부름FILO(먼저 들어온 데이터가 나중에 나감) 특성을 가짐함수를 호출하면 함수는 콜스택에 올라가고, 종료되면 콜스택에서 제거됨버블 정렬(Bubble Sort)앞에 있는 숫자와 뒤에 있는 숫자를 비교해서 자리를 바꾸는 알고리즘데이터를 옆 데이터와 비교하면서 자리를 바꾸는게 버블이 일어나는 것 같아서 붙여진 이름시간복잡도 : O(n^2)장점 : 이해와 구현이 쉽다단점 : 성능이 좋지 않다.function BubbleSort(arr){ for(let i = 0; i < arr.length - 1; i++){ for(let j = 0; j < (arr.length - i - 1); j++){ if(arr[j] > arr[j + 1]){ let temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }선택 정렬 (Sellection Sort)배열의 정렬되지 않은 영역을 순회하며 가장 작은 값을 탐색 후 교체하는 방법시간복잡도 : O(n^2)장점 : 이해와 구현이 쉽다단점 : 성능이 좋지 않다function SelectionSort(arr){ for(let i = 0; i < arr.length - 1; i++){ let minValueIndex = i; for(let j = i + 1; j < arr.length; j++){ if(arr[j] < arr[minValueIndex]){ minValueIndex = j; } } let temp = arr[i]; arr[i] = arr[minValueIndex]; arr[minValueIndex] = temp; } }회고칭찬하고 싶은 점이번 주부터 알고리즘 스터디를 시작하고, 또 매일 출근도 하면서 오늘 있었던 코딩테스트까지 일주일 간 이것저것 할일이 많았는데 포기하지 않고 이번주차 진도를 따라잡았다. CS 중에서도 운영체제는 개념이 잘 잡혀있지 않았는데, 공부를 하면서 운영체제에서 가장 중요한 개념인 프로세스와 CPU 스케줄링에 대해 어느정도 개념을 이해할 수 있는 일주일이었다.아쉬웠던 점이번주에도 역시나 매일매일 정해진 분량을 학습하기보다는 시간이 남는 타임에 몰아들은 경우가 더 많았던 것 같다.보완해야할 점남은 일주일도 바쁠 예정이기 때문에..현실적으로 매일매일 정해진 분량을 지켜서 노트까지 정리해가며 학습하기엔 벅차더라도, 지난 주처럼 너무 한번에 몰아서 하지 말고 출퇴근 시간을 이용해서 강의를 가볍게 보고 추후에 다시 복습하는 개념으로 노트를 정리하면 좋을 것 같다.

워밍업클럽CS발자국

정지형

[인프런 워밍업 스터디 클럽 2기 FE] 정지형 1주차 발자국

💡 1주차 회고강의를 듣기만 하고 따로 적어두진 않아서 정리하는데 오래걸렸다...! 다음주부터는 들으면서 해야겠다.미션같은 경우 순수 js로 구현해본적이 없어서 어려울거라 생각했는데 막상 해보니 괜찮았다.단 효율적인 코드로 작성한건지는 모르겠다...! 일단 기능만 구현하고 스타일은 꾸미지 않았는데 시간 나는 대로 틈틈히 스타일도 추가로 작업해야겠다.역시 스타일이 안들어가니 허전해.. 🤔 직장인이라서 진도를 따라갈 수 있을까 했는데 이번주와 다음주에 공휴일이 있어서 다행이다. 럭키비키잖아🍀다음주도 열심히 뚠뚠 🐜 가보자고!📝 강의 내용 요약 섹션 2 자바스크립트 기초console객체브라우저의 디버깅 콘솔(Firefox 웹 콘솔 등)에 접근할 수 있는 메서드를 제공log뿐만 아닌 time, table, clear...다양한 메서드가 있음.var, let, const변수 선언 방식var - 중복 선언과 재할당 가능 let(ES6) - 중복 선언 불가, 재할당 가능const(ES6) - 중복 선언과 재할당 불가유효한 참조 범위(scope)함수 레벨 스코프(function-level scope) - var블록 레벨 스코프(block-level-scope) - let, const호이스팅(Hoisting)코드가 실행되기 전 변수 및 함수 선언이 로컬 범위의 맨 위로 끌어올려지는 경우를 말함.변수생성 과정선언단계 =[ TDZ(일시적 사각지대) ] => 초기화단계(undefined값 할당) => 할당 단계 (값 할당)타입별 변수 호이스팅var - 선언, 초기화함수 선언문 : 선언, 초기화, 할당let, const - 선언 (선언 전 접근시 TDZ로 오류발생)자바스크립트 타입 (동적 타입)원시 타입 (number, string, boolean,undefined, null, symbol• bigInt)고정된 크기로 Call Stack 메모리에 저장, 실제 데이터가 변수에 할당참조 타입 (object, arrays, functions, classes, ...)데이터 크기가 정해지지 않고 Call Stack 메모리에 저장, 데이터의 값이 heap에 저장되며 변수에 heap 메모리의 주소값이 할당 타입변환js 변수는 새 변수 및 다른 데이터 유형으로 변환할 수 있습니다.1. js 함수를 사용하여,2. js 자체에 의해 자동으로 • 문자열과 숫자: + 연산 시 숫자가 문자열로 변환됨.  • 숫자 연산: -, *, /에서 문자열이 숫자로 변환됨.• 비교: == 연산 시 두 값 중 하나가 다른 타입으로 변환됨.  • Boolean 컨텍스트: if나 while 같은 논리적 평가 시 다양한 값이 true나 false로 변환됨.  • 숫자와 불리언: 숫자 연산 시 true는 1, false는 0으로 변환됨.Math객체Template Literals - backtick(`) 줄바꿈을 쉽게할 수 있고 문자열 내부에 표현식 포함할 수 있게됨.Loops루프의 종류for - 코드 블록 여러번 반복for/in - 객체의 속성을 따라 반복while - 지정된 조건이 true인 동안 코드 블록 반복do/while - 조건이 true인지 검사하기 전 코드 블록 한 번 실행 이후 조건이 true인 동안 루프 반복섹션 3 Window 객체 및 DOMwindow Object브라우저에 의해 자동으로 생성되며 웹 브라우저의 창(window)를 나타냅니다.또한 window는 브라우저의 객체이지 js의 객체가 아닙니다.이 window 객체를 이용해서 1.이 브라우저 창에 대한 정보와 제어를 할 수 있고 2.var 키워드로 변수를 선언하거나 함수를 선언하면 이 window 객체의 프로퍼티가 됨.dom(문서 객체 모델) - 메모리에 웹 페이지 문서 구조를 트리구조로 표현해서 웹 브라우저가 HTML 페이지를 인식하게 해줌.웹 페이지 빌드 과정(Critical Rendering Path CRP)웹 브라우저가 HTML 문서를 읽고, 스타일 입히고 뷰포트에 표시하는 과정document object브라우저 내에서 콘텐츠를 보여주는 웹페이지 자체객체 사용시 웹 페이지의 상태와 모든 HTML 태그에 접근 가능요소 탐색요소 생성 createElement요소 삭제 removeChild요소 교체 replaceChild섹션 4 EventEventListener - 이벤트가 발생했을때 어떠한 액션을 위한 함수를 호출. 해당 함수가 이벤트 리스너addEventListerner() - 이벤트 리스너를 객체나 요소에 등록해야 사용가능. 등록해주는 함수Event 종류UI 이벤트키보드 이벤트마우스 이벤트포커스 이벤트폼 이벤트Event Bubbling가장 깊게 중첩된 요소에 이벤트가 발생했을 때 이벤트가 위로 전달되는 것[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #3 Event,인프런 강의]Event Capturing제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #3 Event,인프런 강의]이벤트의 3단계 흐름1. 캡처링 단계 - 이벤트가 하위 요소로 전파되는 단계2. 타깃 단계 - 이벤트가 실제 타깃 요소에 전달되는 단계3. 버블링 단계 - 이벤트가 상위 요소로 전파되는 단계[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #3 Event,인프런 강의]Event Delegation - 하위요소의 이벤트를 상위 요소에 위임(제어)하는 것[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #3 Event,인프런 강의]섹션 5 자바스크립트 중급자바스크립트 this함수에서 this 사용 => Window 객체를 가리킴메소드에서 this 사용=>해당 객체를 가리킴constructor 함수에서 this 사용 =>빈 객체를 가리킴forEach(callback, thisArg)화살표 함수에서 this 사용 => 상위 스코프의 this를 가리킴(Lexical this)bind, call, apply 메소드함수의 this 컨텍스트를 제어const person1 = { firstName: “John”, lastName: “Doe” } ------------------------------------- const fullName = function() { console.log(this.firstName + “ “ + this.lastName); } //call() fullName.call(person1); ------------------------------------- const fullName = function (city, country) { console.log(`${this.firstName}, ${this.lastName}, ${city}, ${country}`); } fullName.call(person1, "Oslo", "Norway"); // 인수 넣어 사용 가능 //apply() fullName.apply(person1, ["Oslo", "Norway"]); // call 메서드와 비슷하지만 인수에 배열넣어야 함. ------------------------------------- //bind() function func(language) { if (language === “kor”) { console.log(`language: ${this.korGreeting}`); } else { console.log( (`language: ${this.engGreeting}`); } } Const greeting = { korGreeting: “안녕 “, engGreeting: “Hello “, }; Const boundFunc = func.bind(greeting); boundFunc(‘kor’); //call, apply와 다른 점 직접 함수를 실행하지 않고 반환 ㅁ 조건부 삼항 연산자 (result ? result = "" : result = "")Event Loop자바 스크립트 동기 코드인데 비동기 코드를 작성하기 위해 브라우저에서 사용한다면 브라우저 api (window object)Node에서 사용한다면 Node api(global object) 사용.web API 실행시 내부 진행[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #4 자바스크립트 중급, 인프런 강의]자바스크립트 엔진메모리 힙 - 메모리 할당이 발생 (변수를 정의하면 저장되는 창고)호출 스택 - 코드가 실행될 때 스택들이 이곳에 쌓임.[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #4 자바스크립트 중급, 인프런 강의]undefined vs null둘다 원시 자료형undefined = 아무 값도 할당받지 않은 상태null = 비어있는, 존재하지 않는 값 Map, Filter, ReduceClosure다른 함수 내부에 정의딘 함수가 있는 경우 외부 함수가 실행을 완료하고 해당 변수가 해당 함수 외부에서 더 이상 액세스할 수 없는 경우에도 해당 내부 함수는 외부 함수의 변수 및 범위에 액세스할 수 있음.Destucturing배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 js 표현식let { accessory, animal, color } = animalData;전개 연산자특정 객체 또는 배열의 값을 다른 객체, 배열로 복제하거나 옮길 때 사용.const arr = [...arr1, ...arr2];얕은 비교 vs 깊은 비교얕은 비교숫자, 문자열 등 원시 자료형은 값을 비교배열, 객체 등 참조 자료형은 값 혹은 속성을 비교하지 않고, 참조디는 위치를 비교깊은 비교객체의 경우에도 값으로 비교Object depth가 깊지 않은 경우 : JSON.stringfy() 사용Object depth가 깊은 경우 : lodash 라이브러리의 isEqual() 사용얕은 복사 vs 깊은 복사얕은 복사중첩된 배열이나 객체가 있다면 따라서 변경됨.spread operator, Object assign, Array.from(), slice, shallow copyObject.freeze() - 얕은 동결 : 객체를 동결합니다. 중첩된 구조에서 올바른 역할을 수행하지 못함.깊은 복사중첨된 곳에 따로 spread operator 사용lodash 라이브러리를 이용한 deepCopystructuredCloneconst 참조 타입 데이터 변경const array = ["A", "B", "C"];array.push("D");call stack에 reference ID는 같고 heap memory값만 바뀌어서 에러가 나지 않음.함수 표현식 vs 함수 선언문예시// 함수 표현식 function funcDeclaration() { return '함수 선언문'; } // 함수 선언문 let funcDeclaration = function () { return '함수 표현식'; }함수 선언식은 호이스팅에 영향을 받지만 표현식은 받지 안음.strict mode엄격모드는 제한된 버전을 선택하여 암묵적인 느슨한 모드를 해제하기 위한 방법적용방법파일에 "use strict" 지시자 입력함수 안에 "use strict" 사용해서 그 함수만을 위해서 strict mode를 적용class를 사용하면 자동으로 strict mode가 적용됨Intersection observer기본적으로 브라우저 뷰포트와 설정한 요소의 교차점을 관찰하며, 요소가 뷰포트에 포함되지 않는지, 더 쉽게는 사용자 화면에 지금 보이는 요소인지 아닌지 구별Pure Function순수 함수의 규칙1. 같은 입력값이 주어졌을 때, 언제나 같은 결과값을 리턴한다. (same input => same output)2. 사이드 이펙트를 만들지 않는다. (no dise effects)사용하는 이유1. 클린 코드를 위해서2. 테스트를 쉽게하기 위해서3. 디버그를 쉽게 하기 위해서4. 독립적인 코드를 위해서(Decoupled / Independent)Curry functionf(a,b,c)처럼 단일 호출로 처리하는 함수를 f(a)(b)(c)와 같이 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합될 수 있게 변환하는 것자바스크립트 엔진자바스크립트를 실행하려면 자바스크립트 엔진이 필요.브라우저에는 자바스크립트 엔진이 있어서 실행 가능.IIFE(Immediately Invoked Function Expression)정의되자마자 즉시 실행되는 함수를 말한다.사용하는 주된 이유는 변수를 전역으로 선언하는 것을 피하기 위함.내부 안으로 다른 변수들이 접근하는 것을 막을 수도 있음.첫 번째() 소괄호 => 전역 선언 막고, IIFE 내부 안으로 다른 변수 접근두번 째() 소괄호 => 즉시 실행 함수를 생성하는 괄호( function() { // Do fun stuff } )() 섹션 6 OOP ( 객체 지향 프로그래밍) 하나의 문제 해결을 위한 독립된 단위 "객체"들의 모임알아보기 쉽고 재사용성이 높아짐특징자료 추상화불필요한 정보는 숨기고 중요한 정보만 표현해 프로그램 간단히 만드는 것상속기존 클래스의 자료와 연산을 이용할 수 있게 하는 기능다형성한 요소에 여러개념을 넣어 놓는 것 같은 메소드라도 각 인스턴스에 따라 다양한 형태를 가질 수 있는 것.클래스 & 오버 라이딩 - 자식 클래스의 메서드가 부모 클래스의 메서드와 다르게 동작하거나 변수가 다른 값으로 지정될 수 있음.캡슐화클래스 안에 관련 메서드, 변수를 하나로 묶어줌바깥에서의 접근을 막아 보안이 강화되고 잘 관리되는 코드 제공prototype & prototype chain자바스크립트 객체가 다른 객체로부터 메서드와 속성을 상속받는 메커니즘.sub class(Inheritance) - extends 키워드를 사용해 부모클래스 기능 그대로 자식 클래스를 만들 수 있음super() - 부모 생성자 호출ES6 classesstatic 정적 메서드 사용 - "prototype"이 아닌 클래스 함수 자체에 메서드를 설정할 수도 있습니다.사용 예시class Person { // 생성자(constructor)는 클래스의 인스턴스가 생성될 때 호출됩니다. constructor(name, age, job) { this.name = name; // 클래스의 속성 설정 this.email = email; this.birthday = new Date(birthday); } // 메서드 정의: 클래스 내의 함수 introduce() { return `Hello my name is ${this.name}`; } static multipleNumbers(x, y) { return x * y; } } console.log(Person.multipleNumbers(2, 9); 섹션 7 비동기시간이 오래 걸리는 작업을 먼저 시작하고, 그 작업이 끝나지 않아도 다음 작업을 먼저 처리.(<->) 동기 - 작업이 순차적으로 진행되어, 앞선 작업이 끝날 때까지 다음 작업을 실행하지 않음. callback, promise 그리고 Async/Await비동기 요청이 여러개 있을 때 하나의 요청이 다른 요청의 결과에 의존해야하는 경우 사용[출처 : 저자, 따라하며 배우는 자바스크립트 A-Z 강의 자료 #6 비동기,인프런 강의 ] 👩🏻‍💻 미션1번 (Day2)음식 메뉴 앱2번 (Day3)가위 바위 보 앱3번(Day4)퀴즈 앱4번(Day5)책 리스트 나열 앱 5번(Day5)Github Finder 앱

웹 개발워밍업클럽FE과제

Taeho

인프런 워밍업 클럽 - CS Week 2

AlgorithmRecursion(재귀)어떠한 것을 정의할 때 자기 자신을 참조하는 것을 의미한다.재귀함수 : 재귀적으로 정의된 함수재귀함수는 콜스택이라는 메모리 가득차게 되는 경우 자동으로 종료된다.기저 조건 : 재귀함수가 종료될 수 있는 탈출 조건기저 조건이 반드시 있어야 정상적으로 수행할 수 있다.재귀함수는 함수를 호출할 때마다 Call Stack이라는 메모리 공간에 호출정보가 저장된다.→ 재귀함수는 Loop문보다 더 많은 메모리 공간을 차지한다.Call Stack(= Stack)함수가 호출되면서 올라가는 메모리 영역함수가 종료되면 콜스택에서 제거된다.FILO(First-In Last-Out)재귀함수를 사용하는 이유Loop를 대신한다기 보다는 더 복잡한 문제를 쉽게 해결하기 위해 사용된다.ex) Factorial재귀함수를 쉽게 작성하는 방법재귀함수 내에서 자기 자신을 호출할 때 해당 함수가 벌써 구현이 되어있다고 가정한다.재귀 사용하는 패턴단순 반복문반복문으로 구현했을 때보다 이점이 되는 부분이 없음Call Stack에 공간을 많이 차지해 성능이 반복문보다 좋지 않다.하향식 계산하향식 계산 : 하위문제의 결과를 기반으로 현재 문제를 계산하는 방식재귀가 반복문보다 성능이 좋은 경우큰 문제를 해결하기 위해 작은 재귀 함수를 호출한다.재귀를 사용해서만 구현이 가능하다.상향식 계산 : 하위 문제를 모아서 현재 문제를 계산하는 방식반복문으로 구현한 것보다 성능이 좋지 않음반복문이나 재귀를 사용해서 구현할 수 있다.하노이의 탑하향식 계산 방식의 좋은 예시→ 재귀함수의 좋은 예시제약 조건한 번에 하나의 원반을 움직일 수 있다.가장 위에 있는 원반만 옮길 수 있다.아래에 작은 원반이 올 수 없다. Bubble Sort인접한 두 원소를 비교하여 두 원소의 위치를 교환한다.과정배열을 처음부터 끝까지 순회하며 인접한 두 원소를 비교한다.왼쪽 원소가 오른쪽 원소보다 크면 두 원소를 교환한다.이 과정을 배열이 정렬될 때까지 반복한다.시간 복잡도O(n^2)장점이해와 구현이 간단한다.단점성능이 좋지 않다.Selection Sort배열에서 최솟값을 찾아 맨 앞으로 이동시킨다.과정정렬되지 않은 부분에서 최솟값을 찾는다.찾은 최솟값을 정렬되지 않은 부분의 첫 번째 원소와 교환한다.정렬된 부분을 한 칸 늘리고, 정렬되지 않은 부분에서 위 과정을 반복한다.시간 복잡도O(n^2)장점이해와 구현이 간단하다.단점성능이 좋지 않다.참고 : https://visualgo.net/en/sortingCPU Scheduling AlgorithmSJF(Shortest Job First)Burst Time이 짧은 작업부터 CPU를 할당한다.문제점어떤 프로세스가 얼마나 실행될지 예측하기 힘들다.→ 예측하는 것이 거의 불가능하다.Burst Time이 긴 프로세스는 아주 오랫동안 실행되지 않을 수 있다.→ Burst Time이 긴 프로세스는 Burst Time이 짧은 프로세스에게 계속해서 우선순위가 밀린다.⇒ 사용되지 않는다.RR(Round Robin)하나의 프로세스에게 일정 시간만 CPU를 할당하고 할당된 시간이 지나면 강제로 다른 프로세스에게 일정시간만큼 CPU를 할당하는 방식→ 강제로 CPU를 뺏긴 프로세스는 Queue의 가장 마지막으로 밀려난다.Time Slice(=Time Quantum) : 프로세스에게 할당하는 일정 시간Time Slice에 따라서 RR의 성능이 좌지우지된다.Time Slice를 작게 만드는 경우 Context Switching이 빈번하게 발생된다.→ Context Switching이 빈번하게 발생함에 따라 성능이 떨어진다.Time Slice가 큰 경우 FIFO와 동일하게 동작한다.Time Slice 예시Window Time Slice : 20msUnix Time Slice : 100ms단점Context Switching이 존재한다.→ 평균 대기시간이 FIFO와 동일하다면 FIFO가 더 성능이 좋다.MLFQ(Multi Level Feedback Queue)RR의 업그레이드 버전주로 사용되는 CPU 스케줄링 알고리즘CPU Bound Process : CPU를 할당받은 시간을 대부분 CPU 연산을 수행하는 프로세스CPU 사용률과 처리량이 중요I/O Bound Process : 대부분의 시간을 I/O 작업에 수행하고 적은 시간만 CPU 연산을 하는 프로세스- 응답시간이 중요MLFQ는 기본적으로 CPU 사용률과 I/O 사용률이 좋게 나오는 작은 크기의 Time Slice를 사용한다.CPU Bound Process에게는 CPU 사용률을 높이기 위해 Time Slice를 높게 할당한다.I/O Bound Process에게는 I/O 사용률을 높이기 위해 Time Slice를 낮게 할당한다.OS는 어떻게 CPU Bound Process와 I/O Bound Process를 구분할까?CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하는 경우 CPU 사용률이 낮음→ I/O Bound Process일 확률이 높음CPU를 사용하는 프로세스가 실행하다가 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황인 경우 CPU 사용률이 높음→ CPU Bound Process일 확률이 높음구현 방법우선순위를 갖는 큐를 여러개 준비한다.우선순위가 높으면 Time Slice가 작다.우선순위가 낮아질수록 Time Slice가 커진다.Process간 통신하나의 컴퓨터 내에서 프로세스간 통신하는 방법Pipe운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법File통신을 하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법Thread를 이용한 통신하나의 프로세스 내에서 쓰레드간 통신하는 방법쓰레드는 코드, 데이터, 힙 영역을 공유한다.(스택 영역만 별도로 갖는다.)데이터 영역의 전역 변수나 힙 영역을 이용하여 통신할 수 있다.NetworkOS가 제공하는 Socket 통신RPC(Remote Procedure Call)다른 컴퓨터의 함수를 호출하는 방법공유자원과 임계구역공유자원 : 프로세스간 통신을 할 때 공용으로 이용하는 변수나 파일여러 프로세스가 공유하기 때문에 각 프로세스의 접근 순서에 따라서 결과가 달라질 수 있다.컨텍스트 스위칭으로 시분할 처리를 하기 때문에 프로세스간의 실행 순서를 예측하기 어렵다.⇒ 동기화 문제가 발생할 수 있다.임계규역 : 여러 프로세스가 동시에 사용하면 안되는 영역상호배제 메커니즘을 통해 해결할 수 있다.경쟁조건 : 공유자원을 사용하기 위해 서로 경쟁하는 것상호배제 요구사항임계영역엔 동시에 하나의 프로세스만 접근한다.여러 요청에도 하나의 프로세스의 접근만 허용한다.임계구역에 들어간 프로세스는 빠르게 나와야한다.Semaphore상호배제 메커니즘의 한 종류Semaphore :  정수 값을 가지는 변수로, 공유 자원에 접근할 수 있는 프로세스/스레드의 수를 나타낸다.세마포어를 갖고 있는 프로세스가 실행되고 세마포어를 반납한다.기본 연산wait(S): 세마포어 값을 감소시킨다.값이 0이면 프로세스/스레드를 대기 상태로 만든다.signal(S): 세마포어 값을 증가시킵니다.대기 중인 프로세스/스레드가 있다면 깨운다.종류이진 세마포어: 0과 1 두 가지 값만 갖는다.(뮤텍스와 유사하게 사용한다.)카운팅 세마포어: 0 이상의 정수 값을 갖는다.(여러 자원을 관리할 때 사용된다.)장단점장점: 여러 프로세스/스레드 간의 복잡한 동기화 문제를 해결할 수 있다.단점잘못 사용하면 교착 상태나 기아 상태를 유발할 수 있다.ex) 세마포어를 획득하는 함수와 세마포어를 반납하는 함수의 위치 잘못 사용Mutex(MUTual EXclusion)뮤텍스는 이진 세마포어의 특수한 경우여러 스레드가 공유 자원에 동시에 접근하는 것을 방지하는 기술기본 연산Lock: 스레드가 임계 영역에 진입할 권한을 획득Unlock: 임계 영역 사용을 마치고 다른 스레드가 진입할 수 있게 한다.뮤텍스와의 차이세마포어는 여러 프로세스/스레드의 접근을 허용할 수 있지만, 뮤텍스는 하나의 프로세스/스레드만 접근을 허용한다.Monitor세마포어의 단점을 보완한 상호배제 메커니즘OS가 처리하는 것이 아니라 프로그래밍 언어단에서 지원하는 기능ex) Java : synchronized 키워드한 번에 하나의 프로세스/스레드만 실행할 수 있다.교착상태여러 프로세스가 서로 다른 프로세스의 작업이 끝나길 기다리다가 아무 작업도 수행되지 않는 상태발생 원인상호 배제 : 공유 자원은 한 번에 하나의 프로세스만 사용할 수 있다.비선점 : 다른 프로세스가 사용 중인 자원을 강제로 빼앗을 수 없다.점유와 대기 : 프로세스가 이미 자원을 보유한 상태에서 다른 자원을 요청하며 대기한다.원형 대기 : 점유와 대기를 하는 프로세스들의 관계가 원형이다.하나라도 충족하지 않으면 교착상태가 발생하지 않는다.→ 교착 상태를 예방하는 것을 구현하기는 매우 어려워서 교착 상태를 해결하는 방향으로 발전됐다.해결방법교착상태 회피프로세스들에게 자원을 할당할 대 어느 정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 수준의 자원을 할당한다.전체 자원의 수와 할당된 자원의 수를 기준으로 안정상태와 불안정 상태로 나뉜다.OS는 안정상태를 유지하려 한다.안전 상태: 모든 프로세스가 요구한 최대 자원을 할당받아 실행을 완료할 수 있는 상태불안정상태에 있더라도 무조건 교착상태에 들어가는 것이 아니라 교착상태에 빠질 확률이 높아지는 것이다.은행원 알고리즘작동 원리프로세스가 자원을 요청할 때, 그 요청이 시스템을 안전 상태로 유지할 수 있는지 확인한다.안전 상태를 유지할 수 있는 요청만 수락하고, 불안정한 상태를 초래할 수 있는 요청은 거절한다.주요 개념최대 요구량(Max Need): 프로세스가 실행을 완료하기 위해 필요한 최대 자원 양할당량(Allocation): 현재 프로세스에 할당된 자원 양필요량(Need): 최대 요구량에서 현재 할당량을 뺀 값가용량(= 시스템 총 자원, Available): 시스템에서 현재 사용 가능한 자원 양단점비용이 비싸고 비효율적이다.교착상태 검출가벼운 교착 상태 검출타이머를 이용하는 방식프로세스가 일정시간 동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주하고 교착상태를 해결한다.교착상태 해결 방법일정 시점마다 체크포인트를 만들어 작업을 저장하고 타임아웃으로 교착상태가 발생했다면 마지막으로 저장했던 체크포인트로 롤백한다.무거운 교착 상태 검출자원 할당 그래프를 이용하는 방식OS가 자원 할당 그래프를 유지하고 검사해야 하기 때문에 오버헤드가 발생한다.But. 가벼운 교착 상태 검출에서 발생할 수 있는 억울하게 종료되는 프로세스가 발생하지 않는다.OS에서 프로세스가 어떤 작업을 사용하는지 지켜보고 교착상태가 발생했다면 해결한다.Programming LanguageCompile Language개발자가 코드를 작성하고 컴파일을 수행하여 0과 1로된 기계어로 실행파일을 만든다.→ 기계어로 되어 있어 실행 속도가 인터프리터 언어에 비해 빠르다.컴파일 과정에서 개발자의 문법오류를 체크한다.ex) C, C++, C#Interpreter Language개발자가 작성한 코드를 미리 기계어로 만들어 놓지 않고 실행시 코드를 한줄씩 해석해 실행하는 언어→ 미리 검사를 하지 않기 때문에 실행할 때 오류가 발생할 수 있고, 컴파일 언어보다 느리다.ex) Javascript, Python, Ruby프로세스의 영역코드 영역실행해야 할 코드가 들어간다.데이터 영역전역 변수나 배열이 들어가는 영역스택 / 힙프로세스가 실행될 때 할당되는 메모리스택 : 지역변수와 함수 관련 값들이 저장힙 : 실행 중에 메모리 공간을 할당할 수 있는 유동적인 공간Compile 언어가 Process가 되는 방법개발자가 코드 작성전처리 단계 실행개발자가 작성한 코드를 확인하고 전처리 구문을 처리한다.C에서는 #이라는 키워드로 선언된다.ex) #include<stdio.h>, #define MY_NUMBER 100코드에 있는 모든 주석은 삭제된다.결과물로 .i 파일이 생성된다.전처리기에서 나온 결과파일을 컴파일러가 처리한다.컴파일러는 .i 파일을 기계어에 가까운 어셈블리어로 변환시킨다.결과물로 .s 파일이 생성된다.어셈블러 작업이 수행된다.오브젝트 파일.o로 변환된다.오브젝트 파일은 0과 1로 구성되어 있다.코드영역과 데이터 영역이 나뉘어져 있다.링커 작업이 수행된다.모든 오브젝트 파일을 하나의 코드 영역과 데이터 영역으로 묶어준다.실제로 실행될 주소를 매핑시켜준다.결과물로 .exe 파일이 생성된다.사용자가 .exe파일을 실행시키면 OS가 프로세스를 생성한다.OS는 파일에 있는 코드 영역과 데이터 영역을 가져와 프로세스의 코드 영역과 데이터 영역에 넣어주고, 빈 상태의 스택과 힙을 할당한다.PCB를 만들어 프로세스를 관리가 가능하게 한다.PC(프로그램 카운터)에 다음 실행할 명령어의 주소를 생성한 프로세스의 코드영역의 첫번째 주소로 설정한다.→ OS의 CPU 스케줄링에 따라서 프로세스가 실행되다가 작업을 마친다.메모리 종류레지스터가장 빠른 기억장소, CPU 내에 존재한다.휘발성 메모리CPU를 나타내는 값에서 32bit, 64bit를 의미하는 것이 레지스터의 크기이다.CPU는 계산을 수행할 때 메인 메모리에 있는 값을 레지스터로 가져와서 계산한다.계산 결과는 메인 메모리에 저장한다.캐시휘발성 메모리속도가 매우 빠른 레지스터와 레지스터에 비해 상대적으로 느린 메인 메모리 사이의 속도 간극을 메우기 위해 필요한 데이터를 미리 가져와 저장하는 저장소성능의 이유로 여러 개가 존재한다.L1, L2, L3→ 숫자가 커질 수록 느린 캐시CPU가 값을 요청해 레지스터로 값을 옮겨야 한다면 빠른 캐시를 순차적으로 확인하고, 캐시에 데이터가 없으면 메인 메모리를 조회한다.ex) L1 → L2 → L3 → 메인 메모리보조 저장장치(HDD, SSD)비휘발성 메모리메인 메모리실제 운영체제와 다른 프로세스들이 올라가는 공간휘발성 메모리데이터를 저장하기 보다는 실행중인 프로그램만 저장한다.OS는 메모리를 관리하기 위해서 1Byte 크기로 구역을 나누고 숫자(주소)를 매긴다.32bit CPU, 64bit CPU32bit CPU레지스터, ALU, Data Bus : 32bit메모리 : 2^32 = 4GB64bit CPU레지스터, ALU, Data Bus : 64bit메모리 : 2^64 = 16384PiB64bit CPU가 32bit CPU 보다 한번에 처리할 수 있는 양이 많기 때문에 속도가 더 빠르다.물리 주소 & 논리 주소물리 주소 공간 : 0x0부터 시작하는 주소 공간논리 주소 : 사용자 관점에서 바라 본 주소 공간사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있다.OS를 위한 공간은 따로 확보한다.경계 레지스터H/W적으로 OS 공간과 사용자 공간을 나누는 레지스터CPU 내에 존재하는 레지스터메모리 관리자가 사용자 프로세스가 경계 레지스터의 값을 벗어났다면 검사하고, 벗어났다면 해당 프로세스를 종료시킨다.절대 주소 & 상대 주소개발자가 프로그램이 실행될 주소를 신경쓰지 않고 개발할 수 있는 이유→ 컴파일러가 컴파일을 할 때 메모리 0번지에서 실행한다고 가정하기 때문절대 주소 : 메모리 관리자가 바라본 프로세스가 올라간 물리 주소상대 주소 : 사용자가 바라보는 논리 주소재배치 레지스터프로그램의 시작 주소가 저장되어 있다.사용자가 요청한 논리 주소의 데이터를 물리 주소로 치환해준다.사용자가 메모리에 접근할 때마다 논리 주소를 물리 주소로 치환해준다.메모리 할당 방식메모리 오버레이메모리보다 용량이 큰 프로그램을 실행시키는 방법큰 프로그램을 메모리에 올릴 수 있을 정도로 분할하여 일부만 실행하고, 실행되지 않은 프로그램은 HDD의 스왑 영역에 저장하는 방식Swap스왑영역에 있는 데이터 일부를 메모리로 가져오고 메모리에 있는 데이터를 스왑영역으로 옮기는 것가변 분할 방식(= Segmentation, 세그멘테이션)프로세스의 크기에 따라 메모리를 나누는 방식하나의 프로세스가 메모리에 연속된 공간에 할당된다.→ 연속 메모리 할당이라고 한다.장점메모리에 연속된 공간에 할당된다.→ 내부 단편화가 없다.단점외부 단편화가 발생한다.고정 분할 방식(= Paging, 페이징)프로세스의 크기와는 상관없이 정해진 크기로 나누는 방식하나의 프로세스가 메모리에 분산되어 할단된다.→ 비연속 메모리 할당이라고 한다.장점구현이 간단하고 오버헤드가 적다.단점작은 프로세스도 큰 영역에 할당되어 내부 단편화가 발생한다.내부 단편화프로세스에 필요한 메모리보다 더 큰 고정 크기의 메모리 블록이 할당될 때 발생한다.할당된 메모리와 실제 사용된 메모리 사이의 차이로 인해 메모리 공간이 낭비된다.고정 크기 분할 방식에서 주로 발생한다.해결 방법은 딱히 없고, 분할되는 크기를 조절하여 내부 단편화를 최소화한다.외부 단편화메모리 할당과 해제를 반복하면서 작은 빈 공간들이 메모리 곳곳에 흩어져 생기는 현상전체 가용 메모리는 충분하지만, 연속된 큰 블록을 할당할 수 없는 상황을 만든다.가변 분할 방식에서 주로 발생한다.조각모음외부 단편화가 발생한 공간을 합쳐주는 작업현재 메모리에서 실행되고 있는 프로세스들의 작업을 일시 주징하고, 메모리 공간을 이동시켜야 한다.→ 오버헤드가 발생한다.버디 시스템가변 분할 방식 + 고정 분할 방식오늘날의 OS가 채택한 메모리 할당 방식2의 제곱으로 메모리를 분할하여 할당하는 방식→ 근접한 메모리 공간을 합치기 쉽다.→ 조각 모음보다 훨씬 간단하다.장점가변 분할 방식처럼 프로세스 크기에 따라 할당되는 메모리 크기가 달라지고, 외부 단편화를 방지하기 위해 메모리 공간을 확보하는 것이 간단하다.내부 단편화가 발생할 수 있지만 고정 분할 방식에 비해 많은 공간이 낭비되지는 않는다.Retrospect잘한 점매일매일 빠지지 않고 강의를 들은 점매일 들은 강의 내용을 요약/정리하고 그 주차의 내용들을 하나의 게시글로 정리한 것

알고리즘 · 자료구조워밍업클럽CS전공지식Week2

f1rstf1y9

[인프런 워밍업클럽 CS 2기] 1주차 발자국👣

1주차 학습 내용운영체제운영체제의 구조커널프로세스, 메모리, 저장 장치 등을 관리사용자가 직접 접근하지 못하고, 인터페이스로만 접근 가능인터페이스GUI(Graphic User Interface)GLI(Command Line Interface)시스템콜어플리케이션은 시스템콜을 활용해 커널에 접근드라이버하드웨어와 커널의 인터페이스 컴퓨터 하드웨어와 구조메인보드 : 다른 하드웨어를 연결하는 장치로, 장치 간 데이터 전송은 메인보드의 버스가 담당CPU(Central Processing Unit, 중앙 처리 장치)산술논리 연산 장치(ALU) : 실제 데이터 연산 담당제어 장치(Control Unit) : 모든 장치들의 동작을 지시, 제어레지스터: CPU 내에서 계산을 위해 임시로 보관메모리RAM(Random Acess Memory) : 전원을 끄면 데이터가 날아감, 메인 메모리로 사용, 랜덤한 위치의 어떤 데이터를 읽든 속도가 동일ROM(Read Only Memory) : 전원을 꺼도 데이터 보관 가능, 컴퓨터 부팅 관련 바이오스 저장부팅과정컴퓨터 전원 누름 -> ROM에 저장된 BIOS 실행 -> 주요 하드웨어 이상 여부 체크 -> 이상이 없으면 부트 로더 실행 -> 운영체제를 메모리로 불러오기 -> 바탕화면이 보임인터럽트CPU 입출력 명령이 들어왔을 때 언제 완료되는지 계속 확인해야하는 폴링 방식의 단점을 해결한 것CPU가 입출력 관리자에게 명령을 내리고 자기는 다른 작업함 -> 입출력이 완료되면 CPU에게 신호를 주고 CPU는 신호를 받아서 ISR 실행시켜 작업 완료 프로그램과 프로세스프로그램하드디스크와 같은 저장장치에 저장된 명령문의 집합저장 장치만 사용하므로 수동적인 존재프로세스하드디스크에 저장된 프로그램이 메모리에 올라갔을 때, 즉 실행 중인 프로그램메모리, CPU 사용 및 입/출력 등 능동적인 존재code, data, stack, heap 영역으로 구성멀티프로그래밍과 멀티프로세싱멀티프로그래밍 : 메모리에 여러 개의 프로세스가 올라온 것멀티프로세싱 : CPU가 여러 개의 프로세스를 처리하는 것PCB(Process Control Block)프로세스의 정보를 가지고 있는 것으로, 연결리스트 자료구조로 저장됨.포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU 스케줄링 정보 등을 저장프로세스 상태생성 -> 준비 -> 실행 -> *(대기 -> 준비 -> 실행 ->) 완료대기 상태: 입출력 요청이 들어오면 입출력이 완료될때까지 기다리는 상태컨텍스트 스위칭프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 작업컨텍스트 스위칭이 일어날 때 PCB의 내용이 변경됨쓰레드요구하는 작업의 수가 늘어나면 프로세스의 수가 늘어나고, 프로세스의 수만큼 PCB, 코드, 데이터, 스택, 힙 영역을 만들어줘야해서 무거워짐 => 이를 해결하기 위해 쓰레드 고안프로세스 내에 1개 이상 존재하며, PCB, 코드, 데이터, 힙 영역을 공유함CPU 스케줄링운영체제가 모든 프로세스에게 CPU를 할당하거나 해제하는 작업어떤 프로세스에게 CPU 리소스를 줄지, 얼마의 시간동안 CPU를 할당할지를 고려함Burst : 한 작업을 연속적으로 처리하는 것으로, 보통 작업 처리에 필요한 시간을 의미 (CPU Burst, I/O Burst)스케줄링 목표리소스 사용률 높이기, 오버헤드 최소화, 공평성, 처리량, 대기 시간, 응답 시간서로 상반되는 상황이 있기 때문에 사용하는 시스템에 따라서 목표를 다르게 설정CPU 스케줄링 알고리즘 - FIFOFirst In First Out, 먼저 들어온 작업이 먼저 나간다프로세스의 Burst Time에 따라 성능차이가 심하게 나므로 현대 운영체제에서 잘 쓰이지 않고 일괄처리 시스템에서 쓰임알고리즘자료구조와 알고리즘자료구조 : 데이터가 어떤 구조로 저장되고 어떻게 사용되는지를 나타냄알고리즘 : 어떤 문제를 해결하기 위한 확실한 방법자료구조에 따라 알고리즘이 달라지므로, 상황에 맞는 적절한 자료구조를 선택하고 이에 맞는 알고리즘을 적용할 줄 알아야함시간복잡도최선 : 빅-오메가, 평균 : 빅-세타, 최악 : 빅-오주로 빅-오 표기법을 많이 사용함성능 : O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(2^n) < O(n!)표기법계산에 가장 많은 영향을 미치는 항만 표기상수는 큰 의미 없음배열일반적인 배열크기가 정해져있고, 정해진 크기만큼 연속적인 메모리 공간에 값을 할당운영체제는 가장 첫번째 주소만 기억함참조 성능은 O(1), 삭제, 삽입 성능은 좋지 않음자바스크립트의 배열 상황에 따라서 연속적, 불연속적으로 메모리 할당하는데 대부분 불연속적으로 할당(내부적으로 연결)장점읽기, 쓰기와 같은 참조에는 O(1)의 성능을 가짐단점크기 예측이 힘들기 때문에 메모리 낭비가 발생할 수 있음데이터의 삽입, 삭제가 비효율적임연결리스트배열의 단점을 해결하기 위해 저장하려는 데이터를 메모리 공간에 분산해 할당하고, 데이터를 서로 연결해주면 됨 => Node를 만들어 수행Node의 구조 : data를 담는 변수, 다음 노드를 가리키는 변수장점배열에서 초기 크기를 알아야하는 단점이 없음중간에 데이터를 삽입 혹은 삭제하려면, 특정 노드의 다음 가리키는 노드만 바꿔주면 됨단점데이터들이 전부 떨어져있기 때문에 바로 접근하기 힘듦 => O(n)의 성능스택(Stack)First In Last Out(FILO)으로, 먼저 들어간 데이터가 가장 나중에 나오는 규칙이 있음Redo, Undo 기능, 괄호짝 검사 등에 사용큐(Queue)First In First Out(FIFO)로, 먼저 들어간 데이터가 먼저 나오는 규칙이 있음계산대에 줄을 서는 경우, 맛집 대기줄 등 일렬로 기다리는 줄을 생각하면 됨덱(Deque)데이터의 삽입과 제거를 head와 tail 두 군데서 자유롭게 할 수 있는 자료구조해시테이블(Hash Table)해시(Hash), 맵(Map), 해시맵(HashMap), 딕셔너리(Dictionary)라고도 불림해시와 테이블이 합쳐진 자료구조테이블을 그냥 배열에 저장하면, 낭비되는 공간이 발생할 수 있음테이블의 기존 인덱스를 순차적인 인덱스로 만들기 위해 어떤 계산을 하는 함수를 해시라고 함key만 알면 value에 O(1)의 성능으로 읽기가 가능삽입, 삭제, 수정도 O(1)장점빠른 데이터 탐색, 삽입, 삭제를 할 수 있음단점공간의 효율성이 좋지 않음좋은 해시 함수의 구현이 필수적임셋(Set)데이터의 중복을 허용하지 않는 자료구조해시 테이블을 이용하므로 쉽게 구현 가능해시 테이블을 사용한다고 해서 Hash Set이라고도 불림value 값은 사용하지 않고 key만 사용해서 구현함(key가 데이터)회고칭찬하고 싶은 점강의를 허투루 듣지 않기 위해서 강의 노트를 작성하면서, 좀 더 궁금한 점이 생기면 의문점을 작성해두고 추가로 찾아보는 등 디테일한 이해를 위해 노력했다. 아쉬웠던 점휴일이나 주말 등 강의를 들을 시간이 넉넉한 때를 생각하면서 당일에 들어야하는 분량을 미루는 일이 잦았다.보완해야할 점퇴근 후 피곤하더라도 완전히 그날 강의를 안듣기 보다는, 한 강의라도 들으면서 꾸준히 강의를 수강하는 습관을 들이도록 노력하자!

워밍업클럽CS발자국

Taeho

인프런 워밍업 클럽 - CS Week 1

그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)자료구조 & 알고리즘자료구조 : 데이터가 어떤 구조로 저장되고, 어떻게 사용되는지를 나타낸다.자료구조에 따라서 결과를 얻기 위한 처리 방법이 달라진다.알고리즘 : 어떤 문제를 해결하기 위한 확실한 방법시간 복잡도특정 알고리즘이 어떤 문제를 해결하는 데 걸리는 시간Bit-Ω : 최선의 시간 복잡도Big-O : 최악의 시간 복잡도가장 많이 사용된다.Big-θ : 평균의 시간 복잡도ADT(Abstract Data Type)데이터의 논리적인 동작을 정의한다.구현 방법을 명시하지 않고, 자료구조의 특성과 연산만을 설명한다.내부 구현 세부사항은 숨기고 인터페이스만을 제공한다.Array배열의 인덱스 참조는 길이에 상관없이 한 번에 가져온다.삽입, 삭제의 성능이 좋지 않다.Linked List배열의 단점인 삽입, 삭제의 성능을 보완하기 위한 자료구조특정 데이터를 찾고 싶다면 노드를 순차적으로 순회해야 한다.저장하려는 데이터들을 메모리에 분산하여 할당하고, 해당 데이터를 서로 연결한다.노드를 사용하여 데이터들을 저장하고, 각 노드가 다음 노드를 가리키도록 한다.첫 노드의 주소만 알고 있으면 그 이후의 모든 노드에 접근할 수 있다.StackLIFO(Last-in First-out)단방향 Linked List를 사용하여 구현할 수 있다.head를 사용하여 스택을 간단하게 구현할 수 있다.데이터 삽입을 무조건 첫 번째 인덱스에 수행한다.QueueFIFO(First-in First-out)양방향 Linked List를 사용하여 구현할 수 있다.Deque데이터의 삽입과 제거를 head와 tail에서 자유롭게 할 수 있는 자료구조Hash TableHash Function해시 함수는 키(key)를 입력받아 해당 키의 저장 위치(버킷 또는 인덱스)를 결정하는 계산을 하는 함수좋은 해시 함수 ⇒ 데이터를 골고루 분배시켜주는 함수 Hash Collision해시 충돌은 해시 함수가 서로 다른 두 개 이상의 입력 값에 대해 동일한 해시 값을 출력하는 상황을 의미Hash 충돌이 발생한 곳의 Value들을 연결리스트로 구성하여 데이터들을 연결한다.기존값과 새로운 값을 동시에 저장할 수 있다.찾고자 하는 Value가 나올 때까지 연결리스트를 탐색한다.→ O(n)의 성능을 갖는다.Set데이터의 중복을 허용하지 않는 자료구조HashTable을 사용하여 구현할 수 있다.→ HashTable을 사용하기 때문에 HashSet이라고도 한다.→ HashTable의 value 값은 사용하지 않고 key만 사용하여 구현한다.(key가 key와 value의 역할을 수행한다.)그림으로 쉽게 배우는 운영체제OS가 하는 일프로세스 관리 : 여러 개의 프로그램들을 동시에 수행할 수 있게 한다.메모리 관리 : 모든 프로그램은 메모리에 올라가서 동작한다.H/W 관리 : 사용자가 직접 H/W에 접근하는 것을 막는다.File System 관리Program저장장치에 저장된 명령문의 집합체저장 장치만 사용하는 수동적인 존재Process실행중인 프로그램저장장치에 저장된 프로그램이 메모리에 올라갔을 대 프로세스라고 한다.메모리, CPU, I/O 작업을 수행하는 능동적인 존재Multi-Programming메모리 관점메모리에 여러개의 프로세스가 올라온 상태Multi-ProcessingCPU 관점CPU가 여러 개의 프로세스를 처리하는 것을 의미PCB(Process Control Block)프로세스가 만들어지면 운영체제는 해당 프로세스의 정보를 갖고 있는 PCB를 만들고 저장한다.PCB들은 연결 리스트로 저장된다.운영체제는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다.Context Switching프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 전환하는 작업작업 과정에서 PCB의 내용(프로세스 상태, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보 등)이 변경된다.Process의 생성OS가 부팅되고 0번 프로세스가 생성될 때 딱 한 번만 수행된다.→ 그 이후에 생성되는 프로세스는 fork()를 사용하여 복사해서 사용된다.→ 새로 생성하는 것보다 복사를 하는 것이 더 빠르기 때문좀비 프로세스부모 프로세스가 자식 프로세스보다 먼저 종료되거나 자식 프로세스가 비정상적으로 종료돼 exit()신호를 주지 못해서 Exit Status를 읽지 못해 메모리에 계속 살아있는 상태Thread프로세스 내에 존재하고, 1개 이상이 존재할 수 있다.하나의 프로세스 내에 있는 쓰레드들은 프로세스의 PCB, Code, Data, Heap 영역을 공유한다.Stack은 공유하지 않고, 쓰레드 마다 하나씩 갖고 있다.OS에서 작업을 처리하는 단위이다.Process vs Thread안정성Process는 독립적이기 때문에 서로 영향을 받지 않는다.Thread는 하나의 Process를 공유하기 때문에 하나의 Thread에 이상이 생기면 다른 Thread에도 이상이 전파될 수 있다.⇒ Process가 유리속도와 자원각각의 Process는 서로 고유한 자원을 갖는다.코드, 데이터, 힙, 스택 영역을 전부 따로 두고 있다.Process간에 통신을 하려면 IPC를 사용해야 해서 오버헤드가 크고 속도가 느리다.쓰레드는 하나의 Process의 자원을 스택 영역을 제외한 영역을 모두 공유하기 때문에 오버헤드가 느리다.CPU Scheduling목표목표들을 전부 만족할 수는 없다.→ 목표들에 따라 Trade-Off가 있기 때문ex) 처리량 ↑ ⇒ CPU 오래 할당, 응답시간 ↓ ⇒ 여러 프로세스에 CPU를 골고루 할당⇒ 처리량과 응답시간 사이에 Trade-Off가 발생한다.리소스 사용률CPU 사용률 높이기I/O 디바이스의 사용률 높이기오버헤드의 최소화Context Switching시에 발생하는 오버헤드를 최소화하는 것공평성모든 프로세스에게 우선순위에 따라 공평하게 CPU가 할당되어야 한다.처리량같은 시간내에 더 많은 처리를 할 수 있게 하는 것대기시간작업을 요청하고 실제 작업이 실행되기 전까지 대기하는 시간이 짧은 것응답시간사용자의 요청이 얼마나 빨리 요청하는지Retrospect아쉬운 점커리큘럼을 잘못 봐서 운영체제 쪽은 쉬는 날에 몰아서 들었다.커리큘럼을 명확하게 파악하고 당일에 들을 강의들을 정확히 정리해야겠다.잘한 점매일매일 빠지지 않고 강의를 들은 점매일 들은 강의 내용을 요약/정리하고 그 주차의 내용들을 하나의 게시글로 정리한 것

알고리즘 · 자료구조워밍업클럽CS전공지식Week1

꾸이

[인프런 워밍업 스터디 1기 디자인] 4주차 발자국

드디어 스터디의 마지막 주다!! 이번주에는 배리어블을 다크모드, 브랜드, 반응형 디자인, 다중언어 등 모드를 설정해서 적용하는 법을 배우고 페이지에 적용해봤다. 📖 강의 요약8. 모드 설정해서 배리어블 제대로 활용하기모드는 컬렉션 내 배리어블 값의 목록을 나타낸다. 컬렉션 내 다양한 모드가 있는 경우 맥락에 따라 맞춰서 사용할 수 있다.피그마가 제안하는 "맥락을 전환하는 경우"라이트모드/다크모드다중언어 지원디바이스별 대응멀티브랜드 지원다크모드다크모드 제작시 고려사항서비스 특성에 따라 다르게 적용 → 컨텐츠가 돋보여야 하는가? 미디어에 집중해야 하는가?구글 M3, 애플 HIG 참고하면 좋다 → 해당 환경에서 다크모드를 많이 사용한다라이트모드의 색상 체계를 반전시키면 될까? → 아니다!브랜드 아이덴티티, 접근성을 고려하고끊임없는 테스트를 통해 수정하기계획하기라이트모드의 색상 체계를 반전한 뒤접근성, 타 색상과의 조화 고려하고인터랙션: 단계에 따라 밝아지게 할지, 어두워지게 할지 등등 생각적용하기시맨틱에 적용실제로 색상을 계획할 때 참고하면 좋을 것 같은 문서를 덧붙인다.Dark Mode: How Users Think About It and Issues to Avoid Dark Mode (Apple HIG) 브랜드브랜드 구조 유형House of BrandsEndorsed BrandsSub BrandsBranded House적용하기theme에 추가 반응형 디자인최대값과 최소값 적용 → 오토레이아웃이 적용돼야 함기준 width, height값 정해서 모드에 적용 / 불린 프로퍼티 등 다양하게 적용 가능!Page, Header, Content 등 프레임마다 적용 가능잘 정리해서 사용하면 정말 무궁무진하게 확장할 수 있을 것 같다! 다중언어왜 다중언어를 지원하는 것이 중요할까?시장 개척 및 점유율 확대사용자가 접근하기 쉬움넷플릭스, 스포티파이글로벌라이제이션/로컬라이제이션LTR/RTL이미지에도 적용되면 좋음. 라인 좋은 사례현재 피그마 배리어블을 사용한 다중언어는 한계가 있다. 9. 페이지를 만들기 전에 알아야 할 사항컴포넌트 문서 정리하기*10, 11, 12 챕터는 미션에서 서술한다.플러그인Google Sheets Sync 중간점검 : 특강 및 LIVE QnA : 디자인 시스템 문서화 (feat. chatGPT 이용)디자인 시스템 문서화를 하는 이유하나의 제품을 만들기 위해 일관성, 효율성 제공함성공지표: 디자인 시스템을 얼마나 채택하였는가?잘 만든 디자인 시스템 문서: 참고하기 좋고 제대로 사용가능해야 한다라인, 지마켓, GOV.UK디자인 시스템에 나오는 공통된 주제와 내용Spec, States, Usage, Usage: Decide components, Anatomy, Behaviour, Best Practice, Props, Content guidelines, Accessibility, Responsive Design, Research and testing잘 만든 디자인 시스템을 선정해보는 시간이 있었다. “잘 만든 디자인 시스템의 기준이 뭘까” “나는 지금까지 어떤 지표들을 기준으로 디자인 시스템을 참고해왔나?” 라는 의문이 들어서 답하기 힘들었다. 지금 생각해보면 디자이너 입장(내 입장)에서 참고하기 좋았던 디자인 시스템 두 가지를 말했다. 디자인 시스템은 디자이너 외의 직군도 참고하는 문서라는 점! 을 잊지 말아야 한다. 어떻게 디자인 시스템 문서를 효과적으로 만들까?ChatGPT빠르게 효과적으로 작업 → *정확성 문제 있음다른 관점에서 보기 → *신뢰성 문제 있음프롬프트 프레임워크Context 맥락Information 정보Goal 목적Output 결과물이 모든 내용이 필요한가? 검토 필요볼드님께서 제작해주신 템플릿을 ChatGPT 3.5에 적용하여 디자인 시스템 문서를 작성해봤다. 덧붙여 타 수강생분들의 결과물을 보고 피드백해보는 시간도 가졌다. 결과물이 나쁘지는 않지만 확실히 인간 디자이너가 보고 검토할 필요가 있어보였다. 너무 재밌었고 의미있었던 시간! (+피드백을 꼼꼼하게 해주셔서 감동받았다. 감사합니다 !!) 디자인 시스템 문서화 도구와 플러그인Plugin: Propstar, EightShapes Specs, Stark 🎯 미션이번 미션은 전반적으로 정말 재밌었다. 이 강의의 꽃이 아닌가 싶다 ㅎㅎB2B shop admin, B2C learn cource, Mobile OTT 세 서비스의 페이지를 디자인했다.여태껏 만든 컴포넌트들을 조합하고, 서비스 성격이나 레이아웃에 맞지 않거나 혹은 실수가 있었던 컴포넌트를 다시 디자인했다. 개인적으로 이 후자의 과정이 좋았던게, 처음부터 완벽한 컴포넌트는 당연히! 만들 수 없다. 그럴 때 컴포넌트를 수정하여 디자인하는 방법을 알려주시는데, 별거 아닌 것처럼 보일 수 있지만 사실은 배우기 힘든 실무에서 활용하기 좋은 꿀팁들이라 생각한다.레이아웃이나 주로 사용되는 컴포넌트는 서비스 성격에 따라 달라진다. B2B 제품을 많이 디자인하는 입장에서 다른 서비스들도 더 디자인할 수 있는 기회가 생겨 좋았다. 또 데스크탑 화면을 먼저 디자인하고 → 모바일 확장을 고려하는 것과 반대의 경우 디자인 과정이 꽤 달라지는데, 그 과정도 미션중 거치게 되어 좋았다.제일 재밌게 했던 미션.🌼 회고잘 한 점무사히 스터디를 완주했다!아쉬운 점/보완할 점없다! 이번주는 시간관리를 아주아주 잘했다~ 👋 스터디 완주 소감강의를 수강하거나 미션을 진행할 때는 참 길게 느껴졌고 이외의 시간은 너무도 빠르게 만들어줬던 마법같던 한 달이 지나갔습니다. 강의 페이지에 적혀있는 강의 시간은 13시간 29분인데 어째서인지 공부를 하고 미션을 진행하고 하다보면 일주일에 최소 6시간 이상은 투자해야 했습니다. (저만 그런건 아니겠죠)그럼에도 완주할 수 있었던 이유는 다른 러너분들이 열심히 달리시는 모습을 보며 자극을 느끼고, 매주 들었던 라이브 특강에서 학습의 기쁨을 느꼈고, 무엇보다 강의 자체가 잘 짜여졌기 때문이라고 생각합니다. 스터디 진행해주신 인프런 관계자분들, 정말 열정적으로 가르쳐주신 볼드님, 그리고 같이 달려주신 러너님들 전부 감사합니다! ☺이제부터는 지금까지 공부했던 것들을 복습하고, 실무와 사이드프로젝트에서 잘 적용할 수 있도록 응용해보겠습니다. 💨(+첫 라이브특강때 다짐했던 책 샀습니다. ㅎㅎ)

UX/UI워밍업클럽피그마

BoBae Kim

[인프런 워밍업 클럽 1기] 1주차 발자국 👣

강의 요약 📝섹션1. 피그마 배리어블과 디자인 토큰피그마 배리어블과 디자인 토큰의 개념을 이해하고 필요성에 대해 배우는 시간이었다. 디자인 토큰 개념은 이해하고있었는데 디자인 토큰의 특징 중에 참조 기능이 있다는 것은 처음 알았다.  섹션2. 배리어블과 파운데이션 세팅하기색상 배리어블 구조를 이해하고 이름 규칙을 정해서 색상 배리어블을 직접 설정해보았다. 또 타이포그래피, 아이콘, 그림자, 그리드 기준점까지 디자인할 때 기본이 되는 부분들을 하나씩 차근차근 만들었다. 실무 프로젝트에서도 매번 시안 만들기에 바빠서 스타일 가이드를 제대로 작업하지않은 경우도 있었는데 이번 강의를 들으면서 아무리 바쁘더라도 기본을 잘 다져둬야 추후에 디자인의 일관성을 유지하면서 확장성있게 사용할 수 있다는 점을 확실하게 배웠다.  - 스타일 가이드 제작할 때 유용한 플러그인Apply variables : 적용하지않았거나 누락된 스타일의 베리어블을 찾아서 바꿔줌Typescales : 타이포그래피 스타일을 사이즈별로 생성해줌Styler : 설정한 스타일을 local style에 자동으로 등록해줌 Batch styler : 스타일을 수정하고 싶은 컴포넌트를 선택해서 변경 가능함Typorahy style guide : 타이포그래피 스타일 가이드 문서를 제작해줌 Frame all : 컴포넌트 각각의 프레임을 만들어줌- 유용한 단축키 정리control+shift+enter : 베리어블 추가control+ r : 선택된 레이어 이름 수정부모의 컴포넌트를 클릭하고 enter를 누르면 자식 컴포넌트만 선택됨  회고 ✨😆 Liked (좋았던 점) : 강의를 듣고 직접 만들어보면서 배리어블 개념, 용어, 피그마 단축키 등을 한번 더 정리해 볼 수 있는 시간을 가질 수 있어서 좋았다. 그리고 이번주에 진행되었던 특강 내용도 너무 좋았다!! 😅 Lacked (아쉬웠던 점, 부족한 점) : 스터디 첫 주였는데 계획했던것처럼 매일매일 강의를 듣지못했다.. 🧐 Learned (배운 점) : 이번주는 배리어블을 활용해서 스타일 가이드를 만드는 방법을 배웠다! 그동안 배리어블 개념에 대해서 대략적으로만 알고있어서 실무에서 활용하는게 쉽지않았는데 배리어블을 참조해서 새로운 배리어블을 만들고 활용하는 방법과 이름 정하는 규칙에 대한 구체적인 예시를 알려주셔서 실무에서 유용하게 적용해볼 수 있을 것 같다! 🤩 Longed for (앞으로 바라는 것) : 다음주 부터는 조금씩이라도 매일 공부하고 계획한대로 미션을 수행할 수 있도록 노력해보자!  

UX/UI워밍업클럽디자인

꾸이

[인프런 워밍업 스터디 1기 디자인] 1주차 발자국

직장과 사이드 프로젝트를 병행하던 중 디자인 시스템에 대한 심화적인 공부의 필요성을 느꼈다. 사수 없는 디자이너라 스스로 배우고 성장해야만 했는데, 해외 아티클, 유튜브 등을 열심히 찾아봤지만 "어디서부터 어디까지 실무에서 적용시켜야 할지 모르겠다"는 문제 때문에 어려움을 겪었다. 그러던중 인프런 워밍업 클럽 - 스터디 1기의 존재를 알게됐고, 좋은 기회로 보여 신청했다. 📖 강의 요약0. OT첫 프로그램은 OT였다. 줌으로 화상회의를 진행하는 동시에 피그잼에서 강사님과 의사소통했다. 덕분에 집중이 잘됐다. 스터디는 다같이 으쌰으쌰하는 분위기가 중요한데, 참여자 모두가 쉽게 사용할 수 있고 귀여운 의사소통이 가능한 툴이라 그랬던 것 같다.평일 저녁에 짬을 내서 참여할 가치가 있었다. 기존에 존재하는 강의를 바탕으로 스터디로 진행하다 보니 안내사항이 많았는데, OT에서 설명을 잘해주셔서 따라가면서 잘 이해할 수 있었다. 특히 피그잼에서 "내가 왜 이 스터디에 참여했는지" "무엇을 얻고 싶은지" 등을 스스로 생각하고 써나가는 시간이 있었는데 이 시간이 정말 좋았다. 다른 사람들이 어떤 각오로 참여하게 됐는지를 보면서 동감하고 신기해하기도 하면서 "다같이 30일동안 열심히 공부할 사람들이 여기 있구나!"라는걸 새삼 느끼며 설레는 마음으로 스터디를 시작했다. 1. 디자인 시스템과 디자인 토큰강의는 베리어블이 먼저지만, 정리 과정에서 순서를 수정했습니다초반 강의에서는 디자인 시스템과 디자인 토큰 등 강의에서 다루는 개념들을 먼저 정리하는 시간을 가졌다. 아는 내용과 모르는 내용이 섞여있었는데, 전자는 내가 이미 아는 개념들을 강사님 입장에서 설명해주시는 것을 들으면서 "아, 저렇게 설명할 수도 있는 부분이구나!"고 생각하며 복습했고, 모르는 부분은 아는 부분보다 열심히 메모하고, 따로 표시해두었다. 1) 디자인 시스템디자인 시스템은 일관성과 확장성을 가진 재사용 가능한 컴포넌트와 패턴, 가이드를 말한다.디자인 시스템의 구성 요소는 다음과 같다.디자인 원칙/철학 Design Principle스타일 가이드 Style Guide컴포넌트 라이브러리 Component Library패턴 라이브러리 Pattern Library문서화 Documentation시스템 관리 운영 System Governance이 중에서 내가 주로 사용했던 것은 스타일 가이드, 컴포넌트 라이브러리뿐이었어서 다른 부분들을 어떻게 실무에 적용할 수 있을지 고민했다. 디자인 시스템의 장점은 다음과 같다.디자인 일관성 유지브랜드 강화효율적인 개발시간 단축팀 간 협업 강화빠른 온보딩유지 보수 용이높은 품질의 경험 디자인시스템을 시작할 때는 다음 사항들을 주의해야 한다.비즈니스, 디자인, 개발의 이해에서부터 시작디자이너 혼자서 만드는 게 아니라 회사의 여러 구성원이 함께 만드는 것작은 단계에서부터 성공해나가야 함디자인시스템은 보통 '효율'을 위해 만드는 시스템이지만 제대로 만들려면 시간과 비용이 많이 든다. 따라서 초반에 어디까지 만들지 제대로 설정하는 게 중요하다. 그리고 사이드프로젝트를 할 때도 느꼈지만 만들다보면 또 수정할 일이 생기고, 여기서 막히고 저기서 충돌하기 때문에.. 작은 성취들을 소중히 여기는 태도가 꼭 필요하다. 2) 디자인 토큰디자인 토큰은 모든 UI 요소의 기본 구성 요소로 작고 반복할 수 있는 디자인 결정이다. 브래드 프로스트의 아토믹 디자인 개념에서는 '전자'단계에 속한다.전자 -> 원자 -> 분자 -> 유기체 -> 템플릿 -> 페이지 토큰과 관련된 브래드 프로스트의 새로운 아티클도 첨부한다. 다음에 시간될 때 차근차근 읽어보면 개념 이해에 더 도움이 될 듯 하다. 그렇다면 디자인 토큰은 왜 필요할까? 바로 확장이 쉽고 관리가 유연하다는 이유 때문이다.❓ 여기서 "json으로 내보내기 가능해서 여러가지 플랫폼으로 이동 가능하다"고 강사님이 말하셨는데 이유가 궁금해서 찾아봤다.json은 JavaScript Object Notation의 약어로, 데이터를 표현하는 데 사용되는 형식이다. 현재 데이터 교환의 범용 표준이며 프론트엔드와 서비스 측 개발, 시스템, 미들웨어, 데이터베이스를 포함해 프로그래밍의 모든 영역에 사용된다. (출처: 거의 모든 SW 개발의 필수⋯JSON 데이터 포맷의 이해 - ITWorld Korea)디자인 토큰 형식 모듈/4.파일 형식에 따르면 json이 채택된 이유는 다음과 같다.1. 많은 프로그래밍 언어의 표준 라이브러리에서 광범위하게 지원된다. 이것은 개발자의 진입 장벽을 낮출 것으로 예상된다. 2. 현재 인기있으며 광범위하게 사용되는 언어다. 많은 사람들이 익숙하기 때문에 학습 곡선을 낮출 것으로 예상된다.3. 이진법이 아닌 텍스트 기반이어서 기본 텍스트 편집기 이외 특수 소프트웨어 없이 디자인 토큰 파일을 편집할 수 있다. 3) 베리어블의 이름과 구조혼자 공부할 때 가장 어려웠던 부분인데 설명을 너무 잘해주셔서 열심히 들었다. 모든 스터디가 끝난 뒤 가장 먼저 복습하게 될 챕터가 아닐까 싶다. 베리어블의 구조는 다음과 같다.이름(Name), 값(Value), 유형(Type)설명(Description)그룹 베리어블의 계층은 다음과 같다. 기업마다 정의하는 용어가 다를 수 있지만 신경쓰지 말고, 계층마다 기업들이 어떤 목적을 가지고 역할을 분류했는지에 초점을 맞춰야 한다.Raw value: 본래의 값 #D6840BGlobal/primitive/core/base/foundation/root: 사용 맥락에 상관없이 디자인 언어의 기본 값 Orange-mediumAlias/semantic/applied/purpose: 특정 사용 맥락과 의도를 전달할 때 쓰이는 값 Brand-primaryComponent/overwrites/scoped: 컴포넌트와 관련된 모든 디자인 속성을 가진 값 Button-primary-background-color❓ raw value와 primitive는 뜻이 똑같은데 왜 다른 분류 용어로 사용하는지 궁금했다. 베리어블 이름의 구조는 Namespace + Object + Base + Modifier로 이루어져있다.Namespace>System은 다른 디자인 시스템과 구분하기 위한 접두어로, 주로 모든 베리어블/토큰 앞에 위치한다.Object>Component는 디자인 시스템 내에서 특정 컴포넌트의 스타일 및 레이아웃을 적용하고 싶을 때 사용된다.Base는 Category와 Property로 구성되는데, Category는 UI 기본 구성 요소를 공통된 유형으로 그룹화하며 Property는 각 카테고리 내에서 특성에 따라 세분화된 것들이다.Modifier는 하나의 디자인 요소를 여러 상황, 상태에 따라 변형할 수 있도록 한다. Variant와 State로 구성되는데, Variant는 시각적 위계질서와 기능을 표현한다. State는 인터랙션 상태와 크기를 표현한다. ❓ 토큰 앞에 $(달러) 기호를 붙이는 것도 json 기반이라 그런건지 궁금했다. 찾아본 결과는 다음과 같았다.디자인 토큰 형식 모듈에 따르면, 토큰 이름과의 충돌을 방지하기 위해 토큰 속성은 달러 기호($)로 접두사를 붙인다. 이 접두사를 사용하면 예약어 목록이 필요 없고 사양을 미래에 대비하는 데 도움이 된다.덧붙여 다른 변수명에서 잘 사용하지 않는 기호를 사용하여 다른 변수와의 충돌을 줄이기 위해 $를 사용한다는 내용은 이 블로그에 잘 설명되어 있다. 베리어블 구조, 이름을 지을 때 몇 가지 실무 팁도 알려주셨다.개발자와 디자이너 둘 사이의 공통된 이름 짓기미리 80% 정도는 계획을 하도록 한다 (엑셀 시트, 피그잼 추천)2~3개 정도의 레퍼런스에서부터 시작하기사이드프로젝트에서 파운데이션을 제작하던 중 어떻게 보면 벼락치기 개념으로 들은 강의였어서 조금만 더 빨리 들었다면 같이 엑셀로 계획하고 할 수 있었을텐데! 라고 후회했다 😇... 정말.. 정말 중요한 팁을 주셨다. 디자인시스템 관련한 레퍼런스는 사실 너무♾ 많고, 그중에서도 개발하려는 서비스의 특성/규모 등에 맞춰서 조절해야 하니 욕심부리지 말고 적당한 선에서 참고하며 시작해야 한다 ... 2. 스타일 파운데이션 설정색상 Color사이드프로젝트를 할 때 가장 많이 헤맸던 부분인데, 여러가지 레퍼런스를 참고해서 정리해주신 파일을 기반으로 만들어야 할 베리어블을 정리한 뒤 제작하니 시간도 절약하고 이후 개발자가 이해하기도 좋을 것 같았다. 고려사항은 다음과 같다.Color Scopingsematicbg: FrameIcon: Shapetext: Textborder: Stroke특정 베리어블을 publishing하고 싶지 않다면 베리어블 콜렉션/그룹 앞에 _ 작성개별 베리어블 edit color variable -> Hide from publishing 설정이런게 진짜 꿀팁이지 싶었던 부분. 이외에도 강사님이 제공해주시는 피그마 파일을 통해 컴포넌트 정리할 때의 팁을 알아볼 수 있는데, 공부에 많은 도움이 된다. 간격 Spacing, 둥근 모서리 Border Radius기본 단위(Base unit)은 1.5배수 랜더링 이슈로 주로 8pt 그리드를 사용하며, 일반적으로 더 작은 단위로 레이아웃을 정렬하고 싶은 경우 4pt 그리드를 사용한다. 간격 크기(Spacing Scale)도 마찬가지.간격의 사용(Spacing in UI)은 작은 UI 구성 요소 / 카드 UI 패딩, 간격 / 큰 규모의 UI, 레이아웃 등 간격이 사용되는 케이스에 따라 적용하는 간격의 범위를 말한다.❗ 아틀라시안 디자인 시스템에서는 small, medium, large로 나누어서 적용하고 있었다. (아래 사진)간격 베리어블은 다음과 같이 구성할 수 있다.ComponentSemantic : Padding Gap Border Radius Width/Height Border WidthPrimitive : UnitBase Grid Point : 4❗ 시맨틱을 적용한 사례가 궁금해서 찾아봤다. Polaris는 --p-space-card-padding, --p-space-table-cell-padding 같은 식으로 몇몇 컴포넌트의 Padding과 Width, Height까지 정의한다. 둥근 모서리 베리어블은 다음과 같이 구성할 수 있다.Primitive: UnitSemantic: Border Radius 타이포그래피 Typography타이포그래피는 강의 녹화 당시에 베리어블이 없었어서 스타일로 제작하셨으며(추후 추가 예정이시며, 나는 특강으로 들을 수 있다!), 스타일을 쉽게 제작할 수 있는 플러그인을 많이 알려주셔서 도움이 됐다. 아이콘 IconFeather Icons을 불러와서 등록하는 법을 배웠다. 기존에 있는 아이콘을 불러오는 과정에서 생길 수 있는 문제를 유용한 단축키를 소개하면서 해결해주셨다.fn shift enter : 바깥에 있는 프레임 선택 -> 크기 조절enter : child frame 선택ctrl shift g : frame 해제5월 4일에 진행한 특강에서 심화 수업을 들었는데, 이 부분은 정리가 더 필요해서 다음주 발자국으로 넘긴다. 높이 Elevation❗ Material Design 3에 의하면 높이는 z축에 있는 두 표면 사이의 거리다.높이와 그림자는 UI 요소간의 계층구조를 시각적으로 명확하게 하고, 요소들간의 상대적인 거리와 깊이를 나타내 현실감있는 경험을 제공하며, 상호작용을 시각적 피드백으로 표현해 사용자 경험을 향상시킨다. 높낮이의 표현방법은 3가지가 있다. (이미지 출처: Material Design 3)다른 톤으로 표현하기같은 톤인 경우 그림자 효과 주기스크림*을 사이로 구분하기*스크림: 모달 뒷배경에 주로 사용되는 그것을 말한다. Material Design 2에서는 다음과 같이 설명한다. 스크림은 표면의 콘텐츠를 덜 눈에 띄게 만들기 위해 머티리얼 표면에 적용할 수 있는 임시 처리이다. 이는 스크림을 받는 표면에서 벗어나 화면의 다른 부분으로 사용자의 주의를 유도하는 데 도움이 된다. 그리드 Grid, 기준점 Breakpoints그리드 시스템은 시각적 질서, 일관된 레이아웃, 유연함과 확장성, 디자인 효율성을 제공해준다. 반응형 그리드의 기본 용어는 다음과 같다.칼럼(Columns): 섹션거터(Gutters): 칼럼 간의 간격마진(Margins): 그리드 양상단의 여백 Fixed, Fluid, Hybrid 그리드 정의는 다음과 같다.고정형, 유동적 그리드 : 크기 확대됐을 때 고정/유동하이브리드: 다양한 그리드가 한 스크린 안에 있음 그리드는 개념적으로는 이해가 된 상태였는데 피그마에서 오토레이아웃을 적용할 때 헷갈리는 부분들이 있었다. 그런 점들을 잘 짚고 넘어갈 수 있었다. 테두리 간격 Border Width, 투명도 Opacity배리어블을 만든 후 넘버 스코핑에 신경쓰면 되는 부분들이다.  🎯 미션미션 1, 2, 3이번주의 미션은 다음과 같았다.미션1. 컬러 베리어블을 로컬베리어블에 등록하고 다른 디자이너, 개발자 누구나 볼 수 있도록 문서화한다.미션2. 타이포 그래피 스타일, 간격 베리어블을 등록하고 Feather icon을 등록한 후 면으로 모두 바꾼다.미션3. 그림자 효과, 반응형 기준점, 기타 베리어블 등록하기미션4. 스타일 파운데이션 최종적으로 다듬어서 일관되게 문서화해보기그중 미션 1, 2, 3은 시간이 조금 걸리긴 했지만 강의를 따라가면 충분히 해결할 수 있는 과제들이었다. 미션 4미션4는 현재 사이드프로젝트나 회사 업무에 적용한다고 생각했을 때, 어떻게 해야 개발자들이 잘 이해할 수 있을까? 불필요한 커뮤니케이션을 줄일 수 있도록 문서화하고 싶다! 는 생각을 가지고 작업했다. 작업과정은 다음과 같다.참고할 디자인 시스템 정하기: 볼드님의 파운데이션, Wanted Design Library, Polaris Styles 를 참고했다.베리어블 -> 문서화 플러그인 찾기 잘 만들어진 플러그인들이 많았지만 1. 컴포넌트 형식이고 2. 컴포넌트 내부 요소들이 잘 구성되어 있고 3. 오류가 없거나 적은 것을 찾기가 힘들었다.플러그인을 찾은 것들은 컴포넌트를 정리해서 묶었다.플러그인을 찾지 못한 것들은 타 디자인시스템들을 참조해서 새로 제작하거나, 기존에 강의를 따라가면서 제작했던 문서를 가지고와서 정리했다.이후 문서를 통일하고 정리했다. 이 과정에서 볼드님의 파운데이션이 큰 도움이 됐다. 🌼 회고잘 한 점: 직장과 사이드 프로젝트를 병행하면서 1주차를 무사히 끝냈다!아쉬운 점: 미션에 집중하다보니 발자국 작성에 시간을 많이 쓰지 못한 점이 아쉽다.보완할 점실전에서 어떻게 활용할 수 있을지 생각하며 강의 듣기매일매일 강의 들은 뒤 강의 메모 이외 간단한 느낀점 꾸준히 작성하여 이후 발자국 모으기 쉽게 만들기다음주 계획: 이번주만큼만 하기! 💨

UX/UI워밍업클럽피그마

김혅

[인프런 워밍업 스터디 1기 디자인] 1주차 발자국 🐾

OT부터 1주 차 스터디, 그리고 첫 온라인 중간 점검까지 마치고 남기는 첫 발자국!역시 나는 강제성(?)같은 동기가 부여되어야 하는 사람임을 다시 느꼈다. 🙄>짜여진 커리큘럼과 그에 맞는 미션이 설계되어 있어서 따라가기 너무 좋았고,강사님께서 노션과 강의 요약본까지 정리해두셔서 더 편리하게 할 수 있었다. 쵝오...👍강의는 무작정 "자, 일단 따라 해봅시다!"가 아닌 기초 개념부터 쌓아 올려가는 방식이라 너무 좋았고, 설명에 맞는시각적 예시까지 곁들여주셔서 따라가기 너무 좋았다. 유용한 사이트와 플러그인 정보도 유익한 건 덤~(WOW)~아직 아날로그 인간이라 강의를 손으로 필기하는데, 그중 몇 개를 아래에 간단하게 적어 회고를 해보고자 한다!Chapter 1.피그마 배리어블과 디자인 토큰디자인 시스템을 만들어야 하는 이유 ✧ 커뮤니케이션(공감대 형성)스타일, 배리어블? ✧ 기본 디자인 토근 관리를 위해서는 배리어블 ✧ 다수의 디자인 요소의 결합은 스타일 Chapter 2.배리어블과 파운데이션 세팅하기✦ 색상 베리어블 세팅 ✧ border의 경우 너무 두꺼우면 텍스트와 잘 부딪히니 색을 빼주어 구분을 해주자.  ✧ icon은 텍스트와 주로 같이 간다.✦ 그리드 ✧ 4-point grid는 작은 단위로 레이아웃 정렬에 용이하다.  ✧ gutter/columns의 개념 헷갈리지 않기. ✧ fluid의 경우 margin 값을 필수로 넣어주어야 한다. ✧ fixed와 fluid의 constraits 각각의 차이 기억하기.✦ 기타 베리어블 ✧ ex)stroke 배리어블 버튼이 안보일때 우 클릭&apply variable or shift+왼쪽 클릭 ✧ opacity의 경우 fill이 아닌 layer에서 적용시키기. 미션✦ 놓치는 부분이 없는지, 적용이 잘 되었는지 더블의 더블 체크 해주기.✦ 생각보다 어려워서 난항을 겪었던 미션 4 ▸ 참고한 템플릿은 크게 두 가지 범정부UIUX_디자인스타일가이드n컴포넌트 / Wanted Design Library ▸ 컬러 부분이 상당히 오래 걸렸는데, 맘에 드는 플러그인을 찾기 어려웠고 요소가 많은데 그 안에서도 최대한 구분이 되어 보이기를 바라며 구성하였다. -Theme의 경우 각 변수의 수가 똑같기 때문에 가로 정렬 -Sementic의 경우 각 변수의 차이가 약간 있고 내용이 많아 세로 정렬로 진행해 주었다.마치며, 2주 차 다짐📍아직까지는 따라가기 바쁘다, 복습은 필수.📍커리큘럼대로만 잘 따라가자, 부지런해져라(제발🥺) 

UX/UI워밍업클럽1기피그마

이양구

[인프런 워밍업 클럽 FE 0기] 미션8 - 디즈니 플러스 앱

🎞 Disney Plus APP GitHub 🎞 Disney Plus APP DemoRecord by ScreenToGif  개요인프런 워밍업 클럽 FE 0기의 여덟 번째 미션인 '디즈니 플러스 앱' 입니다. 따라하며 배우는 리액트 섹션 4~5(리액트로 Netflix 앱 만들기) 목표swiper 라이브러리 커스텀해보기react-oauth/google 로 구글 로그인 연동해보기 구현swiper 라이브러리 커스텀해보기// LoginPage import "swiper/css/effect-fade"; <Swiper modules={[Autoplay, EffectFade, Pagination, A11y]} autoplay={auto} effect={"fade"} pagination={{ clickable: true, }} loop={true} fadeEffect={{ crossFade: true }} slidesPerView={1} speed={2000} > {...} </Swiper> // Row.tsx import "swiper/css/mousewheel"; <Swiper modules={[Navigation, Pagination, Scrollbar, A11y, Mousewheel]} navigation pagination={{ clickable: true }} mousewheel speed={1000} spaceBetween={10} > {...} </Swiper> 2024년 3월 10일의 디즈니 플러스 메인 페이지를 그대로 옮겨보고자 swiper 라이브러리를 커스텀해봤다.로그인 페이지에서는 좌우로 넘기는 슬라이드가 아닌 fade-in-out의 슬라이드를 구현하기 위해 swiper에 EffectFade 모듈을 추가하고 fadeEffect 속성을 추가했다.이 fadeEffect가 제대로 작동하기 위해선 반드시 해당 이펙트의 css를 추가해야 한다.다른 모듈이나 컴포넌트를 추가할 때처럼 자동으로 추가되지 않으니 주의해야 한다. (이걸 몰라서 한참을 찾았다. 😥)Row 컴포넌트는 마우스 휠에 따라 움직이는 슬라이드를 만들기 위해 Mousewheel 모듈과 속성을 이용했다.이렇게 슬라이드 속성을 정한 뒤에 swiper가 렌더링하는 요소의 class를 찾아 CSS에서 원하는 디자인으로 변경하면 된다.이때 라이브러리의 CSS와 겹치는 속성이 있을 수 있기 떄문에 '!important'를 붙이는 게 좋다. react-oauth/google 로 구글 로그인 연동해보기// index.js <GoogleOAuthProvider clientId={process.env.REACT_APP_CLIENT_ID}> <BrowserRouter> <App /> </BrowserRouter> </GoogleOAuthProvider> // App.jsx const navigate = useNavigate(); const [isLogin, setIsLogin] = useState( localStorage.getItem("user") ? true : false ); useEffect(() => { isLogin ? navigate("/") : navigate("/login"); }, [isLogin]); <Routes> {isLogin ? ( <Route path="/" element={<Layout setIsLogin={setIsLogin} />}> <Route index element={<MainPage />} /> <Route path=":movieId" element={<DetailPage />} /> <Route path="search" element={<SearchPage />} /> </Route> ) : ( <Route path="login" element={<LoginPage setIsLogin={setIsLogin} />} /> )} </Routes> react-oauth/google는 구글 로그인을 지원하는 라이브러리로, 사전에 구글의 Cloud에서 API 등록을 하고 Client ID를 발급받아야 사용할 수 있다.먼저 프로젝트의 최상위에 GoogleOAuthProvider로 감싸준다.그리고 사용자의 로그인 여부에 따라 페이지를 이동시키기 위해 라우터를 설정한 App 컴포넌트에서 관련 코드를 작성했다.페이지가 렌더링 될 때 로컬 스토리지에 저장된 유저 정보를 받아오고 만약 없다면 로그인 페이지로 보내도록 했다. // loginPage const googleLogin = async (credentialResponse) => { localStorage.setItem( "user", JSON.stringify(jwtDecode(credentialResponse.credential)) ); setIsLogin(true); }; <GoogleLogin onSuccess={(credentialResponse) => googleLogin(credentialResponse)} /> GoogleLogin 컴포넌트는 react-oauth/google 라이브러리에서 지원하는 버튼 컴포넌트로 디자인 및 로그인 관련 함수가 내장되어 있다.onSuccess는 사용자의 로그인이 성공했을 때 실행되는 콜백 함수이며, 인자로 로그인한 유저의 정보를 담은 데이터를 갖는다.여기서 credential이라는 값은 유저의 정보를 담고 있는 토큰으로 암호화되어 있기 때문에 jwt-decode 라이브러리를 이용해 디코딩하여 사용해야 한다.여기서 받은 picture는 사용자의 프로필 이미지 링크를 포함하고 있어서 Nav 컴포넌트에서 사용해 로그인한 유저의 프로필 이미지로 변경했다. 회고'Netflix 앱 만들기'를 하면서 사용했던 기술이 대부분이라 오래 걸리지 않을 것 같았지만...라이브러리 알아보고 문서 읽고 실행해보고... 하는 데 너무 오래 걸린 것 같다.배너 하단의 카테고리 부분은 이전에 같은 과제를 하셨던 분의 깃허브를 참고했다. (https://github.com/kimneighbor/clone-disney-plus-app)로그인 페이지는 따라하기 싫어서 현재 디즈니 플러스 홈페이지를 보고 참고했다.그대로 하면 얼마 안 걸릴 거라 생각했는데 생각보다 라이브러리 커스텀에서 좀 애를 먹었다. 😅with_networks: "2739" 2739는 TMDB에서 디즈니 플러스 방송사(networks) 코드라서 axios의 instance 기본 값에 추가했다.몇몇 요청은 해당 파라미터가 통하지 않거나 오류를 보내기도 해서 완벽하진 않다.디즈니 플러스에서 API를 제공했다면 더 알맞게 페이지를 구현할 수 있었을 텐데 하는 아쉬움이 남는다.한편 영화 정보 API를 제공해주는 TMDB(The Movie Database) 같은 곳이 있어 감사하고 다행이라는 생각이 들었다.프론트엔드 공부하는데 API를 제공해주는 곳이 아예 없었다면 혹은 매번 일정 비용을 지불해야 했다면 얼마나 힘들었을까로그인도 사실 좀 더 좋은 라우팅 구조나 상태 관리 라이브러리를 공부하고 사용해보고 싶었지만...계속 욕심만 커지는 것 같아 최대한 간단하게 구현하려 했다.(사실 과제 밀려서 조바심에 아무것도 못 했다... 😂) 

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

[인프런 워밍업 스터디 클럽 2기 백엔드] 4주차 + 회고

 해당 글은 인프런 박우빈 강사님의 「Practical Testing: 실용적인 테스트 가이드」을 바탕으로 작성하였습니다.  강의 요약 Presentation Layer외부 세계의 요청을 가장 먼저 받는 계층사용자 입력 값, 프론트엔드에서 주는 값, 요청 등...주요 로직은 없지만, 최소한의 유효성 검증을 수행한다. 레이어드 아키텍쳐의 단점도메인에 강하게 의존도메인에 레포지토리를 위한 어노테이션을 필연적으로 붙여야 하는 문제 발생⇒ 대안: 헥사고날 아키텍쳐 Mockito로 stubbing 하기가짜 객체를 만들어 행위를 지정하고 테스트하는 방법 (자세한 내용은 미션 6 참조) Test Doubledummy: 아무것도 하지 않는 깡통 객체fake: 단순 형태로, 동일 기능을 수행. 프로덕션에서 쓰기에는 부족한 객체stub: 테스트에서 요청한 것에 대해 기록하여 보여줄 수 있는 객체. 정의하지 않은 요청에는 무응답spy: stub이면서, 호출된 내용을 기록하여 보여줄 수 있는 객체. 일부는 실제 객체처럼 동작.mock: 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체 stub vs mockstub은 상태를 검증mock은 행위를 검증 더 나은 테스트 작성하기한 문단에는 한 가지 주제만!'테스트 코드 = 문서' 라는 것을 항상 인지해야 한다.완벽한 제어시간, 랜덤 등은 외부에서 주입받도록 리팩토링 하기. 강의 예제의 가게의 영업시간을 테스트했던 것을 기억하자.외부 세계와 소통해야 하는 것은 mocking을 이용한다.독립성 보장하기한 테스트 메서드에는 한 가지 기능만 테스트하기given에서는 가급적 순수 생성자 또는 빌더를 통해 생성하기검증이 있는 팩토리 메서드는 사용 시 예외 발생 가능성이 있다.테스트는 순서 보장이 안 되어 있다.Fixture 구성@BeforeEach, @BeforeAll중복 코드를 줄일 수 있지만 테스트 간의 결합이 생겨버린다.신중한 사용이 필요!Fixture 클렌징deleteAll vs deleteAllInBatchdeleteAllInBatch(): 중간 테이블에 외래키 등으로 인한 오류 발생 때문에 데이터 삭제 순서를 고려해야 함. → 코치님의 추천 메서드deleteAll(): 순서 고려 필요가 없고 연관 테이블을 자동적으로 같이 지워주지만, 삭제 쿼리가 복잡하게 나간다! 전체 테이블을 조회하고 건별로 삭제하는 방식이기에 불필요한 쿼리가 늘어난다.@ParameterizedTest케이스 확장할 때 좋은 방식!재고 타입 테스트할 때를 기억하기!@CsvSource로 제공된 데이터를 @ParameterizedTest가 붙은 메서드의 파라미터에 각각 제공 가능@CsvSource 외에도 @MethodSource, @ValueSource 등이 존재@DynamicTest일련의 시나리오를 테스트@TestFactory가 붙은 메서드에서 Iterable한 반환 값을 던지는 형태 공통의 환경에서부터 일련의 사건을 실행시켜 테스트가 가능.given/when/then 세트가 복수로 생기기 때문에 가독성 저하에 주의하기.환경 통합하기gradle 탭의 tesk에서 test를 수행하면 전체 테스트를 수행해보기전체 테스트 시 Spring Boot가 여러번 로딩하게 되면 비용과 시간 증가...! 서버가 발생하는 횟수를 줄여야 한다!서버를 띄우는 @SpringBootTest과 profile을 지정하는 @ActiveProfile을 별도의 상위 클래스에 붙여 Test 클래스들에 상속시키기!mock도 별도의 환경으로 취급하기 때문에 mock 객체는 상위 클래스에서 protected로 생성하거나 mock이 필요한 환경을 별도로 설정하기.환경 통합을 위해, @DataJpaTest보단 @SpringBootTest를 사용하기private 메서드를 테스트하기결론적으로는, 할 필요도 없고 하려고 해서도 안된다!그래도 고민된다면, 객체를 분리할 시점인지 관해 생하기분리가 필요하다고 판단된다면 객체를 별도로 분리해 private 메서드를 공개 메서드로 작성하면 된다.private 메서드는 외부에서 공개하고 싶지 않은 것이고 외부에서는 몰라도 되는 부분이다! public 메서드를 검증하다보면 자연스레 검증되는 부분이다!+ α헥사고날 아키텍쳐도메인 주도의 아키텍쳐QueryDSLJPA 사용 시 거의 필수타입 체크, 동적 쿼리(값에 null이 들어올 시 자동으로 동적으로 조회해줌)가 가능낙관적 락, 비관적 락CQRS(Command and Query Responsibility Segregation)DB에서 조회와 업데이트를 분리  미션미션 5미션 6미션 5, 6은 직접 테스트 코드를 작성했던 네 번째 미션 보다는 훨씬 편안한 내용이었다. 강의 내에서 이미 정답을 다 알려준 느낌이고, 내 나름의 언어로 정리해보는 느낌이었다.쉽다고 만만히 보았기 때문일까... 특강 때 공통 피드백을 받고 바로 아차 싶었다. @BeforeEach 부분은 단순 중복 제거를 위한 것이 아니라는 점을 간과했다. 리팩토링 강의에서부터 가장 강조하신 것 중 하나가 도메인인데 그것을 놓치다니...🤣🤣 정답은 맞췄어도 풀이 과정 때문에 반타작 밖에 못한 기분이었다.  후기벌써 4주차, 마지막 발자국이자 워밍업 클럽 2기의 마무리이다. 한 달이라는 시간이 쏜살같이 지나가버렸다. 테스트 코드와 리팩토링에 대해 심도 있게 다가간 것은 처음이었던 나에게는 정말 어려웠다. 강의에서 들었던 내용을 과제에 적용하는 과정은 험난했다. 과제를 모두 제출하고 완주를 한 것 만으로도 만족해버리고 말았다. 당장 다음주 시작부터, 새로운 스터디가 시작된다. 같이 워밍업 클럽에 참여하신 분의 자바 스터디인데, 기초부터 다시 다잡는다는 느낌이라 굉장히 기대가 된다. 👏👏마지막으로, 이런 자리를 마련해주신 인프런과 코치님, 그리고 내 부족한 미션 피드백을 해주신 다른 스터디 참여자 분께 감사의 말씀을 드리고 싶다. 언젠가 3기가 열린다면, 다시 한 번 도전하고 싶다!

백엔드워밍업클럽백엔드

대협

[인프런 워밍업 클럽 2기 - BE] 1주차 발자국

이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다 나의 첫 인프런 블로그가 이렇게 쓰여질 줄은 몰랐다.. 그동안 인프런 강의들을 많이 애용했지만, 이렇게 블로그를 작성하지는 않아서 낯설기도 하고, 설레기도 한다.발자국 내용은 딱히 형식이 정해져 있지 않아서 발자국 쓰기 전날까지 들었던 강의들 중, 모르는 내용들을 적어서 내가 다시 봤을 때, "아 맞다!" 라는 말이 나올 정도로만 적을 예정이다! 목차모르는 내용 정리 미션 해결 과정회고   1. 모르는 내용 정리 <Gradle>Gradle : Gradle은 Groovy를 기반한 빌드 관리 도구.빌드 관리 도구 : 프로젝트 내에서 다양하게 외부 라이브러리와 로컬 레포지토리에서도 라이브러리 별로 버전 관리를 해야할 때 용이Gradle이 왜 필요할까?Gradle과 Maven 차이를 알면 Gradle이 왜 필요한지 알 수 있다.Gradlegroovy 언어를 사용한 Domain-specific-language를 사용 ( 코드가 간결)어느 task가 업데이트 되었는지 체크이미 반영된 빌드 부분은 더이상 재 실행되지 않는다. -> 빌드 시간 단축Mavenjava8용 프로젝트 관리 도구 apache의 ant 대안외부 저장소에서 필요한 라이브러리, 플러그인들을 다운로드 한 후 , 로컬 시스템의 캐시에 모두 저장그래서 왜 Gradle인데!!!Gradle은 작업 의존성을 그래프, Maven은 고정적이고 선형적 모델을 기반Gralde은 어떤 task가 업데이트되었고 안되었는지를 체크Gradle은 이미 업데이트 된 task에 대해서는 작업이 실행되지 않으므로 빌드 시간 단축빌드 설정 규모가 작으면 큰 차이를 느끼지 못하지만 규모가 크면 훨씬 Gradle의 빌드 시간이 단축된다는걸 알 수 있다. <Dependencies>Spring Web : 웹 어플리케이션을 개발하기 위한 핵심 기능 제공Thymeleaf : View Template, 동적으로 화면을 구성할 수 있게 해줌Spring Data JPA : JPA를 이요한 구현체를 더 추상화시켜 더 쉽고 간편하게 JPA를 이용 가능mysql driver : mysql를 연동할 때 필요한 dependencyh2 database : RDBMS, 테스트 단계 또는 작은 규모의 프로젝트에서 사용validation : 데이터에 대한 유효성 검증 처리를 수행Spring Security : 홈페이지에 인증 및 권한 기능을 빠르게 부여해 인증 및 권한 보호 기능을 손쉽게 추가할 수 있음. <프로그램이 시작되는 시작되는 코드>src/main/kotlin/PortfolioApplicatioin.ktfun main(args: Array<String>) { runApplication<PortfolioApplication>(*args) } Whitelabel Error Page 오류가 뜨는 이유 : 어플리케이션이 뭘 해야 할지 모르기 때문에 Whitelabel Error Page를 보내줌.(정상) <Git 용어>Git : 분산 버전 관리 시스템 ⇒ 협업을 쉽게 해주는 툴 : GitHubCommit : git에 저장하는 단계Rollback : 이력 되돌리기Branch : branch 생성 및 제거, 확인등의 기능을 하는 명령어Merge : 브랜치 병합Conflict : 충돌Repository : 원격 저장소 , 인터넷이나 네트워크 어딘가에 있는 저장소Push : 로컬 브랜치를 원격 저장소로 푸시할 때 사용하는 기본 명령어 <Git 명령어>git init : git 공간으로 초기화git status 명령어 입력시 Untracked files 라는 게 있는데 이건 git에서 따로 설정을 안한다는 소리https://www.toptal.com/developers/gitignore/ : gitignore 파일을 자동으로 만들어줌 <github에 PUSH 방법>터미널에서 git initgit remote “git 저장소”→ 인텔리제이(GUI)로 할 시에는 git → Manage Remotecommitpush <application-default.yml , application-docker.yml>profile이 default 이면, application-default.yml 파일에서 환경변수를 가져오고profile이 docker 이면, application-docker.yml 파일에서 환경변수를 가져온다. application-default.yml 파일에서 spring:jpa:hibernate:ddl-auto:create 인데왜 application-docker.yml 파일에서는 spring:jpa:hibernamte:ddl-auto:none 일까?=> application-default.yml 에서는 개발 목적으로 데이터베이스 스키마를 매번 재생성할 필요가 있지만, application-docker.yml 에서는 베포 및 운영 환경에 적합하게 데이터베이스 구조가 변경되지 않도록 하기 위한 설정 <어노테이션 정리>@Id : 해당 테이블의 PK 필드를 의미@Entity : JPA를 사용해 테이블과 매핑할 클래스에 붙여주는 어노테이션@GeneratedValue : JPA에서 Entity의 PK를 생성하여 주는 기능-> @GeneratedValue(name="member_id") : PK로 사용될 Entity의 프로퍼티에 @Id 어노테이션 선언-> @GeneratedValue(strategy=GenerationType.IDENTITY) : 기본 키 생성을 데이터베이스에 위임한다.-> @GeneratedValue(strategy=GenerationType.AUTO) : 기본값으로 DB 방언에 맞춰 자동으로 설정하여 준다.@Column : 객체 필드와 DB 테이블 칼럼을 맵핑한다.@Component : 클래스를 자동으로 빈으로 등록하기 위해 클래스 레벨에서 사용@Profile : 빈이나, 컴퓨넌트에게 프로필을 정해줄 수 있음@PostConstruct : 객체의 생성이 일어난 직 후에 초기화를 수행하는 메서드에 부착한다.@ManyToOne : 단방향 관계이고 FK관리에 있어서 가장 자연스럽다. @JoinColumn 어노테이션과 같이 쓰인다.@JoinColumn : 엔티티 테이블에 FK 칼럼을 정의해준다. 자료형뒤에 ? 는 무슨 의미일까 ?ex ) Long?자료형 뒤에 ? 가 오는 것은 Kotlin에서 사용되는 문법이고 ?를 자료형 뒤에 붙이는 방식은 nullable 여부를 나타낸다. 예를 들면 var name: String? = null 이 코드는 해당 변수 name에 null 값이 올 수도 있다는 뜻이다.  <코드 분석>var type: SkillType = SkillType.valueOf(type) : SkillType.valueOf(type) 은 type이라는 문자열을 SkillType 열거형의 값으로 변환. 만약 type이 열거형에 없는 값이면 예외 발생var cookies: String? = httpServletRequest.cookies ?.map {"${it.name}:${it.value}"} ?.toString() : httpServletRequest에서 쿠키 정보를 가져오고, 쿠키 이름과 값을 "이름:값" 형식으로 변환하는 코드var referer: String? = httpServletRequest.getHeader("referer") : HTTP 요청에서 "Referer" 헤더 값을 가져온다. 이 코드는 사용자가 어떤 페이지에서 현재 페이지로 이동했는지 나타냄@OneToManyvar details: MutableList<ExperienceDetail> = mutableListOf() : JPA 관계를 나타내고, 엔티티 간의 일대다(One-to-Many) 관계를 나타냄2. 미션미션 1과 2를 제출하는건데, 미션1은 테이블 설계하기와 깃허브 리포지토리에 프로젝트 올리기이다. 미션 1 : https://github.com/HyupTech/LMS/commit/fa47b404d36b3ce418f16213e3bb30ca96b812ed미션 2 : https://github.com/HyupTech/LMS/commit/0993897036a0e17e7a366031b950235edd5d506e   3. 회고발자국을 작성하면서 나는 이제까지 강의를 보면서 공부를 했지만 다시 한번 이렇게 정리를 해가면서 강의를 보지 않았다. 왜냐하면 시간이 너무 아까웠고, 차라리 정리하는 시간에 강의를 하나 더 보자는 마인드였다. 하지만 발자국을 써보면서 왜 이렇게 좋은걸 내가 안했을까라는 후회가 들고, 이렇게 정리를 해가면서 했으면 아마 실력이 조금이라도 더 올랐지 않았나 라는 생각이 들었다. 앞으로 발자국도 쓰고, 내가 따로 공부하고 있는것도 정리해가면서 공부를 해야겠다. 3-1. 미션 회고 이번 미션에서 처음으로 ERD를 구성하고 어디에 PK를 주고 관계 설정을 어떻게 할지에 대한 고민이 많았던 것 같다. 현재 대학교 2-2에 재학중인데 데이터베이스 과목을 수강중인데 꽤 도움이 되었던 것 같고, 백엔드 개발자가 될려면 데이터베이스 공부도 놓지 말아야겠다고 생각이 들었다. 앞으로 더 많은 미션들이 기다리고 있는데 열심히 공부를 해야겠다!   

백엔드인프런워밍업클럽백엔드발자국javakotlin

대협

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다1. controller test 코드 분석애너테이션 조사@AutoConfigureMockMvcMockMvc를 자동으로 설정해 주는 애너테이션. 이 애너테이션을 통해 HTTP 요청을 수행하고 응답을 확인할 수 있다.MockMvc 란 ?실제로 서버를 띄우지 않고 컨트롤러를 테스트할 수 있는 도구@DisplayName("Test")테스트 클래스를 시작할 때 테스트 클래스의 이름을 지정해서 테스트 리포트에 표시된다.위 코드를 실행시키면 리포트에 TEST 라는 이름으로 테스트 성공유무가 표시됨.@Configuration : Spring에서 Bean을 수동으로 등록하기 위해서 사용메서드 분석 @Test @DisplayName("Introductions 조회") fun testGetIntroductions() { val uri = "/api/v1/introductions" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() }api/vi/introduction을 uri 변수에 넣음.HTTP GET 요청을 보낸후, 응답을 문자열로 변환한 후에 JSONArray로 변환JSONArray의 길이가 0보다 큰지 검증, 응답 데이터가 비어 있지 않음을 확인 @Test @DisplayName("Link 조회") fun testGetLinks() { val uri = "/api/v1/links" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } api/vi/links을 uri 변수에 넣음HTTP GET 요청을 보낸후, 응답을 JSONArray로 변환배열의 크기와, 그 데이터가 존재하는지 검증@Test @DisplayName("Resume 조회") fun testGetResume() { val uri = "/api/v1/resume" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonObject = JSONObject(contentAsString) assertThat(jsonObject.optJSONArray("experiences").length()).isPositive() assertThat(jsonObject.optJSONArray("achievements").length()).isPositive() assertThat(jsonObject.optJSONArray("skills").length()).isPositive() } /api/vi/resume를 uri변수에 넣음GET요청을 보낸후, 응답을 JSONObject로 변환experiences, achievements,skills를 JSONArray로 변환 후 그 값이 양수인지와 데이터가 존재하는지 검증@Test @DisplayName("Projects 조회") fun testProjects() { val uri = "/api/v1/projects" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } /api/vi/projects를 uri 변수에 넣음GET요청을 보낸후 응답 본문을 JSONArray로 변환하고, 배열의 길이가 양수인지와 데이터가 존재하는지 검증private fun performGet(uri: String): MvcResult { return mockMvc .perform(MockMvcRequestBuilders.get(uri)) .andDo(MockMvcResultHandlers.print()) .andReturn() } perform(MockMvcRequestBuilders.get(uri)) : 특정 uri에 GET 요청을 보내는 코드. 서버를 띄우지 않고 API 엔드포인트의 동작을 확인할 수 있음andDo(MockMvcResultHandlers.print()) : 요청과 응답을 콘솔에 출력andReturn() : MvcResult를 반환2. 부분 코드 분석<html *lang*="ko" *xmlns:th*="<http://www.thymeleaf.org>" *th:replace*="~{presentation/layouts/layout-main :: layout(~{::#content})}">Thymeleaf 템플릿 엔진에서 레이아웃을 정의하고 해당 레이아웃을 재사용하는 방식, 템플릿 코드의 중복을 줄이고, HTML 파일 간에 공통 요소를 재사용할 수 있게 하는 것. th:replace="~{presentation/layouts/layout-main :: layout(~{::#content})}"th:replace : 다른 파일을 가져와 현재 위치에 삽입하는 기능 수행~{presentation/layouts/layout-main :: layout(~{::#content})} :~{presentation/layouts/layout-main} : layout-main.html 파일 참조:: layout : layout 이라는 이름의 fragment를 사용하겠다는 의미, 위 코드에서는 layout fragment를 가져오겠다는 뜻(~{::#content}) : id="content" 로 지정된 부분을 layout fragment의 특정 위치에 대체할 것이라는 의미3. interceptor 코드 분석@Component class PresentationInterceptor( private val httpInterfaceRepository: HttpInterfaceRepository ) : HandlerInterceptor { override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { val httpInterface = HttpInterface(request) httpInterfaceRepository.save(httpInterface) } }private val httpInterfaceRepository: HttpInterfaceRepository의존성 주입을 통해서 Repository를 사용할 수 있다.override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) {afterCompletion : HTTP 요청 처리 후에 호출되는 메서드val httpInterface = HttpInterface(request)httpInterfaceRepository.save(httpInterface)request 정보를 담고 있는 httpInterface 객체를 생성 후, httpInterfaceRepository에 저장. @Configuration class PresentationInterceptorConfiguration( private val presentationInterceptor: PresentationInterceptor ) : WebMvcConfigurer { override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(presentationInterceptor) .addPathPatterns("/**") .excludePathPatterns("/assets/**", "/css/**", "/js/**", "/admin/**", "h2**", "/favicon.ico", "/error") } }addInterceptors인터셉터를 등록하는 메서드registry.addInterceptor(presentationInterceptor)addInterceptor 메서드를 통해 presentationInterceptor를 등록addPathPatterns("/**")모든 요청 경로에 대해 인터셉터 적용excludePathPatterns(...) : 인터셉터가 동작하지 않도록 설정/assets/**: 정적 자원(예: 이미지, 폰트 등)./css/**: CSS 파일./js/**: JavaScript 파일./admin/**: 관리 페이지.h2**: H2 데이터베이스 콘솔./favicon.ico: 사이트 아이콘./error: 오류 처리 경로.[미션4] 조회 REST API 만들기-회고이번 미션을 하면서 @GetMapping 어노테이션에 대해서는 어느정도 이해를 할 수 있었다. 저번 발자국에서 @Id, @GeneratedValue 어노테이션에 대해서 적었지만 아직 부족하다는 걸 알 수 있었고, @ManyToOne 어노테이션에 대해 더 깊이 공부해야겠다는걸 깨달았다. 아직 Spring에 본질적인걸 이해를 못한걸수도 있는거 같다. 코드를 작성하면 할수록 더 깊게 공부를 해야했고, JAVA 문법도 다시 해야겠다는걸 뼈저리게 느끼면서 한것 같다...3주차 회고Spring은 하면 할수록 재밌는건 맞다. Test 코드를 작성할 때도 이래서 이코드가 작동이 되는것도 알 수 있고, 부분적인 걸 따로 모듈화? 해서 만드는것도 재밌다. 이번 워밍업 클럽도 곧 종료가 되는데 java의 중요성도 깨달아서 java공부도 열심히 하고, Spring에 대해서 더 깊게 공부할거다!참고로 중간점검 때 정보근님께서 내가 작성한 질문에 대해 답변을 해주신거 같다. 나의 질문은 이번 워밍업 클럽이 종료가 되면 java의 정석, spring공부를 할건데 추천해줄 강의가 있냐 라는 질문이었다. 답변은 역시 김영한님의 강의였고 다른 강의도 추천해주셨는데 이거는 확인해보고 글을 수정해야겠다...! 무튼, spring을 선택한건 잘한 일 같다...!

백엔드워밍업클럽javakotlinspringTest코드미션4회고록코드설명백엔드

채널톡 아이콘