블로그
전체 10#카테고리
- 백엔드
#태그
- 인프런
- 인프런워밍업클럽
- 스터디3기
- 워밍업
- 백엔드
- 후기
- 클린
- 테스트
- 코드
- 워밍업클럽
- 스터디
- 발자국
- 회고
- 3기
- 스터디2기
- 프로젝트
- SpringBoot
2025. 04. 09.
1
인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 후기
Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드강의와 함께한 인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot) 후기 입니다.소개이번 스터디 3기는 백엔드 클린 코드, 테스트 코드를 주제로 진행하였습니다. “Readable Code: 읽기 좋은 코드를 작성하는 사고법”과 “Practical Testing: 실용적인 테스트 가이드” 강의를 함께 학습함으로써, 더 나은 코드 가독성과 안정적인 테스트를 위한 다양한 방법론을 실습할 수 있었습니다.지난 2기 때 Kotlin과 Spring Boot로 백엔드 개발 전반을 경험하며 웹 애플리케이션 동작 원리를 학습했다면, 이번 3기에서는 코드 품질과 테스트라는 핵심 주제를 깊이 파고들어, 보다 깨끗하고 유지보수하기 좋은 코드, 그리고 신뢰도 높은 테스트 코드를 작성하는 법을 익혔습니다.아래에서는 각 주차별 학습 내용을 정리하고, 전체 스터디를 통해 느낀 점과 앞으로의 계획을 공유하고자 합니다. 1주차: 클린 코드를 위한 기초 - 추상과 구체, SOLID 원칙1주차 주요 학습 내용추상과 구체의 개념논리와 사고의 흐름SOLID 원칙 (SRP, OCP, LSP, ISP, DIP)리팩토링 미션 수행1주차에서는 코드 가독성을 높이는 가장 기본이 되는 개념들을 배웠습니다. 특히 추상과 구체의 균형을 어떻게 잡아야 코드가 명확해지고, 협업자가 빠르게 이해할 수 있는지 고민할 수 있었습니다.추상은 핵심 개념과 의도만 드러내도록 하는 장점이 있지만, 너무 과도하면 실제 구현과 괴리가 생겨 혼란을 줄 수 있다는 점을 배웠습니다.구체는 세세한 내용을 모두 표현해 직관적이지만, 과도해지면 복잡해지고 가독성이 떨어질 수 있으므로 주의가 필요했습니다.또한 Early Return이나 부정어 최소화 같은 리팩토링 기법을 적용해 보면서, 간단한 습관만으로도 코드의 가독성이 크게 높아진다는 점을 실감했습니다. 2주차: 코드 구조 및 리팩토링 - 패키지 구조, 주석, 적정 기술2주차 주요 학습 내용효과적인 주석 사용 방식변수와 메서드의 나열 순서패키지 구조 설계와 적정 기술(Over Engineering 지양)스터디카페 이용권 시스템 리팩토링2주차에서는 코드 구조 전반을 깔끔하게 정비하는 방법을 중심으로 학습했습니다.주석은 변동이 잦거나 오해를 일으킬 만한 내용을 담지 말고, 정말 필요할 때만 사용해야 한다는 것을 다시금 확인했습니다.변수와 메서드를 사용하는 순서대로 배치하고, 공개 메서드(public) → 비공개 메서드(private) 순서로 자연스럽게 구성함으로써, 읽는 흐름을 방해하지 않는 것이 중요하다는 점을 배웠습니다.특히 리팩토링 미션을 통해 패키지 구조가 지나치게 단순하거나, 반대로 너무 세분화되어 관리가 어렵지 않은지 돌아볼 수 있었습니다. 적정 기술을 사용하는 태도. 즉, 문제를 해결하는 데 필요한 만큼만 기술 스택과 디자인 패턴을 적용하는 것이 얼마나 중요한지도 체감하게 되었습니다. 3주차: Spring & JPA, 계층형 아키텍처, 통합 테스트3주차 주요 학습 내용Spring & JPA를 이용한 계층형 아키텍처 (Controller, Service, Repository)단위 테스트와 통합 테스트의 차이점 및 작성 방법MockMvc, @DataJpaTest 등을 활용한 테스트 실습Bean Validation과 ExceptionHandler로 유효성 검증 및 예외 처리3주차부터는 실무에서 흔히 쓰이는 Spring & JPA 기반의 계층형 아키텍처에 초점을 맞춰, 전체적인 흐름을 학습했습니다.Layered ArchitecturePresentation Layer(Controller)Business Layer(Service)Persistence Layer(Repository)이러한 구조를 바탕으로, MockMvc를 사용해 Controller부터 Service, Repository까지 이어지는 통합 테스트를 작성해 봄으로써, 애플리케이션 전반이 정상 동작하는지 확인할 수 있었습니다.또한 @NotNull, @Positive 등 Bean Validation 애너테이션과 @RestControllerAdvice를 통한 예외 처리 방식도 연습해보았습니다. 4주차: Mock, Spy, @MockBean / @SpyBean, 레이어별 테스트 전략4주차 주요 학습 내용Mockito에서의 @Mock, @Spy, @InjectMocks스프링 환경에서의 @MockBean, @SpyBean레이어별 테스트 설계: 단위 테스트 vs 통합 테스트테스트 시나리오 설계(given-when-then)와 @BeforeEach 활용마지막 주차에서는 테스트 유지보수와 테스트 코드 설계의 중요성을 배웠습니다.@Mock, @Spy를 통해 순수 단위 테스트 환경에서 외부 의존성을 제거(또는 부분 제거)하여 빠른 피드백을 받을 수 있었습니다.반면 @MockBean, @SpyBean은 스프링 애플리케이션 컨텍스트를 띄운 상태에서 기존 Bean을 모의 객체로 교체할 수 있어, 좀 더 넓은 범위의 통합 테스트에 활용할 수 있었습니다.레이어별 테스트 (Controller, Service, Repository)를 분리해 진행하면 테스트가 더욱 명확해지고, 문제 발생 시 어느 레이어가 원인인지 빠르게 파악할 수 있음을 깨달았습니다.가장 크게 느낀 점은 ‘테스트도 코드의 일부’라는 사실이었습니다. 테스트 코드를 지속적으로 관리하고 개선해야, 유지보수가 필요한 시점에 믿을 수 있는 안전망이 되어준다는 것을 명확히 알게 되었습니다.회고이번 스터디 3기를 통해 "클린 코드와 테스트"라는 주제의 중요성을 다시 한번 실감했습니다. 단순히 기능만 구현하는 것이 아닌, 가독성, 유지보수성, 테스트 커버리지까지 고려해야 진정한 의미의 소프트웨어 품질을 높일 수 있음을 배웠습니다.아쉬웠던 점 & 보완 계획실프로젝트 적용: 강의와 미션 중심의 학습이기에, 실제 현업 수준의 복잡도를 가진 코드에 적용할 기회가 많지 않았습니다. 앞으로 개인/팀 프로젝트에서 적극 활용해 경험치를 높이고자 합니다.테스트 시나리오 다양성: 해피 케이스 중심의 테스트가 많았기에, 예외 상황과 경계값 테스트를 더 폭넓게 다루면 좋았을 것 같습니다. 마무리인프런 워밍업 클럽 스터디 3기를 통해, 클린 코드와 테스트 코드 작성 역량을 크게 향상시킬 수 있었습니다.코드: 명료한 이름 짓기, 중복 제거, 적절한 추상화 등을 통해 읽기 좋고 변화에 강한 코드를 추구하게 되었습니다.테스트: 프로젝트가 확장되더라도, 안정성을 확보할 수 있는 테스트 설계가 얼마나 중요한지 다시금 느끼게 되었습니다. 이번 스터디에서 성실히 참여한 결과, 2기에 이어 3기에서도 우수러너로 선정되는 영광도 누릴 수 있었습니다. 앞으로도 스스로 레거시 코드를 리팩토링하거나, 프로젝트를 확장하면서 배운 내용을 꾸준히 적용할 것입니다. 스터디에서 함께한 분들, 그리고 인프런과 워밍업 클럽 관계자분들께 감사드리며, 지속적인 학습과 공유를 통해 더 나은 개발자가 되도록 노력하겠습니다. 감사합니다!
백엔드
・
인프런
・
인프런워밍업클럽
・
스터디3기
・
워밍업
・
백엔드
・
후기
・
클린
・
테스트
・
코드
2025. 03. 30.
0
인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 4주차 발자국
Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드강의와 함께한 인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot)4주차 발자국 입니다.학습 내용 요약이번 주에는 Practical Testing: 실용적인 테스트 가이드 강의에서 계층형 아키텍처(Layered Architecture) 의 개념을 다시 한번 정리하고, 스프링 기반 테스트에서 자주 사용하는 Mock/Spy 기법과 관련 애너테이션들을 배웠습니다.Layered Architecture (계층형 아키텍처)Presentation Layer: 사용자 입력과 응답을 담당. API 요청/응답 혹은 프론트엔드 인터페이스를 제공하며, 기본적인 파라미터 검증과 변환만 수행.Business Logic Layer: 애플리케이션의 핵심 비즈니스 로직과 규칙을 구현. 서비스(Service)나 도메인(Domain) 로직이 위치하며, 트랜잭션 관리의 주된 대상이 됨.Persistence Layer: 데이터베이스/파일시스템 등 영속성 저장소와 직접적으로 상호작용. Repository(DAO) 형태로 CRUD를 담당.Mockito & Spring Test 관련 애너테이션@Mock / @Spy / @InjectMocks: 순수 Mockito 환경(스프링 컨텍스트 없이)에서 가짜 객체(또는 부분 가짜 객체)를 만들어 단위 테스트를 쉽게 작성할 수 있게 함.@MockBean / @SpyBean: 스프링 애플리케이션 컨텍스트를 기동하는 통합 테스트 환경에서 특정 Bean을 Mock 또는 Spy로 교체하여, 외부 의존성을 간단히 제어하고자 할 때 활용.테스트 설계 방향각 레이어별로 테스트 범위를 명확히 하여, “Persistence → Business → Presentation” 순으로 책임을 분리해 점진적으로 테스트 커버리지를 넓힘.@MockBean / @SpyBean을 과도하게 사용하지 않도록 주의: 꼭 필요한 부분만 모의(Mock/Spy) 처리하고, 나머지는 실제 로직을 이용해 통합 테스트를 안정적으로 수행.테스트 시나리오별로 @BeforeEach를 활용하는 방법과, 각 테스트 메서드에서 독립적으로 given-when-then을 구성하는 방법을 비교.학습 회고얻은 인사이트레이어별 책임과 역할이 분명해야 복잡한 서비스에서도 테스트 설계가 한결 명확해짐을 느꼈습니다.Mock/Spy를 올바른 상황에서만 사용하면 외부 의존성을 최소화하여 빠른 단위 테스트를 작성할 수 있으나, 반대로 불필요하게 남발하면 테스트 유지보수가 어려워짐을 체감했습니다.어려웠던 점@MockBean과 @SpyBean을 사용해 스프링 컨텍스트를 띄울 때 테스트 속도가 느려지거나, 동일 타입 Bean이 여러 개일 때 어느 Bean을 대체하는지 혼동될 수 있었습니다.레이어별 테스트를 작성하면서, 중복으로 보이는 코드(예: 테스트 준비 로직)를 어느 정도까지 @BeforeEach로 추출해야 할지 고민이 되었습니다.미션🎯 Day16 미션: Layered Architecture 구조의 레이어별 특징과 테스트 방법요구사항Layered Architecture에서 각 레이어가 하는 역할, 특징, 그리고 테스트 방식을 자기만의 언어로 정리하기나만의 정리Presentation Layer역할: 사용자나 외부 시스템의 요청을 받고 응답을 전달. 파라미터 검증, DTO 변환, HTTP 상태 코드 결정 등을 담당.특징: 비즈니스 로직을 직접 수행하지 않고, 유효성 체크 후 Service 호출 → 결과 반환에 집중.테스트 방법: 컨트롤러 통합 테스트(@SpringBootTest, @WebMvcTest + MockMvc)를 통해 실제 요청/응답 형식을 모의하거나, 프론트엔드와의 e2e 테스트를 진행해볼 수도 있음.Business Logic Layer역할: 애플리케이션의 핵심 규칙, 알고리즘, 트랜잭션 등의 로직 담당.특징: 여러 Repository를 조합하여 도메인 로직을 수행하고, 예외 처리, Validation 등의 업무 로직을 포괄적으로 관리.테스트 방법: 단위 테스트를 통해 특정 비즈니스 로직의 정확성을 검증. 필요 시 Repository를 Mock 처리(예: @Mock, @MockBean)하여 DB 의존성을 제거하고 로직만 집중 테스트.Persistence Layer역할: 데이터의 저장/조회/수정/삭제 등 영속성 처리에 집중.특징: 쿼리 작성, DB 연결, CRUD 로직을 추상화한 Repository/DAO 형태로 제공.테스트 방법: 실제 DB 혹은 In-Memory DB(H2 등)를 활용한 통합 테스트(@DataJpaTest). 쿼리 정확도, 트랜잭션 처리, 성능 등을 검증하기에 좋음.🎯 Day18 미션 1: @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks의 차이점 정리요구사항각 애너테이션이 어떤 환경(단위 테스트/통합 테스트)에서 사용되고, 어떤 특징이 있는지 정리하기1) @Mock주로 사용 환경: Mockito (단위 테스트)스프링 빈 등록 여부: X (별도 Bean 아님)특징:순수 Mock 객체를 생성하여, 내부 로직 없이 호출 기록/결과(Stubbing)만 지정할 수 있음단위 테스트에서 외부 의존성을 배제하고 특정 로직만 검증할 때 유용2) @MockBean주로 사용 환경: Spring Boot Test(통합 테스트)스프링 빈 등록 여부: O (빈으로 등록됨)특징:스프링 애플리케이션 컨텍스트에 등록된 실제 Bean을 Mock으로 교체다른 Bean이 해당 Bean을 의존하고 있으면, 그 의존성도 가짜(Mock)로 처리됨@SpringBootTest나 @WebMvcTest 등 스프링 컨텍스트가 뜨는 환경에서 사용3) @Spy주로 사용 환경: Mockito (단위 테스트)스프링 빈 등록 여부: X (별도 Bean 아님)특징:부분 가짜(Spy) 객체를 생성기본적으로 실제 메서드 동작을 유지하면서, 필요한 부분만 가짜(Stubbing)로 설정 가능복잡한 객체를 테스트할 때, 일부는 실제 로직을 실행하고 일부만 Mock 처리할 수 있어 유연함4) @SpyBean주로 사용 환경: Spring Boot Test(통합 테스트)스프링 빈 등록 여부: O (빈으로 등록됨)특징:스프링 컨텍스트 내 실제 Bean을 Spy로 교체기본적으로는 실제 로직을 수행하되, 특정 메서드만 가짜로 동작시키거나 호출을 기록할 수 있음통합 테스트 환경에서 부분 Mocking이 필요할 때 적합5) @InjectMocks주로 사용 환경: Mockito (단위 테스트)스프링 빈 등록 여부: 해당 없음특징:@Mock 또는 @Spy로 만들어진 객체들을 자동으로 주입(생성자, 세터, 필드 순)해줌예: @InjectMocks UserService라면, UserService가 의존하는 Repository나 다른 객체들을 @Mock으로 생성해 주입받을 수 있음단위 테스트에서 여러 의존 객체를 편리하게 Mock/Spy로 대체할 수 있도록 지원 🎯 Day18 미션 2: 테스트 시나리오(@BeforeEach, given, when, then) 구성요구사항아래 3개의 테스트 메서드가 있을 때, “어떤 준비 로직을 @BeforeEach로 뽑고, 어떤 부분을 각 테스트의 given절에 둘지”, “when절을 어떻게 구성할지”를 구상해보기예시 테스트 3종사용자가 댓글을 작성할 수 있다.사용자가 댓글을 수정할 수 있다.자신이 작성한 댓글이 아니면 수정할 수 없다.나의 구성@BeforeEach void init() { // 공통 데이터를 미리 생성하지 않습니다. /* * 각 테스트가 각각의 상황(사용자, 게시물, 댓글)을 자유롭게 구성할 수 있도록, * 여기서는 사전에 아무것도 세팅해두지 않습니다. * 테스트마다 필요한 데이터 타입이나 조건이 다를 수 있으므로, * 각 테스트 메서드 내부에서 직접 객체를 생성하고 준비해 주는 방식을 채택했습니다. */ } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given // 1-1. 사용자 생성에 필요한 내용 준비 // 1-2. 사용자 생성 // 1-3. 게시물 생성에 필요한 내용 준비 // 1-4. 게시물 생성 // 1-5. 댓글 생성에 필요한 내용 준비 // when // 1-6. 댓글 생성 // then // 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given // 2-1. 사용자 생성에 필요한 내용 준비 // 2-2. 사용자 생성 // 2-3. 게시물 생성에 필요한 내용 준비 // 2-4. 게시물 생성 // 2-5. 댓글 생성에 필요한 내용 준비 // 2-6. 댓글 생성 // when // 2-7. 댓글 수정 // then // 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given // 3-1. 사용자1 생성에 필요한 내용 준비 // 3-2. 사용자1 생성 // 3-3. 사용자2 생성에 필요한 내용 준비 // 3-4. 사용자2 생성 // 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 // 3-6. 사용자1의 게시물 생성 // 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 // 3-8. 사용자1의 댓글 생성 // when // 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then // 검증 }@BeforeEach정말 모든 테스트에 공통으로 필요한 세팅(예: DB clean-up, 동일한 테스트 데이터 세팅 등)이면 이곳에 배치.하지만 테스트마다 시나리오가 크게 다른 경우, 오히려 각 테스트 내부(given 절)에서 데이터를 생성하는 편이 가독성과 유연성이 좋아질 수 있음.given 절테스트에 필요한 사전 조건(사용자, 게시물, 댓글 등) 및 Mock/Stubbing이 필요하다면, 해당 로직을 배치.시나리오별로 조금씩 다른 상황을 구성할 때, @BeforeEach보다 각 테스트 내부의 given 부분에 명시적으로 작성하는 방식이 선호됨.when 절실제 테스트 대상 메서드를 호출하는 구간. 한 개의 테스트에서 “정확히 하나의 when 절”을 유지해, 명확히 어떤 동작을 검증하는지 드러내도록 함.then 절결과 검증(Assertions) 수행. 저장된 데이터 확인, 예외 발생 여부 확인, 반환값 확인 등.미션 회고레이어별 특징을 자기 언어로 설명단순히 문서상 개념을 반복하기보다, 실제 현업/프로젝트에서 마주치는 구조를 떠올리며 다시 풀어내보니, 각 계층이 왜 필요한지, 테스트를 어떻게 접근해야 하는지 더 명확해졌습니다.Mock/Spy 애너테이션 정리정리를 해보니 실제로 코드에 적용할 때 어떤 상황에서 무엇을 써야 하는지가 더 분명해졌습니다.@MockBean/@SpyBean이 스프링 컨텍스트를 사용하는 통합 테스트에서 유용하지만, 속도와 Bean 교체 이슈가 있어 주의가 필요하다는 점이 인상적이었습니다.3가지 테스트 시나리오에서 @BeforeEach & given/when/then 배치시나리오에 따라 @BeforeEach를 최소화하거나, 여러 테스트에 공통적으로 필요한 부분만 추출하는 방식이 각각 장단점이 있음을 확인했습니다.테스트 구조를 “given-when-then”으로 고정하면 가독성이 올라가지만, 너무 세세한 단계 분리는 오히려 장황해질 수 있으므로 균형을 잡아야겠습니다.회고칭찬하고 싶은 점레이어별 테스트 기법과 Mock/Spy 전략이 한층 체계적으로 잡혔습니다.실제 코드를 작성하며, “가짜 객체를 어디까지 써야 하나? 외부 연동은 어떻게 테스트하나?” 같은 고민을 많이 해 봐서, 앞으로는 목적에 맞는 테스트를 설계하는 능력이 향상될 것 같습니다.아쉬웠던 점 & 보완 계획Mock 남발 시 발생할 수 있는 문제(설정 복잡도 상승, 실제 로직 변경 시 Stubbing 깨짐)를 더 구체적인 예제로 다뤄보면 좋을 것 같습니다.@BeforeEach와 개별 테스트 내부 given 절의 적절한 균형점을 찾으려면, 실제 현업 수준의 다양한 테스트 케이스를 더 경험해 봐야겠습니다.다음 목표예외 상황 테스트 강화단순 성공 케이스뿐 아니라, 비정상 입력이나 예외 케이스를 좀 더 체계적으로 정리하고 테스트에 반영. 도메인 별로 테스트 슬라이싱@DataJpaTest, @WebMvcTest 등 스프링이 제공하는 슬라이스 테스트 방식을 적극 활용해 보기.테스트 실행 속도 최적화통합 테스트와 단위 테스트를 적절히 조합하여, 빠르면서도 신뢰성 있는 테스트 환경을 구축해 보기.이번 4주차에는 계층형 아키텍처를 다시 한번 복습하면서 Mock/Spy, @MockBean/@SpyBean 등 스프링 테스트 환경에서 자주 쓰이는 기법들을 정리하고 적용해 보았습니다. 학습 내용과 미션을 통해 각 레이어가 가진 의미와 책임이 더욱 또렷해졌고, 가짜 객체를 어떻게 잘 활용해야 하는지 감이 잡힌 것 같습니다.앞으로도 학습 내용을 기록하고 회고하면서, 점점 더 탄탄한 테스트 코드를 작성해 가도록 하겠습니다.감사합니다!
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
클린
・
테스트
・
코드
・
발자국
・
회고
・
3기
2025. 03. 23.
0
인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 3주차 발자국
Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드강의와 함께한 인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot)3주차 발자국 입니다.학습 내용 요약이번 주에는 Spring & JPA 환경에 계층형 아키텍처(Layered Architecture) 및 테스트 기법(통합 테스트, MockMvc, JPA 테스트 등)을 학습했습니다.1⃣ Spring & JPASpring이 제공하는 IoC/DI 개념과 ORM(JPA, Hibernate) 기반 데이터 접근 방식을 이해했습니다.엔티티(Entity) 설계를 통해 도메인 모델링을 하고, 리포지토리(Repository) 계층으로 데이터 CRUD를 담당하도록 분리했습니다. 2⃣ Layered ArchitecturePresentation Layer(Controller)Business Layer(Service)Persistence Layer(Repository)컨트롤러는 요청/응답을 처리하고, 비즈니스 로직은 서비스가 담당하며, 데이터 접근은 리포지토리를 통해 수행합니다.3⃣ 테스트 코드 작성단위 테스트: 특정 클래스나 메서드 단위 검증. 예: JUnit + AssertJ 사용통합 테스트: 스프링 컨텍스트를 로드해 여러 레이어(Controller, Service, Repository)의 협력을 검증.MockMvc를 사용해 테스트하는 방식을 배웠습니다.4⃣ 유효성 검증(Bean Validation)DTO에서 @NotEmpty, @NotNull, @Positive 등 애노테이션을 사용하여 입력값을 검증하고,RestControllerAdvice로 BindException 등을 처리하여 예외 상황 시 API 응답을 표준화했습니다.✨ 학습 회고Spring & JPA 학습을 통해, 계층형 아키텍처 전체 흐름을 이해해야 함을 느꼈습니다.테스트 코드에서, 단위 테스트와 통합 테스트의 경계와 필요성을 체감했습니다.JUnit5 + AssertJ로 간단한 메서드 단위 검증을 할 때는 편리했지만, MockMvc로 검증하거나, @DataJpaTest로 테스트할 때는 더 많은 설정이 필요했습니다. 그만큼 테스트 커버리지가 넓어지며 신뢰도가 높아진다는 장점을 느꼈습니다.Validation과 ExceptionHandler를 통해 잘못된 입력을 막고, 표준화된 에러 응답을 제공하는 프로세스가 얼마나 중요한지 깨달았습니다.미션 해결 과정🎯 스터디카페 이용권 선택 시스템 테스트 미션미션스터디카페 이용권 선택 시스템의 테스트 코드를 작성하는 미션.미션 목표메시지 출력 테스트할인 로직 테스트사물함 선택 테스트 해결 과정OutputHandlerTest환영 메시지 + 공지사항 “프리미엄 스터디카페” 등의 문구가 제대로 찍히는지 확인.주문 내역 요약에 “이용 내역”, “이용권”, “사물함”, “총 결제 금액” 같은 키워드가 포함되는지 검증.StudyCafePassOrderTest할인율 및 가격 계산이 의도대로 동작하는지 (예: (250,000 + 10,000) - 할인액 25,000 = 235,000) 확인.사물함이 있는지 없는지에 따라 Optional가 올바르게 반환되는지 테스트.StudyCafeSeatPassTest할인율이 0일 때 할인 금액이 0원인지, 0.1이면 정상 할인액이 계산되는지.시간권(HOURLY)은 cannotUseLocker() == true, 고정석(FIXED)은 false인지 등을 테스트로 보장. 회고도메인 로직이 잘 분리되어 있어 테스트 작성이 수월했습니다. 만약 복잡한 코드가 여기저기 있었다면, 테스트도 훨씬 어렵고 중복될 뻔했습니다. 또한 예외 처리 부분에 대한 테스트 코드의 필요성도 느껴졌습니다. 예외 상황에 대한 흐름을 명확하게 검증하고, 안정적인 동작을 보장하기 위해서는 예외 처리에 대한 테스트도 함께 구성되어야 한다고 생각했습니다.🔗 테스트 미션 깃허브 링크회고스스로 칭찬하고 싶은 점도메인 흐름 파악: Controller → Service → Repository 순으로 데이터가 흐르는 구조를 더욱 제대로 이해하게 되었습니다. 다양한 스프링 테스트 어노테이션(WebMvcTest, SpringBootTest, DataJpaTest 등)을 직접 적용하며, 각 용도에 맞게 테스트를 구분해본 경험이 유익했습니다.아쉬웠던 점 & 보완할 점테스트 격리: 통합 테스트 시 상태를 초기화하는 과정이 번거로웠고, 테스트 순서에 따라 의존성이 생기지 않도록 더 철저히 관리해야 함을 느꼈습니다.테스트 시나리오 다양성 부족: 대부분 해피 케이스 위주로 검증한 감이 있어, 더욱 폭넓은 예외 상황에 대한 시나리오를 추가 작성하면 안정성이 높아질 것 같습니다.다음 주 학습 목표Mock과 Test Double: Mock과Test Double 개념을 학습하고, 적절히 사용해 볼 예정입니다.테스트 환경 독립성:테스트 시 독립적인 환경을 유지하는 방법을 살펴볼 예정입니다.테스트 개선 기법:조금 더 간결하고 가독성 높은 테스트 작성을 시도해 볼 계획입니다.이번 주에는 Spring & JPA 환경에서의 테스트 코드 작성을 중점적으로 경험 했습니다. 이를 통해 서비스가 단계적으로 확장되더라도, 테스트 코드가 안정적인 작동을 보장할 수 있다는 점을 다시금 깨달았습니다. 앞으로도 테스트 우선 방식으로 새로운 기능이나 리팩토링을 진행해, 안전하고 효율적인 협업 환경을 유지해 나가겠습니다.감사합니다!
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
클린
・
테스트
・
코드
・
발자국
・
회고
・
3기
2025. 03. 16.
0
인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 2주차 발자국
Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드강의와 함께한 인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot)2주차 발자국 입니다.학습 내용 요약이번 주는 클린 코드 작성법에 이어 코드 구조와 리팩토링, 그리고 테스트 코드 작성법을 본격적으로 학습했습니다.1⃣ 주석의 양면성주석은 코드 자체로 표현하기 어려운 의사결정의 히스토리를 기록할 때 사용해야 합니다.자주 변하는 정보는 주석으로 표현하면 안 되고, 주석은 코드와 함께 꾸준히 관리해야 합니다.부정확한 주석은 주석이 없는 코드보다 더 해롭습니다.2⃣ 변수와 메서드의 나열 순서변수는 사용하는 순서대로 나열하고, 공개 메서드를 먼저 배치하여 외부 세계에 제공하는 기능을 명확히 드러냅니다.비공개 메서드는 공개 메서드에서 호출되는 순서로 나열하여 코드 읽기 흐름을 자연스럽게 만듭니다.나열 순서도 의도를 표현하는 중요한 수단이 될 수 있음을 배웠습니다.3⃣ 패키지 나누기패키지 구조는 도메인 문맥을 반영하여 설계하며, 너무 잘게 나누거나 너무 크게 뭉치는 것을 지양해야 합니다.팀 내 합의가 중요하며 초기 설계 단계에서 패키지 구조를 충분히 고민해야 합니다.4⃣ 적정 기술의 사용모든 기술은 적정한 수준과 시점에서 활용해야 하며, 무리한 추상화나 오버 엔지니어링은 오히려 개발 효율성을 떨어뜨립니다.클린 코드는 만능 해결책이 아니며, 상황과 목적에 맞는 균형 잡힌 접근이 중요합니다.5⃣ 테스트 코드와 TDD자동화된 단위 테스트(JUnit5, AssertJ)를 통해 신뢰성과 유지보수성을 높이고, 빠른 피드백을 받을 수 있습니다.TDD(Test Driven Development)를 통한 선(先) 테스트 작성, 후(後) 기능 구현 방식을 이해했습니다.Given-When-Then 구조를 이용한 BDD(Behavior Driven Development) 스타일로 작성하면 도메인 로직을 명확히 표현할 수 있습니다.미션 해결 과정🎯 스터디카페 이용권 선택 시스템 리팩토링 미션미션'스터디 카페 이용권 선택 시스템'의 기존 시스템에 중복된 로직과 혼재된 책임을 명확히 분리하고, 객체지향 원칙을 준수하여 코드 구조를 개선하는 리팩토링 미션입니다.접근 관점추상화 레벨 맞추기: 중복 로직을 별도 메서드로 추출했습니다.객체의 책임 분리: StudyCafeOrder 객체를 추가해 할인 계산 로직을 전담했습니다.DIP(의존성 역전 원칙): 파일 접근 로직을 인터페이스(StudyCafeRepository)로 추상화하여 확장성을 확보했습니다.해결 과정1. 기존의 복잡한 분기 조건(if-else)을 메서드로 깔끔하게 정리했습니다.Before: if (HOURLY) { ... } else if (WEEKLY) { ... } else if (FIXED) { ... } 로직이 길고, 사물함 로직도 그 안에서 처리.After:public void run() { // 1) passType 선택 (시간권/주단위/고정석) StudyCafePassType passType = inputHandler.getPassTypeSelectingUserAction(); // 2) pass 선택 StudyCafePass selectedPass = selectPass(passType); // 3) 사물함 선택 (고정석 only) StudyCafeLockerPass lockerPass = maybeSelectLocker(selectedPass); // 4) 주문 객체 생성 & 결과 출력 StudyCafeOrder order = new StudyCafeOrder(selectedPass, lockerPass); outputHandler.showOrderResult(order); }이점: 각 단계가 메서드로 분리되어 이해하기 쉬움. passType별로 중복된 분기 로직이 크게 줄었음. 2. 할인 및 총금액 계산 로직을 전담하는 객체를 만들어 로직을 명확히 했습니다.Before: 할인금액, 총액 계산 로직이 OutputHandler.showPassOrderSummary 안에 위치.After: StudyCafeOrder라는 도메인 객체가 이 로직을 담당.public int getDiscountAmount() { return (int) (selectedPass.getPrice() * selectedPass.getDiscountRate()); } public int getTotalPrice() { int discountPrice = getDiscountAmount(); int lockerPrice = (lockerPass != null) ? lockerPass.getPrice() : 0; return selectedPass.getPrice() - discountPrice + lockerPrice; }이점: 필요 시 “할인 정책”이 바뀌어도 StudyCafeOrder만 수정하면 되며, 출력부는 깔끔하게 유지. 3. 파일 접근 방식을 인터페이스와 구현체로 나누어 유지보수와 확장성을 높였습니다.Before: StudyCafeFileHandler라는 클래스에서 직접 파일 접근 + 변환.After: StudyCafeRepository(추상) + StudyCafeFileRepository(구현).StudyCafePassMachine은 StudyCafeRepository repository에만 의존 → DIP 준수.향후 DBRepo나 InMemoryRepo 추가 시 StudyCafeRepository만 구현하면 됨. 회고리팩토링을 통해 코드 가독성과 유지보수성이 눈에 띄게 향상되었습니다. 특히 객체지향 원칙(SRP, DIP)을 철저히 적용한 결과, 각 객체가 단 하나의 명확한 책임을 가지면서, 향후 변경이 발생해도 최소한의 수정만으로 대응 가능해졌습니다. 규칙의 절대성이 아닌 "적정선"을 찾는 것이 매우 중요하다는 점을 깊이 깨달았습니다.🔗 리팩토링 미션 깃허브 링크회고스스로 칭찬하고 싶은 점학습한 내용을 즉시 코드에 적용하며 원칙을 체화하고자 노력한 점단순한 기능적 개선을 넘어, 구조적이고 근본적인 리팩토링을 고민한 점아쉬웠던 점 & 보완할 점코드 리뷰에서 코드 확장성과 유지보수성을 높이기 위한 설계가 부족했음을 느꼈습니다. 다음에는 코드 확장성과 유지보수성을 고려한 구조를 더욱 더 고민해 보겠습니다.지나치게 추상화에 치우치는 경향을 느꼈고, 다음에는 더 실용적인 균형을 유지하려 합니다.다음 주 학습 목표다음 주부터는 TDD 기반으로 더욱 실질적이고 구체적인 테스트 코드 작성을 연습할 계획입니다.리팩토링과 테스트가 결합된 실습을 통해, 코드를 더욱 안정적으로 관리하는 방법을 익힐 예정입니다.이번 주 스터디를 통해 "코드는 언제나 적정한 수준의 추상과 구체 사이에서 균형을 잡아야 한다"는 중요한 원칙을 다시 한번 실감했습니다. 앞으로도 적절한 추상화와 구체적인 구현 사이의 "적정선"을 끊임없이 고민하며, 클린하고 안정적인 코드를 지속적으로 작성하는 개발자가 되도록 노력하겠습니다.감사합니다!
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
클린
・
테스트
・
코드
・
발자국
・
회고
・
3기
2025. 03. 09.
0
인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 1주차 발자국
Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드강의와 함께한 인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot)1주차 발자국 입니다.학습 내용 요약이번 주 동안 [Readable Code: 읽기 좋은 코드를 작성하는 사고법] 강의를 통해 크게 두 가지 주제를 학습했습니다.1⃣ 추상과 구체추상(abstract)은 코드나 로직에서 세부 구현을 생략하고 핵심 의미만 전달하는 방식입니다.구체(concrete)는 코드나 로직의 세부적이고 구체적인 구현을 모두 드러내는 표현 방식입니다.이 개념을 코드에 적용하면 다음과 같은 장점이 있습니다.추상화된 이름 짓기와 메서드 분리를 통해 복잡한 코드를 단순화할 수 있습니다.협업 시 팀원에게 필요한 수준의 정보를 전달할 수 있어 효율적입니다.코드 유지보수가 용이해지고 가독성이 높아집니다.2⃣ 논리와 사고의 흐름, SOLID 원칙📌 논리, 사고의 흐름Early Return: 불필요한 else를 제거하고 조건이 맞지 않을 때 즉시 return해 코드 흐름을 명료하게 유지하는 방법입니다.사고의 Depth 줄이기: 중첩 분기문과 반복문의 깊이를 줄이고, 변수를 필요한 곳 가까이에 선언해 인지적 부담을 낮춥니다.부정어 최소화: 긍정적이고 직관적인 표현으로 메서드 이름을 짓고, 부정 연산자(!) 사용을 줄입니다.📌 SOLID 원칙SRP(단일 책임 원칙): 클래스가 하나의 명확한 책임만 가지도록 설계해야 합니다.OCP(개방-폐쇄 원칙): 기존 코드를 수정하지 않고 확장할 수 있도록 설계합니다.LSP(리스코프 치환 원칙): 자식 클래스가 부모 클래스를 대체해도 프로그램이 정상 작동하도록 설계합니다.ISP(인터페이스 분리 원칙): 사용하지 않는 메서드를 구현하도록 강요받지 않도록 인터페이스를 작게 분리합니다.DIP(의존성 역전 원칙): 고수준 모듈과 저수준 모듈 모두 추상화된 인터페이스에 의존하여 유연성을 높입니다.미션 해결 과정 & 회고Day 2 미션: 추상과 구체 예시미션추상과 구체 강의를 듣고, 생각나는 추상과 구체의 예시 작성해결 과정일상적인 예시를 통해 추상과 구체 개념을 명확히 이해하려고 했습니다.회사 출근이나 배달 음식 주문 등 일상 사례를 통해, 간략히 표현된 추상과 세부적인 표현을 비교하여 정리했습니다.관점 및 이유개념을 일상적이고 친숙한 예시로 접근함으로써 이해를 높이고자 했습니다.추상과 구체의 차이를 분명히 보여줄 수 있는 사례를 선택했습니다.회고일상적 예시 덕분에 개념 이해가 훨씬 쉬워졌고, 추상화의 필요성과 구체적 표현의 중요성을 체감할 수 있었습니다. 앞으로 코드 작성 시 이 관점을 계속 유지할 생각입니다.🔗 Day 2 미션 블로그 링크 Day 4 미션 1: 코드 리팩토링미션중첩 if-else 구조의 주문 검증 메서드 리팩토링접근 관점코드의 인지적 복잡성을 줄이기 위해 Early Return 방식을 사용했습니다.각 조건이 독립적이며, 직관적으로 위에서 아래로 읽히도록 조건 검사를 순서대로 배치했습니다.추가로 주문(Order) 객체가 자기 책임을 다하는 방식으로 책임을 위임하는 방법도 고려했습니다.해결 방법public boolean validateOrder(Order order) { // 주문 항목 유무 if (order.getItems() == null || order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } // 총 가격 검증 if (order.getTotalPrice() 회고Early Return을 적용한 결과, 가독성이 확연히 높아졌고 코드를 읽는 과정이 더 명확해졌습니다. 앞으로도 복잡한 조건 로직을 만날 때 적극적으로 이 방법을 적용할 생각입니다. Day 4 미션 2: SOLID 원칙 정리미션SOLID 원칙을 자신만의 언어로 정리해결 과정각 원칙을 "왜 이런 원칙이 필요한지" 스스로에게 질문하며 이해했습니다.실제 코드 예시를 작성하여, SOLID 원칙을 위반한 코드와 준수한 코드를 비교하면서 학습했습니다.회고원칙을 "내 언어"로 설명하면서, 이전에 막연히 알고 있던 개념들이 훨씬 더 명확하게 다가왔습니다. 단순히 원칙을 외우는 것과 달리, 직접 코드를 작성하고 리팩토링 과정을 거치며 더 깊이 이해할 수 있었습니다.🔗 Day 4 미션 블로그 링크회고이번 주 스터디를 통해 코드를 작성할 때 "추상과 구체의 적정선을 찾는 것이 중요하다"는 점을 깊이 깨달았습니다. 특히 코드가 너무 구체적이면 가독성이 떨어지고, 너무 추상적이면 구체적인 동작이 모호해진다는 점을 직접 실습과 미션을 통해 경험할 수 있었습니다. 또한 Early Return이나 중첩 최소화 등 작은 코드 개선만으로도 가독성이 크게 높아지는 것을 체감할 수 있어 유익했습니다.스스로 칭찬하고 싶은 점미션을 통해 배운 내용을 바로 적용하여 리팩토링하면서 개념을 내 것으로 만들려고 노력한 점이 뿌듯했습니다.SOLID 원칙을 단순히 암기하는 것이 아니라, 스스로 이해하고 예시 코드까지 작성하면서 명확히 내 언어로 표현한 것이 좋았습니다.아쉬웠던 점 & 보완할 점가끔 너무 추상화에 집중하다 보니 코드가 실제 구현에서 너무 멀어지는 경우가 있어, 구체성과 추상성을 더 균형 있게 다루는 연습이 필요하다고 느꼈습니다.SOLID 원칙을 실제 프로젝트 코드에 적용해 보지 못한 점은 조금 아쉬웠습니다. 앞으로 개인 프로젝트에 적용하여 체득할 계획입니다.다음 주 학습 목표다음 주는 강의의 다음 섹션인 "리팩토링" 부분을 학습할 예정입니다. 특히 리팩토링 실습을 통해 SOLID 원칙을 실제 코드에 적용하고, 객체 지향적 사고방식을 내 것으로 만드는 것을 목표로 삼고 있습니다.소감이번 주 강의를 통해 코드 가독성이라는 주제가 얼마나 중요하고 광범위한지 실감했습니다. 앞으로도 이번 학습 내용을 프로젝트에 적극 적용하며, 읽기 좋고 유지보수하기 좋은 코드를 꾸준히 작성하는 습관을 들이겠습니다.감사합니다!
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
클린
・
테스트
・
코드
・
발자국
・
회고
2024. 11. 07.
1
인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 후기
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 후기 입니다. 소개인프런 워밍업 클럽 스터디 2기를 마무리하며, 한 달 동안 진행된 백엔드 프로젝트와 함께한 학습 여정을 회고해보고자 합니다. 이번 스터디는 Kotlin과 Spring Boot를 활용해 실습 중심의 백엔드 개발 프로젝트를 진행하면서, 많은 성장을 경험할 수 있었습니다. 매주 주어진 미션을 해결하고 강의를 수강하며 그 과정에서 직면했던 도전과 성공, 그리고 배움을 함께 나누겠습니다. 1주차: 웹 개발의 기본과 레이어드 아키텍처의 이해1주차는 Spring Boot를 기반으로 한 웹 개발의 기본 개념을 익히고, MVC 패턴과 레이어드 아키텍처를 학습하는 데 집중했습니다. 웹 서비스의 구조와 클라이언트, 서버, 데이터베이스 간의 상호작용을 이해하며, 클라이언트와 서버 간의 데이터 흐름을 REST API의 개념으로 체계화할 수 있었습니다. MVC 패턴의 중요성과 레이어드 아키텍처의 역할을 명확히 이해하면서, 어떻게 하면 유지보수성이 높은 코드를 작성할 수 있을지 깊이 고민하는 시간이 되었습니다.개인적으로 가장 보람찼던 부분은 이론 학습 후 즉시 실습을 통해 프로젝트에 적용해보면서, 개념을 구체화하고 몸에 익힐 수 있었던 점입니다. 특히 강의 내용을 프로젝트에서 직접 구현해보며, 이론과 실제가 어떻게 연결되는지를 깨닫는 과정이 매우 유익했습니다. 2주차: JPA와 API 설계의 시작2주차에는 JPA를 활용하여 데이터베이스와 상호작용하는 방법을 학습하고, CRUD 기능을 직접 구현해보며 JPA의 기본 개념에 익숙해질 수 있었습니다. 실습 프로젝트를 통해 엔티티 간의 관계 설정과 데이터베이스 초기화를 진행하면서 JPA의 다양한 기능을 경험하였고, 강의를 통해 학습한 내용을 실습에 적용하며 개발자로서의 자신감을 쌓을 수 있었습니다.또한, 이번 주에는 REST API를 설계하고 구현하는 미션을 수행했습니다. 사용자와 게시글, 댓글을 관리하는 여러 API를 설계하면서, RESTful한 접근 방식을 유지하기 위해 고민했습니다. API 설계 시 직관적이고 간결한 엔드포인트를 유지하려고 노력한 덕분에, 이후 테스트 코드 작성 및 검증 과정에서도 큰 어려움 없이 진행할 수 있었습니다. 3주차: 컨트롤러 개발과 API 테스트 코드 작성3주차에는 Spring Boot와 JPA를 사용하여 컨트롤러를 개발하고, 다양한 엔드포인트를 구현했습니다. 이와 함께 Thymeleaf를 활용해 프론트엔드 작업을 진행하며, 백엔드와 프론트엔드의 유기적인 연결을 실습해 볼 수 있었습니다.특히 이번 주에는 테스트 코드 작성의 중요성을 다시 한번 실감하게 되었습니다. API의 동작을 검증하는 테스트 코드를 작성하면서, 예상하지 못했던 예외 상황을 처리하고 기능을 보완하는 과정을 통해 코드의 완성도를 높일 수 있었습니다. Thymeleaf를 사용해 프론트엔드를 구성하는 데 있어 부족함이 있었지만, 이를 보완해가며 더 나은 결과물을 만들 수 있었던 점이 인상 깊었습니다. 4주차: 프론트엔드 템플릿 작업과 배포 경험마지막 4주차에는 Thymeleaf의 fragment 기능을 사용하여 HTML 구조를 모듈화하는 작업을 진행했습니다. 프론트엔드를 구성하며 공통 레이아웃을 재사용 가능한 형태로 분리해 유지보수성을 높였고, Docker와 Nginx를 활용해 배포 작업까지 경험할 수 있었습니다. 직접 Docker 이미지를 빌드하고, MySQL 컨테이너와 연동하여 실제 서비스를 배포하는 경험은 매우 실질적이었고, 개발자로서 한 단계 더 성장할 수 있는 계기가 되었습니다.이번 스터디를 통해 가장 크게 느낀 점은 개발 과정에서 이론과 실습의 균형이 얼마나 중요한지였습니다. 각 주차마다 학습한 내용을 프로젝트에 직접 적용해보고, 그 과정에서 발생한 문제들을 해결하면서 실력을 쌓을 수 있었습니다. 또한, API 설계와 테스트 코드 작성, 그리고 실제 배포까지 전 과정을 경험하면서 백엔드 개발의 흐름을 체계적으로 이해할 수 있었습니다.이번 스터디에서 성실히 참여한 결과, 우수러너로 선정되는 영광도 누릴 수 있었습니다. 앞으로도 이번 스터디에서 얻은 배움을 바탕으로 꾸준히 학습하고 성장해 나가고자 합니다. 인프런 워밍업 클럽 스터디를 통해 함께한 모든 분들께 감사드리며, 이후에도 지속적으로 배움을 나누고 함께 성장해 나가기를 희망합니다.
백엔드
・
인프런
・
인프런워밍업클럽
・
스터디2기
・
워밍업
・
백엔드
・
프로젝트
・
후기
2024. 10. 27.
1
인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 4주차 발자국
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 4주차 발자국 입니다. 강의 수강이번 주에는 Spring Boot와 JPA를 사용한 뷰 개발 및 Thymeleaf를 활용한 프론트엔드 템플릿 작업에 중점을 두었습니다. 주로 Bootstrap 템플릿을 가져와 활용하고, Thymeleaf의 fragment 기능을 사용하여 재사용 가능한 HTML 구조를 만들었으며, 배포 작업까지 진행했습니다.주요 학습 내용Bootstrap 템플릿 가져오기 및 적용Bootstrapmade 사이트에서 Admin 템플릿을 다운로드하여 프로젝트에 적용했습니다.템플릿 파일을 프로젝트의 resources 디렉토리에 추가하고, 필요한 CSS, JS 파일들을 적용했습니다.Thymeleaf와 프론트엔드 분리 작업Thymeleaf의 fragment 기능을 활용해 HTML 구조를 모듈화하였습니다. head, header, footer 등 여러 공통 요소를 별도의 fragment로 분리하여 재사용성을 높였습니다.타임리프 문법을 통해 동적으로 페이지를 구성하고 유지보수가 용이하도록 개선했습니다.프로젝트 배포 작업Docker를 이용해 MySQL을 컨테이너로 실행하고, Spring Boot 애플리케이션을 Docker 이미지로 빌드하여 배포했습니다.Nginx를 사용해 80포트와 8080포트를 연결하여 클라이언트 요청을 처리하도록 설정했습니다.Let's Encrypt를 이용해 HTTPS 인증서를 설정하고, 웹사이트를 HTTPS로 안전하게 접근할 수 있도록 구성했습니다. 회고이번 주는 Thymeleaf와 Bootstrap을 활용하여 프론트엔드 작업을 진행하며, 뷰를 모듈화하고 효율적으로 구성하는 방법을 배울 수 있었습니다. 특히 Thymeleaf의 fragment 기능은 HTML 코드의 재사용성과 유지보수성을 크게 개선해 주어 프로젝트의 구조를 더욱 체계적으로 만들 수 있었습니다. 또한, 직접 템플릿을 가져와 수정하고 적용하는 과정을 통해 프론트엔드 개발 역량을 키울 수 있었고, Docker와 Nginx를 이용한 배포 작업을 통해 실제 서비스 환경에서의 배포 경험도 쌓을 수 있었습니다.칭찬할 점Thymeleaf를 사용하여 공통 레이아웃을 fragment로 분리하여 재사용성을 높인 점.Bootstrap 템플릿을 프로젝트에 무리 없이 적용하고, 필요한 수정 작업을 성공적으로 수행한 점.Docker와 Nginx를 이용한 배포 과정을 원활히 진행한 점.아쉬웠던 점 및 보완할 점Thymeleaf 문법에 대한 익숙함이 아직 부족하여 일부 동적 작업에서 어려움을 겪었습니다. 추가적인 연습과 학습을 통해 더 익숙해질 필요가 있습니다.프론트엔드 요소의 커스터마이징에 있어 부족함을 느꼈으며, 좀 더 세밀한 스타일 수정 방법을 연구하고자 합니다. 미션이번 주 미션은 삽입, 수정, 삭제 REST API를 개발하고, 이를 검증하는 테스트 코드를 작성하는 것이었습니다. API는 각 기능별로 POST, PUT, DELETE 요청을 처리하도록 설계하였으며, 모든 케이스에 대해 성공적으로 테스트를 완료했습니다.미션 과정게시글 삽입 API 설계 (POST /api/posts)새로운 게시글을 작성하고, 작성된 데이터를 JSON 형태로 반환하도록 설계했습니다.게시글 수정 API 설계 (PUT /api/posts/{postId})특정 게시글을 수정하고, 수정된 결과를 반환하는 기능을 구현했습니다.게시글 삭제 API 설계 (DELETE /api/posts/{postId})특정 게시글을 삭제하고, 삭제 후 상태 코드 204 No Content를 반환하도록 했습니다.테스트 코드 작성 및 검증각 엔드포인트에 대해 최소 3개의 테스트 케이스를 작성해, 다양한 상황에서의 시스템 동작을 검증했습니다.필수 값이 누락된 경우, 잘못된 ID로 요청했을 때의 예외 처리 등도 함께 테스트하여 안정성을 확보했습니다. 미션 과정추가적으로 가상 프로필을 나의 프로필로 바꾸기 미션과 배포한 프로젝트 공유하기 미션까지 모두 마무리하며, 스터디의 모든 미션을 마무리 하였습니다. 이 발자국을 끝으로 모든 미션과 발자국, 강의 수강 100% 까지 마무리 하며, 스터디를 성공적으로 완주하였습니다. 회고이번 미션을 통해 RESTful한 API 설계 및 테스트의 중요성을 다시 한번 체감할 수 있었습니다. 또한, Thymeleaf를 활용해 프론트엔드를 모듈화하고 코드의 재사용성을 높이는 작업이 실제 프로젝트에서 어떻게 활용될 수 있는지 직접 경험할 수 있는 시간이었습니다. 배포 작업을 통해 실제 서비스 환경에서 발생할 수 있는 문제들을 다루며, 더 나은 품질의 소프트웨어를 개발하기 위한 실무 경험을 쌓을 수 있었습니다. 앞으로 JPA 연관 관계에 대한 이해를 깊이 있게 다지고, 테스트 코드의 가독성을 더욱 높이는 방법을 연구하여 더 나은 품질의 소프트웨어를 개발해 나가겠습니다.
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
프로젝트
・
발자국
・
회고
・
SpringBoot
2024. 10. 20.
1
인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 3주차 발자국
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 3주차 발자국 입니다. 강의 수강이번 주에는 실습 중심으로 Spring Boot와 JPA를 사용한 컨트롤러 개발과 API 설계를 진행했습니다.API 테스트 코드를 작성해보고, Thymeleaf를 활용한 프론트 개발 작업도 수행했습니다.주요 학습 내용Spring MVC와 JPA를 활용한 컨트롤러 개발PresentationApiController 및 PresentationViewController에서 다양한 API 엔드포인트를 구현했습니다.JPA를 통해 데이터베이스와 상호작용하며 데이터를 처리하는 방법을 학습했습니다.Thymeleaf 프론트엔드 개발템플릿을 활용하여 데이터를 프론트엔드에 전달하고 뷰를 생성했습니다.커스터마이징을 통해 유지 보수가 용이한 뷰를 구성했습니다.컨트롤러 테스트 코드 작성API 테스트 코드를 작성하여 정확하게 동작하는지 검증했습니다.실제 API가 예상대로 동작하는지 검증하는 방법을 배웠습니다. 회고이번 주는 Spring Boot와 JPA를 활용한 컨트롤러 개발과 API 설계, 그리고 테스트 코드 작성까지 다양한 실습을 통해 실질적인 개발 경험을 쌓는 데 집중한 한 주였습니다. 특히, 데이터를 조회하고 처리하는 API를 설계하면서 RESTful 구조에 대해 깊이 고민했고, 테스트 코드 작성이 얼마나 중요한지 다시 한번 깨닫게 되었습니다. 실습을 통해 새로운 개념들을 익히고, 실제 프로젝트에 적용해보며 기술적 성장을 이뤘습니다.칭찬할 점테스트 코드를 작성하여 API의 주요 기능들을 효율적으로 검증했습니다.Thymeleaf 템플릿 커스터마이징을 통해 프론트엔드를 구성하고, 유지 보수가 용이하도록 최적화했습니다.아쉬웠던 점 및 보완할 점Thymeleaf 문법에 대한 이해가 부족하여 복잡한 작업에서 어려움이 있었습니다.테스트 코드를 더 간결하고 효율적으로 작성하기 위해 리팩토링 기법을 학습할 계획입니다.미션이번 주 미션은 게시글 조회 REST API를 개발하고, 이를 검증하기 위한 테스트 코드를 작성했습니다.API는 전체 게시글 조회와 특정 게시글 조회 두 가지 기능을 제공합니다. 미션 과정전체 게시글 조회 API 설계GET /api/posts 엔드포인트에서 전체 게시글을 조회하고, JSON 형식으로 데이터를 반환합니다.특정 게시글 조회 API 설계GET /api/posts/{postId}로 특정 게시글 ID를 기반으로 게시글을 조회하여 반환하는 기능을 구현했습니다.테스트 코드 작성 및 검증각 엔드포인트에 대해 단위 테스트를 작성하여 모든 기능이 예상대로 동작하는지 검증했습니다.특히 게시글이 없는 경우와 같은 예외 상황을 처리하는 테스트도 포함시켜 로직의 완성도를 높였습니다. 회고이번 미션을 통해 RESTful한 API 설계의 중요성을 다시 한번 느꼈습니다. 엔드포인트를 직관적이고 간결하게 설계하기 위해 많은 고민을 했으며, 테스트 코드를 작성하며 API 동작을 검증하는 과정에서 테스트의 중요성을 다시 한번 실감할 수 있었습니다.아쉬운 점 및 보완할 점테스트 코드의 가독성과 효율성을 높이기 위해 추가적인 리팩토링이 필요합니다.JPA의 복잡한 연관 관계 처리에서 어려움을 겪었으며, 이러한 부분을 더 명확하게 이해하기 위해 추가적인 학습이 필요합니다.이번 주의 학습과 미션을 통해 부족했던 부분들을 확인할 수 있었고, 앞으로도 지속적인 학습과 실습을 통해 문제를 개선해 나갈 계획입니다. 특히, JPA 연관 관계와 테스트 코드의 리팩토링에 집중하여 더 나은 품질의 코드를 작성하고, 실무에 적용할 수 있도록 역량을 키워가겠습니다.
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
프로젝트
・
발자국
・
회고
・
SpringBoot
2024. 10. 13.
1
인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 2주차 발자국
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 2주차 발자국 입니다. 강의 수강이번 주에는 JPA를 활용해 데이터를 초기화하고, 기본적인 CRUD 작업을 진행하면서 프로젝트의 기초적인 부분을 다졌습니다. 강의를 통해 실습을 진행하며, 코드 작성과 실행 과정을 통해 JPA와 Spring Boot에 익숙해질 수 있었습니다. 특히, 강의를 통해 코드를 작성하는 과정에서 JPA의 기본 사용법을 익히는 데 집중했습니다.주요 학습 내용Spring Data JPA의 기본 CRUD 기능 실습엔티티 간의 기본적인 연관 관계 설정JPA와 데이터베이스 초기화를 통한 실습 환경 설정테스트 코드 작성과 JUnit을 활용한 기본적인 테스트 환경 설정 회고강의와 함께 실습 프로젝트를 진행하면서 JPA와 Spring Boot의 기능을 익혔습니다. 이론 학습보다는 코드 작성에 집중하여, Spring Boot와 JPA의 실질적인 사용법을 몸에 익히는 데 중점을 두었습니다. 실습을 통해 프로젝트 구조와 JPA의 기초 개념을 이해하는 데 도움을 받았습니다.칭찬할 점매일 강의를 듣고 실습 프로젝트를 꾸준히 진행한 점새로운 기술을 익히며 이를 프로젝트에 바로 적용해 본 점실습을 통해 테스트 코드 작성법을 익혀본 점 아쉬웠던 점 및 보완할 점강의를 따라가는 데 집중하다 보니 개념적인 이해가 부족한 부분이 있습니다.실습을 통해 얻은 질문이나 궁금증을 정리해두고, 추가적인 학습을 통해 보완할 계획입니다.미션이번 주 미션은 REST API 설계하기로, 사용자가 게시글과 댓글을 작성하고, 좋아요를 추가하거나 삭제할 수 있는 RESTful API를 설계하는 것이 목표였습니다. 이를 통해 사용자 관리, 게시글과 댓글 관리, 좋아요 기능을 포함한 API를 구축했습니다. 미션 과정API 설계사용자 API: 회원가입, 로그인, 로그아웃, 사용자 정보 조회 및 수정, 비활성화 기능을 설계했습니다.게시글 API: 게시글 작성 및 수정, 삭제 기능과 더불어 게시글 목록 조회 및 특정 게시글 조회를 위한 엔드포인트를 설계했습니다. 또한, 좋아요 추가 및 취소 기능도 포함하여 사용자의 상호작용을 풍부하게 했습니다.댓글 및 답글 API: 댓글 작성, 수정, 삭제 기능과 게시글별 댓글 목록을 조회할 수 있는 기능을 설계했습니다. 댓글에 좋아요를 추가하거나 삭제할 수 있는 기능도 포함하여 사용자가 게시물과 댓글에 대해 보다 활발히 상호작용할 수 있도록 했습니다. 구체적인 API 엔드포인트 및 메서드사용자 API: /api/users 및 /api/users/{userId}를 통해 사용자를 관리할 수 있도록 하였고, 로그인, 로그아웃, 비활성화 기능을 위한 별도의 엔드포인트를 설정했습니다.게시글 API: /api/posts 및 /api/posts/{postId}를 통해 게시글 CRUD와 좋아요 기능을 관리할 수 있도록 설계했습니다.댓글 및 답글 API: /api/posts/{postId}/comments 및 /api/comments/{commentId}로 댓글 CRUD와 좋아요 기능을 관리할 수 있도록 했습니다. 회고이번 API 설계는 RESTful한 접근 방식을 유지하며, 간결하고 직관적인 구조를 갖도록 신경을 썼습니다. 테이블 간의 관계를 고려하여 API를 설계하는 과정에서 실무에서의 데이터 흐름과 REST API의 설계 원칙을 이해하는 데 도움이 되었습니다.아쉬운 점 및 보완할 점아직 JPA 관련 용어와 개념이 생소해서, 이해도가 높아지기까지 시간이 걸렸습니다. 다음 주에는 API 설계를 더욱 구체화하고, 실습하면서 느낀 궁금한 점들을 정리해 해결해 나갈 계획입니다.이번 주는 강의를 통해 프로젝트를 진행하고 API 설계를 하는 경험을 통해 많은 것을 배울 수 있었고, 다음 주에도 꾸준히 학습하며 부족한 부분을 보완해 나가겠습니다.
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
프로젝트
・
발자국
・
회고
・
SpringBoot
2024. 10. 06.
1
인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 1주차 발자국
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기강의와 함께한 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 1주차 발자국 입니다. 강의 수강이번 주에는 웹 개발의 기본 개념을 학습하며, Spring Boot를 중심으로 한 웹 개발에 대한 전반적인 내용을 다루었습니다. 특히, 웹 서비스의 구성 요소인 클라이언트, 서버, 데이터베이스의 상호작용 방식을 이해하고, 클라이언트와 서버가 데이터를 주고받는 과정에서 발생하는 HTTP 통신과 REST API의 개념을 명확히 정리했습니다.Spring Boot를 활용한 프로젝트 구조와 레이어드 아키텍처(Controller, Service, Repository)를 학습하며, 각 레이어의 역할과 책임에 대해 더욱 깊이 이해할 수 있었습니다. 또한, MVC 패턴과 디자인 패턴의 중요성도 학습하며, 어떻게 하면 코드의 결합도를 낮추고 유지보수성을 높일 수 있는지 고민하는 시간을 가졌습니다. 회고일주일간 강의를 들으면서 웹 개발의 전반적인 흐름과 기본 개념을 더 체계적으로 정리할 수 있었습니다. 이전에도 어느 정도 개념을 알고 있었지만, 이번에는 MVC 패턴이나 레이어드 아키텍처의 필요성에 대해 더 명확히 이해하게 되어 좋았습니다. 프레임워크와 라이브러리의 차이도 명확해져, 앞으로 어떤 상황에서 어떤 도구를 선택할지에 대한 기준이 생긴 것 같아 뿌듯합니다.칭찬할 점매일 꾸준히 강의를 들으며 웹 개발의 기본기를 다진 점학습한 내용을 직접 실습 프로젝트에 적용하면서 이론과 실제를 연결 지은 점이번 주 계획했던 학습 목표를 모두 달성한 점 아쉬웠던 점스프링의 의존성 주입(Dependency Injection)에 대한 이해가 조금 부족하다는 느낌이 있었습니다. 강의에서 개념을 배웠지만, 실제로 이를 프로젝트에 어떻게 적용해야 하는지 고민하는 시간이 좀 더 필요할 것 같습니다. 보완할 점의존성 주입을 주제로 더 깊이 파고들어 실습해보고, 관련된 자료를 찾아보면서 이해도를 높여야겠습니다. 특히, 생성자 주입 방식을 더 명확하게 습득하고 싶습니다. 다음 주 목표다음 주에는 이번 주에 학습한 내용을 바탕으로 더 구체적인 프로젝트를 진행하며, 의존성 주입과 스프링 빈 관리에 대한 이해를 심화할 계획입니다. 이를 통해 Spring Boot의 기능을 제대로 활용할 수 있도록 하겠습니다.미션이번 주 미션은 미니 프로젝트 개발을 주제로, 웹 개발의 기본적인 데이터베이스 테이블을 설계하고 이를 GitHub에 업로드하는 것이 목표였습니다. 프로젝트의 주제는 다양한 활동에서 함께할 사람을 찾고 소통할 수 있는 게시판 서비스로, 사용자, 카테고리, 게시글, 댓글, 그리고 좋아요 기능을 포함한 테이블을 설계했습니다. 미션 과정테이블 설계 사용자 테이블 (users): 사용자의 이메일, 비밀번호, 이름, 닉네임 등을 저장하며, user_role 필드로 사용자 권한을 설정할 수 있습니다.카테고리 테이블 (categories): 게시글의 카테고리를 관리하기 위해 설계된 테이블로, 카테고리 이름을 저장할 수 있습니다.게시글 테이블 (posts): 사용자가 작성한 게시글을 저장하는 테이블로, 사용자와 카테고리와의 관계를 참조하도록 했습니다.댓글 테이블 (comments): 게시글에 달린 댓글을 저장하는 테이블로, 답글까지 고려한 설계를 진행했습니다.좋아요 테이블 (post_likes, comment_likes): 게시글과 댓글에 대한 '좋아요' 기능을 구현하기 위한 테이블을 설계했습니다. 프로젝트 깃허브에 업로드미니 프로젝트를 깃허브에 올리는 작업을 진행했습니다. 이번 작업을 통해 버전 관리와 협업의 중요성을 다시 한번 확인할 수 있었습니다. 회고테이블 설계를 처음부터 끝까지 진행하면서, 데이터베이스 간의 관계를 설계하는 것이 얼마나 중요한지 다시 한번 깨달았습니다. 또한, 테이블 관계를 명확히 이해하지 못했던 부분에서 여러 번 수정을 거치면서 실무적인 감각도 더 키울 수 있었습니다. 특히, 외래 키 제약 조건을 걸어 테이블 간의 참조 무결성을 유지하는 방법을 다시 복습하게 된 것이 큰 수확이었습니다.아쉬운 점테이블 설계를 처음 진행할 때, 부모-자식 관계나 외래 키 제약 조건을 제대로 설정하지 못해 몇 번의 수정을 반복해야 했습니다. 이를 통해 초기 설계의 중요성을 다시 한번 느끼게 되었고, 더 많이 연습해야 한다는 생각이 들었습니다.보완할 점초기 설계 단계에서 더 철저하게 준비하여, 데이터베이스 구조를 명확하게 하고 오류를 최소화하는 방향으로 나아갈 계획입니다.이번 주는 강의와 미션 모두에서 많은 것을 배웠고, 실습을 통해 이론을 실제 프로젝트에 적용하면서 자신감을 얻었습니다. 다음 주에도 꾸준히 학습하며 부족한 부분을 보완해 나갈 계획입니다.
백엔드
・
인프런
・
워밍업클럽
・
스터디
・
백엔드
・
프로젝트
・
발자국
・
회고
・
SpringBoot