블로그
전체 11#카테고리
- 시스템 · 운영체제
- 백엔드
#태그
- 워밍업클럽3기
- CS
- 발자국
- cs
- 미션
- 운영체제
- 자료구조
- 테스트코드
- 워밍업클럽2기
- 백엔드
- 4주차
- 회고
- Day18
- 모킹
- Day15
- 발자국3주차
- 클린코드-테스트코드
- 2주차
- 1주차
- ReadableCode
- Day4
2025. 03. 16.
0
[워밍업 클럽 3기 - CS 전공 지식] - 2주차 발자국
✍ 학습 내용 복습Q. 공유 자원(Shared Resource)이란?A. 공유 자원은 여러 프로세스나 스레드가 동시에 사용하거나 접근할 수 있는 자원을 의미한다. 프로세스 또는 스레드 간에 공통으로 사용되기 때문에, 자원에 대한 접근을 관리하는 것이 중요한다.Q. 임계 구역(Critical Section)이란?A. 공유 자원에 동시에 접근이 가능한 구간.(보통 코드 구간을 의미)Q. 상호 배제(Mutual Exclusion)이란?A. 공유 자원에 대해 한 번에 하나의 프로세스나 스레드만 접근할 수 있도록 보장하는 것.Q. 교착 상태(Deadlock)이란?A. 여러 개의 프로세스나 스레드가 서로 자원을 기다리며 무한히 대기하는 상태. 교착 상태가 발생하기 위해서는 다음의 4가지 조건이 필요하다. 상호 배제, 비선점, 점유와 대기, 원형 대기. 하나라도 만족하지 못한다면 교착상태에 빠지지 않는다
워밍업클럽3기
・
CS
・
발자국
2025. 03. 16.
0
[워밍업 클럽 3기 - CS 전공 지식] - Day 9 미션 2
운영체제FIFO 스케줄링의 장단점이 뭔가요?장점단순하고 이해하기 쉽다단점실행 시간(burst time)이 짧은 프로세스는 실행 시간이 길더라도 일찍 도착한 프로세스의 완료를 기다려야한다 SJF를 사용하기 여러운 이유가 뭔가요?A. 프로세스의 실행시간을 예측하기 어렵다. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?A. 컨텍스트 스위칭을 처리하는 비용이 증가한다. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?A. CPU 사용시간에 따라 우선순위 큐에 다르게 배치하면서 구분한다. 예를 들어, CPU 바운드 작업은 타임 슬라이스를 I/O 바운드 작업보다 오래 점유해서 사용하기 때문에, 우선순위가 낮은 큐에 배치시키고, 더 짧게 사용하는 I/O 바운드 프로세스는 우선순위가 더 높은 큐에 배치시킨다. (타임 슬라이스를 사용하는 시간과 요청 빈도에 의한 피드백) 공유자원이란 무엇인가요?A. 프로세스간 통신에서 공통으로 접근해서 이용하게 되는 데이터. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?상호 배제: 자원은 한번에 하나의 프로세스만 사용비선점: 이미 점유한 자원은 다른 프로세스가 뺏어갈 수 없다점유와 대기: 이미 자원을 점유한 프로세스가 추가적인 자원을 기다리는 상태원형 대기: 프로세스들이 서로가 가지고 있는 자원을 기다리며 대기하는 상태자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?A. 함수에서 탈출하지 못하기 때문에 무한하게 재귀를 호출하게 되면서 스택 오버플로우(StackOverflow)가 발생한다.0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.A.function sumOdd(n) { if (n 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.import fs from "fs"; import path from "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("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 console.log("------------------------"); function traverseDirectory2(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); traverseDirectory2(filePath); // 재귀 호출하여 내부 탐색 } else { // 파일인 경우 console.log('파일:', filePath); } } } traverseDirectory2("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력
워밍업클럽3기
・
cs
・
미션
2025. 03. 09.
0
[워밍업 클럽 3기 - CS 전공 지식] - Day 5 미션 1
운영체제 1. while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? A. 인터럽트(Interrupt) 방식 프로그램과 프로세스가 어떻게 다른가요?A. 프로그램 자체는 명령어의 집합일 뿐이다. 반면에 프로세스는 해당 프로그램을 실행하여, 프로세스가 사용할 독립된 메모리 공간을 할당받는다. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요? A. 멀티 프로그래밍은 메모리에 여러개의 프로세스를 올려서 처리하는 방식이다. CPU가 한 프로그램의 I/O 작업 등을 기다리는 동안 다른 프로그램을 실행할 수 있게한다. 멀티 프로세싱은 여러 CPU(또는 코어)를 사용하여 여러 프로세스를 실제로 동시에 처리하는 것을 말한다. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요? A. 프로세스를 관리하기 위한 주요 요소는 다음과 같다.프로세스의 정보를 담고있는 PCB(Process Control Block)를 사용생성, 준비, 대기, 실행, 완료로 프로세스 상태를 관리한다어떤 프로세스에 CPU 시간을 할당할지 결정하기 위해 CPU 스케쥴링(Scheduling)을 사용한다 컨텍스트 스위칭이란 뭔가요?A. 운영 체제가 CPU를 하나의 프로세스에서 다른 프로세스로 전환하는 과정. 과정을 대략적으로 설명하면 다음과 같다.인터럽트가 발생하면, 운영 체제는 현재 실행 중인 프로세스의 상태 정보를 PCB에 저장(스케줄러는 준비 상태 큐에 있는 프로세스 중에서 선택)선택된 프로세스의 PCB에서 상태 정보를 참조해서 상태를 복원 자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. A1. 단일 교실 규모라면 배열 또는 리스트를 사용한다이유: 학생에 대한 변경(추가/삭제)는 자주 일어나지 않는다. 순서를 보장할 수 있다. 교실 전체의 학생을 순회하여 조회하는 경우가 많다.A2. 학교 전체를 관리하는 경우 해시 맵을 사용한다이유: 읽기/쓰기/삭제 등의 작업에 O(1)의 성능을 보장하기 때문에 효율적이다. 현재 컴퓨터의 성능을 고려하면, 메모리 문제가 발생할 가능성은 낮다. 특정 정보를 키로 활용할 수 있다.(예시: 학번을 키로 사용) 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.A. 큐(Queue) 자료구조를 사용한다이유: 가장 먼저 들어온 데이터가 가장 먼저 나가는 구조이기 때문에, 주문이 들어온 순서대로 처리하기에 적합하다. 우리가 구현한 스택은 0번 인덱스, 즉 입구쪽으로 데이터가 삽입되고 나오는 구조입니다. 반대로 마지막 인덱스, 즉 출구쪽으로 데이터가 삽입되고 나오는 구조로 코드를 변경해주세요.A.push(data) { // 0번 인덱스 대신 마지막 인덱스에 삽입 this.list.insertLast(data); } pop() { try { // 0번 인덱스 대신 마지막 노드 삭제 및 반환 return this.list.deleteLast(); } catch(e) { return null; } } 해시테이블의 성능은 해시 함수에 따라 달라집니다. 수업 시간에 등번호를 이용해 간단한 해시 함수를 만들어봤습니다. 이번엔 등번호가 아닌 이름을 이용해 데이터를 골고루 분산시키는 코드로 수정해주세요. 힌트: charCodeAt() 함수를 이용 예시: name1 = "이운재"; name1.charCodeAt(0); // 51060 이운재의 0번 인덱스 ‘이’의 유니코드 출력 hashFunction(name) { let hashValue = 0; for (let i = 0; i
워밍업클럽3기
・
CS
・
미션
2025. 03. 09.
0
[워밍업 클럽 3기 - CS 전공 지식] - 1주차 발자국
✍ 학습 내용 복습Q. 배열(Array)의 특징은?A. 가장 기본적인 자료구조배열은 같은 종류의 데이터들이 순차적으로 저장되어 있다배열의 크배열은 메모리 주소가 연속될 것을 요구하기 때문에 배열의 크기를 늘리는 것은 불가능기에 상관 없이 인덱스를 알고 있으면 해당 원소로 접근하는데 걸리는 시간은 O(1)이다(참조의 성능이 좋다)배열의 크기를 늘릴 필요가 있다면 크기가 더 큰 새로운 배열을 생성하여 기존 배열의 내용을 복사하는 과정이 필요하다 Q. 연결 리스트(Linked List)의 특징은?A.연결 리스트는 낭비되는 메모리 없이 필요한 만큼만 메모리를 확보해서 사용하기 위해서 노드를 만들고 각 노드를 서로 연결해서 사용한다노드는 저장할 데이터와 다음 노드로 향하는 참조를 가지고 있다. 첫 노드(헤드 노드)의 주소만 알고 있으면, 다른 연결된 모든 노드에 접근할 수 있다초기에 크기를 정해야 하는 기존 배열의 단점을 해결할 수 있다 Q. 해시 테이블(Hash Table)의 특징은?A.키-값(Key-Value) 형태의 자료구조키를 알고 있다면, O(1)의 성능으로 값을 읽기/삽입/수정/삭제하는 것이 가능하다(해시 충돌이 없다는 가정)해시 함수(해시 알고리즘)를 사용한다. 해시 함수를 통해 값에 대한 해시값을 계산한다.해시 인덱스(hash index)는 데이터가 저장될 위치라고 생각하면 편한다해시 값에 대한 해시 인덱스를 구하는 과정을 해싱(hashing)이라고 한다해시 충돌(hash collision)은 이미 키에 값이 존재하는 경우에 값을 삽입되는 경우 발생한다. 이 경우 해당 키에서는 값들을 리스트로 저장해서 사용한다. Q. 프로세스(Process)란?A. 실행 중인 프로그램. 프로그램 자체는 명령어의 집합일 뿐이다. 반면에 프로세스는 해당 프로그램을 실행하여, 프로세스가 사용할 독립된 메모리 공간을 할당받는다. Q. 시분할 시스템(Time-Sharing System)이란?A. CPU가 여러 프로세스에게 짧은 시간 간격(시간 조각)을 할당하고, 각 프로세스는 이 시간 동안만 실행되는 방식의 시스템. 시간 간격이 매우 짧아서 여러 프로세스가 동시에 실행되는 것처럼 보이게 만들 수 있다. Q. 컨텍스트 스위치(Context-switch)란?A. 운영 체제가 CPU를 하나의 프로세스에서 다른 프로세스로 전환하는 과정. 과정을 대략적으로 설명하면 다음과 같다.인터럽트가 발생하면, 운영 체제는 현재 실행 중인 프로세스의 상태 정보를 PCB에 저장(스케줄러는 준비 상태 큐에 있는 프로세스 중에서 선택)선택된 프로세스의 PCB에서 상태 정보를 참조해서 상태를 복원CPU가 새 프로세스를 실행하기 시작 🤔 회고CS 지식을 복습할 수 있어서 너무 좋았다
시스템 · 운영체제
・
워밍업클럽3기
・
CS
・
운영체제
・
자료구조
2024. 10. 27.
0
[워밍업 클럽 2기 - Clean Code & Test Code] 4주차 발자국
워밍업 클럽 2기: Clean Code & Test Code의 4주차 발자국 작성입니다.3주차 발자국 보러가기 📝 학습 내용Presentation Layer 테스트 작성Mock더 나은 테스트를 작성하기 위한 여러 팁REST Docs ✍ 학습 내용 복습Q. Presentation Layer의 특징은?클라이언트로 부터 입력을 받아서 비즈니스 계층으로 해당 요청을 보내는 계층요청을 제일 먼저 받는 계층입력 데이터에 대한 기본적인 검증을 수행한다Presentation 계층에서의 검증과 Business 계층에서의 검증을 분리해서 생각해야 한다Presentation 계층에서는 보통 형식적인 검증을 한다예시: 필수 입력 값 검사, 데이터 타입 검사, null 검사, 빈 문자열 검사Business 계층에서는 비즈니스 로직에 따른 도메인 유효성 검사가 이루어진다Business 계층으로 부터 결과를 받아서 클라이언트로 반환한다컨트롤러에서 사용하는 요청 DTO가 서비스 계층으로 침투하지 못하도록 컨트롤러 계층에서 서비스 전용 DTO로 변환하는 것을 권장한다(상황에 따라 다를 수 있을것 같다. 만약 받는 포맷이 변할 가능성이 거의 없다면, 그냥 컨트롤러의 DTO를 쭉 사용해도 괜찮지 않을까 생각이 된다.)Q. Presentation Layer의 테스트 방법은?Business, Persistence 계층을 모킹해서 테스트한다MockMvc 같은 도구를 사용해서 HTTP요청과 응답을 시뮬레이션 한다모킹을 위해서 Mockito 같은 프레임워크를 사용할 수 있다 Q. Test Double의 종류를 정리해보자면?Dummy: 아루런 동작도 하지 않는 객체. 잘 사용되진 않지만, 보통 파라미터 전달용으로 사용된다.Fake: 실체 객체와 동일한 기능은 수행하지만, 프로덕션 용도로 사용하기에는 적합하지 않은 객체.예시: 인메모리로 맵을 사용해서 가짜 레포지토리를 구현하는 경우Stubs: 테스트에서의 요청에 대해 미리 준비된 결과를 제공하는 객체. 미리 반환할 데이터가 정의되어 있고, 호출하는 경우 해당 데이터를 반환한다. 미리 정의되어 있지 않은 것들은 응답하지 않는다.Spies: Stub이지만 정복 기록도 함께하는 객체. 호출 여부, 호출 횟수 등의 정보를 기록할 수 있다. 일부는 실제 객체 처럼 동작하고, 일부는 Stubbing할 수 있다.Mocks: 행위에 대한 기대를 명세하고, 그 명세에 따라 동작되도록 설계 된 객체. 그러니깐 개발자가 직접 그 객체의 행동을 관리하는 객체이다.Q. Stub과 Mock을 구분하는 기준은?Stub : 상태 검증(State Verification)Mock : 행동 검증(Behavior Verification) TIP. 테스트 작성을 위한 여러 팁을 정리해보면Mockito 프레임워크를 한번 래핑하는 BDD Mockito 프레임워크를 사용해서 조금 더 자연스러운 API 네이밍으로 프레임워크를 사용할 수 있다테스트 간의 독립성을 보장하자 테스트에서 전역 변수를 정의해서 사용하는 것은 권장하지 않는다@BeforeEach또는 @AfterEach 메서드를 사용한 레포지토리 클렌징@Transactional사용 Test Fixture용 클래스를 따로 분리해서 사용하는 것은 권장하지 않는다Test Fixture를 @BeforeEach를 사용한 셋업 메서드에서 사용하는 경우, 중복 제거보다 해당 테스트에 해당 내용을 알아야하는지 고려해보고 적용하자테스트 내용은 동일한데 입력값만 변경해보면서 테스트 해보고 싶으면 @ParameterizedTest 사용private메서드에 대한 테스트가 필요하다면 해당 메서드의 책임을 분리할지 고민해본다단순히 테스트하기 위해서 public으로 열어두는 것은 권장하지 않는다 Q. REST Docs vs Swagger의 차이는?REST Docs테스트를 통과해야 문서가 만들어지기 때문에 신뢰도가 높다프로덕션 코드에 비침투적이다코드의 양이 많고 설정이 상대적으로 어렵다Swagger적용이 쉽다문서에서 바로 API 호출이 가능하다애노테이션을 달아줘야 하기 때문에 프로덕션 코드에 침투적이다🤔 회고워밍업 클럽의 마지막 주차가 되었다. 강의 양이 많아도 내가 정말 필요한 내용을 담아서 만들어져있어서, 시간 가는 줄 모르고 시청했다.강의와 미션을 따라가면서 학습에 많은 도움을 받았다. 만약 워밍업 클럽 3기가 있다면 다시 참가할 예정이다.지금까지 학습 내용을 다시 복습해보고 더 나아가서 프로젝트에 적용하는 것이 목표이다. 🔍 참고Practical Testing: 실용적인 테스트 가이드
백엔드
・
테스트코드
・
워밍업클럽2기
・
백엔드
・
발자국
・
4주차
・
회고
2024. 10. 25.
0
[워밍업 클럽 2기] Day 18 - 모킹 애노테이션의 종류, 테스트 내용 배치
워밍업 클럽 2기: Clean Code & Test Code의 Day 18 미션입니다. 🎯 미션 11. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다. @MockMockito의 기본 모킹 애너테이션Mock 객체를 만들어 해당 객체의 메서드 호출에 대해 미리 정의된 값을 반환하도록 설정 가능(stub)Mock 객체는 실제 메서드를 호출하지 않고 동작만 시뮬레이션 한다@MockBeanMock 객체를 빈으로 등록합니다. 이는 테스트 대상 클래스가 의존성 주입을 통해 해당 Mock 빈을 받을 수 있도록한다.보통 @SpringBootTest나 @WebMvcTest와 같은 Spring 컨텍스트와 함께 사용되는 경우에 적합하다 @SpyMockito에서 객체의 일부 메서드만 모킹하고 나머지는 실제 메서드를 호출할 수 있다객체의 일부 기능만 변경하여 테스트하고 싶은 경우 사용한다실제 객체가 만들어져서 사용된다doReturn().when.() 사용SpyBean부분 모킹을 위해 스프링 컨텍스트에 등록된 실제 빈을 Spy로 대체한다실제 빈의 일부 메서드만 모킹하고, 나머지는 실제 메서드를 호출하게 할 때 유용하다@InjectMocks테스트 클래스에 정의된 @Mock 또는 @Spy로 선언된 객체를 주입하여, 대상 클래스의 의존성을 자동으로 설정한다 🎯 미션 22. 아래 3개의 테스트가 있습니다. 내용을 살펴보고, 각 항목을 @BeforeEach, given절, when절에 배치한다면 어떻게 배치하고 싶으신가요? (@BeforeEach에 올라간 내용은 공통 항목으로 합칠 수 있습니다. ex. 1-1과 2-1을 하나로 합쳐서 @BeforeEach에 배치) As-Is@BeforeEach void setUp() { ❓ } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { 1-1. 사용자 생성에 필요한 내용 준비 1-2. 사용자 생성 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 1-5. 댓글 생성에 필요한 내용 준비 1-6. 댓글 생성 // given ❓ // when // then - 검증 } @DisplayName(""사용자가 댓글을 수정할 수 있다."") @Test void updateComment() { 2-1. 사용자 생성에 필요한 내용 준비 2-2. 사용자 생성 2-3. 게시물 생성에 필요한 내용 준비 2-4. 게시물 생성 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 2-7. 댓글 수정 // given ❓ // when ❓ // then - 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { 3-1. 사용자1 생성에 필요한 내용 준비 3-2. 사용자1 생성 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 3-6. 사용자1의 게시물 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 3-9. 사용자2가 사용자1의 댓글 수정 시도 // given ❓ // when ❓ // then - 검증 } 다음은 미션을 수행한 To-Be 입니다.To-Be@BeforeEach void setUp() { 1-1. 사용자 생성에 필요한 내용 준비, 2-1. 사용자 생성에 필요한 내용 준비, 3-1. 사용자1 생성에 필요한 내용 준비 3-3. 사용자2 생성에 필요한 내용 준비 1-3. 게시물 생성에 필요한 내용 준비, 2-3. 게시물 생성에 필요한 내용 준비, 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-2. 사용자 생성 1-4. 게시물 생성 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then - 검증 } @DisplayName(""사용자가 댓글을 수정할 수 있다."") @Test void updateComment() { // given 2-2. 사용자 생성 2-4. 게시물 생성 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then - 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-2. 사용자1 생성 3-4. 사용자2 생성 3-6. 사용자1의 게시물 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then - 검증 }고려한 내용@BeforeEach()에는 각 테스트에서 반복되지만, 검증하는 대상과는 직접적인 관련이 없는 공통 준비 사항을 처리하려고 했다. 여기서 준비하는 내용은 없어도 각 테스트를 이해할 수 있어야 하고, 각 내용이 변경되어도 각 테스트는 정상적으로 수행될 수 있어야 한다.when에는 각 테스트에서 검증하는 행위만을 배치시켰다 🔍 참고Practical Testing: 실용적인 테스트 가이드
백엔드
・
워밍업클럽2기
・
테스트코드
・
Day18
・
모킹
2024. 10. 21.
0
[워밍업 클럽 2기] Day 15 - 레이어 별 특징과 테스트 방법
워밍업 클럽 2기: Clean Code & Test Code의 Day 15 미션입니다. 🗄 Persistence(Data Access) 계층특징데이터 소스와의 상호작용을 담당한다데이터를 저장하고, 읽고, 업데이트하고 삭제하는 CRUD 작업을 수행한다데이터 JPA, JPQL, JDBC, 등의 여러 기술이 사용될 수 있다비즈니스 로직이 포함되면 안된다테스트 방법어느 기술을 사용하든, 신뢰성있는 테스트를 위해서 레포지토리의 테스트를 하는 것을 권장한다@SpringBootTest 또는 @DataJpaTest를 사용해서 데이터베이스에 CRUD 작업이 제대로 수행 되는지 테스트 한다@SpringBootTest와 @DataJpaTest의 차이를 알자 🚀 Business 계층특징핵심 비즈니스 로직을 처리하는 계층Persistence(Data Access)와의 상호작용을 통해 비즈니스 로직을 수행한다트랜잭션이 보장되어야 한다읽기 전용 트랜잭션과 CUD 트랜잭션(Command)을 적재적소에 적용하면 좋다트랜잭션의 종류에 따라 추후에 서비스를 나누는 것도 생각할 수 있다테스트 방법Persistence 계층까지 묶어서 통합 테스트를 하는 방식으로 테스트하거나, Persistence 계층을 모킹해서 단위 테스트 방식으로 테스트 한다.테스트 간 격리를 위해서 레포지토리를 초기화하는 로직이 필요하다@BeforeEach, @AfterEach, 등을 사용한 setUp이나 tearDown 메서드를 만들어서 레포지토리를 비운다@Transactional을 사용한다(서비스에 @Transactional이 붙어있지 않아도 동작한다. @Transactional의 효과에 대해 잘 파악하고 있어야 한다.) 💻 Presentation 계층특징클라이언트로 부터 입력을 받아서 비즈니스 계층으로 해당 요청을 보내는 계층요청을 제일 먼저 받는 계층입력 데이터에 대한 기본적인 검증을 수행한다Presentation 계층에서의 검증과 Business 계층에서의 검증을 분리해서 생각해야 한다Presentation 계층에서는 보통 형식적인 검증을 한다(예시: 필수 입력 값 검사, 데이터 타입 검사, null 검사, 빈 문자열 검사, 등...)Business 계층에서는 비즈니스 로직에 따른 도메인 유효성 검사가 이루어진다Business 계층으로 부터 결과를 받아서 클라이언트로 반환한다컨트롤러에서 사용하는 요청 DTO가 서비스 계층으로 침투하지 못하도록 컨트롤러 계층에서 서비스 전용 DTO로 변환하는 것을 권장한다(상황에 따라 다를 수 있을것 같다. 만약 받는 포맷이 변할 가능성이 거의 없다면, 그냥 컨트롤러의 DTO를 쭉 사용해도 괜찮지 않을까 생각이 된다.)테스트 방법Business, Persistence 계층을 모킹해서 테스트한다MockMvc 같은 도구를 사용해서 HTTP요청과 응답을 시뮬레이션 한다모킹을 위해서 Mockito 같은 프레임워크를 사용할 수 있다 🔍 참고Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽2기
・
테스트코드
・
Day15
・
미션
2024. 10. 20.
0
[워밍업 클럽 2기 - Clean Code & Test Code] 3주차 발자국
워밍업 클럽 2기: Clean Code & Test Code의 3주차 발자국 작성입니다.2주차 발자국 보러가기✍ 학습 내용 복습Q. 자동화된 테스트가 필요한 이유는?값을 직접 출력해서 확인하는 수동 테스트는 사람이 개입해서 확인해야 한다. 검증을 사람이 하기 때문에, 값을 확인하는 과정에서 휴먼 에러가 발생할 확률이 높다.자동화된 테스트를 도입하면 검증을 기계에 맡길 수 있기 때문에 사람이 직접 검증하는 것 보다 신뢰할 수 있다.사람이 일일이 확인하는 것보다 빠르다. Q. 단위(Unit) 테스트란?단위 테스트(Unit Test)라는 것은 코드의 가장 작은 기능적 단위를 독립적으로 검증하는 테스트를 일컫는다.여기서 작은 기능적 단위(Unit)는 보통 내가 작성한 클래스 또는 메서드를 의미한다.Q. 테스트할 때 신경 써야하는 부분들은?예외 케이스를 고민한다경계값에 대한 테스트는 중요하다(예시: 범위, 구간, 날짜, 등의 경계값에 대한 테스트) Q. TDD(테스트 주도 개발)란?프로덕션 코드보다 테스트 코드를 먼저 작성해서 테스트가 코드의 구현 과정을 주도하도록 하는 개발 방법론Red, Green, Blue의 3단계 과정으로 이루어진다Red제일 먼저 실패하는 테스트 코드를 작성한다이때 테스트 코드는 컴파일 조차 안돼도 괜찮다Green테스트를 통과하도록 위해 실제(프로덕션) 코드를 작성한다이때 작성하는 코드는 테스트를 통과할 정도로만 최소한의 코드를 작성하도록 한다최대한 빠르게 작성하려고 노력한다Blue코드를 리팩토링한다설계나 구현을 개선한다이때 테스트의 통과 상태는 유지되어야 한다 Q. 좋은 Display Name(테스트 네이밍)은?행위에 대한 결과까지 담는다도메인 용어를 사용한다코드의 단위를 검증하는 것이 아닌 동작(기능)의 단위를 검증하려고 노력한다 🤔 회고중간에 1, 2주차에서 활용했던 StudyCafe 애플리케이션에 대한 단위 테스트를 작성해보는 미션을 수행 했지만, 잘 작성하지 못했던 것 같다.코드를 따라 쳐보면서 학습 해야겠다 🔍 참고Practical Testing: 실용적인 테스트 가이드
백엔드
・
발자국3주차
・
테스트코드
・
워밍업클럽2기
・
백엔드
2024. 10. 13.
0
[워밍업 클럽 2기 - Clean Code & Test Code] 2주차 발자국
워밍업 클럽 2기: Clean Code & Test Code의 2주차 발자국 작성입니다.1주차 발자국 보러가기 ✍ 학습 내용 복습이전의 클린 코드에 대해 학습한 내용을 직접 코드에 적용해서 리팩토링하는 시간을 가졌습니다.메서드 추출 시 고려할 점중복 제거무조건적인 중복 제거 보다는 상황에 맞춰서(어설픈 중복 제거 보다는 사람들이 이해하기 쉬운 코드가 더 좋음!)주변의 추상화 레벨과 동떨어져 있는지 항상 확인 객체의 책임 파악 시 고려할 점책임은 상황에 따라서 변할 수 있음예시특정 주문의 할인 금액과 총 가격을 출력하는 기능이 있다고 가정하자. 할인 금액과 총 가격이 단순히 출력 용도로만 사용된다면 해당 가격 계산을 출력을 담당하는 클래스에서 정의할 수 있겠지만, 보통은 추후에 다른 곳에서도 사용될 가능성이 있기 때문에 주문 클래스의 책임으로 만드는 것이 더 좋은 설계일 가능성이 높다(물론 이것은 상황에 따라 언제든지 변할 수 있다) 🤔 회고처음부터 내가 설계한 코드를 리팩토링 하는 것과 남의 코드를 리팩토링 하는 것은 굉장히 다르다는 것을 체감했다남의 코드 리팩토링 하는 것이 더 어렵다 😭그냥 강의만 듣고 넘어가는 것 보다, 코드를 작성하고 강사님의 코드와 비교하는 것이 학습에 훨씬 도움이 된다!🔍 참고Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽2기
・
백엔드
・
클린코드-테스트코드
・
발자국
・
2주차
2024. 10. 06.
0
[워밍업 클럽 2기 - Clean Code & Test Code] 1주차 발자국
워밍업 클럽 2기: Clean Code & Test Code의 1주차 발자국 작성입니다. ✍ 학습 내용 복습 Q. 클린 코드를 작성하는 이유?미래의 나, 미래의 동료가 더러운 코드로 인해 고통 받지 않도록 하기 위해서 클린 코드를 작성한다.코드를 작성하는 순간부터 그 코드는 사실상 기술 부채를 가지게 된다. 기술 부채를 최대한 줄이기 위해서 클린 코드를 작성한다. Q. 클린 코드를 작성하기 위해서 사용하는 가장 핵심적인 개념은?추상화라고 생각한다. 추상화의 본질은 핵심 개념만 드러내고, 불필요한 정보는 감추는 것이다.추상화 레벨이 높아질수록 더 함축적인 개념을 다루고, 낮아질수록 구체적인 동작과 세부 구현에 집중한다.추상화 레벨이 높아지면 높아질수록 정보의 함축 수준이 높아지고 이해하기 쉬워진다. 그렇다고 너무 함축시키면 실제 구체(정보)의 재현이 어렵기 때문에 적절한 추상화가 필요하다. Q. 적절한 추상화란?적절한 추상화란 해당 도메인 내에서 핵심적인 부분만 드러내면서 구체적인 구현은 필요에 따라 숨기는 것이다핵심적인 부분과 불필요한 정보의 구분은 문맥에 따라 언제든지 달라질 수 있다도메인을 파악하는 것이 중요하다 Q. 효과적인 네이밍은?네이밍(이름짓기)을 통해서 의도를 드러낼 수 있다. 높은 추상화 레벨에서는 세부 사항을 숨기고, 큰 개념을 드러내는 네이밍을 사용한다. 낮은 추상화 레벨에서는 더 구체적인 동작을 설명하는 이름을 사용한다.대부분의 경우 내부로 들어갈수록 추상화 레벨이 낮아진다주변 코드와의 추상화 레벨이 동떨어져 있는지 지속적으로 확인하는 것이 좋다 Q. 가독성이 좋은 코드는?가독성이 좋은 코드는 불필요한 정보를 덜 인지 해도 되면서 이해하기 수월한 코드라고 생각한다. Q. 가독성이 좋은 코드를 작성하는 방법들은?early return 사용하기이중 반복문, 분기문의 depth를 줄일 수 있는지 고민하기부정어 표현 !을 제거할 수 있는 방법이 있는지 고민하기 Q. 객체란?캡슐화비공개 데이터(필드), 비공개 로직(프라이빗 메서드)을 가질 수 있다공개 메서드를 통해서 외부와 소통한다객체 간 상호작용(협력)을 한다하나의 객체로 관심사가 모이기 때문에 유지보수하기 쉬워진다 Tip. 객체 사용시 주의점하나의 관심사를 가지는지 확인하자웬만하면 setter의 사용을 자제하고, 값의 변경은 updateXxx, addXxx 같은 명확한 네이밍을 사용하자 Q. SOLID(객체 지향 설계의 5개 원칙)는 무엇인가?https://www.inflearn.com/blogs/8391 에 정리 Q. 상속 보다 조합을 권장하는 이유는?상속 관계에서 자식과 부모간의 결합은 매우 강하다. 이는 부모 클래스의 변경은 자식 클래스에도 영향을 준다는 의미이다. 변경의 가능성이 매우 적고, 상위 클래스의 활용이 필요한 경우가 아니라면 조합과 인터페이스의 사용이 훨씬 유연한 구조를 제공한다 🤔 회고코드를 같이 따라치면서 학습하는 것이 더 효율적일 것 같다. 주말 동안 코드도 같이 따라 치면서 복습할 생각이다.토이 프로젝트에 배운 내용을 직접 적용해보면서 학습할 예정이다. 참고Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽2기
・
백엔드
・
클린코드-테스트코드
・
발자국
・
1주차