블로그

노을

[인프런워밍업클럽] 2주차 발자국 미션

섹션4 프로세스 동기화유닛 1 프로세스간 통신프로세스는 독립적으로 실행 or 다른 프로세스와 데이터를 주고 받으며 통신통신은 한 컴퓨터 내에서 실행되고 있는 다른 프로세스와 할 수도 있고, 네트워크로 연결된 다른 컴퓨터에 있는 프로세서와 할 수 도 있음종류한 컴퓨터 내에서 통신파일과 파이프파일통신을 하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법스레드코드, 데이터, 힙 영역을 공유하고 스택만 각자 자기의 것을 가지고 있음데이터 영역에 있는 전역변수나 힙을 이용하면 통신이 가능네트워크운영체제가 제공하는 소켓통신이나 다른 컴퓨터에 있는 함수를 호출하는 RPC(원격 프로시저 호출)를 이용해 통신유닛2 공유자원과 임계구역공유자원프로세스 간 통신을 할 때 공동으로 이용하는 변수, 파일문제공유 자원은 여러 프로세스가 공유하고 있기 때문에 각 프로세스의 접근 순서에 따라 결과 달라짐컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행되고 어떤 프로세스가 나중에 실행되는지 예측하기 힘듦연상결과를 예측하기 힘들고 여기에 발생한 문제를 동기화 문제라고 함예) 게임을 예시로 듦캐릭터 총 체력 100, 현재 체력 20지금은 적에게 공격을 받고 있고 플레이어는 죽지 않기 위해 물약을 먹음이때 물약을 먹는 코드와 적에게 공격받는 코드에서 발생할 수 있는 동기화 문제를 살펴봄두 가지 코드가 동시에 실행됐는데 CPU 스케줄러에 의해 공격받는 코드가 먼저 실행됐다고 가정두번째임계구역여러 프로세스가 동시에 사용하면 안되는 영역경쟁조건공유자원을 서로 사용하기 위해 경쟁하는 것임계구역 문제 해결 방법상호배제의 메커니즘이 필요함요구사항주어진 시간에 항상 하나의 프로세스만 임계구역에 접근 가능동시에 여러개의 요청이 있더라도 하나의 프로세스만 진입하도록 허용임계구역에 들어간 프로세스는 최대한 빠르게 나와야함 → 다른 프로세스들이 오래 기다리기 떄문에유닛3 세마포어프로세스 : 프린트를 사용하려는 직원, 프린터는 여러 프로세스들이 같이 쓰고 있는 공유자원대기큐 : 프린트를 사용하기 위해 프로세스가 기다리는 공간운영체제 : 열쇠관리자세마포어 : 열쇠관리자가 들고 있는 열쇠, 정수형 변수사용법세마포어를 사용하면 공유자원에 여러 프소세스가 동시에 접근하지 못함 → 동기화 문제가 일어나지 않음세마포어는 실제로 여러개의 열쇠를 가질 수 있음정수형 변수, 공유자원이 2개라면 세마포어의 값은 2, → 열쇠 2개로 설정단점웨이트 함수와 시그널 함수의 순서를 이상하게 호출해서 세마포어를 잘못 사용할 수 있다는 가능성섹션5 데드락교착상태여러프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무 작업도 진행하지 못하는 상태이유공유자원 때문에 발생어떤 자원을 여러개의 포로세스가 공유하지 않는다면 교착상태는 발생하지 않음예시) 식사하는 철학자필요조건상호배제 : 어떤 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 프로세스에게 공유가 되면 안됨비선점 : 프로세스 A가 리소스르 점유하고 있는데 프로세스 B가 리소스를 뺏을 수 없음점유와 대기 : 어떤 프로세스가 리소스 A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야만 함원형대기 : 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있다는 것해결방법교착상태 회피프로세스들에게 자원을 할당할 때 어느 정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 자원을 할당함시스템의 총 자원 : 운영체제는 프로세스들에게 자원을 할당하기 전에 자기가 가지고 있는 전체 자원의 수를 알고 있어야 함최대 요구 자원 : 프로세스들은 각자 자기가 필요한 자원의 초대 숫자를 운영체제에게 알려줘야 함교착상태 알아내는 법가벼운 교착상태 검출타이머를 이용하는 방식, 프로세스가 일정시간동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주하고 교착상태를 해결무거운 교착상태 검출자원할당 그래프를 이용, 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결섹션 6 컴파일과 프로세스컴파일언어개발자가 코드 작성 → 컴파일 → 0과1 기계어로 실행파일 만듦인터프리터언어개발자가 작성한 코드를 미리 기계어로 만들지 않고 실행시 코드를 한 줄 씩 해석해 실행하는 언어프로세스의 메모리 구조스택 : 지역 변수, 함수 관련 값힙 : 실행 중 메모리 공간을 할당할 수 있는 유동적인 공간데이터 : 전역변수나 배열코드 : 실행해야 할 코드중간정리하드웨어, 운영체제 구조, 프로세스 회고운영체제는 강의를 듣고 복습을 하면 이해가 조금 잘 되는데 자료구조와 알고리즘은 이해하는데 시간이 많이 필요하다.. 복습을 더 많이 하고, 관련 서적들도 좀 찾아서 공부해야 할 것 같다

알고리즘 · 자료구조

워밍업 클럽 3기_PM/PO_2주차 발자국

강의 정보강의명: 시작하는 PM/PO들에게 알려주고 싶은, 프로덕트의 모든 것강사명: 김민우링크: https://inf.run/gQh4a강의 내용고객과 직접 만나야 하는 이유고객을 직접 만나는 것이 고객에 대한 이해를 높이는 가장 좋은 방법이다. 고객과 서비스에 대해 직접 문답하면서 고객이 가진 멘탈 모델을 정확하고, 구체적으로, 해상도 높게 가져갈 수 있다.중간 매개자로부터 받는 고객의 의견은 매개자의 시선에서 생략 및 요약되기 때문에 핵심 문제들을 놓치게 될 수 있다. 고객 리서치 방법의사결정을 명확하게 하고, 그에 맞는 리서치 방법과 계획을 세워야 한다.1:1 심층 인터뷰제품 사용 동기, 경험, 문제점 등에 대한 고객의 의견을 수집하는 방식이다.행동이 아니라 말에 의존해서 정보를 수집한다는 점을 유의해야 한다.인터뷰 대상은 10명을 기본으로 추천하나, 의사결정을 하기 충분한 답변을 모았다면 멈춰도 된다.사업>리서치>인터뷰로 질문을 만들고 준비해야 한다. 사업 상의 목적을 명확히 하고, 이를 알아가기 위해 필요한 리서치 방향을 생각한 뒤에 인터뷰 대상자가 답변 가능한 쉬운 질문으로 다듬어 가야 한다. 인터뷰 가이드 작성이 필요하다.답변은 유형화, 전반적인 테마를 발굴하여 중요 내용을 추려서 활용한다.사용성 테스트유저가 사용, 이해, 기능을 발견할 수 있는 제품이 좋은 제품이다.매몰 비용을 최소화하기 위해 사용성 테스트를 진행해야 한다.어림 법칙에 따라 5명 정도면 테스트는 충분하다. 그러나 유저 그룹에 여러 개라면 이를 고려하여 진행해야 한다.테스트 진행 시에는 2인 1조, 녹화 및 녹음이 필수이다.PM이 갖춰야 할 데이터 역량데이터 축적 역량과 활용역량이 필요하다.축적 역량은 로그 데이터를 설계하는 것을 의미한다.활용 역량은 지표를 이해하고 해석하는 것이다.데이터를 쪼개서 자세히 바라보는 연습이 필요하다.후기사용자의 의견을 듣기 위해 온라인 설문조사를 진행한 경험이 있었다. 그땐 가이드가 없어서 알고자 하는 목적에 집중해서 문항을 작성했는데, 지금 생각해 보니 너무 직접적인 질문이었던 것 같다. 목적을 선명히 해야 이후의 작업들을 펼치고 모을 수 있다는 것을 배웠다.국내가 아닌 국외 사용자들은 어떻게 심층 인터뷰나 사용성 테스트를 진행하는 게 좋을지 고민해 보게 되었다.데이터를 활용한 업무를 진행하기 위해서는 그런 환경이 놓인 회사에 가는 것이 필요하다는 이야기가 맘에 와닿았다. 데이터를 수집하기 위해서는 앞서 선행되어야 할 작업들이 많고, 후에 해석에도 많은 시간이 걸린다. 이를 낭비라고 생각하지 않는 회사로 가려면 면접에서 어떤 것을 확인해 봐야 하는 지 궁금해졌다. 미션앱 고도화 작업 이후에 특정 기능을 활용하는 사용자의 수가 감소한 사례가 있었다. 경험한 사례를 기준으로 고객 조사 방법을 설계해보려 한다.  

기획 · PM· PO워밍업클럽3기

안지수

[워밍업 클럽] CS 전공지식 2주차 발자국

운영체제프로세스 동기화공유 자원 : 프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들임계 구역(Critical Section) : 여러 프로세스가 동시에 사용하면 안되는 영역경쟁 조건(Race Condition) : 공유 자원을 서로 사용하기 위해 경쟁하는 것상호 배제(Mutual Exclusion) : 임계 구역 문제 해결하기 위한 메커니즘상호 배제 요구사항1. 임계영역엔 동시에 하나의 프로세스만 접근한다.2. 여러 요청에도 하나의 프로세스의 접근만 허용한다.3. 임계구역에 들어간 프로세스는 빠르게 나와야한다.세마포어 : 상호 배제 메커니즘/정수형 변수/동기화 방지/잘못 사용할 가능성 있음모니터 : 세마포어 단점 해결한 상호 배제 메커니즘/프로그래밍 언어 차원에서 지원(예: 자바의 synchronized)데드락데드락(교착상태) : 여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태/공유자원 때문에 발생교착상태의 필요조건 상호배제비선점점유와 대기원형 대기 교착상태 회피(Deadlock avoidance) - 은행원 알고리즘교착상태 검출가벼운 교착 상태 검출 : 타이머 이용무거운 교착 상태 검출 : 자원 할당 그래프 이용자료구조재귀어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀 함수는 호출할 때마다 콜스택의 영역을 차지기저 조건(탈출 조건)이 반드시 있어야하위 문제의 결과를 기반으로 현재(상위) 문제 계산하는 데 유용(하향식 계산) 회고칭찬하고 싶은 점강의를 듣고 주력 언어인 자바로 복습하고 있다.아쉬웠던 점계획보다 진도가 밀려서 목표한 학습량을 채우지 못한 점보완하고 싶은 점공부한 내용을 나의 언어로 정리해서 발행하기(Output 만들기)

삼각커피포리

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

🐾 두번째 발자국개인적인 일정으로 평일에 시간이 많이 나지 않았고, 업데이트 된 입력 컴포넌트 강의 분량이 늘어나면서 시간이 많이 소요한 주차였다. 그래도 매일 조금씩 들었는데 이번주 분량을 모두 듣지 못 한 것 같아서 개인적으로 매우 아쉬운 주차였다. 📚 배운 점FrameAll 플러그인으로 모든 프레임을 쉽게 선택할 수 있다.아이콘은 오픈소스 아이콘을 사용하여 시간을 단축할 수 있다. 아이콘 미션아이콘이 이상한 경우 가장 추천하는 정리 방법은 Union → Flatten Selection아이콘을 10배 크기로 키워서 픽셀이 어긋난 부분을 화살표를 이용하여 위치를 조절하여 수정해두고 다시 10배 축소 시켜서 정리하면 깔끔하다.입력 컴포넌트 미션Q를 누르면 multi-edit이 가능해서 컴포넌트 편집 시 유용하다.버튼 스택 파트가 추가 되었는데 그 전에 버튼을 각각 만들어서 썼던 경험이 떠올라서 왜 이런 생각을 못했지 싶었다.한 번 컴포넌트를 만들어두면 다음 컴포넌트에서 반복적으로 사용되는 것들이 많다.😊 좋았던 점입력 컴포넌트 미션에서 각 컴포넌트 별로 설명과 만들어야 하는 Type, Style, State 같은 프로퍼티 값이 섹션에 쓰여 있어서 동영상을 보며 놓쳤던 것을 쓰여진 것을 보면서 확인 할 수 있었다.복습임에도 불구하고 내용이 업데이트 되어 새로 강의를 듣는 것과 같았다.전에는 라이브로 진행했던 앤트맨 작전이 강의에 업데이트 되어 복습할 수 있어서 좋았다. 😭 아쉬웠던 점매일매일 조금씩 강의를 듣고 multi-edit을 사용하며 과제를 했는데도 입력 컴포넌트 미션에 시간이 많이 소요되었다. (그래도 보너스 미션까지 완료했다!)이번주에는 미션4와 미션5를 해야하는데 시간이 부족하여 미션4만 수행할 수 있었다. 

UX/UI피그마Figma피그마배리어블

양종문

워밍업 클럽 3기 BE 클린코드&테스트 - 2주차 발자국

Reable Code 강의 요약섹션 6. 코드 다듬기주석의 양면성주석이 많다는 것은, 그만큼 비즈니스 요구사항을 코드에 잘 못 녹였다는 이야기.코드를 설명하는 주석을 쓰면, 코드가 아니라 주석에 의존한다. 주석에 의존하여 코드를 작성하면, 적절하지 않은 추상화 레벨을 갖게 되어 낮은 품질의 코드가 만들어진다.우리가 가진 모든 표현 방법을 총동원해 코드에 의도를 녹여내고, 그럼에도 불구하고 전달해야 할 정보가 남았을 때 사용하는 주석변수와 메서드의 나열 순서변수는 사용하는 순서대로 나열한다.공개 메서드를 상단에 배치하는 것을 선호하는 편.공개 메서드끼리도 기준을 가지고 배치하는 것이 좋다.상태 변경 >> 판별 >= 조회 메서드비공개 메서드는, 공개 메서드에서 언급된 순서대로 배치한다.공통으로 사용하는 메서드라면, (가장 하단과 같은) 적당한 곳에 배치한다.패키지 나누기패키지는, 문맥으로써의 정보를 제공할 수 있다.패키지를 쪼개지 않으면 관리가 어려워진다.패키지를 너무 잘게 쪼개도 마찬가지로 관리가 어려워진다.처음 만들 때부터 잘 고민해서 패키지를 나눠놓는 것이 제일 좋다.IDE의 도움 받기코드 포맷 정렬 (Ctrl + Alt + L)코드 품질 (Sonarlint)포맷 규칙 (.editorconfig)   섹션 7. 리팩토링 연습 스터디 카페 이용권 선택 시스템리팩토링 포인트추상화 레벨객체로 묶어볼만한 것은 없는지객체지향 패러다임에 맞게 객체들이 상호 협력하고 있는지SRP : 책임에 따라 응집도 있게 객체가 잘 나뉘어져 있는지DIP : 의존관계 역전을 적용할만한 곳은 없는지일급 컬렉션리팩토링 한 단계마다, 그 이유를 설명할 수 있어야 한다. 섹션 8. 기억하면 좋은 조언들능동적 읽기복잡하거나 엉망인 코드를 읽고 이해하려 할 때, 리팩토링하면서 읽기공백으로 단락 구분하기메서드와 객체로 추상화 해보기주석으로 이해한 내용 표기하며 읽기핵심 목표는 우리의 도메인 지식을 늘리는 것. 그리고 이전 작성자의 의도를 파악하는 것.오버 엔지니어링필요한 적정 수준보다 더 높은 수준의 엔지니어링은탄환은 없다클린 코드도 은탄환이 아니다.모든 기술과 방법론은 적정 기술의 범위 내에서 사용되어야 한다. 미션 (Day7)지금까지 배운 내용을 기반으로 리팩토링 진행결과: https://github.com/iPhone-design/readable-code/pull/1 과정추상화 레벨 리팩토링Early return 리팩토링DIP 리팩토링 아쉬운점새로운 도메인을 도출하는 과정에서 많은 어려움을 겪었습니다. 도메인 모델을 명확히 정의하고 적절한 개념을 추출하는 작업이 예상보다 복잡하고 까다로워 리팩토링에 많은 시간이 소요되었습니다. 또한, 리팩토링 과정에서 새로운 버그가 유입되거나 기존 기능이 손상되는 등의 부작용도 발생하여 기대만큼 만족스러운 결과를 얻지 못한 점이 아쉬웠습니다. 특히, 도메인을 명확히 정의하고 코드의 책임을 명확히 분리하는 클린 코드의 기본 원칙과 사고방식을 더욱 깊이 이해하고 습관화할 필요가 있다고 생각합니다. 앞으로는 작은 단위로 점진적으로 리팩토링을 진행하고, 자동화된 테스트를 적극적으로 활용하여 코드의 품질과 안정성을 높이도록 노력해야겠다 느꼈습니다.Pratical Testing 강의 요약섹션 2. 테스트는 왜 필요할까?우리가 얻고자 하는 것빠른 피드백자동화안정감테스트 코드를 작성하지 않는다면변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 한다.변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야 한다.빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.테스트 코드가 병목이 된다면프로덕션 코드의 안정성을 제공하기 힘들어진다.테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.잘못된 검증이 이루어질 가능성이 생긴다.올바른 테스트 코드는자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.소프트웨어의 빠른 변화를 지원한다.팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.가까이 보면 느리지만, 멀리 보면 가장 빠르다.테스트는 귀찮다. 귀찮지만 해야 한다. 섹션 3. 단위 테스트단위 테스트작은 코드 단위를 독립적으로 검증하는 테스트검증 속도가 빠르고, 안정적이다.JUnit 5단위 테스트를 위한 테스트 프레임워크AssertJ테스트 코드 작성을 원활하게 돕는 테스트 라이브러리풍부한 API, 메서드 체이닝 지원테스트 케이스 세분화하기암묵적이거나 아직 드러나지 않은 요구사항이 있는가?테스트 케이스 세분화하기 (해피 케이스, 예외 케이스)테스트하기 어려운 영역을 구분하고 분리하기관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터베이스에 기록하기 등 섹션 4. TDD: Test Driven DevelopmentTest Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론실패하는 테스트 작성 > 테스트 통과 최소한의 코딩 > 구현 코드 개선 테스트 통과 유선 기능 구현, 후 테스트 작성테스트 자체의 누락 가능성특정 테스트 케이스만 검증할 가능성잘못된 구현을 다소 늦게 발견할 가능성선 테스트 작성, 후 기능 구현복잡도가 낮은, 테스트 가능한 코드로 구현할 수 있게 한다.쉽게 발견하기 어려운 엣지(Edge) 케이스를 놓치지 않게 해준다.구현에 대한 빠른 피드백을 받을 수 있다.과감한 리팩토링이 가능해진다. 섹션 5. 테스트는 문서다.문서프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.DisplayName을 섬세하게명사의 나열보다 문장으로테스트 행위에 대한 결과까지 기술하기도메인 용어를 사용하여 한층 추상화된 내용을 담기테스트의 현상을 중점으로 기술하지 말 것BDD(Behavior Driven Development) 스타일로 작성하기TDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트케이스(TC) 자체에 집중하여 테스트한다.개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 추상화 수준(레벨)을 권장Given / when / then 발작국 2주차 회고이론으로만 접하고 있었던 부분을 실제 리팩토링 실습을 통해 더욱 피부로 와닿게 느낄 수 있었습니다. 특히, 직접 코드를 개선하는 과정에서 이론과 실무 간의 차이를 명확히 이해할 수 있었고, 클린 코드와 리팩토링의 중요성을 더욱 깊이 깨닫게 되었습니다. 또한 이번 주는 다른 개발자분들의 코드를 함께 리뷰하고 피드백을 주고받는 시간을 통해 다양한 접근법과 사고방식을 경험할 수 있었던 의미 있는 시간이었습니다. 혼자서는 생각하지 못했던 다양한 관점과 해결책을 알게 되었고, 협업을 통한 코드 리뷰의 중요성도 다시금 느끼게 되었습니다. 더불어 두 번째 강의에서 다루었던 테스트 코드의 중요성 또한 다시 한번 상기하게 되었습니다. 리팩토링 과정에서 테스트 코드가 얼마나 중요한 역할을 하는지 실질적으로 체감할 수 있었으며, 앞으로 테스트 코드 작성 능력을 향상시키기 위해 더욱 노력해야겠다는 생각이 들었습니다.

백엔드워밍업클럽

이제

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

2주 차 - 학습했던 내용 요약피그마 베리어블과 스타일 파운데이션 실습을 저번 주차에 이어서 작업했고 이번주는 컴포넌트들을 만드는 법에 대해 배웠t습니다. 목표한 진도까지는 아직 나가지 못해서 다음주에 조금 더 시간내서 과제랑 마무리해보려고 합니다. [주요 내용 복습] [이론📖] 간격 배리어블 이름, 구조 짜기일관성 있는 간격과 유연한 레이아웃을 구축하기 위해 그리드를 사용1.5배수 랜더링 이슈로 주로 8-point grid를 사용함일반적으로 더 작은 단위로 레이아웃을 정렬하고 싶은 경우 4-point grid를 사용함+1.5배수 랜더링 이슈란?1.5배수 렌더링 이슈란?1.5배수는 1픽셀을 1.5배 크기로 변환해야 하는데, 픽셀은 소수점 단위로 정확히 나눌 수 없는 정수 단위의 단위라서 렌더링 시 오류가 발생할 가능성이 높음.✅ 예제:10px 크기의 요소를 1.5배수 스케일로 렌더링 → 10 × 1.5 = 15px하지만 15px을 정확히 2배 또는 3배 해상도에 맞출 수 없음결과적으로 픽셀 보정(Anti-aliasing) 과정에서 모호한 렌더링(Blurry)이 발생그래서 8pt 그리드를 사용하는 이유8pt 그리드는 모든 크기를 8의 배수(8, 16, 24, 32...)로 설정하는 디자인 시스템.8의 배수를 사용하면, 2배수(2x)나 3배수(3x)와 같은 정수 배율에 정확히 맞출 수 있어서 렌더링 오류를 방지 가능!✅ 예제:8px → 2x 스케일 적용 → 8 × 2 = 16px (정확히 나눠짐)8px → 3x 스케일 적용 → 8 × 3 = 24px (정확히 나눠짐)8px → 1.5x 스케일 적용 → 8 × 1.5 = 12px (정수 단위로 맞춰짐)→ 1.5배수에서 발생하는 반올림 문제를 최소화할 수 있음.[이론&실습] 그리드 시스템과 반응형 기준점 설정하기 ✅break pointmobile(320-767)Count4 stretch Margin:16 Gutter: 16{FluidRange: 320-767} tablet(768-1023)Count8 stretch Margin:24 Gutter: 24{fluiderange: 768-1023} laptop(1024-1415)Count12 stretch Margin:24 Gutter: 24{fluiderange:1024-1415} desktop(1424-)Count12 center W:96 Gutter: 24{Fixedrange:1416-} Grid 적용 후 구현 plugin:Layout Grid Visualizer2주 차 - 회고2주 차에는 1주차 내용을 거의 복습하고 마무리했고 컴포넌트 수업도 조금 듣는 정도로 진도를 나갔습니다. 요즘 ai에게 물어보면서 수업을 정리해가고 있는데 더 머리에 잘 들어오고 좋은 것 같아 좋은 것 같은데 진도가 스케쥴 보다는 많이 뒤쳐지고 있는것 같아서 다음주에 조금 더 많이 진행해보려고 합니다. 아직 진행을 많이 못했지만 컴포넌트 실습 부분이 정말 유익한 것 같은데 많이 연습해봐야 할 것 같습니다. +완성된 배리어블을 Variable Print 로 문서화 했는데 완성작의 문서들이랑 조금 다른 것 같아서 다시 복습해봐야 할 것 같습니다. 인프런 워밍업 클럽 스터디 - 후기유익하고 과제일자가 정해져 있으니 확실히 스터디에 속도가 나는 것 같아서 좋은 것 같습니다. 앞으로도 열심히 진행해보려고 합니다.

UX/UIUXUIfigma디자인시스템베리어블

Berry

[인프런 워밍업 클럽 스터디 3기] 프로덕트 디자인 2주 차 발자국

2주 차 강의 회고아쉬웠던 점 / 보완하고 싶은 점 / 다음 주 계획수업과 과제를 더 열심히 해야하는데 그부분이 아쉽습니다. 다음 주에는 학습한 내용을 더 많이 반복하고, 실제 상황에 적용해보는 연습을 할 계획입니다. 이해안가는 부분도 다시 공부하고, 실무에서 어떻게 활용할 수 있을지 구체적으로 생각하며 학습할 예정입니다.2주 차 미션 해결 과정이번 미션에서는 주어진 강의 내용에 따라 컴포넌트 만들기 준비, 라이브러리 세팅, 디스플레이 및 입력 컴포넌트들을 활용한 실습을 진행했습니다. 반복 학습을 통해 더욱 확실하게 이해하였습니다.특히 버튼, 체크박스, 라디오 버튼, 스위치와 같은 기본적인 컴포넌트들을 실제로 사용하면서, 아이콘 등록과 UI 스타일링도 함께 실습한 점이 중요했습니다. 이러한 컴포넌트들은 실제 프로젝트에서 자주 사용되기 때문에, 실제 프로젝트에서 바로 적용할 수 있는 능력을 키우는 데 큰 도움이 되었습니다. 미션을 해결하는 과정에서 강의 내용을 실무에 바로 적용할 수 있도록 학습하는 점이 인상 깊었습니다.이번 주 학습을 통해 실무에서 사용할 수 있는 기술들을 체계적으로 연습했고, 앞으로도 더 깊이 있는 학습을 통해 실력을 쌓아 나갈 예정입니다. 2주 차 주요 학습 내용컴포넌트 만들기 준비: 기본적인 컴포넌트 구조 설계, 라이브러리 세팅입력 컴포넌트: 버튼, 체크박스, 라디오 버튼, 스위치 등디스플레이 컴포넌트: 아바타, 아코디언, 배지, 툴팁, 칩 등실제 활용: UI 요소를 실무에 맞게 커스터마이징하였습니다.이번 주 학습을 바탕으로, 다음 주에도 실무에서 바로 활용할 수 있는 능력을 키우기 위해 꾸준히 실습하고, 더 심화된 내용을 공부할 준비를 하려고 합니다.

UX/UI

jinwoo2511

CS 전공지식 스터디 3기 [2주차] 자료구조와 알고리즘 미션

CS 전공지식 스터디 3기 [2주차] 자료구조와 알고리즘 미션Q. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?A.재귀 함수란 자기 자신을 호출하는 함수를 재귀 함수라고 합니다.문제를 작은 부분으로 나누어 해결하는 방식으로, 주로 반복적인 구조의 문제를 해결할 때 사용됩니다.재귀 함수에서 기저 조건(Base Case)을 만들지 않거나 잘못 설정했을 때 발생하는 문제는무한 루프(무한 재귀 호출) 발생기저 조건이 없으면 함수가 끝없이 자기 자신을 호출하게 되어 스택 오버플로우(Stack Overflow)가 발생합니다.잘못된 결과 반환기저 조건이 부정확하면 예상한 결과를 얻지 못할 수 있습니다.Q. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ // 재귀 로직 } console.log(sumOdd(10)) // 25 A.function sumOdd(n) { if (n <= 0) return 0; // 기저 조건 return (n % 2 === 1 ? n : 0) + sumOdd(n - 1); } console.log(sumOdd(10)); // 25 Q. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(currentDir, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 A.const fs = require("fs"); const path = require("path"); function traverseDirectory(directory) { const files = fs.readdirSync(directory); for (const file of files) { const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectory(filePath); // 재귀 호출 } else { console.log("파일:", filePath); } } } traverseDirectory("."); // 현재 경로의 모든 하위 파일과 디렉토리 출력

주이

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

재귀어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀적으로 정의된 함수 → 재귀함수 콜스택함수가 호출되면서 올라가는 메모리 영역 → 스택이라고도 부름First In Last Outfor문으로 처리할 수 있는 작업을 재귀함수로 처리한다면 더 비효율적인 상황이 생김→ 재귀함수가 더 많은 메모리 공간 차지대신, 재귀함수를 사용하면 처리하기 쉬운 예도 있음. ex) 팩토리얼패턴 1. 단순 반복 실행반복문 구현보다 큰 이점은 없음. 콜스택 공간을 많이 차지해 오히려 성능 저하패턴 2. 하위 문제 결과를 기반으로 현재 문제 계산예) 팩토리얼, 하노이탑for 문을 이용한 계산 - 상향식 계산재귀를 이용해 하위 문제 계산 - 하향식 계산 (상향식도 구현 가능하지만 성능 발휘는 딱히 X)// 재귀를 이용한 상향식 계산 function factorial2(number, i = 1, sum = 1) { if (i > number) return sum; return factorial2(number, i + 1, sum * i); }  정렬 알고리즘버블 정렬(Bubble Sort)앞에 있는 숫자와 옆에 숫자를 비교해서 자리를 바꾸는 알고리즘장점: 이해 및 구현 간단단점: 성능이 좋지 않음성능 - O(n^2)(n-1) + (n-2) + (n-3) … + 2 + 1 → 등차수열n(n-1)/2 → (n^2 - n)/2 선택 정렬(Selection Sort)배열의 정렬되지 않은 영역의 첫 번째 원소를 시작으로 마지막 원소까지 비교 후 가장 작은 값을 첫 번째 원소로 가져옴장점: 이해 및 구현 간단단점: 성능이 좋지 않음성능 - O(n^2)(n-1) + (n-2) + (n-3) … + 2 + 1 → 등차수열n(n-1)/2 → (n^2 - n)/2

인프런 워밍업 클럽 BE-박우빈 클린코드&테스트 2주차 회고

직접 리팩토링 해보기첫 리팩토링은 절망적이었다.강의를 들을 때는 분명 과정들을 이해했고 어떻게 해야하는지 알았다고 생각했다. 하지만 막상 직접 리팩토링 해야할 코드를 마주하니 정말로 머리속이 새하얗게 변했다.나는 지금까지 동영상을 틀어놓고 영혼 없이 타이핑만 했는가? 2주의 시간은 어디로 갔는가.조금 진정하고 왜 이렇게 어려울까 고민해본 결과, 일단 내용이 어려워서는 아닌 것 같다. 들은 설명은 충분히 이해했고 다른 학습에서 본 코드에 적용해볼만하다 생각 했다. 제일 큰 원인은 내가 코드에 아직 익숙하지 않다는 것. 나는 아직 직접 코드를 짜본 경험이 매우 적다. 스스로 생각해서 작성한 코드보다 강의 듣고 따라 타이핑한 코드 양이 훨씬 많다. 직접 짜본 코드도 백지에서 요구사항을 스스로 분석해서 내 마음대로 만들었기 때문에 자유로웠다. 반면 이미 만들어진 코드를 보니 내가 파악하지 못하는 부분들이 많았다. 무슨 요구사항에 의해 이 코드가 작성 된 건지, 어떤 의도로 이런 클래스, 메서드가 생겼는지 직접 코드를 읽고 파악해야하는게 낯설었다. Readable Code, 이 강의의 목표를 다시 한번 느낄 수 있는 순간이었다.여차저차 미션은 제출했지만 만족스러운 학습은 아니었다. 때문에 미션의 피드백인 섹션 7은 잠시 접어뒀다. 리팩토링 부분을 다시 학습하고, 다시 미션을 수행한 다음 남은 강의를 수강해 완주할 예정이다. 테스트 코드테스트 코드 학습이 시작되었다. 테스트의 중요성은 들은 적이 많지만 언제나 뒷전이었다. 여전히 내용은 어렵지 않아 보인다. 이전 실패를 기억해 좀 더 실전적인 것에 집중하여 여러 검증 메서드들을 정리해보고 직접 테스트 코드를 작성해봐야한다.

백엔드

찬우 이

인프런 워밍업 클럽 3기 풀스택 - 2주차 발자국

2주차 학습 내용Part 1 - Git Repository 생성 및 초기 설정 진행create-next-app을 통해 초기 세팅을 했으며,이전에 TODO에서 했던 코드들을 일부 가져와서 빠르게 세팅함. Part 2 - UI 작업알게된 사실 - page.tsx에는 클라이언트 컴포넌트를 사용하면 좋지않다.그 이유는 나중에 메타데이터를 쓰고 하는데 그건 서버 컴포넌트에서만 돌아가기 때문에 피해줘야 한다.나는 평소 flex만 사용하고 grid는 잘 사용하지 않는다. 항상 쓰던것만 써서 그렇기도 하고 grid로 편하게 구현하는 것도 flex로 구현은 가능하기 때문에 그렇게 했다. 강의에서는 grid를 사용했고 디테일하진 않지만 간단하게 3단계로 반응형도 쉽게 구현되는 모습을 보고 grid를 다시보게 됨className="grid md:grid-cols-3 lg:grid-cols-4 grid-cols-2"그 이후로는 컴포넌트 별로 분리해서 퍼블리싱 작업을 구현했다. Part 3 - 파일 업로드 구현(Supabase Storage) 사진을 업로드 하는데 알 수 없는 에러가 있었고, 분명 코드도 다른부분이 없는데 문제가 생겨서 오랫동안 붙잡고 있었다.원인은 사진이름이 한글로된 경우 안되는 부분이였고, 잠시 오류 수정으로 고쳐서 한글이름으로 된 사진도 업로드가 가능하게 했다. 하지만 한글이름이 아닌 a__a__a같은 이름으로 저장되는 문제가 발생해서 이 문제는 추후 고쳐봐야 할 문제 같다.// actions/storageActions.ts function sanitizeFileName(fileName: string) { return fileName .normalize("NFKD") // 유니코드 정규화 .replace(/[^\w.-]/g, "_") // 특수 문자 제거 .replace(/\s+/g, "_") // 공백을 `_`로 변경 .toLowerCase(); // 소문자로 변환 } export async function uploadFile(formData: FormData) { const supabase = await createServerSupabaseClient(); const file = formData.get("file") as File | null; if (!file) { console.error("❌ 업로드할 파일이 없습니다."); throw new Error("파일이 없습니다."); } // 파일 이름을 안전한 형식으로 변환 const safeFileName = sanitizeFileName(file.name); console.log("✅ 변환된 파일 이름:", safeFileName); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET!) .upload(safeFileName, file, { upsert: true }); if (error) { console.error("❌ Supabase 업로드 실패:", error.message); throw new Error(error.message); } return data; }  Part 4 - 파일제거 구현, Darg & Drop, 멀티파일 업로드 구현Darg & Drop을 위해 설치해줌.  npm i --save react-dropzone이번주 미션 - 파일의 마지막 수정(업로드) 시간을 표시하는 기능을 추가하기!// components/dropbox-image.tsx <div>생성일: {formatDate(image.updated_at)}</div> 간단하게 이 부분 넣어서 해결함. 미션 이외로...- 강사님과 같은 코드로 하니까 생긴 에러가 있어서 코드를 약간 수정함.수정한 부분은 actions/storageActions.ts 의 uploadFile 부분임1⃣ 파일 필터링 (undefined 값 제거)✅ 첫 번째 코드 (위 코드) → undefined 또는 잘못된 파일 제거const files = Array.from(formData.entries()) .map(([name, file]) => file as File) .filter((file) => file instanceof File && file.name); // ✅ undefined 제거 filter()를 사용하여 undefined 또는 비정상적인 파일을 제거파일이 null이거나 undefined면 upload()에서 에러 발생 가능성이 있음 → 이를 방지❌ 두 번째 코드 (아래 코드) → 필터링 없음const files = Array.from(formData.entries()).map(([name, file]) => file as File); undefined 파일이 포함될 가능성이 있음 → 업로드 시 오류 발생 가능 2⃣ 파일명 변환 (sanitizeFileName)✅ 첫 번째 코드 (위 코드) → 파일명 변환 추가function sanitizeFileName(fileName: string) { return fileName .normalize("NFC") // ✅ 한글 깨짐 방지 .replace(/[^a-zA-Z0-9ㄱ-ㅎㅏ-ㅣ가-힣_.-]/g, "_"); // ✅ 특수 문자 제거 } const safeFileName = sanitizeFileName(file.name); 특수 문자, 공백 제거 (file.name을 정리)한글 깨짐 방지 (NFC 정규화)→ Supabase는 일부 특수 문자나 공백이 포함된 파일명을 허용하지 않으므로 안정적❌ 두 번째 코드 (아래 코드) → 원본 파일명 그대로 사용supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(file.name, file, { upsert: true }); 파일명을 그대로 사용하기 때문에, 특수 문자나 공백이 포함되면 Supabase에서 오류 발생 가능 3⃣ async 처리 및 오류 핸들링✅ 첫 번째 코드 (위 코드) → async 사용 및 오류 처리const results = await Promise.all( files.map(async (file) => { // ✅ async 사용 const safeFileName = sanitizeFileName(file.name); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(safeFileName, file, { upsert: true }); if (error) { // ✅ 오류 처리 console.error("❌ Supabase 업로드 실패:", error.message); throw new Error(error.message); } return data; }) ); 각 파일 업로드가 비동기(async)로 처리됨오류 발생 시 console.error로 출력하고 예외 처리각 파일 업로드 후 결과(data) 반환❌ 두 번째 코드 (아래 코드) → 오류 핸들링 없음const results = await Promise.all( files.map((file) => supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(file.name, file, { upsert: true }) ) ); async 키워드 없이 바로 upload() 실행오류가 발생해도 catch되지 않으며, 전체 업로드가 실패할 가능성이 있음업로드 성공 여부를 확인할 방법 없음 (data를 반환하지 않음)  2주차 회고 2주차에는 중간점검을 하는 시간을 가졌다. 수강생들이 하고 싶었던 질문을 하나하나 답변해주시는 시간을 가져서 꽤 유용한 시간이였고, 더 열심히 하자는 마음을 다지는 계기가 되었다.첫주때보단 수퍼베이스에 적응을 하는거같다. 아직 친해지기에는 시간이 더 많이 필요할꺼 같긴한데 정처기 준비하고 CS 스터디 하고, 다른 프젝도 마무리 하고, 매일 알고리즘 문제도 풀고 있다보니 시간이 많이 부족한 것 같다.중간점검때 강사님께서 시간관리에 대한 얘기도 했었는데, 매우 동감하는 부분...시간 관리나 스케줄 관리를 잘 해야 할 것 같다.. 의욕만 앞서서 살짝 망하는거 같기도함.그래도 뭐 흥미있고 재미있으니까 만족한다.

풀스택풀스택미션인프런워밍업클럽supabasenext.js

jinwoo2511

CS 전공지식 스터디 3기 [2주차] 운영체제 미션

CS 전공지식 스터디 3기 [2주차] 운영체제 미션Q. FIFO 스케줄링의 장단점이 뭔가요?A.FIFO(First In, First Out) 스케줄링은 먼저 도착한 프로세스가 먼저 실행되는 방식의 스케줄링 알고리즘입니다.이는 큐(Queue) 구조를 사용하며, 도착한 순서대로 실행되기 때문에 공평하지만 비효율적인 경우가 발생할 수 있습니다. 장점:공정성: 먼저 도착한 프로세스를 먼저 처리하기 때문에 기아(Starvation) 현상이 발생하지 않음간단한 구현: 큐(Queue) 자료구조를 사용하여 구현이 간단함비선점(Non-Preemptive) 방식: 한 프로세스가 CPU를 점유하면 끝날 때까지 다른 프로세스가 실행되지 않음단점:긴 작업이 먼저 도착하면 대기 시간이 증가예를 들어, 긴 실행 시간을 가진 프로세스가 먼저 들어오면 뒤의 짧은 프로세스들이 오래 대기해야 함이를 Convoy Effect(호위 효과)라고 부름 응답 시간이 일정하지 않음짧은 작업이 있어도 먼저 도착한 긴 작업이 끝날 때까지 기다려야 함 FIFO 스케줄링 수행 과정P1 → P2 → P3 순서로 실행됨P1이 먼저 CPU를 점유하고 끝날 때까지 P2와 P3는 기다려야 함 Q. SJF를 사용하기 여러운 이유가 뭔가요?A.SJF(Shortest Job First) 스케줄링은 CPU 실행 시간이 가장 짧은 프로세스를 먼저 실행하는 방식입니다.즉, Burst Time(실행 시간)이 짧은 순서대로 프로세스를 실행하기 때문에 평균 대기 시간(AWT)이 최소화되는 장점이 있습니다. SJF 스케줄링의 종류비선점형 SJF (Non-Preemptive SJF)실행 중인 프로세스가 끝날 때까지 CPU를 점유 (중간에 빼앗기지 않음) 선점형 SJF (Preemptive SJF, SRTF: Shortest Remaining Time First)새로운 프로세스가 도착하면 현재 실행 중인 프로세스와 실행 시간을 비교하여 더 짧은 실행 시간이 남은 프로세스가 있으면 CPU를 빼앗김 실행 순서먼저 도착한 P1 실행 (7ms)다음으로 P3 실행 (1ms)P2 실행 (4ms)마지막으로 P4 실행 (4ms)SJF를 사용하기 어려운 이유실행 시간이 가장 짧은 작업을 먼저 실행해야 하는데, 프로세스의 CPU Burst Time(실행 시간)을 정확히 예측하기 어렵습니다.I/O Bound 프로세스와 CPU Bound 프로세스를 구분하기 쉽지 않습니다.비선점(Non-Preemptive) 방식이라 실시간 시스템에 적합하지 않을 수 있습니다. Q. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?A.RR(Round Robin) 스케줄링은 각 프로세스가 일정한 시간(Time Quantum) 동안만 실행되며, 시간이 지나면 다음 프로세스로 넘어가는 방식입니다.즉, 모든 프로세스가 공평하게 CPU를 사용할 수 있도록 설계된 선점형(Preemptive) 방식입니다.RR스케줄링의 타임 슬라이스가 아주 작으면 아래와 같은 문제가 발생합니다.Context Switching 증가:타임 슬라이스가 너무 작으면 프로세스가 자주 CPU에서 교체되므로 컨텍스트 스위칭(Context Switching) 비용이 증가하여 오버헤드가 커진다.CPU 사용률 저하:CPU가 실제 작업을 수행하는 시간보다 문맥 전환(Context Switching) 처리에 더 많은 시간을 사용하게 되어 효율성이 떨어진다.하지만 RR 스케줄링은 모든 프로세스가 공평하게 실행되고, 응답 시간이 빨라서 실시간 시스템에 적합하다는 장점이 있습니다. Q. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?A.MLFQ(Multi-Level Feedback Queue, 다단계 피드백 큐) 스케줄링은 여러 개의 큐를 사용하여 프로세스를 우선순위별로 분류하고, 프로세스의 실행 시간이나 행동 패턴에 따라 다른 큐로 이동시키는 방식입니다.즉, CPU 사용 시간에 따라 우선순위가 조정되며, 프로세스가 낮은 우선순위로 이동할 수도 있고 다시 높은 우선순위로 복귀할 수도 있는 유동적인 스케줄링 방식입니다.운영체제는 프로세스의 행동 패턴을 기반으로 CPU Bound Process와 I/O Bound Process를 구분합니다.CPU Bound Process:CPU를 오래 사용하는 프로세스계산량이 많고, 연산이 많은 작업 (예: 영상 처리, 데이터 분석)CPU를 길게 사용하여 타임 퀀텀을 초과하면 하위 큐로 이동 I/O Bound Process:I/O 작업(디스크 접근, 네트워크 요청 등)이 잦은 프로세스키보드 입력, 파일 읽기 등의 작업이 많음 (예: 웹 브라우저, 텍스트 편집기)자주 I/O 요청을 하면 다시 상위 큐로 이동즉 운영체제는 프로세스가 얼마나 자주 I/O 요청을 하는지 모니터링하며 CPU Bound와 I/O Bound를 자동으로 구분합니다.Q. 공유자원이란무엇인가요?A.공유 자원이란 여러 개의 프로세스가 동시에 접근할 수 있는 자원을 의미합니다.예시:메모리 (공유 메모리 영역)파일 시스템 (파일 접근)프린터, 네트워크 소켓 등 Q. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야 할까요?A.교착 상태는 4가지 조건을 모두 만족해야 교착 상태에 빠지게 됩니다.아래 4가지 중 한가지라도 만족하지 않는다면, 교착 상태에 빠지지 않게 됩니다.교착 상태 4가지 조건상호 배제 (Mutual Exclusion):한 번에 하나의 프로세스만 자원을 사용할 수 있어야 한다.점유와 대기 (Hold and Wait):하나의 자원을 점유한 프로세스가 다른 자원을 기다리는 상태여야 한다.비선점 (No Preemption):프로세스가 강제로 자원을 빼앗기지 않는다.순환 대기 (Circular Wait):프로세스들이 원형(사이클)으로 자원을 서로 점유하고 대기한다.

[인프런 워밍업 클럽 3기 / 백엔드 프로젝트] 1주차 발자국

1.강의 요약1.개요이번주는 컨트롤러, 서비스, 리포지토리, DTO설계와 개발 테스트 그리고 Thymeleaf를 중점으로 공부했던 시간을 가졌다. 2.이번에 배운 내용들@Controller용도: 컴포넌트 스캔 대상이 되어 빈으로 등록되며, 주로 서버 사이드 렌더링(SSR) 방식에서 사용특징: 리턴된 문자열과 동일한 이름의 HTML 템플릿 파일을 찾아 클라이언트에 응답한다@RestController용도: 컴포넌트 스캔 대상이 되어 빈으로 등록되며, 클라이언트 사이드 렌더링(CSR) 또는 API 개발 시 사용특징: 리턴 값이 HTTP 응답 본문에 직접 포함되며, String 이외의 객체는 JSON 등으로 자동 변환@RequestMapping용도: 클래스 또는 메소드에 붙여 HTTP 요청 경로를 지정특징: 클래스에 적용 시 해당 클래스의 모든 메소드에 기본 경로가 붙으며, 메소드 단위로 세부 경로와 HTTP 메서드를 설정할 수 있음@GetMapping용도: HTTP GET 요청에 대한 처리를 명시특징: @RequestMapping(method = RequestMethod.GET)과 동일하게 동작하며, 특정 경로에 GET 요청이 왔을 때 해당 메서드가 실행 @Service용도: 비즈니스 로직을 담당하는 서비스 레이어의 클래스에 사용특징: 빈으로 등록되어 컨트롤러와 리포지토리 사이의 중재자 역할을 수행@Repository용도: 데이터 접근 계층의 클래스를 지정하는 어노테이션특징: 데이터베이스 관련 작업을 수행하며, 컴포넌트 스캔을 통해 빈으로 등록@Component용도: 특별한 역할 분류 없이 범용적으로 사용되는 빈을 등록할 때 사용@Transactional 용도: 트랜잭션을 자동으로 시작하고 종료하며, 예외 발생 시 롤백할 대상을 지정할 수 있음특징: readOnly, rollbackFor, isolation 등의 속성을 통해 트랜잭션의 세부 동작을 설정할 수 있음@ExtendWith용도: JUnit 5에서 테스트 확장을 지원하기 위한 어노테이션@InjectMocks / @Mock용도: Mockito를 사용한 단위 테스트에서 대상 클래스에 필요한 의존성을 주입하거나 모의 객체를 생성할 때 사용@SpringBootTest용도: Spring Boot 애플리케이션의 전체 컨텍스트를 로드하여 통합 테스트를 실행할 때 사용@AutoConfigureMockMVC용도: Spring MVC를 모의 테스트할 수 있도록 MockMVC 객체를 자동 구성  2.미션이번주는 REST API 설계를 했다. https://github.com/Seunggyo/GameReviewHub/commit/95871575bcd3f9680b6089401de86df43e4abe9b  처음으로 원칙을 두고 API를 설계하다보니 어려움을 많이 느꼈지만 노력해보는 시간을 가져보았다. 

백엔드

찬우 이

인프런 워밍업 클럽 3기 CS - 2주차 미션

2주차 학습 내용 - 미션자료구조 & 알고리즘 1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저조건을 만들지 않으면 함수가 계속 실행되서 콜스택이 메모리에 쌓이게 되고, 각자의 메모리 용량에 따라 다르겠지만 메모리끝에 다다르게 되면 실행이 종료된다. 그것을 스택 오버플로우 오류라고 한다. 2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n) { if (n % 2 !== 0) { // 홀수가 되는 경우 return n + sumOdd(n - 1); } else if (n === 0) { // 종료가 되는 경우 return 0; } else { // 짝수가 되는 경우 return sumOdd(n - 1); } } console.log(sumOdd(10)); // 25이 방법이 100점짜리 정답인지는 모르겠지만 우선 sumOdd 값에 다른 수를 넣어도 홀수의 합만 뽑아서 더하고 있다.로직은 3가지의 조건으로 나뉘고 있다.n이 홀수인경우 n을 더하고 n-1한 sumOdd 함수를 재호출n이 0인경우 0을 리턴하며 종료n이 짝수인 경우 n을 더하지는 않고 n-1한 sumOdd 함수를 재호출이로써 sumOdd(10)을 할 경우 25(1+3+5+7+9)라는 값이 나오게 됨. 3. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectoryRecursive(directory) { const files = readdirSync(directory); // 현재 디렉토리의 파일 및 폴더 가져오기 for (const file of files) { const filePath = join(directory, file); const fileStatus = statSync(filePath); if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectoryRecursive(filePath); // 🔥 폴더라면 재귀 호출 (스택 역할) } else { console.log("파일:", filePath); } } } traverseDirectoryRecursive(".")이 문제의 경우 솔직히 너무 힘들었음..... (나한텐 어려워😐)gpt.. 의 힘을 빌려 성공하긴 했지만 이 코드를 봐도 이해하기 힘들어서 재귀가 눈에 익게 자주 문제를 풀어보고 생각해야할 것 같다. ✅ 재귀 함수 정의function traverseDirectoryRecursive(directory) { const files = readdirSync(directory); // 현재 디렉토리의 파일 및 폴더 목록 가져오기 traverseDirectoryRecursive(directory):directory를 입력받아 해당 폴더 내의 파일과 폴더를 탐색하는 함수readdirSync(directory):해당 디렉토리 안에 있는 파일/폴더 목록을 배열로 반환✅ for문을 사용하여 모든 파일 및 폴더를 탐색 for (const file of files) { const filePath = join(directory, file); // 전체 경로 생성 const fileStatus = statSync(filePath); // 파일 정보 가져오기 for (const file of files):files 배열 안의 파일 또는 폴더를 하나씩 순회join(directory, file):현재 디렉토리 경로 + 파일 이름을 합쳐서 파일의 전체 경로 생성statSync(filePath):해당 경로가 파일인지 폴더인지 확인할 수 있는 정보 가져오기✅ 폴더인 경우 재귀 호출 if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectoryRecursive(filePath); // 🔁 재귀 호출하여 하위 폴더 탐색 } else { console.log("파일:", filePath); } } ✔ 폴더인 경우 (fileStatus.isDirectory())"디렉토리: [폴더 경로]"를 출력재귀적으로(traverseDirectoryRecursive(filePath)) 다시 탐색 → DFS(깊이 우선 탐색) 방식✔ 파일인 경우"파일: [파일 경로]"를 출력하고 다음 파일로 넘어감✅ 함수 실행 (탐색 시작)traverseDirectoryRecursive("."); // 현재 디렉토리부터 탐색 시작 "."는 현재 실행 중인 디렉토리를 의미현재 디렉토리부터 재귀적으로 모든 파일과 폴더를 탐색운영체제 1. FIFO 스케줄링의 장단점이 뭔가요?FIFO 스케줄링의 로직은 큐에 들어온 순서대로 CPU를 할당받는 방식이다.장점으로는 단순하고 직관적이라는 점단점으로는 한 프로세스가 완전히 끝나야 다음 프로세스를 실행하기 때문에 앞의 프로세스에서 시간이 지연될수록 뒤에 있는 프로세스는 너무 지연되기 때문에 효율성을 따지면 문제가 생김.2. SJF를 사용하기 여러운 이유가 뭔가요?SJF는 Burst Time이 짧은 순서대로 실행하는 로직이다.이론적으로 생각하면 짧은 순서대로 치기때문에 크게 지연되서 생길 문제도 줄어들긴 하지만,2가지 문제점이 발생하게 된다.첫째는 어떤 프로세스가 얼마나 실행될지 알 수 없다는 점.둘째는 Burst Time이 긴 프로세스는 오랜시간동안 실행되지 않을 수 있다는 점.결과적으로 이런 문제때문에 SFJ 알고리즘은 사용되지 않는다. 3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?RR 스케줄링은 모든 프로세스에게 공평하게 CPU 시간을 할당해주는 방식으로 돌아가는 로직이다.RR프로세스의 단점중 타임 슬라이스를 너무 짧게 부여하게 되면, 다른 프로세스로 전환하는 과정인 컨텍스트 스위칭이 자주 일어나게 되어 불필요한 처리가 늘어난다는 것이다. 그래서 너무 길지도 짧지도 않은 적정선을 찾아서 지정해줘야 한다. 4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?현대 운영체제에서 가장 일반적으로 쓰이는 방식.CPU Bound Process 와 I/O Bound Process에게 자신에게 맞는 타임 슬라이스를 부여해야하기 때문에 구분을 해야한다.구분하는 방법은 CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 CPU 사용이 적은 것이기 때문 에 I/O 바운드라고 예상할 수 있고, 프로세스가 타임 슬라이스 크기를 오버해서 CPU에게 강제로 뺏기면 CPU 바운드라고 예상 할 수 있다. 5. 공유자원이란무엇인가요?공유자원이란 프로세스 간의 통신을 위해 공동으로 사용하는 변수나 파일, 장치 등을 의미한다. 6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착상태란 여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태이다.교착상태가 발생되는 원인으로는 공유자원을 사용하기 때문이다.교착상태가 발생하기 위해서는 4가지중 하나라도 해당된다면 발생한다.1. 상호배제: A프로세스가 A리소스를 차지한다면, 다른 프로세스에게 공유되면 안된다.2. 비선점: A프로세스가 A리소스를 차지하고 있을때, 프로세스B가 A리소스를 빼앗을 수 없다야 한다.3. 점유와 대기: A프로세스가 리소스A를 차지한 상태에서 리소스B를 원하는 상태여야 한다.4. 원형 대기: 서로가 서로의 리소스를 원하는 경우가 해당하지만 이 4가지 규칙을 지켜도 예방하기란 쉽지 않았고, 결국 교착상태에 빠졌을 경우 해결하는 방법에 대해 연구하게 된다.

알고리즘 · 자료구조자료구조알고리즘운영체제미션인프런워밍업클럽CS

박소윤

[워밍업 클럽 3기 Backend 클린코드 & 테스트코드] 두 발자국 👣

이 글은 박우빈 강사님의 Readable Code: 읽기 좋은 코드를 작성하는 사고법 강의를 기반으로 인프런에서 진행하는 [워밍업 클럽 3기] Backend 클린 코드 & 테스트 코드 스터디 회고록입니다.아래 학습 내용은 박우빈 강사님의 Readable Code: 읽기 좋은 코드를 작성하는 사고법 강의를 듣고 학습한 내용입니다.저작권 보호를 위해 강의 내용보다는 학습하면서 느낀 점 위주로 정리하였습니다. 2주차는 아쉬움이 많이 남는 한 주였다. ✏2주차 학습 내용2주차에 학습한 내용은 크게 네 가지로 나눌 수 있을 것 같다.1⃣ 코드 다듬기Section 6에서는 코드 다듬기에 대해 학습하였다.코드 다듬기와 관련된 내용은 항상 궁금했지만, 너무 사소한 것 같아 어디에 물어보기가 어려웠다. 그런데 이번 강의에서 그런 부분들이 다뤄져서 무척 유익했다.특히, 변수와 메서드 나열 순서에 대한 강의가 가장 기억에 남는다. 변수의 경우, 나는 항상 사용하는 순서대로 나열해왔기 때문에 비교적 괜찮았지만, 메서드 나열 순서는 평소 내가 작성하던 방식과 차이가 있었다.강의에서는 두 가지 예시를 들었는데, 나는 그중 첫 번째 예시(public-private-private / public-private)와 비슷한 방식으로 메서드를 정리해왔다. 그렇게 하는 것이 가독성에 더 좋다고 판단했기 때문이다. 하지만 강의를 듣고 나니, 내가 작성한 방식은 코드를 작성한 사람에게는 가독성이 좋을 수 있지만, 처음 보는 사람에게는 그렇지 않을 수도 있겠구나 하는 생각이 들었다.아직 대규모의 코드를 작성해 본 경험이 부족해서, 이런 차이를 체감하지 못했던 것일 수도 있다. 앞으로도 이 부분에 대해 더 고민해보고, 실제 프로젝트에서 적용해 보며 경험을 쌓아야겠다고 생각했다.2⃣ 리팩토링 실습화요일에는 미션 7을 통해 실제 코드를 리팩토링하는 경험을 해보았다.강의를 보면서 따라할 때는 강사님의 사고를 그대로 따라갈 수 있어 어려운 점이 없었지만, 막상 혼자서 리팩토링을 해보려니 예상보다 훨씬 어려웠다.가장 먼저 부딪힌 문제는 다른 사람이 작성한 코드를 읽고 이해하는 데 걸리는 시간이었다. 지금까지는 내가 작성한 코드만 읽고 리팩토링해왔기 때문에, 처음 보는 코드의 구조를 파악하는 일이 생각보다 쉽지 않았다.또한, 가장 최선의 답을 찾아야 한다는 점도 어려웠다. 리팩토링에는 정답이 존재하는 것이 아니라, 주어진 상황에서 최적의 해결책을 찾는 과정이기 때문에 더 고민이 많아졌다.객체의 책임을 적절히 나누는 것도 쉽지 않았다. 객체의 책임이 명확하게 하나로 분리된 것인지를 판단하는 것부터가 어렵게 느껴졌다. 게다가, SOLID 원칙에 맞게 코드가 잘 설계되었는지 파악하는 과정조차도 쉽지 않았다.강의를 들으며 실습할 때는 리팩토링이 생각보다 어렵지 않다고 착각했지만, 실제로 혼자 진행해보니 엄청난 연습이 필요하다는 걸 절실히 깨달았다.무엇보다도, 리팩토링을 잘하기 위해서는 먼저 다른 사람의 코드를 읽는 능력부터 길러야겠다고 다짐한 시간이었다.3⃣ 중간 점검금요일에는 약 2시간 동안 중간 점검 라이브를 진행했다.코드 리뷰를 신청해보고 싶었지만, 아직 다른 사람들 앞에서 내 코드를 공개할 자신이 없어 망설이다가 기회를 놓치고 말았다. 그 점이 많이 아쉬웠지만, 대신 다른 사람들의 코드 리뷰를 보며 설명을 듣는 것만으로도 큰 도움이 되었다.이번 라이브는 좋은 배움의 기회가 되었고, 다음에는 꼭 용기를 내어 코드 리뷰를 직접 신청해봐야겠다고 다짐했다.4⃣ 자바 기반의 테스트 코드학부생 때부터 연구실에서 프로젝트를 진행할 때 테스트 코드를 작성하고, 요구사항에 대한 테스트를 항상 진행해왔다. 덕분에 테스트 코드의 필요성에 대해서는 늘 인식하고 있었지만, Junit과 같은 자동화된 도구를 사용하지 않고 수동 테스트만 진행해왔다.그렇다 보니 테스트 도구를 배워야겠다는 필요성을 계속 느끼면서도, 제대로 공부할 기회가 없었다. 하지만 이번 스터디를 통해 마침내 테스트 도구를 배울 수 있어서 정말 좋은 경험이 되었다. 📜미션이번 주는 Day 7에 미션을 수행했다. 미션에 관련한 내용은 아래 링크에서 확인할 수 있다.Mission 3 | Day 7MISSION 3https://github.com/ParkSoyun/inflearn-pwb-readable-code/pull/1 👍Keep: 잘한 점이번 주는 전체적으로 아쉬움이 많이 남는 한 주였다.그럼에도 불구하고, 좋지 않은 컨디션 속에서도 해야 할 일들을 포기하지 않고 끝까지 수행했다는 점은 스스로 칭찬해주고 싶다.👎Problem: 개선이 필요한 점컨디션이 좋지 않은 상태에서 무리하다 보니 한 주 내내 몸이 아팠고, 결국 완주를 위해 꼭 필요한 최소한의 일만 수행할 수밖에 없었다는 점이 아쉽다.다행히 주말 동안 충분히 휴식을 취하며 컨디션을 회복했으니, 다음 주부터는 다시 집중해서 달려야겠다.🤙Try: 더 나은 결과를 위해 시도할 점이번 주를 통해 컨디션 관리가 가장 중요하다는 것을 절실히 깨달았다. 앞으로는 몸 상태를 잘 살피면서 최선을 다해야겠다는 다짐을 했다.또한, 월요일 미션을 빠르게 마친 후 코드 리뷰를 신청하는 것을 목표로 삼았다. 사실 아직 다른 사람들 앞에서 내 코드를 공개하는 것이 부끄럽지만, 이번 중간 점검 때 다른 사람의 코드를 보는 것만으로도 큰 도움이 되었다. 그렇다면 내 코드로 직접 리뷰를 받으면 더욱 많은 인사이트를 얻을 수 있지 않을까?조금 더 용기를 내서 이번 미션에서는 코드 리뷰를 꼭 신청해봐야겠다.

개발 · 프로그래밍 기타워밍업클럽워밍업클럽3기

gptjddl777

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

[학습내용]섹션3. 고객에 대한 전문성 쌓기#Chapter1. 고객 전문가가 되기 위한 유일한 방법 : 고객 직접 만나기고객을 직접 만남으로써 얻을 수 있는 6가지고객이 어떤 맥락에서 어떤 경험을 하고, 어떤 생각과 감정을 느끼는지 중요한 정보를 얻을 수 있음 (중간 매개자를 통해 전달 받으면 이런 것들이 생략됨 → 고객을 직접 만나 소통하는 것이 중요)우리가 고객을 얼마나 몰랐는지 자각할 수 있음고객에 대한 더 정확하고 좋은 멘탈모델(mental model)을 가질 수 있음 (*멘탈모델 : 고객에 대한 상(이미지) )고객의 문제를 더 잘 알게 되어 질적인 아이디어를 얻을 수 있음재미와 보람PM으로서의 전문성 축적 (고객을 만나 본 적 없는 PM/PO와의 차별성) 안티패턴 6가지 1. 바빠서 고객을 만나지 못함2. 고객에게 안좋은 피드백을 듣거나, 인터뷰하는 방법을 몰라서 고객을 만나는 것을 두려워함3. 다른 조직 (영업, CS)에서 전달 받는 것에 의존함4. 내부직원을 고객이라고 착각 함5. 가깝고 편한 고객들만 만남 (목적에 맞는 리크루팅을 하지 않음)6. 고객만나기 = 연례행사, 프로젝트 처럼 1회성으로 한번 하고 마는것 (꾸준히 고객을 만나고 제품을 검증해야 함)PM의 필수 고객조사 → 1:1 심층 인터뷰, 사용성테스트#Chapter2. 고객 리서치 설계 방법목적 설정이 중요리서치의 목적 : 더 나은 의사결정을 하기 위해서의사결정을 위한 리서치 설계 1) 해야 할 의사결정 정의하기 2) 알아야 하는데 모르는 것 정의하기 3) 적합한 리서치 방법 계획하기 4) 리서치 수행계획 구체화 하기#Chapter3. PM이 고객을 파악하는 가장 강력한 도구 1. 심층 인터뷰 하는 법심층 인터뷰를 통해 얻을 수 있는 정보심층 인터뷰 활용 상황심층 인터뷰의 한계점심층 인터뷰 적정 인원 수립은? → 10명에서 시작 새로운 정보를 계속 얻는다면 계속해서 진행  인터뷰 설계하기 사업 질문우리 사업이 이뤄야 하는 중요한 목표사업에서 해결해야 하는 중요한 문제와 관련해서 답을 찾고 싶은 질문 예) 어떻게 하면 고객 이탈을 줄일 수 있을까?사업에서 해결해야 하는 문제에 따라서 리서치도 달라져야 함사업 질문을 명확히 정의하지 않으면 모든 질문을 욱여 넣는 실수 발생리서치 질문사업에서 문제를 해결하고 목표를 달성하기 위해 우리가 리서치에서 답을 얻어내고자 하는 질문인터뷰 질문리서치 질문에 답을 얻기 위해 인터뷰에서 실제로 하는 질문인터뷰 질문 설계의 기술 : 기본 원칙들 & 다양한 질문들 1) 인터뷰 기본 규칙2) 다양한 질문들 (다양한 유형의 인터뷰 질문들 참고) 원하는 정보를 얻어내기 위해 다각도로 질문하는 것이 중요인터뷰 대상자 : 목적에 맞게 선정하기 1) 인터뷰 목적에 맞는 대상자 조건 설정2) 우리 고객중에서 대상자 섭외하기 : 데이터로 필터링3) 섭외 대상자에게 인터뷰 요청하기4) 사전 설문으로 필터링 하기인터뷰 가이드 작성하기인터뷰 가이드 = 인터뷰 계획문서: 인터뷰 질문 + 인터뷰에서 해야 할 모든 일을 계획한 문서인터뷰 결과 종합1) 고객 인터뷰 내용, 자료와 친숙해지기2) 고객 답변을 유형화 하기3) 여러 인터뷰에서 테마(=패턴) 찾기 인터뷰 결과를 사업에 반영하기인터뷰에서 드러난 중요한, 많은 사람들이 겪는 문제들을 주요 과제로 삼는다인터뷰에서 나온 내용을 의사결정의 근거로 활용한다#Chapter4. PM이 고객을 파악하는 가장 강력한 도구 2. 사용성 테스트사용성 테스트 하는 법우리 제품을 사용할 수 있나? 우리 제품을 이해할 수 있나? (우리 제품이 뭘 해 주는 제품인지?, 이용해서 뭘 할 수 있는지 이해할 수 있어야 ) (사용성이 좋은 제품 : 유저들이 올바른 멘탈 모델을 쉽게 형성) 기능을 발견할 수 있는가?사용성 테스트는 언제 하나?새로운 제품이나 기능을 만들떄앱 리디자인기존 기능 개선할 때어느 시점에 하면 좋을까?가능하면 일찍 (매몰 비용 최소화를 위해)단, 구체적인 유저 인터페이스, 인터랙션 디자인이 갖춰진 상태에서 (→ 사용자들이 실제로 손에 쥐고 경험할 것이 있을때)몇 명을 테스트하면 좋을까?어림법칙 : 5명을 테스트하면 충분하다.단, 5명 보다 더 필요한 경우 → 한 제품을 2개 이상의 서로 다른 유저 그룹이 이용하는 경우 예) 피그마 : 디자이너, pm, 엔지니어들이 다른 용도로 사용사용성 테스트 실행 방법task 를 주고 사용성 확인해보기 (task 시나리오 ) 질문하기task 관련 질문테스트 장소 : 다양한 방식 가능오프라인 , 원격, 실시간으로 만나지 않고도 수행 가능녹화 할 것 [학습회고]PM/PO 관련된 다른 강의에서는 들어보지 못한 내용이라 새로웠고 고객 인터뷰 설계를 굉장히 전략적으로 세심하게 준비해야 한다는 것을 알 수 있었다. PM이 되어 고객 인터뷰, 사용성 테스트를 진행해야 하는 상황이 생겼을 때 굉장히 많은 도움이 될 것 같다. 단순히 어떻게 설계해야 하는지 방법론 뿐만이 아니라 어떠한 이유로 고객을 만나야 하는지 고객 리서치를 하기 위한 목적은 무엇인지에 대한 내용을 함께 다루고 있어 PM으로서의 역할과 전문성에 대한 인사이트를 얻을 수 있었다.  [미션회고]프로덕트를 선정하는 것부터 막막하다 보니 어떤 의사결정을 위한 고객 리서치를 할 것인가에 대한 계획을 세우는 것도 잘 떠오르지 않았다. 리서치 목적이 명확하지 않다보니 구체적인 계획을 세워나가는 것도 어려웠고 처음으로 고객 인터뷰 질문을 짜는 것이다 보니 질문이 많이 떠오르지 않았다. 강의를 들었을 때는 만약 실무를 하게 된다면 순서대로 착착 진행할 수 있을 것만 같았는데 미션으로 해보니 정말 쉽지 않았다. PM이 수행하는 업무, 역할은 정말 많은 것 같다

기획 · PM· POPMPO

jinwoo2511

인프런 워밍업 클럽 스터디 3기 - CS 전공지식 <2주차 발자국>

'그림으로 쉽게 배우는 운영체제 2주차'[섹션 04]프로세스 동기화CPU 스케줄링에서 고려해야 할 사항CPU 스케줄러가 고려해야 할 요소는 다음과 같습니다.프로세스에게 CPU 리소스를 줘야 하는가?실행 가능한 프로세스 중에서 어떤 프로세스에 CPU를 할당할 것인지 결정.우선순위가 높은 프로세스를 먼저 실행할 것인지 고려해야 함.CPU를 할당받은 프로세스가 얼마 동안 실행되어야 하는가?특정 프로세스가 너무 오랫동안 CPU를 독점하지 않도록 타임 퀀텀(Time Quantum) 을 설정.선점형(Preemptive) 스케줄링과 비선점형(Non-preemptive) 스케줄링 방식 중 선택.CPU Burst와 I/O BurstCPU Burst: 프로세스가 연속적으로 CPU에서 실행되는 시간.I/O Burst: 프로세스가 I/O 작업을 수행하는 시간.CPU 작업과 I/O 작업이 번갈아 가며 실행됨.프로세스 간 통신 (IPC, Inter-Process Communication) 종류파일과 파이프(Pipe) 이용파일: 프로세스 간 데이터를 파일을 통해 공유하는 방식.파이프: 한 프로세스가 데이터를 쓰고 다른 프로세스가 읽는 구조 (ex. | 연산자).스레드(Thread) 이용같은 프로세스 내의 여러 스레드가 메모리를 공유하면서 데이터를 주고받는 방식.네트워크 이용소켓(Socket) 통신, 원격 프로시저 호출(RPC) 등을 사용하여 원격 프로세스와 데이터 교환.RPC (Remote Procedure Call, 원격 프로시저 호출)네트워크를 통해 다른 시스템에서 동작하는 프로세스의 함수를 호출하는 기법.클라이언트가 마치 로컬 함수처럼 호출하면, 원격 서버에서 실행되고 결과가 반환됨.공유 자원 & 동기화 문제공유 자원(Shared Resource): 여러 프로세스가 동시에 접근할 수 있는 자원 (예: 변수, 파일).동기화 문제(Synchronization Issue): 여러 프로세스가 공유 자원에 접근할 때 데이터 충돌이 발생할 위험이 있음.임계구역 (Critical Section)공유 자원에 접근하는 코드 영역.한 번에 하나의 프로세스만 임계구역에 접근해야 함.상호 배제(Mutual Exclusion) 매커니즘 요구사항 3가지단일 접근 원칙: 주어진 시간에 오직 하나의 프로세스만 임계구역에 접근 가능.동시 요청 처리: 여러 프로세스가 동시에 요청해도 한 개의 프로세스만 진입 가능.빠른 실행 보장: 임계구역에 들어간 프로세스는 최대한 빠르게 나와야 함.세마포어 (Semaphore)공유 자원의 접근을 제한하는 동기화 기법.프로세스 간 상호 배제(Mutual Exclusion) 를 보장함.세마포어 메커니즘P(S) (wait 연산): 세마포어 값을 감소시키고, 0이면 대기(block).V(S) (signal 연산): 세마포어 값을 증가시키고, 대기 중인 프로세스가 있으면 깨움.C++ 예제#include <iostream> #include <semaphore.h> #include <pthread.h> sem_t semaphore; void* worker(void* arg) { sem_wait(&semaphore); // P(S) 연산 (진입) std::cout << "임계구역 실행 중...\n"; sem_post(&semaphore); // V(S) 연산 (해제) return nullptr; } int main() { sem_init(&semaphore, 0, 1); // 초기값 1 (binary semaphore) pthread_t t1, t2; pthread_create(&t1, nullptr, worker, nullptr); pthread_create(&t2, nullptr, worker, nullptr); pthread_join(t1, nullptr); pthread_join(t2, nullptr); sem_destroy(&semaphore); }  세마포어를 잘못 사용할 경우 발생할 위험성데드락(Deadlock)여러 프로세스가 세마포어를 무한정 대기하면 교착 상태 발생.기아 상태(Starvation)특정 프로세스가 세마포어를 계속 점유하면, 다른 프로세스는 계속 대기해야 함.우선순위 반전(Priority Inversion)낮은 우선순위 프로세스가 세마포어를 점유하면, 높은 우선순위 프로세스가 대기할 수 있음.모니터(Monitor)란?세마포어의 단점을 해결한 상호 배제(Mutual Exclusion) 매커니즘.프로그래머가 wait()과 signal()을 직접 사용하지 않고, 자동으로 동기화를 제공.Java에서 모니터 예제class SharedResource { synchronized void print() { System.out.println(Thread.currentThread().getName() + " 실행 중..."); } } class MyThread extends Thread { SharedResource sr; MyThread(SharedResource sr) { this.sr = sr; } public void run() { sr.print(); } } public class MonitorExample { public static void main(String[] args) { SharedResource sr = new SharedResource(); Thread t1 = new MyThread(sr); Thread t2 = new MyThread(sr); t1.start(); t2.start(); } }synchronized 키워드를 사용하면, 임계구역에 하나의 스레드만 진입할 수 있음.프로그래머가 직접 세마포어를 관리할 필요 없이 안전한 동기화를 제공.[섹션 05]데드락 데드락(Deadlock)이란?정의:데드락(교착 상태)은 두 개 이상의 프로세스가 서로 상대방의 작업이 끝나기를 기다리면서 무한히 멈춰 있는 상태를 의미예제:식사하는 철학자 문제다섯 명의 철학자가 둥근 테이블에서 식사를 하려면 양옆의 포크 두 개를 동시에 집어야 한다.모든 철학자가 왼쪽 포크를 집고 오른쪽 포크를 기다리면 교착 상태(Deadlock)가 발생하여 아무도 식사를 할 수 없게 된다. 교착 상태 (Deadlock)정의:여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태교착 상태 발생 조건 (4가지 필요조건)데드락이 발생하려면 다음 4가지 조건이 동시에 만족해야 함이 중 하나라도 충족되지 않으면 데드락은 발생하지 않음!! 상호 배제 (Mutual Exclusion)한 번에 하나의 프로세스만 특정 자원을 사용할 수 있어야 함예: 한 개의 프린터를 여러 프로세스가 사용할 경우, 한 프로세스가 사용하는 동안 다른 프로세스는 대기해야 함.2. 점유와 대기 (Hold and Wait)프로세스가 이미 할당받은 자원을 보유한 채로 추가적인 자원을 기다려야 한다.예: 프로세스 A는 프린터를 가지고 있고, 프로세스 B가 사용하는 스캐너를 기다리는 상황비선점 (No Preemption)할당된 자원을 강제로 빼앗을 수 없음즉, 자원을 점유한 프로세스가 스스로 해제할 때까지 다른 프로세스는 기다려야 한다.순환 대기 (Circular Wait)프로세스들이 서로 원형(사이클) 형태로 자원을 점유하고 대기한다.예:A → B가 가진 자원을 기다림B → C가 가진 자원을 기다림C → A가 가진 자원을 기다림이처럼 순환 구조가 형성되면 데드락 발생! 데드락 해결 방법데드락을 해결하기 위해 예방, 회피, 검출 및 복구 방법이 존재 데드락 예방 (Prevention)데드락 필요조건 4가지 중 하나 이상을 제거하여 방지하는 방법방법:상호 배제 제거: 여러 프로세스가 동시에 자원을 공유하도록 설계점유와 대기 방지: 모든 자원을 한 번에 요청하도록 함비선점 가능하게 변경: 자원을 강제로 회수할 수 있도록 설정순환 대기 방지: 자원에 우선순위를 부여하여 순환이 생기지 않도록 설계  데드락 회피 (Avoidance)시스템이 미리 안전 상태(Safe State)를 유지하며 자원 할당을 조절하는 방법대표적인 알고리즘:은행원 알고리즘 (Banker’s Algorithm)프로세스가 최대 자원 요청량을 미리 선언해야 함시스템은 프로세스가 요청하는 자원을 할당했을 때 데드락이 발생하지 않는지 검토한 후 할당장점교착 상태 예방 가능안전 상태에서만 자원 할당 → 시스템 안정성 증가 단점프로세스가 최대 요구량을 미리 선언해야 함시스템이 항상 가능한 상태를 계산해야 하므로 오버헤드 발생 교착 상태 검출 및 복구이미 발생한 데드락을 감지하고 해결하는 방법방법:자원 할당 그래프(Resource Allocation Graph, RAG) 분석교착 상태 발생 시 체크포인트로 롤백교착 상태 프로세스 강제 종료 또는 자원 선점교착 상태 검출1) 가벼운 교착 상태 검출시스템이 주기적으로 자원 할당 그래프를 분석하여 교착 상태 가능성을 확인2) 체크포인트 롤백 (Checkpoint Rollback)마지막으로 저장한 체크포인트(Checkpoint)로 프로세스를 되돌려 교착 상태 해소[섹션 06]컴파일과 프로세스프로그램이 실행되는 과정 소스 코드 작성 (C, Java, Python 등)컴파일 (Compile)소스 코드를 기계어(바이너리 코드)로 변환링크 (Link)여러 개의 오브젝트 파일(.o, .obj)을 합쳐 실행 가능한 파일(.exe) 생성로드 (Load)실행 파일을 메모리에 로드실행 (Execute)CPU가 프로그램 명령어 실행[섹션 07] 메모리 메모리의 종류 메모리 주소1) 물리 주소 (Physical Address)실제 RAM의 주소CPU가 직접 접근하는 주소2) 논리 주소 (Logical Address)프로그램이 보는 가상의 주소OS가 논리 주소를 물리 주소로 변환재배치 레지스터 (Relocation Register)논리 주소를 물리 주소로 변환하는 데 사용되는 레지스터프로그램을 다른 메모리 위치로 이동해도 주소 수정 없이 실행 가능메모리 오버레이 (Memory Overlay)큰 프로그램을 작은 조각(Overlay)으로 분할하여 필요한 부분만 메모리에 적재하는 기법초창기 컴퓨터에서 메모리가 부족할 때 사용메모리 할당 방식 (2가지)1. 고정 분할 방식 (Fixed Partitioning)메모리를 고정된 크기의 블록(파티션)으로 나누고, 프로세스를 할당하는 방식각 파티션 크기는 시스템 부팅 시 미리 정해짐단순한 구조이지만 메모리 낭비(내부 단편화)가 발생할 수 있음특징프로세스가 할당된 크기보다 작으면 남은 공간이 낭비됨 (내부 단편화 발생)파티션 크기를 변경할 수 없음작은 프로세스가 들어가야 할 공간에 큰 프로세스가 오면 메모리 낭비가 발생관리가 쉬운 대신 유연성이 부족장점관리가 단순함 (구현 쉬움)메모리 할당/해제 속도가 빠름CPU 스케줄링이 단순해짐단점내부 단편화(Internal Fragmentation) 발생 → 프로세스보다 큰 파티션을 할당받으면 남는 공간이 낭비됨파티션 크기를 미리 설정해야 함 → 크기 조정 불가능큰 프로그램을 실행하기 어려움 (적절한 크기의 파티션이 없으면 실행 불가)예시2.가변 분할 방식 (Variable Partitioning)프로세스가 요청하는 크기만큼 메모리를 할당하는 방식동적 메모리 할당 방식 → 프로세스가 들어올 때마다 필요한 만큼만 메모리를 할당메모리를 효율적으로 사용할 수 있지만, 외부 단편화 문제 발생특징메모리 크기에 맞게 프로세스를 할당하므로 내부 단편화가 없음하지만 메모리가 여러 개의 작은 조각으로 나뉘어 외부 단편화 발생메모리를 동적으로 관리할 수 있어 유연성이 높음장점내부 단편화 없음 → 프로세스 크기에 맞춰 메모리를 할당큰 프로그램도 실행 가능 → 고정된 크기 제한이 없음메모리 활용률이 높음단점외부 단편화(External Fragmentation) 발생 → 메모리 사이에 작은 빈 공간이 많아져 사용 불가메모리 관리가 복잡 → 동적 할당을 위해 추가적인 관리 필요메모리 검색 시간 증가 → 적절한 크기의 공간을 찾기 위해 시간이 오래 걸릴 수 있음 예시메모리 단편화1) 외부 단편화 (External Fragmentation)메모리가 남아 있지만, 연속된 공간이 부족하여 할당 불가능한 상태해결 방법: 메모리 압축(Compaction) 또는 페이징(Paging) 기법 사용2) 내부 단편화 (Internal Fragmentation)고정 분할 방식에서 할당된 공간보다 작은 프로그램이 로드될 때 남는 공간해결 방법: 가변 분할 방식 사용   '그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)' 2주차[섹션 03]알고리즘  재귀함수 (Recursive Function)란?자기 자신을 호출하는 함수를 재귀 함수라고 함문제를 작은 부분으로 나누어 해결하는 방식으로, 주로 반복적인 구조의 문제를 해결할 때 사용재귀 함수의 탈출 조건 (Base Case)이란?재귀 호출이 무한히 반복되지 않도록 종료되는 조건을 기저 조건(Base Case) 이라고 함만약 기저 조건이 없으면 무한 루프에 빠져 프로그램이 멈추지 않는 문제가 발생할 수 있음재귀함수 예시: 팩토리얼 계산 c++#include <iostream> using namespace std; // 팩토리얼 함수 (재귀) int factorial(int n) { if (n == 0) return 1; // 기저 조건 (탈출 조건) return n * factorial(n - 1); // 재귀 호출 } int main() { cout << factorial(5); // 5! = 5 * 4 * 3 * 2 * 1 = 120 return 0; }factorial(0)의 경우 1을 반환하면서 재귀 호출이 종료 재귀적으로 생각하는 방법?작은 문제로 나눈다 → 현재 문제를 더 작은 문제로 분할2. 탈출 조건을 찾는다 → 가장 작은 입력에 대한 결과를 명확하게 정의3. 점화식(재귀 관계식)을 찾는다 → 현재 상태와 작은 문제 사이의 관계 정의4. 재귀 호출을 구현한다 → 주어진 입력에서 자기 자신을 호출하는 구조예제: 피보나치 수열int fibonacci(int n) { if (n <= 1) return n; // 기저 조건 return fibonacci(n - 1) + fibonacci(n - 2); // 재귀 호출 }fibonacci(0) = 0, fibonacci(1) = 1 → 기저 조건을 만족하면 종료  하노이 탑 문제 (Hanoi Tower)세 개의 기둥과 여러 개의 원반이 있음한 번에 하나의 원반만 이동 가능작은 원반이 큰 원반 위에 올라가면 안 됨재귀적 풀이1. 가장 큰 원반을 제외한 나머지를 보조 기둥으로 이동2. 가장 큰 원반을 목표 기둥으로 이동3. 보조 기둥의 원반들을 다시 목표 기둥으로 이동#include <iostream> using namespace std; void hanoi(int n, char from, char to, char aux) { if (n == 1) { cout << "Move disk 1 from " << from << " to " << to << endl; return; } hanoi(n - 1, from, aux, to); // n-1개를 보조 기둥으로 이동 cout << "Move disk " << n << " from " << from << " to " << to << endl; hanoi(n - 1, aux, to, from); // 보조 기둥에서 목표 기둥으로 이동 } int main() { hanoi(3, 'A', 'C', 'B'); return 0; }정렬 알고리즘버블 정렬 (Bubble Sort)인접한 두 개의 값을 비교하여 정렬가장 큰 값이 점점 오른쪽으로 이동하는 방식시간 복잡도최선(O(n)) → 이미 정렬된 경우최악(O(n²)) → 완전히 뒤집힌 경우  장점 & 단점구현이 간단함안정 정렬(Stable Sort)시간 복잡도가 높아 비효율적C++ 코드#include <iostream> using namespace std; void bubbleSort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { swap(arr[j], arr[j + 1]); } } } } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int n = sizeof(arr) / sizeof(arr[0]); bubbleSort(arr, n); for (int i : arr) cout << i << " "; return 0; }선택 정렬 (Selection Sort)가장 작은 값을 찾아서 앞쪽에 배치하는 방식정렬된 부분과 정렬되지 않은 부분으로 나눠 진행시간 복잡도O(n²) (최선, 최악 동일)  장점 & 단점비교 횟수가 일정하여 안정적추가적인 메모리 사용이 적음시간 복잡도가 높아 비효율적안정 정렬이 아님 (같은 값의 순서가 바뀔 수 있음) C++ 코드#include <iostream> using namespace std; void selectionSort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { int minIdx = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIdx]) { minIdx = j; } } swap(arr[i], arr[minIdx]); } } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int n = sizeof(arr) / sizeof(arr[0]); selectionSort(arr, n); for (int i : arr) cout << i << " "; return 0; } 삽입 정렬 (Insertion Sort)현재 원소를 정렬된 부분에 적절히 삽입하는 방식버블, 선택 정렬보다 효율적작은 데이터에서 성능이 좋음시간 복잡도최선(O(n)) → 거의 정렬된 경우최악(O(n²)) → 역순 정렬된 경우  장점 & 단점 정렬된 부분을 활용하여 효율적으로 정렬 가능비교적 빠른 알고리즘 (특히 데이터가 거의 정렬된 경우)큰 데이터에서는 비효율적C++ 코드#include <iostream> using namespace std; void insertionSort(int arr[], int n) { for (int i = 1; i < n; i++) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } int main() { int arr[] = {5, 2, 9, 1, 5, 6}; int n = sizeof(arr) / sizeof(arr[0]); insertionSort(arr, n); for (int i : arr) cout << i << " "; return 0; } 정렬 알고리즘 비교배우고 느낀점한 주가 지났다고 벌써 운영체제 앞부분의 기억이 희미해져서 강의를 보면서 다시 앞부분 내용을 일부 확인하는 과정이 있었습니다.. 복습을 다시 해야겠다는 생각을 하게 됐습니다.CS를 알아야 컴퓨터의 모든 실행 과정(메모리 할당 및 컴파일 과정)을 알 수 있다는 것을 다시 한번 느끼게 되었습니다.처음 접한 단어들이 많아서 다시 한번 학습해야 할 것 같습니다. 어려웠던 점수학 지식이 부족해서 시간복잡도를 이해하기 힘들었습니다. (어떤게 빠르고 어떤게 느린건지)전 주에 들었던 강의 내용을 일부만 기억해서 이번 과정을 이해하는데 힘들었습니다. 앞으로 개선할 점운영체제 초반부분부터 다시 복습하기..코드 구현 시 혼자 생각하면서, 구현 절차를 먼저 생각하는 데에 시간을 많이 소모한 후 구현하기=> 먼저 구현하면서 구현 과정 중 생각하기 X

찬우 이

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

2주차 학습 내용 - 발자국자료구조 & 알고리즘재귀함수function sum(n) { if (n === 1) return 1; // ✅ 기본 조건(Base Case): n이 1이면 재귀 종료 return n + sum(n - 1); // 🔁 재귀 호출(Recursive Case): sum(n-1) 호출 } console.log(sum(5)); // 5 + 4 + 3 + 2 + 1 = 15함수 내부에서 자기 자신을 다시 호출하는 구조를 가진 함수기본조건재귀 함수가 계속 반복되지 않도록 종료 조건(기저 조건)을 설정해야 함.없으면 무한 루프가 발생하여 Stack Overflow(스택 오버플로우) 오류가 발생함.재귀 호출재귀 호출을 통해 문제를 점점 더 단순하게 만들어 Base Case에 도달하도록 함. 하노이 탑(재귀)function hanoi(count, from, to, temp) { if (count === 0) return; hanoi(count - 1, from, temp, to); console.log(`원반${count}를 ${from}에서 ${to}로 이동했습니다.`); hanoi(count - 1, temp, to, from); } hanoi(3, "A", "C", "B"); 재귀문제의 기본으로 알려진 하노이탑 문제의 원리큰 원반을 옮기기 전에, 그 위에 있는 원반들을 다른 기둥으로 옮긴다.가장 아래에 있는 큰 원반을 목표 기둥으로 이동한다.다른 기둥에 옮겨둔 원반들을 다시 목표 기둥으로 옮긴다.hanoi 함수의 매개변수는 (원반개수, 시작위치, 도착위치, 거치는위치)4개로 구성된다.   버블정렬function bubbleSort(arr) { let n = arr.length; for (let i = 0; i < n - 1; i++) { // 전체 반복 횟수 for (let j = 0; j < n - 1 - i; j++) { // 점점 줄어드는 비교 범위 if (arr[j] > arr[j + 1]) { // 오름차순 정렬 [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // Swap (교환) } } } return arr; } let arr = [5, 3, 8, 4, 2]; console.log(bubbleSort(arr)); // [2, 3, 4, 5, 8] 배열을 반복하면서 인접한 두 요소를 비교하고 조건에 따라 서로의 위치를 바꿈구현하기는 쉽지만 성능면(O(n²))에서는 그렇게 좋지 않음.  선택정렬function selectionSort(arr) { let n = arr.length; for (let i = 0; i < n - 1; i++) { let minIndex = i; // 현재 정렬된 부분 이후에서 가장 작은 값의 인덱스 저장 for (let j = i + 1; j < n; j++) { // i 이후 요소들과 비교 if (arr[j] < arr[minIndex]) { minIndex = j; // 더 작은 값이 발견되면 minIndex 갱신 } } // 최소값을 현재 위치(i)와 교환 (swap) if (minIndex !== i) { [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; } } return arr; } let arr = [5, 3, 8, 4, 2]; console.log(selectionSort(arr)); // [2, 3, 4, 5, 8] 배열영역의 첫 번째 원소를 시작으로 마지막 원소까지 비교 후 가장 작은 값을 첫 번째 원소로 가져온다.버블정렬과 같은 경우로 구현하기는 쉽지만 성능면(O(n²))에서는 그렇게 좋지 않음. 운영체제 프로세스 간 통신한 컴퓨터내에 있는 다른 프로세스와 통신하는 방법 ex) 파일, 파이프파일: 프로세스 간 데이터를 저장하고 읽을 수 있음.파이프: 한 프로세스의 출력이 다른 프로세스의 입력이 되는 방식.네트워크로 연결된 다른 컴퓨터에 있는 프로세스와 통신을 하는 방법 ex) 소켓통신, RPC소켓통신: 네트워크를 통해 데이터를 주고받는 방식RPC: 원격 프로시저 호출을 이용하여 다른 컴퓨터에서 실행되는 함수 호출.쓰레드 간 통신같은 프로세스 내에서 실행되는 여러 개의 쓰레드 간의 통신 방법쓰레드는 코드, 데이터, 힙을 공유하며, 각자의 스택만 별도로 가짐.전역 변수(Global Variable)나 힙(Heap)을 이용하면 쓰레드 간 데이터 공유 가능. 공유자원프로세스나 쓰레드 간의 통신에서 공동으로 사용하는 변수나 파일을 의미한다.임계구역여러 프로세스가 동시에 접근하면 안 되는 공유 자원의 영역세마포어공유자원을 함께 쓰는 프로세스 간의 충돌을 막기 위해 프로세스가 사용하는 동안 다른 프로세스는 동작하지 않고 기다리는 것모니터세마포어의 단점을 개선한 방법운영체제(OS) 차원이 아니라, 프로그래밍 언어에서 제공하는 동기화 방법내부적으로 뮤텍스(Mutex)와 조건 변수(Condition Variable)를 사용하여 동기화 수행여기부터교착상태(데드락)프로세스들이 서로가 가진 자원을 기다리면서 아무것도 실행되지 않는 상태각 프로세스가 다른 프로세스의 작업이 끝나기를 기다리지만, 아무도 자원을 해제하지 않음교착상태가 발생하려면 다음 4가지 조건이 모두 충족되어야 한다.상호배제: 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 한다.비선점: 점유한 자원을 강제로 빼앗을 수 없다.점유와 대기: 이미 자원을 점유한 상태에서 추가적인 자원을 기다려야 한다.원형 대기: 프로세스들이 서로 다음 프로세스의 자원을 기다리는 원형 구조가 형성되어야 한다.하지만 필요조건을 지켜도 교착상태는 발생한다는 것을 깨달았고, 교착상태를 예방하기보단 교착상태가 발생했을때 해결하는 방법을 찾으려고 했다.교착상태 해결방안교착상태 회피프로세스들에게 자원을 할당할 때 어느정도 자원을 제공해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 선에서 할당해주는 것전체 자원의 수와 할당된 자원의 수를 비교해서 안정상태와 불안정 상태로 나눔시스템의 총 자원과 각 프로세스간의 최대 요구자원을 계산해서 여유분의 자원을 남기고 프로세스에게 제공해야 안정상태를 유지할 수 있다.교착상태 검출가벼운 교착 상태 검출: 타이머를 이용해 프로세스가 일정시간 동안 작업을 진행하지 않으면 교착상태가 일어났다고 생각하고 해결함(해결 방법은 주기적으로 상황을 업데이트해서 만약 교착이라고 느끼면 롤백해서 이전으로 되돌아감)무거운 교착 상태 검출: 자원 할당 그래프를 이용하며, 교착 상태를 발견하면(발견은 자원이 순환하면 교착상태임) 해결함.해결방법은 교착상태를 인지하면 교착을 일으킨 프로세스를 강제종료하고 다시 실행할때 이전 업데이트로 롤백함.컴파일 언어소스 코드 전체를 한 번에 기계어(0과 1)로 변환한 후 실행하는 언어속도가 빠름.언어: C, C++, C# 등컴파일에서 실행파일로 변환 과정test.c -> 전처리기 -> test.i -> 컴파일러 -> test.s -> 어셈블리 -> test.o -> 링커 -> test.exe1⃣ test.c → 전처리기(Preprocessor) → test.i (주석 제거, 매크로 처리 등)2⃣ test.i → 컴파일러(Compiler) → test.s (어셈블리 코드 생성)3⃣ test.s → 어셈블러(Assembler) → test.o (목적 파일 생성)4⃣ test.o → 링커(Linker) → test.exe (최종 실행 파일 생성) 인터프리터 언어코드를 한 줄씩 읽고 실행하는 방식의 언어컴파일 과정 없이 즉시 실행되지만, 실행 속도는 컴파일 언어보다 느림언어: JS, Python, Ruby 등 메모리 종류 레지스터CPU 내부에 존재하는 가장 빠른 기억장소매우 빠른 연산을 위해 사용되며, CPU가 직접 접근할 수 있음휘발성(Volatile) 메모리 → 전원이 꺼지면 데이터가 사라짐 캐시메인 메모리(RAM)와 CPU(레지스터) 사이에 위치하는 고속 메모리CPU가 자주 사용하는 데이터를 미리 저장하여 접근 속도를 높임 메인메모리(RAM)운영체제(OS)와 실행 중인 프로그램이 올라가는 공간휘발성 메모리가격이 비싸기 때문에, 데이터 저장보다는 실행 중인 프로그램을 로드하는 용도로 사용HDD(하드디스크)나 SSD보다 훨씬 빠르지만, 레지스터나 캐시보다는 느림 보조저장장치(HDD,SSD)가격이 저렴하며, 데이터를 영구적으로 저장하는 용도로 사용됨비휘발성(Non-Volatile) 메모리 → 전원이 꺼져도 데이터가 유지됨 메모리 할당 방식 메모리 오버레이프로그램이 메모리보다 클 경우, 실행에 필요한 부분만 메모리에 로드하는 방식나머지 코드는 하드디스크에 저장되며, 필요할 때만 메모리에 불러옴가변 분할 방식프로세스 크기에 맞춰 메모리를 동적으로 분할하는 방식외부단편화 발생: 여러 개의 작은 빈 공간이 생겨 새로운 프로세스를 할당하기 어려운 문제고정 분할 방식프로세스 크기와 상관없이 미리 정해진 크기로 메모리를 나누는 방식장점: 구현이 간단하고 오버헤드가 적음단점: 작은 프로세스는 큰 영역에 할당되서 공간이 낭비되는 내부단편화 발생버디 세스템가변 분할 방식과 고정 분할 방식을 혼합하여 단점을 최소화한 메모리 할당 방식메모리를 2의 승수 크기로 분할하여 할당2주차 회고재귀가 너무 어렵다.. 정렬은 그래도 예전에 공부해본적이 있어서 한두번 더 보니까 이해가 되는데 재귀는 봐도봐도 이해가 어려움..특히 하노이ㅋㅋㅋㅋ 새로운 벽이였다. 그래도 자주 보다보니 적응이 되는것 같기도 하고 아닌거 같기도하고,,,그렇다 보니 미션 3번째 문제는 도무지 이해가 쉽지 않았다. 그래서 GPT의 도움과 함께 계속 이해해려하고 있고 지금도 하고있다,,ㅎ그리고 2주차때는 중간점검을 통해 다같이 구글밋을 했다. 주 내용은 운영체제같은 CS지식이 있으면 다른 프레임워크나 컴퓨터 쪽의 지식을 쌓고 배울때 지식이 없는사람에 비해 더 빠르게 습득할 수 있고, 흡수하는게 빠르다고 했다. 벌써 다음주가 3주차라서 CS는 마지막 주 인데 마무리 잘해서 수료하고, 수료 이후에도 강의 반복해서 듣고 자료구조 & 알고리즘은 심화버전이 있어서 그걸 들어야 할 것 같다.

알고리즘 · 자료구조자료구조알고리즘운영체제인프런워밍업클럽CS

워밍업 클럽 3기 BE 클린코드&테스트 - 2주차 발자국

회고록2주차로 넘어가면서 벌써 한 강의가 끝났다. 개발을 업으로 하면서 항상 깔끔한 코드에 대한 갈증 있는데 이번에 완료한 강의로 그 갈증을 모두 채우기에는 역시나 아쉬움이 있었다. 이것은 아마도 강의의 문제가 아닌 클린코드 라는 작업 자체에 대한 어려움일 것이다. 그리고 나 자신의 작문 실력의 부족함 때문일것이다. 1. 무엇을 배웠나?이번 주에는 다음과 같은 내용을 학습했다. 섹션 5 객체 지향 적용하기상속과 조합 : 상속보다는 조합을 사용하여 유연한 구조를 설계하는 것이 좋다.내 경험에선 상속을 사용한 클래스를 보기 힘들었다. (사실 본적이 없다.) 아마도 숨겨진 변수에 찾기에 대한 어려움 때문일것이라 생각한다.Value Object (VO) :도메인 개념을 값으로 표현하는 객체로, 불변성과 동등성을 보장해야 한다.개인적으로는 VO객체를 많이 사용하려고 노력한다. 값이 스스로 검증 할 수 있다는 것이 매력적이기 때문일까?DTO 내부에 들어가게 될 경우 어떻게 써야할지 좀 막막하기는 하다. 해당 내용도 있었으면 좋았을텐데일급 컬렉션 :컬렉션을 객체로 감싸서 의미를 부여하고, 가공 로직을 포함할 수 있도록 한다.잘 사용하지 않는 패턴이긴하다. 이건 새로 도입할지 여부를 결정해봐도 좋을것 같다.Enum의 특성과 활용 :상수의 집합이며, 관련된 로직을 포함할 수 있는 추상화된 객체로 활용된다.개인적으로 Enum을 사랑하는 사람이다. 한글로 명확히 표현 할 수 있는건 매력적이다.interface를 적용하는 방법은 적절히 사용하면 좋은 패턴인것 같다.다형성 활용하기 :반복적인 if 문을 제거하고, 변화하는 부분을 분리하여 OCP(Open-Closed Principle)를 지킨다.사실 코드 depth를 줄이기 위해 자주 애용하는 패턴이다.숨겨져 있는 도메인 개념 도출하기 :도메인 개념을 발견하여 설계에 반영하고, 완벽한 설계가 아닌 최선의 설계를 지향해야 한다.자세한 내용은 아래에서 섹션 6 코드 다듬기주석의 양면성 :주석은 코드의 가독성을 높일 수도 있지만, 코드 품질이 낮다는 신호가 될 수도 있으며, 꼭 필요한 경우에만 작성해야 한다.자세한 내용은 아래에서변수와 메서드의 나열 순서 :변수와 메서드는 사용 순서대로 배치하며, 공개 메서드를 상단에 배치해 객체의 협력을 더 쉽게 이해할 수 있도록 해야 한다.사실 배열 순서가 꽤나 개발자 취향을 타는 문제라 내 배열 순서랑 한번 비교해 보는 시간이라 좋았다. (나는 목록,상세,생성,수정,삭제, 기능으로 자주 호출되는 순서로 정리한다.)패키지 나누기 :패키지는 문맥을 제공하므로 적절한 크기로 분리하되, 과도한 세분화나 무분별한 변경은 피해야 한다.패키지 나누기는 어려운 문제다. 대부분은 사내 컨벤션이 있기때문에 마음대로 조정하기 어렵다. 기능 유지보수하기 (1) - 버그 잡기 :기존 기능의 오류를 찾아 수정할 때는 코드의 변경이 최소화되도록 해야 한다.기능 유지보수하기 (2) - 알고리즘 교체하기 :알고리즘을 변경할 때는 성능과 메모리 사용을 고려하여 적절한 방법을 선택해야 한다.사실 리펙토링의 핵심은 이런 부분 때문이 아닐까 싶다. 리팩토링 잘된 코드는 추가 요구사항을 적용할때 때로는 코드 한줄 만으로 처리 가능하게 한다. 개발자라면 그럴때 느끼는 감정은 따로 말하지 않아도 잘 알지 않을까 싶다.(물론 항상 그렇지는 않다.)IDE의 도움 받기 :코드 정렬, linting, 스타일 가이드를 활용하여 가독성과 유지보수성을 높인다.개인적으로 코드 스타일 같은 경우는 툴에 의존되야 되는것이 맞다고 생각한다. (코드 컨벤션은 사람이 지키기에는 정말 어렵다.) 섹션 7 리팩토링 연습리팩토링 (1) - 추상화 레벨 :중복 코드를 제거하고, 메서드를 추출하여 적절한 추상화 레벨을 맞춘다.리팩토링 (2) - 객체의 책임과 응집도 :IO 처리와 화면 출력(display) 기능을 분리하고, 일급 컬렉션과 Order 객체를 도입하여 책임을 명확히 한다. 리팩토링 (3) - 관점의 차이로 달라지는 추상화 :같은 기능이라도 구현 중심과 도메인 개념 중심으로 접근하는 방식에 따라 추상화가 달라질 수 있다.강의를 따라하면서 의문이 들었던 부분은 MVC, MVVC 와 같은 아키텍처 부분이 나올줄 알았는데 안나왔다는 것이다. 강의 분량 때문에 안 나온건지 아니면 일부러 포함을 안 시킨 건지 잘 모르겠지만 중간에 "Controller"라는 표현을 한것 을 보면 후자에 가까운 것으로 보인다.섹션 8 기억하면 좋은 조언들능동적 읽기 : 핵심 목표는 도메인 지식을 늘리는 것이게 정답이다. 중요한 건 도메인이지 기술이 아니다.오버 엔지니어링 : 적정 수준보다 더 높은 수준의 엔지니어링자세한 내용은 아래에서은탄환은 없다 : 클린 코드도 은탄환이 아니다.자세한 내용은 아래에서2. 무엇이 인상적이었나?이번 주 학습 중 가장 인상 깊었던 내용은 숨겨져 있는 도메인 개념 도출하기, 주석의 양면성, 오버엔지니어링, 은탄환은 없다. 이었다.숨겨져 있는 도메인 개념 도출하기업무를 하면서 도메인의 관점에서 생각을 해보지 않아서 새로웠다.주석의 양면성주석이 참 업무를 하다보면 매력적으로 다가올때가 많다. 하지만 레거시에서는 그렇게 보기 싫더라... 히스토리 용으로만 쓰면 좋다는 내용은 동의하지만 고객에게 전달할때 어떻게 코드만으로 전달 수있을지는 여전히 잘 모르겠다.오버엔지니어링사실 개발하면서 신규 요구사항을 한방에 해결하기 위해 오버엔지니어링을 많이 하게되는것 같다. "필요하기전에 만들지 마라"라는 말이 있듯이 참 지키기 어려운 부분인것 같다.은탄환은 없다."머리는 애자일, 몸은 워터풀" 인 상황이 많았다. 사실 강의에서는 "지속 가능한 소프트웨어의 품질 VS. 기술 부채를 안고 가는 빠른 결과물" 이지만 클라이언트의 요구사항은 거의 대부분 "지속 가능한 소프트웨어의 품질을 가진 빠른 결과물" 인 경우가 많다. 그래서 아마 대부분의 개발자가 품질을 높이기 위해 작업 공수를 실 공수보다 높게 부르는 것이라 생각한다. 이게 보통 성과에 직결되는 부분이라 참 어렵다.3. 이번 주 학습을 통해 얻은 것이번 주 학습을 통해 나는 Enum 활용법에 대해 배웠고 도메인에 대한 생각을 더 깊게 해야겠다고 생각했다.특히, 도메인에 대한 생각을 깊게 하는 연습을 게을리 하면 안될것이라 생각한다. 4. 다음 주 목표다음 주에는 테스트 코드 방법론 적용을 달성하고 싶다.항상 로직을 먼저 작업하고 테스트 코드를 작성하는 버릇이 있는데 차주에는 그런 버릇을 의식적으로 수정해 보리라.. 

백엔드

노을

[인프런워밍업클럽] 2주차 자료구조와 알고리즘 미션

자료구조와 알고리즘1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저조건이 없으면 함수가 계속해서 자기 자신을 호출하기 때문에 무한 반복된다.콜 스택이 계속 쌓여서 스택 오버 플로우가 발생함2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요. function sumOdd(n){ if (n <= 0) return 0; return (n % 2 !== 0 ? n : 0) + sumOdd(n - 1); } console.log(sumOdd(10)) // 25 3. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(currentDir, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 변경const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory(directory) { const files = fs.readdirSync(directory); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(directory, file); // directory와 file을 하나의 경로로 합쳐줌 const fileStatus = fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); traverseDirectory(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } traverseDirectory("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력   

알고리즘 · 자료구조

채널톡 아이콘