블로그

minme9055

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

운영체제세그멘테이션(배치정책)메모리를 논리적 단위(세그먼트)로 분할각 세그먼트는 다양한 크기 가능외부 단편화 문제 발생 가능페이징(배치정책)메모리를 동일한 크기의 페이지로 분할물리 메모리와 가상 메모리 간 매핑내부 단편화 발생 가능, 외부 단편화 해결페이지드 세그멘테이션(배치정책)세그멘테이션과 페이징 결합세그먼트를 페이지 단위로 나눔유연성과 효율성 향상디맨드 페이징(가져오기 정책)필요한 페이지만 메모리에 로드페이지 부재 시 디스크에서 가져옴메모리 사용 효율성 증가페이지 교체정책FIFO, LRU, LFU 등 다양한 알고리즘새 페이지 로드 시 어떤 페이지를 교체할지 결정페이지 부재율 최소화 목표스레싱과 워킹셋스레싱: 과도한 페이지 교체로 성능 저하워킹셋: 프로세스가 자주 참조하는 페이지 집합워킹셋 관리로 스레싱 방지주변장치(I/O 디바이스, 저장장치)CPU, 메모리 외 하드웨어 장치입력, 출력, 저장 기능 수행인터럽트 기반 동작마우스/키보드사용자 입력 장치이벤트 기반 동작인터럽트 처리 필요하드디스크/Flash Memory(SSD)하드디스크: 기계식, 대용량, 저렴SSD: 전자식, 고속, 고가비휘발성 저장 장치파일과 파일시스템파일: 관련 데이터의 논리적 집합파일시스템: 파일 저장, 조직, 검색 관리메타데이터 관리 포함디렉토리파일들의 논리적 컨테이너계층적 구조 (트리 구조)파일 검색, 그룹화 용이파일과 디스크파일 할당 방식: 연속, 연결, 인덱스 할당빈 공간 관리디스크 스케줄링 알고리즘 자료구조와 알고리즘정렬 - 삽입정렬원리: 정렬된 부분에 새 원소를 적절한 위치에 삽입시간 복잡도: 평균 및 최악 O(n^2), 최선 O(n)특징: 작은 데이터셋에 효율적, 부분 정렬된 배열에 유리안정적 정렬 알고리즘정렬 - 병합정렬원리: 분할 정복 방식, 작은 부분으로 나누고 병합하며 정렬시간 복잡도: 항상 O(n log n)특징: 대규모 데이터 정렬에 효율적, 추가 메모리 필요안정적 정렬 알고리즘정렬 - 퀵정렬원리: 피벗 선택 후 분할 정복 방식으로 정렬시간 복잡도: 평균 O(n log n), 최악 O(n^2)특징: 실제 구현에서 매우 빠름, 불안정 정렬피벗 선택 방법이 성능에 큰 영향동적 프로그래밍 - 메모이제이션원리: 계산 결과를 저장하고 재사용 (캐싱)특징: 주로 하향식(top-down) 접근법장점: 중복 계산 방지로 효율성 향상적용: 피보나치 수열, 최장 공통 부분 수열 등동적 프로그래밍 - 타뷸레이션원리: 작은 부분 문제부터 해결하며 표를 채움특징: 상향식(bottom-up) 접근법장점: 일반적으로 메모리 사용량이 적음적용: 냅색 문제, 최단 경로 문제 등3주차 후기지난 주차보다는 익숙한 단어들이 많이 보였다. 그래서 조금 가벼운 마음으로 시작했다가 어김없이 혼돈으로 접어드는 루트의 반복이었던 주였다. 언제쯤 이 단어와 개념과 친구 먹을 수 있을까 😂운영체제에서는 가상 메모리에 대해 배우면서 세그멘테이션과 페이징의 개념을 잡고, 메모리 관리 기법의 발전 과정을 따라 공부해 보았다. 입출력 장치와 파일 시스템에 대해 공부하면서는 하드웨어와 소프트웨어의 상호작용을 중점으로 공부했는데, SSD와 하드디스크에 대한 내용을 공부할 때는 노트북 살 때의 경험을 떠올리면서 들으니 다른 파트보다 조금 더 재밌게 들을 수 있었던 것 같다.알고리즘에서는 다양한 정렬 방법들과 동적 프로그래밍에 대해 배웠다. 정렬에 대해 공부할 때는 각각의 장단점을 비교하면서 언제 적합하게 사용할 수 있을지를 주요 포인트로 공부했다. 이미 이전에도 몇 번 봤던 개념이라 막 어렵다는 느낌은 없었다. 그런데 동적 프로그래밍이 개인적으로 좀 어려웠던 것 같다. 동적인건 언제나 어렵다, 다 정적이었으면 좋겠다 라고 궁시렁 거리면서 공부했다. 그래도 감자쌤과 함께 찬찬히 공부하니 완벽하게는 아니어도 어렴풋이 개념은 잡을 수 있었던 것 같다. 인프런 워밍업 클럽 2기 후기한 번도 공부해보지 않은 CS를 공부해보겠다고 시작한 워밍업 클럽은 생각보다 빠르게 지나갔다. 회사 일이랑 이직 준비랑 다른 스터디에 엄청 치이면서도 워밍업 클럽을 포기하지 않은 건, 하루에 수행할 수 있는 적합한 학습량과 감자쌤의 친절나긋한 설명 덕분이 아닐까 싶다. 그리고 워밍업 클럽을 같이 진행하면서 열심히 하시는 다른 분들의 모습에도 많은 자극을 받았던 것 같다. 3주 동안 감자쌤과 함께 배운 내용들을 완벽하게 이해했다고 할 수는 없지만, 전반적인 내용을 파악했고 어느 부분이 어려운지도 알았으니 앞으로 공부하면서 부족한 부분들을 더 채워나가야겠다.

알고리즘 · 자료구조인프런인프런워밍업클립CS운영체제자료구조알고리즘감자3주차

minme9055

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

운영체제1. 메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요.RAM: 빠른 읽기/쓰기가 가능하지만, 전원이 꺼지면 내용이 사라집니다.ROM: 읽기 전용이며, 내용이 영구적으로 보존됩니다.캐시: CPU와 가까이 있어 매우 빠르지만, 비용이 높습니다.가상 메모리: 하드디스크 일부를 RAM처럼 사용합니다. 속도는 느리지만 큰 용량을 사용할 수 있습니다.2. 사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?경계 레지스터(Boundary Register)입니다. 이것이 없으면 프로그램들이 운영체제 영역을 무단으로 접근할 수 있어 문제가 생길 수 있습니다.3. 메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?고정 분할: 설정과 관리가 쉽습니다. 하지만 메모리 낭비가 심할 수 있습니다.가변 분할: 메모리를 효율적으로 사용할 수 있습니다. 다만 관리가 조금 복잡할 수 있습니다.4. CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?스래싱(Thrashing)이라고 합니다. 시스템이 너무 바빠서 정작 실제 작업은 못 하는 상황을 말합니다.5. HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요? 이유를 함께 적어주세요.네, 필요합니다. 전원이 꺼져도 데이터를 유지해야 하기 때문입니다. 하지만 RAM만으로 운영되는 특수한 시스템도 있긴 합니다. 이를 "RAM 디스크" 또는 "메모리 전용 시스템"이라고 부릅니다. 주로 아주 빠른 처리 속도가 필요하거나, 데이터의 영구 저장이 필요 없는 특수한 경우에 사용됩니다.6. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?파일을 삭제해도 실제 데이터는 지워지지 않고, 그 공간을 재사용 가능하다고 표시만 합니다. 그래서 덮어쓰기 전이라면 복구가 가능합니다.자료구조와 알고리즘1. 지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블 정렬: 구현이 쉽지만, 속도가 느립니다 (O(n^2))선택 정렬: 구현이 쉽지만, 역시 속도가 느립니다 (O(n^2))삽입 정렬: 작은 데이터에 효과적이며, 평균/최악의 경우 O(n^2)입니다병합 정렬: 안정적이고 항상 O(n log n)의 성능을 보이지만, 추가 메모리가 필요합니다퀵 정렬: 평균적으로 빠르며 O(n log n), 최악의 경우 O(n^2)의 성능을 보입니다2. 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요.타뷸레이션을 사용하는 것이 좋습니다. 메모이제이션은 재귀 호출을 많이 하기 때문에 스택 오버플로우가 발생할 수 있어요. 반면 타뷸레이션은 반복문으로 해결하기 때문에 메모리를 덜 사용합니다.

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

강지원

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

따라하며 배우는 리액트 A-Z (7~13강) Day 11 (리액트 테스트 경험하기) TDD (Test Driven Development)개발 전 테스트 코드를 먼저 작성하는 방법론 순서테스트 코드를 작성 → 실행 (당연히 실패) → 딱 이 테스트 코드를 통과할 만큼의 코드만 작성 → 성공 → 다른 테스트 코드 작성으로 이동전부를 다 한 다음에 리팩토링 작업을 실행여기서 문제가 된다면 다시 테스트 코드를 확인하고 수정함 TDD의 장점소스 코드에 안정감을 줌디버깅 시간과 개발 시간이 줄어듦시스템 전반적인 설계 향상 (클린 코드가 나올 확률이 높아짐)개발 집중력 향상 (테스트를 하나씩 깨나가면서 개발할 수 있기 때문)  Day 12 (NextJS, 타입스크립트)내용을 복습하면서 원래 알고 있던 것 + 새로 알게 된 내용을 공부하는 방식으로 공부했다.특히 TS의 타입 들을 코드로 정리하면서 어떤 타입이 있었는지 다시 새길 수 있었다. Next.jsReact의 SSR을 쉽게 구현할 수 있게 도와주는 간단한 프레임 워크 특징 Full-StackFile-based RoutingSEO, Image, Font OptimizationServer Side RenderingHybrid Rendering CSR (Client Side Rendering)리액트만으로 프로젝트를 만들면 발생 → 렌더링 하는 주체가 클라이언트 (브라우저) 장점한번 로딩 되면, 빠른 UX 제공서버의 부하가 작음 단점페이지 로딩 시간(TTV)이 김 (FCP가 오래 걸린다고도 함)자바스크립트 활성화가 필수임SEO가 힘듦보안에 취약 (모든 react 라이브러리, js 소스 코드를 다 다운 받아야 하기 때문에)CDN(Content Delivery Network)에 캐시가 안됨 → 이러한 많은 단점들을 해결하기 위해서 나온 것이 SSR SSR (Server Side Rendering렌더링 하는 주체가 서버렌더링 되는 순간 : 요청 시 렌더링 (미리 해두지 않음) 장점페이지 로딩 시간(TTV)이 빠름자바스크립트 활성화 여부가 필요 없음SEO 최적화가 좋음보안이 뛰어남CDN에 캐시가 됨실시간 데이터를 사용!사용자 별 필요한 데이터를 사용함 (요청 시 렌더링 하기 때문에 요청하는 사람에 맞게 데이터 제공이 가능) 단점비교적 느릴 수 있음서버에 과부하가 걸릴 수 있음 (몇 천명의 페이지를 요청 시 마다 계속 만들어야 하기 때문에)CDN에 캐시가 안됨 (요청마다 새로운 페이지를 만들기 때문에) Typescript 타입 : value가 가지고 있는 프로퍼티나 함수를 추론할 수 있는 방법JS의 dynamically type이 야기할 수 있는 runtime error를 해결하기 위해 statically type을 적용 시킨 언어 사용하는 이유Typescript는 JS코드를 단순화하여 더 쉽게 읽고 디버그할 수 있도록 함Typescript는 코드 유형 검사를 통해 JS를 작성할 때 고통스러운 버그를 피할 수 있도록 도와줌  Day 13 (리덕스 학습하기 및 리액트 19) ReduxJS 어플리케이션을 위한 상태 관리 라이브러리 data flowAction간단한 JavaScript 객체수행하는 작업의 유형을 지정하는 'type' 속성이 있으며 선택적으로 redux 저장소에 일부 데이터를 보내는 데 사용되는 'payload' 속성을 가질 수도 있음 Reducer어플리케이션 상태의 변경 사항을 결정하고 업데이트 된 상태를 반환하는 함수store 내부의 상태를 업데이트함 Redux Store어플리케이션의 전체 상태 가지고 있는 객체내부 상태를 변경하는 유일한 방법은 해당 상태에 대한 Action을 전달하는 것 Redux 미들웨어action을 dispatch하고 reducer에 도달하는 순간 사이에서 사전에 지정된 작업을 실행할 수 있게 해주는 중간자 Redux Thunk비동기 작업을 할 때 많이 사용하는 방법Redux Thunk도 리덕스 미들웨어액션 내부에서 다양한 작업을 할 수 있게 해줌 Redux ToolkitRedux 로직을 작성하기 위한 공식 권장 접근 방식Redux 코어를 둘러싸고 있고, Redux 앱을 빌드하는 데 필수적인 패키지와 기능이 포함되어 있음Redux 작업을 단순화하고 일반적인 실수를 방지하며, Redux 앱을 더 쉽게 작성할 수 있도록 도와줌 느낀 점 redux의 기본 사용 법을 처음으로 배우는 것이라 신기하고 어렵게 느껴졌다. 강의를 따라가면서 기초에 집중하려고 노력했는데, 처음 배운 개념을 이용해서 앱을 만드려니 꽤나 막막해서 시간이 많이 걸렸다. 앞으로 더 능숙해지고 싶다. 일주일 회고스터디 중간에 몸이 3일 동안 아팠어서 시간이 많이 없었지만 열심히 달려서 겨우 완주 조건까지 달성했다.매일 새벽까지 과제를 개발한 덕에 JS 과제 5개와 React 과제 3개를 해냈다. 모든 과제를 해내면 신입 역량 이상이라고 하셨었는데 나는 아직 신입 역량 정도였나 보다. 아쉽다.그동안 머릿속에 스터디만 가득한 채로 3주를 보냈는데 막상 끝나려고 하니까 아쉽지만 3주전의 나와 지금의 나를 비교했을 때 많은 성장을 이뤄낸 것 같아서 뿌듯하다.이번에 알게 된 부족한 점들을 바탕으로 앞으로의 공부 계획을 세워나갈 예정이다.정말 의미 있는 시간이었고, 꼭 필요했던 시간이라고 생각한다. 강의 출처강의 주소(React) : https://www.inflearn.com/course/따라하는-리액트/코치님 성함 : John Ahn

ReactNextJSTypescriptRedux프론트엔드인프런스터디3주차

보키

[인프런 워밍업 클럽 3기 - BE/Project] 3주차 회고 발자국 🐾

2주차와 마찬가지로 KPT 회고 프레임워크를 선택해서 작성해보려고 한다! Keep(만족, 지속하고 싶은 부분)이번 3주차는 개인프로젝트에서는 프로젝트쪽에서는 조회 API를 만들었다. API 테스트에서는 mockMVC를 사용하지 않고, 실제 인증 엔드포인트를 호출하고, AccessToken을 받아서 Authorization 헤더에 넣어서 Project 목록을 가져오는 것을 RestClient로 작성했다.DB url은 src단과 test단에서 다른 곳을 바라보게 만들었다. 개인적으로는 컨트롤러->서비스->레포지토리->서비스->컨트롤러 로 흐르는 스택트레이스 요청&응답을 제대로 검증하기위해서는 실제로 사용하는 DB 벤더까지 맞춰야 한다고 생각한다.실제로 배포했다면 AWS 인스턴스로 요청을 날려보면 되겠고! 갠적으로 h2는 학습용으로는 괜찮지만 실제 프로젝트를 할때는 테스트에도 비슷하거나 같은 환경으로 해야한다고 생각한다.강의에서는 ADMIN단을 진행했다. 거의 끝나가고있다!! 좋아! Problem(부족, 아쉬웠던 부분)사실, 이번주에 면접이 있었고, 면접준비도 하느라고 조회과제 테스트코드랑, 금요일까지였던 미션을 완료 못했다.늦게라도 제출을 해서 마무리를 하는 멋쥔 사람이 되려고 노력할 것이다!Try(도전, P에 대한 해결책 등으로 다음번에 보완하거나 시도할 부분)거의 다 온거, 내 프로젝트도 천천히 그리고 차근차근 보완해가며 완성시켜보고 싶다.프론트엔드도 예전에 학습한거를 바탕으로 현업에서 썼던 Vue3대신 React(CRA)로 붙여보고 싶다.테스트코드도 한번 작성해놓으니까 Fixture-Monkey나 Kotest, mockk 사용법이 새록새록 기억도 나고 새로 배우는 것도 있고 그렇다.앞으로 쭉 잘하면 된다!! 나 자신을 응원하자!!!

웹 개발인프런워밍업클럽회고KPT3주차백엔드프로젝트KotlinSpringboot

재영

[인프런 워밍업 클럽 3기] CS - 3주차 미션 (운영체제)

메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요.레지스터가장 빠른 기억장소로 CPU 내에 존재컴퓨터의 전원이 꺼지면 데이터가 사리지므로, 휘발성 메모리에 해당메인메모리 RAM레지스터에 비하면 한참 느린 메모리휘발성 메모리실제 운영체제와 다른 프로세스들이 올라가는 공간하드디스크나 SSD 보다 속도는 빠르지만 가격이 비쌈데이터를 저장하기 보다는 실행 중인 프로그램만 올림캐시메인메모리에 있는 값을 레지스터로 옮기려면 시간이 한참 걸림이때, 미리 가져와서 저장하는 공간이 필요한데 캐시가 이에 해당휘발성 메모리성능의 이유로 여러개를 둠 (L1, L2, … )보조저장장치 (HDD, SSD 등)비휘발성 메모리사무용 프로그램이나 게임, 작업한 파일을 저장하는 공간가격이 메인 메모리에 비하면 매우 저렴함 사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?경계 레지스터하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 레지스터에 해당CPU 내에 존재하며, 메모리 관리자가 사용자 프로세스가 경계 레지스터의 값을 벗어났는지 검사하고, 만약 벗어났다면 그 프로세스를 종료시킴 메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?가변 분할 방식 - 세그멘테이션장점 : 메모리를 가변적으로 분할할 수 있고, 코드영역, 데이터 영역, 스택 영역, 힙 영역을 모듈로 처리할 수 있기 때문에 공유와 각 영역에 대한 메모리 접근보호가 편리단점 : 외부 단편화가 발생 외부 단편화?프로세스들이 메모리에 적재되고 제거될 때 할당되지 않고 작은 조각들로 메모리가 나뉘어져 있는 상태 외부 단편화 해결책메모리의 내용을 한쪽으로 밀어서 큰 공간을 만드는 방법 : 밀집→ 시간 낭비가 심함요구되는 메모리 크기보다 더 크게 할당→ 이때, 할당 했지만 안쓰는 공간을 내부 단편이라고 함 고정 분할 방식 - 페이징장점 : 모든 페이지의 크기가 동일해서 세그멘테이션과 다르게 크기를 표현하는 Bound Address가 필요하지 않으며, 이러한 특징떄문에 외부 단편화가 발생하지 않음. 메모리를 효율적으로 관리할 수 있음.단점 : 하지만, 정해진 크기의 페이지보다 프로세스의 정보가 작으면 공간이 낭비, 이를 내부 단편화라고 부름.세그멘테이션과 비교하면 많은 공간을 낭비하는 것은 아니므로 심각하게 생각하지 않음.페이지로 나누기 때문에 논리적인 영역을 나눌 수 없음. 그래서 특정 영역에 대해서 공유하거나 권한을 부여하는 것이 어려움.  CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?스레싱 Thrashing스레싱의 원인OS는 CPU의 이용률이 낮아지면 다중 프로그래밍 정도를 높임페이지 부재가 많아지고 이로 인한 페이지 교체가 과도하게 발생하여 시스템 성능이 저하 → 스레싱근본적인 원인은 물리 메모리의 크기가 작은것→ 하드웨어적으로 해결하려면 메모리의 크기를 늘리면 됨  HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요? 이유를 함께 적어주세요.운영체제는 파일을 관리하기 위해 파일 관리자를 두고 파일 테이블을 이용해 파일을 관리한다.이때, 파일을 저장 하기 위한 저장장치(HDD, SSD)는 반드시 필요   파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?디스크에 파일을 저장할 때마다 빈 공간을 찾으려 모든 공간을 뒤지는 방식은 비효율적이므로, 파일 시스템은 효율적인 관리를 위해 빈 공간을 모아둔 free block list 를 가지고 있다.만약 파일을 삭제한다면 파일 시스템은 파일의 모든 정보를 지우는 것이 아니라 파일 테이블의 헤더를 삭제하고 사용했던 블록을 free block list 에 추가하는 방식으로 진행된다.이렇게 처리하면 사용자는 파일이 삭제된 것처럼 느껴지는데, 사용했던 블록의 데이터는 그대로 남아있기 때문에포렌식으로 데이터를 복구할 수 있음

인프런워밍업클럽3기CS3주차미션운영체제

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

3주차에는 Admin 개발 실습을 진행했다.Presentation vs. AdminPresentation사용자(방문자)가 보게될 화면에 대한 기능 개발(ex) 홈페이지 메인 페이지, 회원가입/로그인, 계정 정보, 검색 기능 등등 Admin내부 운영진이 보게될 화면에 대한 기능 개발(ex) 사용자 관리, 사용 통계 대시보드, 시큐리티 관리 등등 Q. 굳이 사용 영역을 나눠주는 이유는 무엇일까?A1. 보안 강화: 외부에 노출되면 안되는 데이터(사용자 정보, 매출 등)를 별도로 다루기 위해A2. 개발 및 배포 분리: 각 영역을 독립적으로 관리하기 위해 -> Admin은 내부적으로, Presentation은 외부적으로A3. 권한 분리: 데이터 접근 권한을 달리 하기 위해 -> 운영자 한정으로 고급 권한을 부여 즉, 쉽게 말해 홈페이지와 구별되는 '운영자 전용 작업 페이지'를 만드는 작업이다.Admin 작동 구조크게 보았을 때, 이전에 실습했던 Achievement, Skill 등등 포트폴리오에 들어갈 사항들을 DB 테이블에 맞춰 각자 service 기능을 서술하고 이를 응답했을 때의 예외 처리 기능인 exception이 메인이었다.  작동 방식Presentation과 같다! 아래는 이해를 돕기 위해 이미지. 느낀 점controller, service, exception 등등 이때까지 해오면서 본 과정과 비슷했다.물론 이해하기 어려운 부분이 있었지만 Kotlin을 써보지 못한 낯섬에서 오는 문제라고 생각했다.이번 주에 아쉬운 점이 있다면 강의에서 사용된 뷰 템플릿의 유료화로 강의 진행에 차질이 있었다는 점.물론 강사님의 잘못은 아니지만 기간 내 완강을 하지 못하는 것에 아쉬움이 남는 것은 어쩔수가 없겠다.

워밍업3주차

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

1. 기본 정보강의명: 시작하는 PM/PO들에게 알려주고 싶은, 프로덕트에 대한 모든 것 (데이터 전문성 파트)2. 학습 목표 및 배경학습 배경: PM/PO로서 데이터 분석 역량이 점점 더 중요해지고 있어, 프로덕트 지표 설정부터 이벤트 기반 분석, 데이터 축적 방법 등을 정리하고자 강의를 수강.학습 목표:PM이 데이터를 어떻게 바라보고 활용해야 하는지 전체적인 흐름 파악제품(프로덕트) 지표를 설정하고 활용하는 다양한 프레임워크 이해이벤트 기반 분석 개념 및 Event Taxonomy 설계 방법 터득3. 일자별 요약 4. 데이터에 대한 전문성 쌓기 3/14 (금)4-1. PM의 데이터 활용PM이 데이터를 활용하는 전반적인 프로세스와 중요성에 대한 개념어떤 데이터를 수집해 어떻게 의사결정에 반영할 수 있는지 사례 소개4-2. 데이터 역량 쌓기데이터 역량을 단계별로 높이기 위한 구체적인 학습 및 업무 적용 방안통계, SQL, 시각화 툴, 분석 프레임워크 등 기초 역량 로드맵 제시 5. 데이터 전문성 : 프로덕트 지표 프레임워크3/17(월)5-1. 지표 설정 프레임워크 (1) – 지표란 무엇인가, Proxy 지표지표의 정의와 함께 실제 목표를 대체(Proxy)하는 지표 사례지표의 목적과 문제점을 잘 구분해서 설정하는 방법5-2. Acquisition사용자를 유입시키는 단계(Acquisition)에 관여하는 주요 지표들CAC(Customer Acquisition Cost), Conversion Rate 등 유입 관점 핵심 지표3/18 (화)5-3. Activation신규 유입 사용자가 “활성 사용자”로 전환되는 과정에서 보는 지표Core Action 지표 정의, Onboarding 과정을 개선하는 방식5-4. Engagement제품(서비스)에 대한 사용자의 참여도(Engagement)를 측정하는 지표DAU, WAU 등 사용자 활성도 추이를 모니터링하고 이탈을 방지하는 접근법3/19 (수)5-5. RetentionRetention(잔존율) 지표와 고객이 이탈하지 않도록 하는 관리 포인트AARRR 프레임워크의 Retention 부분을 구체적으로 파악5-6. Monetization, Metric Hierarchy제품/서비스에서 매출(수익화)을 고려한 지표 설정 방법Metric Hierarchy를 통해 조직 차원에서 지표 체계를 일관되게 관리 6. 데이터 전문성 : Event-Based Product Analytics3/20 (목)6-1. Event-Based Analytics, 데이터 축적을 위한 기본개념 이해하기이벤트 기반 분석이 무엇이며, 왜 필요한지(데이터 축적 구조와 방법)이벤트 단위로 사용자 행동을 추적해 인사이트를 도출하는 과정6-2. 필수 작업, Event Taxonomy 설계하기이벤트 명세서(Event Taxonomy) 설계의 중요성과 구체적 스키마 작성 방법마케팅, 개발, 운영 등 각 조직과 협업해 일관된 이벤트 명을 정의하는 사례 4. 학습 내용 및 주요 논의 정리데이터 역량의 필요성: PM이 전략적인 결정을 내릴 때 데이터가 필수적이며, 가설 수립부터 지표 모니터링, 후속 개선까지 모든 단계에 관여하게 됨.지표 설정 프레임워크 (AARRR): Acquisition, Activation, Retention, Revenue(Monetization), Referral로 이어지는 전형적인 사용자 여정별 핵심 지표를 어떻게 잡고 추적할지 습득.Proxy 지표: 최종 목표(예: 매출, 사용자 만족도 등)를 직접 측정하기 힘든 경우, 대체 지표(Proxy)를 설정해 제품 개선 방향성 확인.이벤트 기반 분석: 사용자 행동을 ‘이벤트’로 정의하고, 이를 수집·분석해 인사이트를 도출. 이벤트 Taxonomy 설계가 중요하며, 여러 팀 간 협업이 필수.Metric Hierarchy: 여러 지표를 계층적으로 구성해 우선순위를 두고 모니터링할 수 있도록 조직 차원에서 관리가 필요. 5. 결론 결론:단순히 “지표만 보는” 접근이 아니라, 비즈니스 목표 달성을 위해 적절한 지표(Proxy 포함)를 설정하고 이벤트를 추적·분석해야 함을 학습.데이터 역량은 ‘도구 사용’뿐 아니라, “무엇을 측정하고 왜 측정해야 하는가?”라는 질문에 대한 답을 찾는 논리적·전략적 사고력에서 비롯됨을 다시 확인.

PM/PO발자국3주차

재영

[인프런 워밍업 클럽 3기] CS - 3주차 미션 (자료구조와 알고리즘)

지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블 정렬시간 복잡도 : $O(n^2)$장점 : 이해와 구현이 간단.단점 : 성능이 좋지 않음. 선택 정렬시간 복잡도 : $O(n^2)$장점 : 이해와 구현이 간단.단점 : 성능이 좋지 않음. 삽입 정렬시간 복잡도 : $O(n^2)$장점 : 이해와 구현이 간단.단점 : 성능이 좋지 않음. 병합 정렬시간 복잡도 : $O(nlogn)$장점 : 위 알고리즘들 보다 성능이 좋다.단점 : 재귀적인 기법으로 이해하기가 어렵고, 구현도 어려움 퀵 정렬시간 복잡도평균 : $\Theta(nlogn)$최악 : $O(n^2)$대부분의 경우 피벗을 중간값으로 설정하므로 배열을 매번 반으로 가를 수 있으므로 평균적인 성능을 가진다고 봄장점 : 병합 정렬보다 더 적은 비교와 더 적은 메모리 공간을 차지하므로, 병합 정렬보다 더 좋은 알고리즘으로 평가됨단점 : 재귀적인 기법으로 이해하기가 어렵고, 구현도 어려움 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요. 타뷸레이션을 선택. 메모이제이션은 재귀를 이용해 문제를 하향식으로 해결하며 복잡한 문제를 쉽게 해결할 수 있음.메모이제이션은 계산 결과를 저장하는 방식으로 단점을 해결하는데, 이때 메모리를 이용해 성능을 향상시킴그러므로, 메모리가 부족한 시스템에서는 메모이제이션을 사용하는것은 오버플로우가 발생할 수 있을것으로 예상됨. 즉, 상향식 접근인 타뷸레이션을 선택하여 메모리를 절약하고, 속도도 빠르게 해결하는 것이 좋아보임.

인프런워밍업클럽3기CS3주차미션자료구조와알고리즘

치현

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

학습 내용인프런 워밍업 클럽 스터디 3주차로,이번 주는 넷플릭스 프로젝트를 다루는 시간이었다.useInfiniteQuery와 Jotai(recoil 대체 전역상태 라이브러리)를 사용해볼 수 있었다.미션 3 구현 내용과제 구현 저장소Netflix 중 찜하기 관련 기능 포인트 1: favorites 테이블 추가actions/favoriteActions.ts"use server"; import { createServerSupabaseClient, handleError, PostgrestError, } from "@next-inflearn/supabase"; // Movie 타입 정의 export type Movie = { id: number; image_url: string; overview: string; popularity: number; release_date: string; title: string; vote_average: number; // Movie 타입에 favorites 필드 추가 favorites?: { // optional field로 추가 id: number; } | null; }; // SearchMoviesResponse 타입 정의 export type SearchMoviesResponse = { data: Movie[]; page: number; pageSize: number; hasNextPage: boolean; }; // 에러 케이스를 위한 타입 정의 type SearchMoviesError = { data: never[]; count: number; page: null; pageSize: null; error: PostgrestError; }; // 성공 케이스를 위한 타입 정의 type SearchMoviesSuccess = { data: Movie[]; page: number; pageSize: number; hasNextPage: boolean; }; export async function searchMovies({ search, page, pageSize, }: { search: string; page: number; pageSize: number; }): Promise<SearchMoviesSuccess> { const supabase = await createServerSupabaseClient(); // 현재 사용자 정보 가져오기 const { data: { user }, } = await supabase.auth.getUser(); // 쿼리 설정 const query = supabase .from("movie") .select( user ? ` *, favorites!left ( id ) ` : "*", // 로그인하지 않은 경우 favorites 정보를 가져오지 않음 { count: "exact" } ) .ilike("title", `%${search}%`) .order("popularity", { ascending: false }); // 로그인한 경우 현재 사용자의 즐겨찾기만 조회하도록 필터링 if (user) { query.eq("favorites.user_id", user.id); } const { data, count, error } = await query.range( (page - 1) * pageSize, page * pageSize - 1 ); const hasNextPage = count ? count > page * pageSize : false; if (error) { return { data: [], page, pageSize, hasNextPage: false, }; } // 반환된 데이터를 Movie 타입에 맞게 변환 const moviesWithFavorites = (data || []).map((movie: any) => ({ ...movie, favorites: movie.favorites?.[0] || null, // 즐겨찾기 정보 포함 })); return { data: moviesWithFavorites, page, pageSize, hasNextPage, }; } export async function getMovie(id: string) { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase .from("movie") .select("*") .eq("id", id) .maybeSingle(); handleError(error); return data; } 포인트 2: profiles 테이블 추가utils/AuthProvider.tsx"use client"; import { useEffect } from "react"; import { createBrowserSupabaseClient } from "@next-inflearn/supabase"; import { useSetAtom } from "jotai"; import { userAtom } from "@/utils/jotai/atoms"; export function AuthProvider({ children }: { children: React.ReactNode }) { const setUser = useSetAtom(userAtom); const supabase = createBrowserSupabaseClient(); useEffect(() => { // 현재 세션 확인 supabase.auth.getSession().then(({ data: { session } }) => { setUser(session?.user ?? null); }); // Auth 상태 변경 구독 const { data: { subscription }, } = supabase.auth.onAuthStateChange((_event, session) => { setUser(session?.user ?? null); }); return () => subscription.unsubscribe(); }, [supabase, setUser]); return children; } 포인트 3: movies / favorites / profiles 테이블 연결favorites 테이블 내 profiles 테이블 내 회고 시간이 부족하다는 핑계로,더 디벨롭할 수 있는 부분이 많음에도 불구하고 생각했던 것들을 다 구현하진 못했던 것 같다.다만, 이렇게 틀을 갖춰놧으니 추후에 추가적인 기능을 정의해서 구현해보기 너무 좋을 것 같다.  

풀스택풀스택인프런워밍업스터디클럽Next3기SupabaseReact프론트엔드3주차발자국

leeebug

워밍업 클럽 스터디 3기 FS - 3주차 발자국

워밍업 클럽도 벌써 3주차!처음 스터디를 시작할 때와 비교하면 가장 큰 소득은 React Query에 익숙해졌다는 것 그리고 무언가에 몰입하면서 성취감을 느꼈다는 것이다.단순히 기능을 구현하는 걸 넘어서 최적화나 에러 핸들링까지 고민하는 과정이 꽤 재밌었다.이번주에는 인피니트 쿼리와 추가 기능으로 좋아요 기능을 구현해야해서 지난주와 마찬가지로 조금 일찍 학습을 시작했다.깃 레포는 역시 첫번째 과제에 사용했던 템플릿을 거의 수정없이 그대로 사용해서 역시나 개발환경 구축은 무리없이 진행했다.다만, 한 가지 아쉬운 점이라면 터보레포 같은 모노레포 도구를 도입했어야 하지 않았나 하는 생각이 들었다는 점이다.현재 방식은 각 주차별 과제를 독립적인 레포로 관리하고 있는데, 공통 유틸이나 자주 사용하는 설정 파일을 계속 복붙하는 과정에서 의외로 피로감을 느꼈다.우선 마지막 과제까진 지금의 방식을 유지하고 스터디 마무리 이후에 터보 레포에 대해서는 개별적으로 학습을 해볼 예정이다.📝 3주차 학습useInfiniteQuery무한 스크롤 및 페이지네이션을 위한 React Query 훅fetchNextPage를 사용해 추가 데이터 요청getNextPageParams로 다음 페이지 여부 관리 useInViewreact-intersection-observer 라이브러리의 훅특정 요소가 화면에 보이는지 감지(뷰포트 진입 여부로 확인)무한 스크롤 구현 시 useInfiniteQuery와 함께 사용threshold, rootMargin으로 감지 범위 조절 가능📋 3주차 미션💬 GitHub 저장소🚀 데모 영상 보러가기미션 해결 과정 요약이번주 미션의 필수 구현 과제는 무한 스크롤과 SEO 추가, 영화 검색 기능 구현하기였다. 추가 기능으로 영화 좋아요 기능을 구현했는데, 예전에 SNS를 만들때 경험해봤던 기능이라 쉽게 구현할 수 있을 것이라 기대했다. 하지만 예상과는 달리, 유저 식별 기능이 없다는 점이 문제였다. SNS 좋아요 기능 구현 당시에는 사용자 ID 기반으로 좋아요를 관리했지만 이번 프로젝트는 익명 유저 환경이라 데이터를 어떻게 저장하고 관리할지 고민이 필요했다.처음에는 movies, users, liked_movies 3개의 테이블을 생성하여 user_id, movies_id를 복합키로 설정해 브라우저별 익명 유저를 관리하는 방식을 시도했으나 구현 복잡도가 너무 높아지는 문제로 단순화하는 방식으로 변경했다.movies 단일 테이블에 like_count 필드를 추가하고 브라우저별로 좋아요 상태를 관리하는 방식으로 해당 기능을 구현했다. 이 방식의 단점은 브라우저 변경 시 개인별 좋아요 리스트를 추적할 수 없다는 점이지만 애초에 유저 식별 기능을 배제한 상황에서 선택할 수 있는 최적의 방식이라고 판단하여 적용했다.그리고 강의에서는 movies.id를 auto increment id로 구현했지만 더 나은 확장성을 위해서 uuid를 고려했다. 다만 uuid는 URL에서 사용하기 불편하여 가독성이 좋은 slug 칼럼을 별도로 추가하였다. API 요청 파라미터를 id에서 slug로 대체하면서 가독성과 SEO 최적화까지 함께 챙겨갈 수 있었다.slug Column 추가ALTER TABLE myreel_movies ADD COLUMN slug TEXT UNIQUE;중복되는 Row 제거 (제공되는 DB에 중복되는 데이터가 9건 발견되었다.)DELETE FROM myreel_movies WHERE id NOT IN ( SELECT id FROM ( SELECT id, title, order_index, ROW_NUMBER() OVER (PARTITION BY title ORDER BY order_index ASC) AS row_num FROM myreel_movies ) ranked WHERE row_num = 1 );영화 title 기준으로 slug 생성예시 - 'Dune: Part Two' -> 'dune-part-two'UPDATE movies SET slug = LOWER(REGEXP_REPLACE(title, '[^a-zA-Z0-9]+', '-', 'g')) WHERE slug IS NULL;과제 추가 구현 기능✅ 영화 좋아요 추가api/movies/:slug/likeconst likeMovie = async () => { try { const res = await fetch(`${baseUrl}${API_ENDPOINTS.LIKE(slug)}`, { method: 'POST', }) if (!res.ok) { throw new Error(CLIENT_ERROR.MOVIE_LIKE_FAILED.message) } const data: LikeMovieResponseDTO = await res.json() setLikeCount(data.like_count) // 서버에서 받아온 새로운 좋아요 수로 업데이트 setIsLiked(true) // 로컬 스토리지에 영화 추가 또는 업데이트 const likedMovies: LikedMovie[] = JSON.parse(localStorage.getItem('likedMovies') || '[]') // 이미 좋아요를 누른 영화가 있다면, likeCount를 업데이트 const existingMovieIndex = likedMovies.findIndex((movie) => movie.slug === slug) if (existingMovieIndex >= 0) { likedMovies[existingMovieIndex].likeCount = data.like_count // 좋아요 수 업데이트 } else { // 좋아요를 누른 적이 없다면 새로 추가 const newLikedMovie = { slug, likeCount: data.like_count } likedMovies.push(newLikedMovie) } localStorage.setItem('likedMovies', JSON.stringify(likedMovies)) } catch (error) { console.error(error) } }✅ 영화 좋아요 삭제api/movies/:slug/unlikeconst unlikeMovie = async () => { try { const res = await fetch(`${baseUrl}${API_ENDPOINTS.UNLIKE(slug)}`, { method: 'POST', }) if (!res.ok) { throw new Error(CLIENT_ERROR.MOVIE_UNLIKE_FAILED.message) } const data: LikeMovieResponseDTO = await res.json() setLikeCount(data.like_count) setIsLiked(false) // 로컬 스토리지에서 해당 영화 정보 삭제 const likedMovies: LikedMovie[] = JSON.parse(localStorage.getItem('likedMovies') || '[]') const updatedLikedMovies = likedMovies.filter((movie) => movie.slug !== slug) // 로컬 스토리지 갱신 localStorage.setItem('likedMovies', JSON.stringify(updatedLikedMovies)) } catch (error) { console.error(error) } }개인 챌린지 기능✅ 메인 페이지 최상단으로 가는 버튼 추가메인 페이지에서 500px 이상 스크롤 내릴 경우 최상단으로 이동하는 버튼 생성behavior: 'smooth' 로 부드럽게 이동 ✅ 검색 결과 없을 경우, 좋아요 많은 순 추천 영화 6개 노출되는 기능 구현좋아요가 많은 영화 외에도 최근 개봉한 영화 같은 다양한 리스트 제공 예정api/movies/most-liked👀 3주차 회고지난주에 적용했던 매니져 컴포넌트 / UI 컴포넌트로 분리하는 방식이 Container-Presentational Component 패턴 과 유사한 방식이라는 것을 다른 러너분의 발자국을 통해 알게되었다. 궁금해서 조금 더 찾아보니, 이 패턴은 과거 클래스형 컴포넌트 시절에는 HOC(High Order Component)와 함께 많이 사용되었지만, 함수형 컴포넌트에서도 여전히 유효한 방식이라는 것을 알게되었다. 이번주에는 기존 패턴을 유지하면서도, 비즈니스 로직을 최대한 커스텀 훅으로 분리하는 연습을 진행했다. 이를 통해 컴포넌트의 역할을 더욱 명확하게 나누고, 재사용성과 유지보수성을 높이는 방향으로 조금씩 개선되고 있다는 것을 체감했다.👻 배포 관련 이슈 (3월 22일 추가)4주차에 스터디 기간 개발한 4개의 프로젝트를 모두 배포하는것이 기존 스터디 일정이지만.. 시간적 여유가 생겨서 1~3주차 프로젝트를 미리 배포해봤다. vercel은 기존에 사용하던 툴이었는데 한번에 3개의 프로젝트를 배포하려고 시도하는 과정에서 수 많은 에러를 경험했다. 4주차 프로젝트 배포시, 추후 다른 프로젝트 배포시에 참고할 수 있도록 간단하게 정리해본다. ✅ @/components/... 앨리어스 관련 캐싱 이슈문제 개발 환경에서는 정상 작동하던 import가 Vercel 배포 시에만 Module not found 에러 발생원인Vercel의 캐싱 문제 또는 파일명 인식 관련 문제(대소문자, 내부 경로 변경 후 캐시 꼬임)해결@ 앨리어스 문제를 의심하여 상대 경로로 변경 후 재배포 시도 -> 해결 안됨컴포넌트 경로의 대소문자 확인후 재배포 시도 -> 해결 안됨 Title.tsx 파일명을 AppTitle.tsx로 변경하여 강제로 캐시 무력화 후 재배포 시도 -> 해결 ✅ params 비동기 처리 관련 타입 에러 (Next.js 15)문제page.tsx에서 params를 비동기적으로 처리하려 하자, params 타입이 Promise로 인식되어 타입 오류 발생원인 (깃헙 이슈 참고)Next.js 15 내부적으로 PageProps가 비동기적 처리를 기대하거나 타입 추론이 변경됨params 타입이 Promise<any>로 추론되어 관련 에러 발생PageParams 제네릭 타입 해석 충돌next dev에서는 정상 작동하지만 next build 시 오류 발생해결params의 인터페이스를 명시적 타이핑 -> 해결 안됨params의 타입 any로 명시하고 타입 단언으로 처리 -> 해결 안됨배포 시 안정성 확보를 위해서 Next.js 14 + React 18 버전으로 롤백 -> 해결✅ Tailwind CSS 적용 안됨문제배포된 페이지에서 Tailwindcss 클래스가 적용되지 않음원인Next.js 15 -> Next.js 14, React 19 -> React 18로 롤백하는 과정에서 관련된 의존성 충돌이 일어난것으로 예상됨해결Tailwindcss, postcss, autoprefixer 의존성 삭제 후 캐시 초기화 후 재설치 -> 해결 ✅ 환경 변수(NEXT_PUBLIC_BASE_URL) 미설정으로 fetch 실패문제빌드 시 fetch 요청이 localhost:3000으로 날아가면서 ECONNREFUSED 에러 발생원인Vercel 환경 변수 설정 시 NEXT_PUBLIC_BASE_URL 값을 localhost:3000으로 설정하여 에러 발생해결해당 환경 변수를 실제 배포 URL로 변경 후 재배포 시도 -> 해결

풀스택워밍업클럽3기회고발자국3주차

lar

[인프런 워밍업 클럽 스터디 1기] 세번째 발자국

1. 3주차 학습한 내용 [10일차 - 객체지향과 JPA 연관관계]1. JPA 연관관계에 대한 추가적인 기능들1:1 관계 - @OneToOne예) 한 사람은 한 개의 실거주 주소만을 갖고 있다.@OneToOne 어노테이션을 사용한다.연관관계 주인이 아닌 쪽에 mappedBy 옵션을 사용한다.연관관계의 주인 효과객체가 연결 기준이 된다.상대 테이블을 참조하고 있으면 연관관계의 주인이다.연관관계 주인이 아니면 mappedBy를 사용한다.연관관계의 주인의 setter가 사용되어야만 테이블을 연결한다.연관관계의 사용 시 주의해야 할 점트랜잭션이 끝나지 않았을 때, 한 쪽만 연결해두면 반대 쪽은 알 수 없다. > setter 한번에 둘이 같이 이어주면 된다.N:1 관계 - @ManyToOne과 @OneToMany@ManyToOne을 단방향으로만 사용할 수도 있다.cascade 옵션 : 한 객체가 저장되거나 삭제될 때, 연결되어 있는 객체도 함께 저장되거나 삭제되는 옵션이다.orphanRemoval 옵션 : 객체간의 관계가 끊어진 데이터를 자동으로 삭제하는 옵션이다.실제 DB에서 데이터를 삭제하고 싶을 때 사용한다.@JoinColumn연관관계의 주인이 활용할 수 있는 어노테이션을 의미한다.필드의 이름, null여부, 유일성 여부, 업데이트 여부 등을 지정한다.N:M 관계 - @ManyToMany구조가 복잡하고, 테이블이 직관적으로 매핑되지 않아 사용하지 않는 것을 권장한다.도메인 계층에 비즈니스 로직이 들어갔다?BookService는 UserLoanHistory 객체를 직접 사용하지 않도록 변경하였다.User와 UserLoanHistory, 2개의 객체가 서로 협력하도록 변경하였다. 이를 도메인 계층에 비즈니스 로직이 들어갔다라고 표현한다.2. 영속성 컨텍스트의 4번째 특징지연 로딩(Lazy Loading) : 연결되어 있는 객체를 꼭 필요한 순간에만 가져온다.@OneToMAny의 fetch 옵션이다.(기본적으로 Lazy로 설정되어 있다.)연관관계를 사용하면 무엇이 좋을까?각자의 역할에 집중하게 된다. (=응집성)새로운 개발자가 코드를 읽을 때 이해하기 쉬워진다.테스트 코드 작성이 쉬워진다.연관관계를 사용하는 것이 항상 좋을까?지나치게 사용하면 성능 상의 문제가 생길 수도 있고, 도메인 간의 복잡한 연결로 인해 시스템을 파악하기 어려워질 수 있다.비즈니스 요구사항, 기술적인 요구사항, 도메인 아키텍쳐 등 여러 부분을 고민해서 연관관계 사용을 선택해야 한다.[11일차 - 기본적인 배포를 위한 준비]1. 배포란?최종 사용자에게 SW를 전달하는 과정을 의미한다.전용 컴퓨터(AWS)에 우리의 서버를 옮겨 실행시키는 것이다.최종 사용자가 우리의 서버를 쓸 수 있는 방법전용 컴퓨터에 코드를 옮기고 스프링, MYSQL 등을 설치해 사용자가 접속하게 한다.AWS에서 컴퓨터를 빌릴 때 알아둬야 할 점컴퓨터를 살 때 운영체제도 같이 선택한다.윈도우, 리눅스, 맥OS2. profile과 H2 DBprofile 적용스프링 서버를 실행할 때 db와 같은 설정들을 코드 변경 없이 제어할 수 있는 방법spring: config: activate: on-profile: local datasource: url: "jdbc:h2:mem:library;MODE=MYSQL;NON_KEYWORDS=USER" username: "sa" password: "" driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true dialect: org.hibernate.dialect.H2Dialect h2: console: enabled: true path: /h2-console --- spring: config: activate: on-profile: dev datasource: url: "jdbc:mysql://localhost/library" username: "root" password: "" driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: none properties: hibernate: show_sql: true format_sql: true dialect: org.hibernate.dialect.MySQL8Dialect 3. git과 githubgit이란?코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램을 의미한다.버전 A, 버전 B를 쉽게 만들 수 있게 해주고 여러 버전을 쉽게 취합이 가능하다.github이란?git으로 관리되는 프로젝트의 코드가 저장되는 원격 저장소를 의미한다.왜 github에 코드를 저장하는걸까?컴퓨터의 있는 소스코드가 소실될 수 있기 때문에 코드를 원격의 저장하는 것이다.배포할 때도 활용한다.4. git 기초 사용법git을 활용해서 github 프로젝트 업로드하기github 사이트 접속github 저장소 생성한다.(Create Repository)IntelliJ Terminal을 이용해 git 명령어 입력git 프로젝트 시작하기 / git init : 이 프로젝트를 이제 git이 관리하겠다는 의미git 프로젝트의 github 저장소 설정하기 / git remote add origin [각자의 주소]기초 셋팅 완료git 기초 명령어코드를 git에 추가할 때 명령어git add.git에 메세지 붙이는 명령어git commit-m "메세지"git을 github에 보내기git push현재 상황 확인하기git status파일들 빼주기git reset5. AWS의 EC2 사용하기회원가입AWS 계정 생성(회원가입) - 회원정보/결제정보/본인인증/Support 플랜 (무료) 선택로그인루트 사용자 선택 - 계정입력 후 로그인콘솔 홈지역(서버) 서울로 설정서비스에서 EC2 검색 및 클릭 - 리소스 : 인스턴스(빌린 컴퓨터) 클릭인스턴스 시작 클릭 - 이름 및 태그 : 이름 입력 - 아마존 리눅스 선택 - 인스턴스 유형(빌린 컴퓨터의 사양) CPU 및 메모리 t2.micro 선택 - 키 페어 : 새 키 페어 생성 - 키 페어 이름 입력 수 생성 - 네트워크 설정 : 보안 그룹 생성 선택 - 스토리지 구성(용량) 8gib - 설정 후 인스턴스 시작 클릭인스턴스 목록을 보면 실행 중인 서버가 확인된다. [12일차 - AWS와 EC2 배포]1. EC2에 접속해 리눅스 명령어 다뤄보기다운로드 받은 키 페어를 이용하는 방법우리가 접속하려는 EC2의 IP 주소 : 퍼블릭 IPv4 주소이전 시간에 다운로드 받았던 키 페어접속하기 위한 프로그램(git CLI 또는 Mac treminal)기본적인 리눅스 명령어mkdir : 폴더를 만드는 명령어ls : 현재 위치에서 폴더 또는 파일을 확인하는 명령어cd : 폴더 안으로 들어가는 명령어pwd : 현재 위치를 확인하는 명령어2. 과제여섯 번째 과제(6일차)일곱 번째 과제(7일차)3. 회고프로젝트 배포 하는 법을 알 수 있어서 좋았고, 배포를 하면서 오류가 발생해서 한번에 되지 않아 시간이 오래 걸렸다. 리눅스에 대한 공부도 해야겠다는 생각이 들었다. 아직 미니 프로젝트를 진행하진 못했지만 배운 것을 활용해서 잘 마무리해야겠다!

백엔드워밍업발자국회고3주차

lar 2024.05.19
miiro

[인프런 워밍업 스터디 클럽 1기] BE 3주차 회고록

세 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 세 번째 회고록입니다. 학습 내용배포란?최종 사용자에게 SW를 전달하는 과정이다. = 전용 컴퓨터에 우리의 서버를 옮겨 실행시키는 것서버용 컴퓨터는 보통 리눅스를 사용한다.profile과 H2 DBprofile : 똑같은 서버 코드를 실행시키지만, 실행될 때 설정을 다르게 하고 싶다.(ex. Database)[예시]local profile -> H2 DBdev profile -> MySQL DB  H2 DB경량 database로, 개발 단계에서 많이 사용하며 디스크가 아닌 메모리에 데이터를 저장할 수 있다.메모리에 데이터를 저장하면 휘발되는 특징으로 인해 개발 단계에서만 사용한다개발단계에서는 테이블이 계속 변경되는데, 데이터가 휘발되기에 ddl-auto 옵션을 create로 주면 테이블이 자동 생성/삭제가 되기에 주로 사용된다.git/githubgit코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램githubgit으로 관리되는 프로젝트의 코드가 저장되는 저장소사용하는 이유?코드는 어떠한 이유로든 소실이 될 가능성이 있다.배포를 할 때 활용할 수 있다.git 명령어git init해당 프로젝트를 git이 관리하겠다는 의미git 프로젝트의 github 저장소 설정git remote add origin [git 주소]코드를 git에 모든 파일을 넣는다git add .Git 커밋 명령어git commit -m '메시지'Git 푸시 명령어git push코드 github에 최초로 보내기git push --set-upstream origin masterGit 상태 확인git status.gitignore파일 안에 적힌 폴더 및 파일의 이름은 깃으로 관리하지 않는다. EC2에 접속해서 리눅스 명령어 다뤄보기 EC2 접속 방법다운로드 받은 키 페어(pem key)를 이용하는 방법접속하려는 EC2의 IP 주소다운로드 받은 키 페어 접속하기 위한 프로그램(git CLI or Mac Terminal) chmod 400 키페어이름.pemssh -i 경로/키페어이름.pem ec2-user@IPAWS 콘솔을 활용해서 접속하는 방법 기본적인 리눅스 명령어mkdir : 폴더를 만드는 명령어ex) mkdir folder1ls : 현재 위치에서 폴더나 파일을 확인하는 명령어ls -l : 조금 더 자세한 정보를 확인할 수 있다. drwxrwxr-x : folder1은 폴더이다.drwxrwxr-xr : 읽는 권한, w : 쓸 수 있는 권한, x : 실행 권한rwx/rwx/r-x폴더 소유자 권한 / 폴더 소유 그룹 권한/ 모든 접근의 권한2 : 폴더에 걸려 있는 바로가기 개수ec2-user : 폴더 소유주의 이름ec2-user : 폴더 소유 그룹의 이름6 : 폴더(파일의 크기) 단위 : byte cd(change directory) : 폴더 안으로 들어가는 명령어ex) cd folder2pwd(print working directory) : 현재 위치 확인하는 명령어/home/ec2-user/folder1cd .. : 상위 폴더로 올라가는 명령어rmdir : 특정 폴더(디렉토리) 제거하는 명령어 배포를 위한 프로그램 설치하기 코드를 가져오기 위한 Gitsudo yum install git : yum을 이용한 프로그램 다운로드 진행한다.서버를 구동할 Javasudo yum install java-11-amazon-corretto -yjava -version : 자바 버전 확인데이터베이스 MySQLsudo dnf install https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpmsudo dnf install mysql-community-serversudo systemctl status mysqldsudo systemctl restart mysqldsudo cat /var/log/mysqld.log | grep "A temporary password"mysql8의 임시 비밀번호를 확인하는 명령어alter user 'root'@'localhost' identified with mysql_native_password by 'Abdc1234!';비밀번호는 대/소문자, 특수문자 포함 8자 이상 리눅스에서 스프링 배포 프로그램 설치sudo yum updatesudo : 관리자 권한 실행yum : 리눅스 패키지 관리 프로그램(ex. gradle과 비슷한 역할)update : 현재 프로그램들을 최신화 설정한다. 빌드와 실행, 그리고 접속 git 코드 로딩 :git clone [github 저장소 주소]swap 설정기존에는 RAM을 사용해야하지만 RAM의 용량이 부족한 경우, 일부 Disk를 사용하게 해준다.#swap 메모리를 할당한다. (128M 16 = 2GB) sudo dd if=/dev/zero of=/swapfile bs=128M count=16 #스왑 파일에 대한 권한 업데이트 sudo chmod 600 /swapfile #swap 영역 설정 sudo mkswap /swapfile #swap 파일을 사용할 수 있도록 만든다. sudo swapon /swapfile #swap 성공 확인 sudo swapon -schmod +x ./gradlewgradlew를 사용하기 위해 실행할 수 있도록 설정한다../gradlew build -x testgradle을 이용해 프로젝트를 빌드한다. -> 테스트코드는 실행하지 않는다. java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev--spring.profiles.active=dev : 설정 파일등록 이후에 인스턴스 인바운드 규칙 설정을 해줘야한다.8080 포트 Open  jar 파일만 실행했는데 서버가 동작하는 이유?SpringBoot 에는 톰캣(Tomcat)이 내장되어 있기 때문이다.톰캣(Tomcat)웹 애플리케이션 서버(WAS)의 한 종류로써, 요청이 들어오면 그 요청을 약속된 형식에 맞추어 스프링에 전달해준다.실행 중인 서버 중단ctrl + c./gradlew clean현재 빌드되어 있는 결과물 제거 foreground vs background foreground우리가 보고 있는 프로그램ex) PDF 프로그램이 foreground 프로그램 background우리가 보고 있지 않은데 실행중인 프로그램ex) 컴퓨터에서의 백신 프로그램 리눅스에서 background로 동작하게 만드는 명령어nohup [명령어] &nohup java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar &rm nohup.out  background 서버 다운작업관리자 명령어ps aux : 현재 실행중인 프로그램 목록을 확인할 수 있다.ps aux | grep java : java가 들어가는 프로그램을 확인한다.kill -9 프로그램번호 : 해당 프로그램을 종료시킨다.파일의 내용물을 확인하는 방법파일에 직접 들어가 내용물 확인vi : 리눅스 편집기인 vim을 사용하여 파일을 접속한다. (ex. vi nohup.out)파일에 들어가지 않고 현재 접속중인 터미널을 활용하는 방법cat : 파일에 있는 내용물을 모두 출력하는 명령어(ex. cat nohup.out)파일 내용물의 양이 많지 않고, 실시간 업데이트가 잘 되지 않는 파일을 확인할 때 사용한다.tail : 현재 파일의 끝 부분을 출력하는 명령어tail -f : 현재 파일의 끝부분을 실시간으로 출력해준다.  과제 내용Day 6Controller, Service, Repository의 3단 분리 구조를 채택하여 백엔드 설계를 진행했습니다.Repository 클래스에서는 jdbcTemplate를 활용해 SQL문을 직접 작성하고 데이터베이스와 직접적으로 연결하는 방식을 택했습니다. 이 과정에서 @Repository 어노테이션을 활용한 생성자를 통한 의존성 주입이 이루어지는 것을 확인할 수 있었습니다.특히, 다양한 저장소 구현체(FruitMySqlRepository, FruitMemoryRepository)를 만들면서, @Primary 어노테이션을 활용하여 서비스 로직이 실행될 때 어떤 레포지토리 레이어를 우선적으로 사용할지 결정하는 방식을 경험했습니다. 이러한 구조적 접근은 유연하고 확장 가능한 백엔드 시스템을 구축하는 데 큰 도움이 되었습니다.📋 6일차 미션: 레이어 3단 분리 Day 7JDBCTemplate을 사용해 시스템을 구축한 DB를 성능 개선과 유지보수의 편의성을 위해 JPA로 전환하였습니다.엔티티 클래스인 Fruit에서는 과일의 이름, 입고 날짜, 가격, 판매 여부를 관리했습니다. JPA의 강력함은 FruitRepository 인터페이스를 통해 드러났다. 여기서 단순 조회부터 복잡한 조건의 데이터 처리까지 어노테이션 몇 개로 해결할 수 있었습니다. FruitServiceV2에서는 과일의 저장, 판매 상태 업데이트, 통계 조회 등 핵심 비즈니스 로직을 구현하여, 코드의 간결함과 효율성을 극대화했습니다.특히, 과일의 개수를 세거나, 특정 가격 이상 또는 이하의 과일을 조회하는 기능을 추가하며, JPA의 유연성과 편리함에 다시 한번 감탄했습니다. 이 모든 과정을 통해, 나는 JPA의 놀라운 잠재력을 경험하며, 보다 나은 소프트웨어 개발자로 성장할 수 있는 계기를 마련한 것 같습니다.📋 7일차 미션: JPA 구현회고SW 배포는 최종 사용자에게 소프트웨어를 전달하는 과정으로, 리눅스 기반 서버 컴퓨터에서 주로 이루어집니다. 개발 단계에서는 경량화된 H2 DB를 활용하여 데이터의 휘발성을 감안한 개발 환경을 구축합니다. Git과 GitHub을 통한 버전 관리 및 코드 저장소 활용은 코드 소실 방지와 효율적인 배포 과정을 지원합니다. EC2와 리눅스 명령어를 통한 서버 접속 및 관리, 그리고 리눅스 환경에서의 스프링 배포는 필수적인 프로세스라는 것을 알게 되었습니다.또한, Controller, Service, Repository의 3단 분리 구조를 채택하여 백엔드 설계를 진행하고, JDBCTemplate에서 JPA로 전환하여 성능 개선과 유지보수의 편의성을 높였습니다. 이 모든 과정은 유연하고 확장 가능한 백엔드 시스템 구축과 개발자로서의 성장에 밑거름이 된 거 같습니다.

백엔드인프런워밍업스터디클럽3주차회고록

채널톡 아이콘