안녕하세요! 꾸준함이 가장 강한 무기라고 생각하며 열심히 달리고 있습니다.
개인 블로그 : https://twojun-space.tistory.com/
GitHub : https://github.com/twojun
블로그
전체 52024. 03. 09.
0
[인프런 워밍업 클럽 0기 백엔드] 3주차(최종) 발자국 (내용 정리)
인프런 워밍업 스터디의 마지막 주차가 마무리되어 가고 있습니다.3주차에 학습했던 내용들을 전체적으로 정리해 보고자 합니다.미니 프로젝트 수행은 하단의 깃허브 주소를 남겨두도록 하겠습니다.이전과 동일하게 학습한 내용, 미니 프로젝트 관련 내용들을 개인 블로그, 깃허브에 모두 정리하고 있습니다.하단은 학습 내용을 정리한 제 블로그 주소입니다.https://twojun-space.tistory.com/category/%EA%B8%B0%EB%A1%9D%2C%20%ED%9A%8C%EA%B3%A0/InFlearn%20Warming-up%200%EA%B8%B0%20BE (1) GitHub (Mini project)https://github.com/twojun/inflearn_warmingup_be_project 1. [11일 차] - 배포(Deployment), H2 DB를 통한 Profile 적용, Git & GitHub, AWS EC2(1) 11일 차 관련 학습 내용 개인 블로그 정리https://twojun-space.tistory.com/194 1-1. 배포의 뜻, 스프링 Profile(1) 애플리케이션에서의 배포의 뜻, 배포의 특징에 대해 알아보았다.(2) 사용자가 최종적으로 서비스를 이용할 수 있게 진행하는 일련의 작업으로 보면 된다.(3) 그리고 profile에 대해서도 알아보았는데 우리는 개발을 하면서 자연스럽게 profile 기능을 사용하고 있었다.(4) 이처럼 profile의 경우 똑같은 서버 코드를 실행시키지만 실행환경과 장소에 따라 각 다른 프로그램과 자원을 사용할 수 있도록 하는 것을 의미하게 된다. 1-2. Profile 적용(1) 간단하게 인메모리 DB인 H2 Database에 대해 알아보고, application.properties 또는 application.yml에서 DB profile을 설정하기 위한 옵션 적용이 가능함을 학습했다. (2) Run/Debug Configurations 메뉴에서 Active profiles를 yml 또는 properties에서 설정한 값으로 채워두고 서버를 실행시킨다. 1-3. Git & GitHub(1) Git, GitHub의 특징과 차이점을 알아보고 GitHub를 왜 많은 개발자들이 사용하고 있는지 그 장점과 특징에 대해 중점적으로 알아보았다. (2) git init, git remote, git status 등 Git의 기본적인 명령어 학습 1-4. AWS EC2(Amazon Web Service Elastic Computer Cloud)(1) 아마존에서 웹 서비스의 배포와 운영을 위해 제공하는 클라우드 서비스인 AWS EC2와 특징에 대해 학습했다.(2) AWS EC2를 통해 개발한 서비스의 배포와 운영을 위해 가상 서버 인스턴스를 생성할 수 있으며 애플리케이션의 트래픽, 규모 등을 고려하여 생성한 서버 인스턴스의 리소스를 확장할 수도 있다. 1-5. 11일 차 학습 내용 개인 회고(1) 개발만큼 배포와 운영 단계도 백엔드 개발에서 가장 중요한 부분이다. 이 부분에 대해 학습하고 실제 프로젝트에도 적용할 수 있는 능력을 기르고자 한다. 2. [12일 차] - AWS EC2 접속, 기본적인 Linux command, AWS Computing 환경에서 서버 배포를 위한 환경 구성, & 배포, 종료되지 않는 실행(foreground & background)(1) 12일 차 관련 학습 내용 개인 블로그 정리https://twojun-space.tistory.com/195 2-1. AWS EC2의 두 가지 접속 방법(1) key pair를 통한 접속 (Mac os의 경우 Iterm을 통해 접속 가능)(2) AWS Console을 통한 접속 2-2. 기본적인 리눅스 커맨드 학습(1) 디렉토리 생성 및 삭제, 경로 이동 등 기초적인 리눅스 명령에 대해 학습 2-3. AWS Linux에서 서버 배포 준비(1) 우선 Console에서 Git을 별도로 설치한다. (2) 서버 코드의 실행을 위한 JDK를 설치한다. (3) DBMS 설치(RDB : MySQL) 2-4. EC2 환경에서도 동일하게 데이터베이스 구성, 빌드와 배포(1) EC2 환경에서도 동일한 테이블 구조를 세팅한다. (2) Remote repository에서 Git Clone으로 기존 서버 코드를 모두 가져온다. (3) AWS EC2 Free tier의 경우 성능이 좋지 않다. 요즘은 가벼운 애플리케이션이더라도 서버 리소스를 많이 잡아먹기 때문에 Swap Setting을 통해 저사양의 인스턴스를 대상으로 메모리와 함께 추가적으로 스토리지도 함께 사용할 수 있도록 설정한다. (4) gradlew를 통해 빌드를 진행한다. 무료 서버를 사용하는만큼 테스트는 돌리지 않는 것이 성능상 유리하다. (5) 빌드 성공 시 빌드 디렉토리가 생성되고 내부로 이동하면 .jar 파일이 생성되어 있다. 이제 빌드된 .jar 파일을 통해 서버 실행이 가능한 상태이다. java -jar 명령으로 서버를 실행한다. 2-5. 종료되지 않는 실행(1) foreground & background의 차이에 대해 알아보았다. (2) nohup 명령어를 알아보고, 파일 내부를 확인할 수 있는 cat, tail 등 명령어에 대해 추가 학습했다. 2-6. 12일 차 학습 내용 개인 회고(1) 배포에 대한 전반적인 내용을 빠르게 학습해볼 수 있는 파트였던 것 같다. 서버 애플리케이션의 경우 대부분 리눅스 환경에서 다루어지기 때문에 리눅스에 대한 이해와 커맨드를 빠르게 체화시키는 부분이 중요할 것 같다. 3. [13일 차] - build.gradle, Spring & Spring Boot(1) 13일 차 관련 학습 내용 개인 블로그 정리https://twojun-space.tistory.com/196 3-1. build.gradle(1) build.gradle이 무엇인지 빌드 도구인 gradle이 무엇인지 알아보고 프로젝트에 필요한 의존성을 관리할 수 있는 도구임을 학습했다. (2) build.gradle을 이루는 plug-in, repositories, dependencies, dependencies에 대해 학습했다. 3-2. Spring & Spring Boot(1) Spring, Spring Boot를 시기별로 출시된 버전, 버전이 갖는 의미에 대해 학습했다. (2) 기존 스프링과 스프링 부트의 차이에 대해 학습했다.스프링, 스프링 부트와의 차이점 : (1) 간편한 설정 제공스프링, 스프링 부트와의 차이점 : (2) 간단한 의존성(라이브러리, 프레임워크) 설정 관리스프링, 스프링 부트와의 차이점 : (3) 강력한 확장성, MSA(Micro-Service Architecture)에 적합한 모니터링 기준 제공 등 3-3. application.yml(properties), Lombok library(1) application.yml, application.properties 모두 스프링 프로젝트의 전반적인 설정 정보를 정의하기 위한 파일로 볼 수 있다. (2) yml은 계층 구조를 갖고 properties는 동일한 key, value 타입이지만 계층 구조가 존재하지 않는다. (3) Lombok 라이브러리는 개발자에게 많은 편리성을 제공해주는 라이브러리이다. Getter, Setter와 같이 반복되는 Boiler plate code를 제거할 수 있게 도와준다. 3-4. 13일 차 학습 내용 개인 회고(1) 스프링으로 개발을 진행하며 의존성을 관리하는 도구인 build.gradle과 스프링, 스프링 부트의 차이점, 설정 정보를 관리하는 application.yml에 대해 학습할 수 있었다. 무심하게 사용해오던 도구들이지만 의미를 다시 한 번 더 정리하고 제대로 알고 사용할 수 있으면 좋겠다는 생각을 하게 되었다. 4. 14일 차 마지막 마무리 영상, 스터디 마지막 최종 회고(1) 마무리 섹션에서는 코치님께서 백엔드 개발에 있어 전체적인 학습 방향성을 개인적으로 조언해 주시는 시간과, AWS 호스팅 서비스의 과금 계산, 강의에서 소개되지 않았던 SQLMapper인 MyBatis, ORM 기반 기술인 JPA의 비교, 클라이언트 사이드 렌더링, 서버 사이드 렌더링에 대해 간단하게 정리해 주셨다. (2) 약 3주 간 온라인 강의와 세션 외에도 수강생들의 끊임없는 질문에 항상 웃으며 친절하게 대답해 주셨던 열정이 가득한 최태현 코치님, 열심히 배우고 성장하기 위해 끊임없이 달리는 러너분들이 있어서 스터디를 잘 마무리할 수 있었던 것 같습니다. 짧았다면 짧고, 길었다면 긴 시간이었지만 스터디를 완주할 수 있게 되어서 기쁘고 이번 스터디 수료를 통해 많은 성장은 아니지만 개인적으로 어느 정도 성장하는 데 도움이 되었다고 생각합니다. 스터디를 참여하면서 많은 분들을 만났고, 꾸준히 배움을 멈추지 않는 수강생분들을 보며 저 자신도 많이 반성하게 되었던 기간이었던 것 같습니다 다시 한 번 코치님, 러너분들, 이 스터디 기회를 만들어주신 인프런 관계자 여러분들께 감사하다는 말씀을 드리고 싶습니다. 코치님, 0기 백엔드 러너분들, 인프런 관계자분들을 항상 응원하겠습니다!모두 화이팅입니다. 😁
백엔드
・
인프런워밍업
・
백엔드
・
스프링
・
발자국
・
회고
2024. 02. 28.
0
[인프런 워밍업 클럽 0기 백엔드] 2주차 발자국 (내용 정리 + 과제 + 미니 프로젝트)
인프런 워밍업 스터디의 2주차가 마무리되어 가고 있는 한 주입니다.2주차 동안 학습했던 내용들과 과제 수행 관련된 내용까지 한 번에 정리하고자 합니다.추가로 2주차 동안 학습한 내용, 과제 수행 부분은 개인 블로그에 항상 정리하고 있습니다.참고하실 분들은 참고해 주시면 좋을 것 같습니다 :)제 블로그 주소 링크 남겨드리겠습니다.(1~10일차 학습 및 과제 수행 내용)https://twojun-space.tistory.com/category/%ED%9A%8C%EA%B3%A0/InFlearn%20Warming-up%200%EA%B8%B0%20BE추가적으로 과제가 마무리 된 후 미니 프로젝트가 시작됩니다.미니 프로젝트는 제 GitHub에 소스 코드, 기능 설명을 남겨두고자 합니다.하단은 제 GitHub 주소입니다.https://github.com/twojun/inflearn_warmingup_be_project 1. [6일 차] - Spring Bean & Spring Container, Spring Container를 다루는 방법, Spring Bean 주입 받기, 스프링 빈의 우선 순위 설정1-1. Spring Bean?(1) 스프링 빈에 대한 정의, 스프링 빈이 사용되는 이유스프링 컨테이너와 연관지어 설명, 스프링 빈의 라이프 사이클 의존성 확인 및 주입을 담당하는 스프링 컨테이너 내부에 스프링 빈이 존재한다. 1-2. Spring Container(1) 스프링 컨테이너가 사용되는 이유(2) 스프링 컨테이너의 역할(3) 스프링 컨테이너를 사용할 때와 사용하지 않을 때의 Controller-Service-Repository, 사용 전 후로 달라지는 점1-3. 의존성 주입(Dependency Injection), 제어의 역전(Inversion of Control, IoC)스프링 프레임워크의 핵심 기능인 의존성 주입, 제어의 역전이 무엇인지 코드를 통해 직접 알아보며 스프링 프레임워크가 DI, IoC를 제공해 줌으로써 가져다 주는 이점에 대해 정리 생성자 주입, Setter 주입 등 스프링 컨테이너가 제공해주는 다양한 기능 정리 1-4. @Controller, @Service, @Repository를 계층형 아키텍처에 직접 적용(1) 관련 객체들이 스프링 빈으로 등록되어 컨테이너 내부에서 서로 간의 의존성, 라이프 사이클이 관리됨을 이해한다. 1-5. 스프링 컨테이너를 다루는 방법, @Configuration, @Bean, @Component, 스프링 빈을 주입받는 방법@Configuration, @Bean이 직접적으로 사용되는 시기에 대해 학습@Component의 효과스프링 빈 주입 시 Constructor injection 사용(불변 타입의 객체와 함께 사용)Constructor injection 사용 시 테스트 용이 1-6. @Qualifier, @Primary(1) 동일한 타입의 빈에 대해서 어떠한 빈을 주입 대상으로 설정할지 우선권을 부여하는 어노테이션직접 타겟을 텍스트로 지정하는 @Qualifier가 @Primary보다 우선권이 높다. 1-7. 6일 차 개인 회고(1) 스프링 빈, 스프링 컨테이너, DI(Dependency Injection), IoC(Inversion of Control) 등 스프링을 이루고 있는 주요 핵심 기능에 대해 학습할 수 있었다. (2) 스프링을 이루고 있는 핵심 기술인만큼 확실하게 이에 대해 인지하고 있어야 할 필요성을 느끼게 되었다. 2. [6일 차] - 과제 수행 : 계층 구조인 Controller - Service - Repository로 분리하기(1) 과제 수행 코드 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 (2) 6일차 과제수행 리뷰 : (개인 블로그)https://twojun-space.tistory.com/188 2-1. 문제 1번 : Fruit 서비스를 각각의 계층구조로 분리하기(1) 문제 접근 및 해결 방법기존에 스파게티처럼 얽혀 있던 코드를 각각의 역할에 맞게 수행할 수 있도록 코드를 분리했다.사용자의 요청을 받아 응답을 반환하는 Controller, 비즈니스 로직을 처리하는 Service, 데이터베이스와의 통신을 담당하는 Repository로 분리했다.기존 코드도 그렇고, 분리 과정에서 각 계층마다 역할이 뚜렷했기 때문에 분리하는 데 큰 어려움은 없었던 것 같다. 2-2. 정상 동작 확인(1) 기존 코드를 계층적으로만 분리해서 조금 더 유지보수성을 높였기 때문에 이전과 동일하게 API 반환, 데이터베이스에 데이터가 적재되는 등 정상적으로 동작하는 부분을 확인했다. 2-3. 문제 2번 : FruitRepository 코드를 FruitMysqlRepository, FruitMemoryRepository로 구분하고 리포지토리를 변경해가며 코드 실행하기(1) 문제 접근 및 해결 방법우선 동일한 타입을 갖는 객체에 대해 FruitMysqlRepository, FruitMemoryRepository 두 개 중, FruitMysqlRepository 클래스에 @Primary 어노테이션을 적용하여 코드를 실행해보니 정상적으로 코드가 동작하는 것을 확인할 수 있었다. 기능은 동일하고 어떤 빈을 주입받을지만 선택하면 되는 부분이었기에 큰 어려움 없이 해결할 수 있는 과제였다. 2-4. 6일차 과제 개인 회고(1) 기존의 코드를 Controller - Service - Repository로 분리하며 각 계층이 가져야 하는 역할, 책임에 대해 생각해 볼 수 있었다. (2) 조금 더 좋은 코드를 위해 지켜야 되는 부분은 무엇인지, 공부해야 되는 부분은 무엇인지 찾아볼 수 있었다. 3. [7일 차] - 지금까지 코드를 작성하며 Repository에 대해 개선할 점, JPA 도입, 추상화 레벨을 높인 Spring Data JPA 3-1. Repository 영역에서 지금까지 작성된 코드의 아쉬운 점(1) 문자열 기반으로 직접 쿼리를 작성하고 있다.(2) 이 부분에 대한 심각한 문제 : 컴파일 타임이 아닌 런타임 시점에 오류가 발생한 것을 인지하게 된다.(3) 특정 DB에 대한 종속적 쿼리 발생(4) 기본적인 CRUD에 대한 반복 작업 등등... 3-2. 객체와 DB 테이블의 패러다임 불일치 문제(1) 객체와 데이터베이스 테이블은 서로 간의 패러다임이 완전히 불일치한다.(대표적으로 연관 관계 문제, 상속구조를 표현할 수 없는 문제, 서로 참조할 수 있는 매커니즘이 아예 다른 문제 등) (2) 대부분의 애플리케이션이 객체지향적 설계를 지향한다. 객체와 관계형 데이터베이스를 같이 사용하기 위해서는 이 부분을 어떻게 해결할까? -> JPA 도입 3-2. JPA(Java Persistence API)(1) JPA의 정의, ORM 기술이 어떠한 기술인지 학습(2) JPA의 구현체인 하이버네이트의 등장 3-4. 객체와 테이블을 매핑하기 위한 여러 가지 어노테이션, 기타 옵션(1) @Id, @GeneratedValue(2) @Column 등 ...(3) JPA에 대한 여러 가지 설정 및 옵션 설정 : application.yml(4) spring.jpa.hibernate.ddl-auto 옵션 : create, create-drop, validate, update, none 존재(5) spring.jpa.properties.hibernate.show_sql(6) spring.jpa.properties.hibernate.format_sql(3) spring.jpa.properties.hibernate.dialect 3-5. Spring Data JPA를 통한 CRUD 작업 공통화, Repository 작성(1) Spring Data JPA의 대한 개념, 정의 학습(2) Spring Data JPA는 높은 추상화 레벨을 가진 라이브러리로 스프링에서 데이터베이스에 대한 접근을 단순화하고 효율적으로 처리하며 반복적인 CRUD 작업 또한 추상화하여 개발자가 직접 코드를 작성하지 않고 간단한 CRUD 기능을 수행할 수 있도록 설계되어 있다.(3) 회원 도메인에 직접 Spring Data JPA 적용해 보기 (4) 인터페이스를 사용하는 데 구현체를 생성하지 않았음에도 불구하고 해당 인터페이스를 사용할 수 있는 이유 학습(5) 스프링 데이터 JPA 쿼리 메서드 작성 방법, 여러 가지 옵션 확인 3-6. 7일 차 학습 내용 개인 회고(1) Spring Data JPA가 갖는 편리함 덕분에 개발 생산성이 높아졌지만 내부적으로 동작하는 매커니즘을 알기 위해선 JPA에 대한 기초적인 이해가 선행되어야 한다고 생각했다. (2) JPA를 이루는 기초적인 개념을 다시 한 번 정리할 수 있었고 헷갈렸던 부분에 대해 제대로 학습해 볼 수 있었다. 4. [7일 차] : 과제 수행 - Spring Data JPA 적용(1) 과제 수행 GitHub 주소 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 (2) 7일 차 과제 정리 블로그 주소 : https://twojun-space.tistory.com/190 4-1. 과제 수행 : 문제 1번(1) 기존 Fruit 서비스가 Spring Data JPA Repository를 사용할 수 있도록 FruitRepository 인터페이스를 생성한다. (2) 이후 서비스 계층에서 새롭게 생성된 FruitRepository (Interface)를 의존할 수 있도록 설정한다.(3) 접근법은 매우 간단하다. 인터페이스를 생성하고 서비스 계층에서 해당 인터페이스를 의존할 수 있도록 의존 관계를 변경해 주기만 하면 된다. 4-2. 과제 수행 : 문제 2번(1) 문제 요구사항 : 특정 과일을 기준으로 판매된(거쳐간) 과일의 개수를 출력하는 API 설계 (2) 접근 방법 및 문제 해결 과정서비스 계층에 로직이 모두 몰리는 것을 막기 위해 과일 상태 변경에 관한 구현 로직을 도메인 계층에서 구현한다.판매 전 과일 판매 상태는 false, 판매 이후 true로 변경한다.// 판매 상태 변경 public void changeSalesStatus(boolean salesStatus) { this.salesStatus = salesStatus; }또한 Setter를 사용하는 것은 좋지 않다. 의미 있는 비즈니스 메서드(changeSalesStatus) 등을 생성하는 것이 좋다.@Repository public interface FruitRepository extends JpaRepository { // select * from fruit where name = ? and salesStatus = true; long countByNameAndSalesStatusIsTrue(String name); }Repository 영역에 쿼리 메서드를 통해 판매된 과일의 개수를 계산하는 코드를 작성한다.(3) 기능 테스트본인은 매번 데이터 로우를 넣는 부분이 번거로워서 별도의 InitDbService를 만들어서 서버가 재시동될 때마다 해당 데이터들을 추가하도록 설정했다.@Component @Transactional @RequiredArgsConstructor static class InitDbService { private final EntityManager em; public void initFruitDb() { Fruit fruit1 = createFruit("사과", 4000L, LocalDate.of(2024, 02, 01)); Fruit fruit2 = createFruit("바나나", 2000L, LocalDate.of(2024, 02, 01)); Fruit fruit3 = createFruit("사과", 6500L, LocalDate.of(2024, 02, 01)); Fruit fruit4 = createFruit("사과", 7000L, LocalDate.of(2024, 02, 01)); Fruit fruit5 = createFruit("사과", 3000L, LocalDate.of(2024, 02, 01)); Fruit fruit6 = createFruit("포도", 12000L, LocalDate.of(2024, 02, 01)); Fruit fruit7 = createFruit("사과", 2500, LocalDate.of(2024, 02, 01)); Fruit fruit8 = createFruit("사과", 5000L, LocalDate.of(2024, 02, 01)); em.persist(fruit1); em.persist(fruit2); em.persist(fruit3); em.persist(fruit4); em.persist(fruit5); em.persist(fruit6); em.persist(fruit7); em.persist(fruit8); } private static Fruit createFruit(String name, long price, LocalDate warehousingDate) { return new Fruit(name, price, warehousingDate); } }테스트 진행 시 판매된 과일의 개수가 정상적으로 출력됨을 확인했다.4-3. 과제 수행 : 문제 3번(1) 문제 요구사항아직 판매되지 않은 특정 금액 이상, 금액 이하의 과일 리스트를 출력하는 API 설계 (2) 문제 접근 및 해결 방법 / 테스트Controller에 판매되지 않은 특정 금액, 이상, 이하 과일들, 결과 반환 개수까지 반환하는 메서드를 만든다.응답 DTO에 판매되지 않은 과일 개수를 나타내기 위해 별도의 resultSize 필드를 추가한다.이후에 과일의 판매 상태 컬럼을 활용해 판매되지 않은 과일의 리스트를 반환하는 로직을 각각 짜고 결과를 테스트 해 봤을 때 정상적으로 API 반환값이 확인된다.4-4. 과제 개인 회고(1) 높은 추상화 덕분에 우리의 개발 생산성이 올라갔지만, 그 뒤에는 우리가 편리한 기술을 사용하기 위해서 뒷받침되는 기술들이 많다는 것을 다시 한 번 느껴볼 수 있었다.(2) 지금 작성한 코드들도 문제없이 작동하지만 코드를 더 좋은 방향으로 짤 수 있지 않을까라는 생각이 계속 들었다.5. [8일 차] - 트랜잭션의 정의, 커밋과 롤백(Commit & Rollback), JPA의 Persistence Context, Persistence Context의 여러 가지 기능 살펴보기(1) 관련 내용 정리 (개인 블로그) : https://twojun-space.tistory.com/191 5-1. 트랜잭션의 정의와 트랜잭션의 커밋과 롤백(1) 예시와 함께 트랜잭션의 정의, 성공적인 트랜잭션 후 데이터베이스와의 동기화를 진행하는 커밋 옵션, 트랜잭션 실패 시 작업 이전으로 되돌아가는 롤백 옵션에 대해 확인해 보았다.5-2. 실제 코드에 선언적 트랜잭션(Declarative transaction) 적용하기(1) 코드에 @Transaction 어노테이션(선언적 트랜잭션 방법)을 적용하여 서비스 계층에서 메서드가 실행될 때 트랜잭션이 적용될 수 있도록 하고 작업 성공 시 커밋, 실패 시(예외 발생 시) 롤백하게 된다.5-3. JPA의 Persistence Context, Persistence Context의 여러 가지 기능(1) Persistence context(영속성 컨텍스트)의 정의에 대해 학습했다.(2) 첫 번째 기능 : 변경 감지트랜잭션 커밋 시점에 엔티티에 대한 변경사항을 감지하여 이에 대한 쿼리가 실제 데이터베이스로 전송되는 것을 말함(3) 두 번째 기능 : 쓰기 지연 저장소엔티티를 관리하며 발생한 관련 쿼리들을 쓰기 지연 저장소에 두고 트랜잭션 커밋 시점에 모든 쿼리를 데이터베이스로 전송한다.(4) 세 번째 기능 : 1차 캐시 기능 지원엔티티의 Identifier를 기준으로 영속성 컨텍스트에 영속화된 엔티티는 1차 캐시에 스냅샷(영속화 당시 엔티티의 정보)이 저장되어 있고 추후 해당 엔티티를 조회하는 경우라면 데이터베이스까지 조회 쿼리를 날리지 않고 1차 캐시에서 조회함에 따라 성능상 조금의 이점이 생긴다.5-4. 8일차 학습 회고(1) JPA의 기능들을 무심하게 사용해 오다가 JPA의 내부 매커니즘을 이해할 수 있는 영속성 컨텍스트에 대해 다시 한 번 리마인드 할 수 있었다. 관련 기반 기술의 이해가 선행되어야 해당 기술을 문제없이 잘 사용할 수 있다고 생각하기 때문에 이 부분에 대해 다시 한 번 정리해볼 생각이다.6. [9일 차]- 추가 기능에 대한 API 개발학습 내용 관련 블로그 정리 : https://twojun-space.tistory.com/1926-1. 도서 등록, 대출, 반납 요구사항 추가에 대한 API 개발, 개인 회고(1) 이전과 동일하게 요구사항을 확인하고 요청/응답 DTO의 스펙, Controller, Service, Repository를 개발했다.(2) 이를 통해 회원 관리, 도서 등록과 대출 반납에 대한 기능 구현이 모두 완료되었지만 한 가지 의문점이 남는다. 서비스 계층을 중심으로 모든 로직이 돌아가고 절차지향적인 코드라는 느낌이 많이 든다. 각 생성된 엔티티 간의 협력을 통해 개발할 수 없을까? 라는 의문점이 들고 JPA에서 제공하는 연관관계 기능을 사용해서 엔티티의 역할과 협력을 추가적으로 사용해서 조금 더 객체지향적으로 설계해 보는 것이 좋다고 생각했다.7. [10일 차] - JPA 연관관계와 지연 로딩(Lazy Loading), 객체지향적 설계, 도서 대출/반납 기능 Refactoring(1) 관련 학습 내용 블로그 정리 : https://twojun-space.tistory.com/1937-1. 연관관계란 무엇인가?(1) 연관관계의 정의에 대해 알아봤다. 데이터베이스 테이블과 객체 간 서로를 참조하는 방식에 대한 패러다임이 불일치하기 때문에 JPA의 연관관계를 통해 객체와 테이블을 정확하게 매핑하는 것이 중요하다.7-2. 연관관계의 주인(1) 일대일의 경우 핵심 비즈니스 로직이 존재하는 엔티티를 연관관계의 주인으로 둔다.(2) 다대일의 경우 외래 키가 존재하는 엔티티를 연관관계의 주인으로 설정한다.(3) 연관 관계의 주인으로 설정된 엔티티는 객체가 서로 연결될 수 있는 기준이 된다.(4) 일대일 관계에서는 @OneToOne 어노테이션을 사용한다.(5) 다대일 관계에서는 @ManyToOne, @OneToMany를 사용한다.(6) 양방향 연관관계를 가진다면, 한 쪽 엔티티에 대한 변경이 다른 쪽 엔티티에도 반영될 수 있도록 도와주는 메서드인 연관관계 편의 메서드를 만든다.(7) 양방향 연관관계를 사용하게 된다면, 신중하게 선택해야 한다.7-3. 실무에서 다대다 연관관계는 사용하지 않는다.따라서 중간에 별도의 테이블을 생성하여 처리하는 방법으로 매핑한다.7-4. @ManyToOne은 단방향으로만 사용한다,1쪽에서 @OneToMany로 참조하는 부분을 없애고 @ManyToOne 단방향으로만 남겨놓는다. 7-5. 연관관계의 주인이 사용할 수 있는 어노테이션@JoinColumn을 통해 연관관계의 주인이라는 부분을 명시한다. 7-6. 영속성 전이(Cascade)옵션과 orphanRemoval(1) cascade 옵션의 경우 연관관계와 관련은 없다.(2) 부모 엔티티가 자식 엔티티를 관리해야 할 때 사용한다.(3) orphanRemoval은 고아 객체를 제거할 때 사용하는 옵션으로 부모 엔티티와 자식 엔티티 간 연관관계가 제거된 경우 해당하는 자식 엔티티를 삭제하게 된다. 7-7. 도서 대출/반납 기능 리팩토링(1) 지금까지 학습한 내용을 바탕으로 각 엔티티가 협력할 수 있도록 모든 코드를 수정한다.(2) 엔티티에 도서 대출, 도서 반납 등의 핵심 로직을 설계한다.(3) 이를 통해 도메인 간 협업이 가능하도록 설계하여 서비스 계층의 로직이 단순해지고 특정 기능이 필요한 경우 엔티티의 기능을 직접 호출하도록 설계한 것을 확인할 수 있었다.7-8. 9일차에서 소개되지 않은 영속성 컨텍스트의 기능 : 지연 로딩(Lazy Loading)(1) 지연 로딩은 두 엔티티를 대상으로 특정 엔티티를 조회함에 있어서 연관된 엔티티는 바로 가져오지 않고, 해당 연관된 엔티티를 필요로 할 때(사용될 때) 로딩하는 기법을 의미한다.(2) 지연 로딩의 핵심 매커니즘은 프록시 기술과 연관되어 있다.7-9. 연관관계를 사용해서 도메인 중심으로 설계 시 얻는 장점?(1) 각자의 역할에 집중하게 된다 :계층별로 응집성이 강해진다. 도메인끼리의 협업 관계를 통해 서비스 계층에서는 외부 트랜잭션 관리, 의존성 관리 등의 역할만 맡게됨으로써 각자의 역할에 더 집중하는 코드가 완성된다.(2) 협업 시 코드 리딩이 쉬워진다.서비스 계층에 너무 많은 로직이 몰려있다 보면 코드를 리딩하는 입장에서 번거로울 수 있다. 하지만 도메인 중심으로 코드를 설계하면 계층이 어느 정도 분리됨을 가져가면서 도메인 계층이 각각 어떤 역할을 수행하는지 파악하기 수월해진다.(3) 테스트 코드 작성 시 용이하다.(4) 결론원론적인 이야기이지만 항상 연관관계를 사용하는 것이 정답은 아니기에 요구사항, 도메인 아키텍처 등 여러 가지 사항을 충분히 고민해서 연관관계 사용을 선택해야 한다.7-10. 학습 내용 개인 회고(1) 개인적으로는 이번 섹션이 가장 중요한 내용인 것 같다.(2) 영속성 컨텍스트(JPA 내부 동작 방식 이해)를 이해하는 것과 객체와 테이블을 매핑시킬 때 가장 중요한 연관관계에 대한 내용이라 더욱 그렇게 느꼈던 것 같다.(3) 연관관계를 조금 더 정확히 이해하고 항상 주의깊게 코드를 설계하도록 노력해야 할 것 같다.8. 2주 차 회고(1) 벌써 스터디에 참여한지 2주차가 마무리되는 시점이다.(2) 스터디 완주까지 최선을 다하고 싶고, 기회가 된다면 우수 러너도 도전해 보고 싶다. 많은 것을 경험하고 얻어갈 수 있는 시간이 되었으면 좋겠다.(3) 0기 스터디원분들 모두 화이팅입니다 :)
백엔드
・
인프런워밍업
・
스프링
・
백엔드
・
발자국
2024. 02. 25.
0
[인프런 워밍업 클럽 0기 백엔드] 1주차 발자국 (내용 정리 + 미션 수행 정리)
인프런 워밍업 스터디의 1주차가 마무리되어 가고 있는 한 주입니다.1주차 동안 학습했던 내용들과 미션 수행 관련된 내용까지 한 번에 정리하고자 합니다.추가로 1주차 동안 학습한 내용, 과제 수행은 개인 블로그에 별도로 상세하게 정리해 둔 부분이 있습니다.참고하실 분들은 참고해 주시면 좋을 것 같습니다😁제 블로그 주소 링크 남겨드리겠습니다.😁 (1~7일 차 학습 내용, 과제 수행)https://twojun-space.tistory.com/category/%ED%9A%8C%EA%B3%A0/InFlearn%20Warming-up%200%EA%B8%B0%20BE 1. [0일 차] - 인프런 워밍업 스터디 0기 Orientation1-1. 스터디 진행 방식, 일정, 완주 러너와 우수 러너 기준 정리 등(1) 스터디 진행에 있어 필요한 부분들을 코치님께서 모두 정리해 주셨습니다.(2) 또한 디스코드에 발자국 작성법, 완주, 우수러너의 기준 선정 등 다양한 내용들이 디스코드에 나와 있어서 과제 수행에 별 어려움은 없었습니다. 1-2. 코치님의 추가 강의 : 자바의 역사(1) 코치님께서 Orientation 이후 자바의 역사에 대해 간단하게 정리해 주셨는데, 이 부분에 대해 정리해 보겠습니다. 1-3. Java 7(1) 프로그래밍 언어 자바의 암흑기가 찾아온 버전으로, 다른 언어들보다 오래 되었고, 기능이 한참 부족하다는 의견들이 다수 존재한 상황 (2) 당시 사람들의 생각 : 데이터 타입, 조건문, 반복문, OOP, Generic 정도만 다루면 잘 다루는 거 아니야? 라는 생각들이 당시 대다수 사람들의 생각 1-4. Java 8 (2014년)(1) 자바 8을 기점으로 언어의 대격변이 발생했던 시기 (2) Functional Programming(FP), Lamba Expression, Stream API, Optional operation, 날짜, 시간을 다루는 방법 등 (LocalDateTime) 등 현재 시점에서도 가장 많이 사용되는 자바의 핵심 문법들이 등장하기 시작함 1-5. Java 9 (2017년)(1) 자바 9부터 자바의 버전업 주기가 대부분 6개월로 변경 1-6. Java 11(1) 2024년 현재 기준으로 서비스 기반 IT 기업들의 주력 프로그래밍 언어로 선정된 자바 1-7. Java 21 (2023년)(1) 자바의 현 시점 가장 최근 버전 2. 0주 차 개인 회고(1) 이번 스터디를 통해 지금까지 학습해 왔던 스프링, JPA와 관련된 내용을 적용해 보고 싶었다.(2) 자바 8에 등장하게 된 핵심 문법들은 지금도 많이 사용되고 있고 이 부분에 대해 따로 한 번 정리해야겠다는 생각을 하게 되었다.(3) 우수 러너로 선정되어 개인적인 성장에 한 걸음 더 다가가고 싶다는 생각을 할 수 있었다.(4) 파이팅😊 2. [1일 차] - 스프링 프로젝트 메타 데이터, 서버와 네트워크, HTTP, URL 등 기본 지식 등 학습 내용 정리2-1. 프로젝트 메타데이터(1) 스프링 부트 프로젝트 생성 시 메타데이터인 Group, Artifact, Description, Dependencies 추가 등 프로젝트를 구성함에 있어 설정할 수 있는 메타데이터들, 의존성을 추가하는 방법을 알아봤다. 2-2. 서버와 네트워크(1) 서버와 네트워크의 정의와 특징 HTTP 통신의 핵심이 되는 네트워크 지식, IP, DNS, 등에 대해 빠르게 요약 및 정리할 수 있었다. 2-3. 웹 기반 서비스에서의 통신 규약, HTTP(HyperText Transfer Protocol)(1) HTTP의 정의, 요청과 응답에 각각 사용되는 HTTP Request Message, HTTP Response Body, REST API를 정의할 때 자원과 행위를 명시하는 데, 이때 행위를 명시할 때 사용되는 HTTP Method(GET, POST...등)에 대해 학습했다. 2-4. API(Application Programming Interface)(1) API는 프론트엔드와 백엔드 간의 통신을 위한 규약, 규칙 수단을 의미, 추가적으로 REST API, RESTful API에 대해 개인적으로 따로 정리해 보았다. 2-5.API를 개발하기 위한 다양한 Annotation(1) API 명세의 중요성, @RestControler, @GetMapping, @PostMapping, @RequestParam 등 다양한 어노테이션에 대해 정리할 수 있었다. 2-6. 1주차 학습에 대한 회고(1) 백엔드를 공부하면서 지금까지 다양한 용어를 공부했었지만 무의식적으로 용어를 계속 사용하다보니 정의와 아예 어긋나게 알고 있었던 개념들이 조금 있었다. (2) 이번 학습을 통해 잘못 이해하고 있던 부분을 바로 잡긴 했지만 조금 더 빨리 알았으면 좋았을 것 같다는 생각을 해보며 과거에 공부했던 부분을 다시 정리해 보고 잘못 알고 있는 부분은 바로 잡을 필요가 있다고 생각했다. 3. [1일 차] - 과제 수행 : 자바의 어노테이션(1) 인프런 블로그에 별도로 정리한 내용 : https://www.inflearn.com/blogs/6610 3-1. 자바의 어노테이션이란?, 어노테이션을 활용하면서 생기는 장점(1) 코드 가독성 향상, 반복되는 어노테이션의 공통화(2) 커스텀 어노테이션 생성 가능(3) 컴파일 시점에서의 오류 체크 가능 등어노테이션을 활용하면 다양한 장점이 존재한다. 3-2. 어노테이션의 종류(1) 표준 어노테이션(빌트 인 어노테이션), 메타 어노테이션(2) 표준 어노테이션 : @Override, @FunctionalInterface, @Deprecated 등...(3) 메타 어노테이션 : @Target, @Retention, @Inherited, @Repeatable 3-3. 커스텀 어노테이션 정의 방법public @interface SimpleAnnotation { }(1) 별도의 커스텀 어노테이션 생성 가능 @Retention(RetentionPolicy.RUNTIME) @Inherited @Target(ElementType.TYPE) @RestController @RequestMapping("/new") public @interface CustomMyAnnotation { String name() default "MemberController"; String value(); }@CustomMyAnnotation(name = "MemberController", value = "MemberController") @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @GetMapping("/list") public List getAllMemberList() { List allMemberList = memberService.findAllMembersList(); return allMemberList.stream() .map(member -> new MemberListResponseDto(member)) .collect(Collectors.toList()); } } 3-4. 과제 접근 방법, 회고(1) 접근 방법코드 공통화 등 여러 이점을 챙기기 위해 커스텀 어노테이션을 사용해야 하는데, 이 부분에 대해서는 메타 어노테이션에 대한 이해가 필요하다고 생각하여 우선 커스텀 어노테이션을 정의하기 위한 메타 어노테이션을 별도로 공부했다. 이후 위의 코드에서 공통으로 묶을 수 있는 어노테이션을 확인하고 이 부분에 대해 별도로 메타 어노테이션까지 적용해 봄으로써 커스텀 어노테이션을 생성해 볼 수 있었다. (2) 과제 회고개발을 해 보면서 별도로 커스텀 어노테이션을 사용해 본 적이 없어서 이 부분이 조금 낯설게 느껴졌지만 계속 반복해서 학습하다 보니 커스텀 어노테이션의 필요성, 언제 사용되는지 등에 대해 조금 인사이트가 생긴 것 같다. 4. [2일 차] - JSON, HTTP API 코드 작성, 배운 내용을 기반으로 도메인(회원) Entity 개발, 데이터베이스에 대한 기본 개념 4-1. POST 방식에서 데이터를 주고받는 방법, JSON의 구조(1) POST 방식에서 요청 데이터를 서로 주고받는 데 사용되는 데이터 형식 : JSON(2) 자바스크립트 객체 문법으로 구조화된 데이터들을 담을 수 있는 구조 : JSON(3) Key=value의 타입 구성 4-2. HTTP API 코드 작성, @RequestBody(1) 실제 코드를 작성해 보고 Postman을 이용해 API 응답 결과가 반환되는 것을 확인(2) @RequestBody : POST, PUT 방식에서 요청 바디에 적재한 데이터를 자바의 컨트롤러 메서드의 파라미터 객체와 매핑하는 어노테이션 4-3. 회원 도메인 개발(1) @RestController 어노테이션의 경우 응답 결과의 형식이 JSON으로 반환되도록 설계되어 있다. 4-4. Section 1 정리(1) 스프링 프로젝트의 구조, 실행 방법(2) 네트워크, IP 주소, 도메인 네임, 포트 번호, HTTP Request/Response 구조, 클라이언트-서버 구조, 기본적인 API 개념들 학습 (3) Spring Boot 기반으로 기본적인 GET, POST API 설계 방법4-5. 지금까지 설계한 API의 문제점(1) 데이터베이스의 부재 - 영속성을 관리하기 위한 수단이 존재하지 않는다.4-6. 데이터베이스의 개념(1) RDBMS(Relational Database Management System)의 개념과 정의, SQL(Structured Query Language)4-7. 2일 차 학습 내용 개인 회고(1) 위의 회원 API를 개발할 때 데이터베이스를 전혀 사용하지 않고 메모리에서 동작하도록 자바 컬렉션을 사용해서 데이터를 저장하고 조회했는데 평소 데이터베이스에서 CRUD를 하다 보니 자바 컬렉션에서 처리하는 코드들이 조금 낯설게 느껴진 것 같다.5. [2일 차] - 과제 수행 : GET, POST API 설계소스 코드 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 5-1. 문제 1번(1) 두 수를 입력하면 다음과 같은 결과가 반환되는 GET API를 설계한다.(2) URL Path : /api/v1/calc(3) Query parameter : num1, num25-2. 접근 및 해결 방법(1) 쿼리 파라미터가 사용되므로 @RequestParam을 통해 매핑시킬 수 있도록 한다.(2) DTO를 제외한 순수 엔티티 계층에는 @Setter를 열지 않는다.(3) 응답을 위한 별도의 DTO를 만들어서 클라이언트 측으로 반환한다.5-3. 문제 2번(1) 날짜를 입력하면 무슨 요일인지 알려주는 GET 조회 API를 설계한다.(2) URL Path, Query parameter의 경우 임의로 설계해도 상관없다.(3) 본인은 문제에서 기재된 URL과 쿼리 파라미터를 동일하게 설계했다.5-4. 접근 및 해결 방법(1) 날짜를 원하는 형식으로 포맷팅하기 위해, getDayOfWeek(), getDisplayName(TextStyle.SHORT, Locale.ENGLISH등의 날짜와 관련된 메서드를 별도로 찾아보고 문제에 적용시켰다.5-5. 문제 3번(1) 요청 메시지 바디에 리스트 형태로 여러 수를 입력하고 해당 수들의 모든 합을 계산하는 POST 조회 API를 설계한다.(2) API에서 받게 되는 요청 바디의 예시는 아래와 같다.5-6. 접근 및 해결 방법(1) 클라이언트에서 리스트 형태로 바디를 전송하기 때문에 이를 받아서 객체로 파싱하기 위해 위와 같이 List 컬렉션을 내부에 선언해 주었다.(2) 해당 과정에서 자바의 기본 생성자가 필요하다.(2) 반환 결과에서 기본 생성자가 추가적으로 필요한데 이유는 다음과 같다.위의 예외는 스프링의 Jackson 라이브러리의InvalidDefinitionException 예외이며, jackson 라이브러리가 JSON 내부에 객체 형태로 넘어온 값을 실제 객체로 변환하기 위해 역직렬화 과정을 거치는데, 이 과정에서 기본 생성자가 없어서 역직렬화가 실패했기 때문에 위와 같은 예외가 발생하는 것. 따라서 관련 클래스에 기본 생성자를 추가해 줘야 한다.5-7. 과제 수행 회고 (1) 과제를 수행하면서 날짜 정보를 나타낼 수 있는 LocalDate, 날짜와 시간 정보를 모두 나타내는 LocalDateTime에 대해 한 번씩 정리해 볼 수 있었다. 날짜 + 시간 정보가 함께 필요한 환경에서 LocalDateTime은 거의 필수로 사용되는 것 같다. (2) 또한 API 반환 관련 부분을 많이 찾아보면서 Jackson 라이브러리의 역직렬화에 대해 조금 더 자세히 찾아볼 수 있었는데, JSON ↔ 객체 사이의 데이터를 변환해야 하는 일이 있을 때 주체 클래스에서 기본 생성자가 변환 과정에서 반드시 필요하다는 것을 인지했고 이런 부분을 설계할 때는 기본 생성자를 조금 더 신경쓰도록 주의해야 할 것 같다.6. [3일 차] - 데이터베이스 기본적인 DDL, DML, MySQL 데이터 타입, 데이터베이스 도입에 따른 도메인 코드 수정6-1. 데이터베이스 DDL(Database Definition Language) (1) 기본적인 데이터베이스 및 테이블 생성, 및 목록 확인 6-2. MySQL의 대표적 데이터 타입(1) 숫자형 타입(정수형, 실수형 타입)(2) 문자열 타입(3) 날짜, 시간 타입 6-3. 데이터베이스 CRUD(DML : Database Manipulation Language)(1) INSERT INTO~ VALUES(2) SELECT ~ FROM ~ WHERE(3) BETWEEN ~ AND ~(4) IN, NOT IN,(5) UPDATE ~ SET ~ WHERE (조건절 명시 유의)(6) DELETE FROM ~ WHERE ~ (조건절 명시 유의) 6-4. 회원 도메인 Controller 코드 수정(1) 코드 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 (2) jdbcTemplate.update() : 쿼리를 통해 데이터베이스에 대한 갱신(update, delete insert) 발생 시 사용 가능한 메서드로 파라미터로 넘어온 값들을 실제 SQL의 ?(와일드 카드) 부분과 매핑시키는 역할을 수행한다. (3) jdbcTemplate.query(sql, new RowMapper()RowMapper의 경우 쿼리의 결과를 받아서 원하는 결과 객체를 반환하는 역할을 수행한다.이후 결과 반환을 위해 UserListDto가 필요하므로 생성자에 원하는 결과값을 파라미터로 넣어서 해당 객체를 생성 후 반환한다.(4) 또한 람다식을 이용해 코드를 좀 더 간결하게 작성할 수 있었다. 6-5. 3일 차 학습 내용 개인 회고(1) 스프링에서 Repository를 다룰 때 거의 하이버네이트와 같은 ORM 기반 기술만 쓰다 보니 직접적으로 JdbcTemplate을 통해 데이터베이스에 접근하는 것은 코드가 손에 익숙하지 않았던 것 같다. 이 부분이 조금 아쉬웠다. (2) 람다와 스트림에 대한 추가 정리가 필요하다고 생각했다. 7. [3일 차] - 함수형 프로그래밍, 람다식, Stream API, Method Reference (1) 과제 수행 GitHub : https://github.com/twojun/java8_core_study 7-1. 익명 클래스의 정의, 특징 정리(1) 익명 클래스의 의미, 익명 클래스가 갖는 주요 특징과 함께 코드를 작성하면서 익명 클래스를 실제로 사용하는 이유(함수형 인터페이스와 람다식과 연계) 7-2. 함수형 프로그래밍(Functional Programming) & 람다 표현식(Lambda expression) 정리(1) 함수형 프로그래밍의 뜻, FP가 자바에서 가지게 되는 의미(2) 람다 표현식 정의와 특징, 일급 객체(3) 함수형 인터페이스의 뜻과 사용될 수 있는 데이터 타입(4) 람다 표현식 작성 방법과 람다식을 더 줄일 수 있는 메서드 참조(Method Reference)(5) Method Reference : 실행하려는 람다식의 메서드를 참조해서 파라미터의 정보, 반환 타입을 추론한 뒤 람다식에서 선언이 불필요한 부분을 제거 7-3. 자바에서 기본적으로 제공하는 함수형 인터페이스Predicate , Consumer, Function, Supplier 7-4. Stream API(1) 스트림의 정의와 주로 사용되는 곳(2) 스트림 파이프라인 : 중간 연산과 최종 연산 정리(3) 중간 연산과 최종 연산의 주요 메서드들, 주의사항 7-5. 과제 수행 회고(1) 하이버네이트와 같은 ORM 기술을 사용하면서 람다와 스트림이 자주 사용되고, 코드의 가독성을 올려주는 데 효과적이라고 생각했었으며 이번 계기로 이 부분을 다시 한 번 정리해 볼 수 있었다. (2) 람다식, 스트림의 코드 스타일을 외우기 보다는 많이 사용해보면서 체화시키는 부분이 중요하다고 생각했다. 8. [4일 차] - 회원 도메인 수정, 삭제 API (1) 4일차 관련 내용은 도메인에 대한 코드 수정 위주이다.(2) 관련 내용 수행 코드 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 8-1. 회원 수정, 삭제 API를 직접 작성해 보면서 생각해 보아야 할 것?(1) 현재 회원 도메인만 봐도 컨트롤러 레벨에서 문제점이 하나 있다.(2) 하나의 컨트롤러가 너무 많은 책임과 역할을 갖고 있다.조회, 예외 처리(비즈니스 로직), 데이터베이스 통신 등 많은 역할을 수행하고 있다.지금은 요구사항이 예제 수준으로 작지만 요구사항이 10가지만 되어도 컨트롤러에서 모든 코드를 감당하기 어려울 것이다.따라서 이 부분을 해결해야 한다. 8-2. 학습 내용 개인 회고(1) 좋은 컨트롤러는 들어온 요청에 대해 적절한 처리를 다른 계층에서 수행해 주고 응답만을 돌려받아 다시 클라이언트측으로 반환하는 역할을 수행해야 하는데 좋은 컨트롤러란 무엇인가? 라는 부분에 대해 다시 한 번 생각해 봤다. (2) 너무 많은 기능을 담당하는 코드가 컨트롤러에 존재하면 가독성은 물론 유지보수가 매우 어려워진다. 이 부분을 빠르게 개선해야 할 것 같다고 생각했다. 9. [4일 차] - 과제 수행 : API 개발9-1. 문제 1번(1) 과일 가게에 입고된 과일 정보를 저장하는 API를 설계하자.(2) HTTP Method : POST(3) HTTP Path : /api/v1/fruit 9-2. 문제 접근 및 해결 방법(1) 이후 문제의 요구사항에 맞추기 위해 미리 테이블 컬럼에 판매 여부를 저장하는 is_sale 컬럼을 생성한다.(2) 이후 코드는 과일 정보를 저장하기 위한 SQL 문자열을 별도로 작성하고 jdbcTemplate.udpate() 메서드를 사용해서 실제 과일 상품의 정보를 저장하도록 한다. (3) 이후 정상적으로 테이블에 로우가 적재된 것을 확인 (4) int보다 long 타입을 사용해 보도록 하자.본인이 생각하고 있는 이유가 정확하진 않을 수도 있지만, 수의 표현 범위에서의 차이이지 않을까 싶다. int의 경우 약 21억 정도의 크기를 갖는 수를 저장할 수 있는데 해당 자료형이 담는 수도 매우 커보이지만, 이 부분이 실무를 넘어가면 21억보다 큰 수를 받아야 하는 상황이 종종 생길 수도 있기 때문에 long 타입을 사용하는 것으로 알고 있다 9-3. 문제 2번(1) 과일이 판매되면 판매된 과일 정보를 기록하는 API를 설계하자.(2) HTTP Method : PUT(3) HTTP Path : /api/v1/fruit9-4. 문제 접근 방식 및 해결 방법(1) 입고된 과일의 컬럼 정보 is_sale을 1로 변경해야 입고된 과일로 간주한다.(2) 입고되지 않은 과일의 정보를 바꾸는 것 자체가 모순이기에 이 부분에 대해선 IllegalStateException 예외를 던지도록 한다.(3) 코드를 작성해서 정상 결과 반환을 확인했다.9-5. 문제 3번(1) 특정한 과일을 대상으로 판매된 금액, 판매되지 않은 금액의 총합을 계산해보는 API를 설계하자.(2) HTTP Method : GET(3) HTTP Path : /api/v1/fruit/stat(4) HTTP Query parameter : name 9-6. 문제 접근 방법 및 해결 방법(1) 위에서 정의한 판매 상태를 기준으로 각각의 총합 금액을 계산하는 쿼리를 작성한다.(2) 이후 각각 조회된 결과를 받고 별도의 결과 반환 DTO를 만들어서 해당 값들을 DTO로 반환할 수 있도록 코드를 작성했다.(3) 정상적으로 문제에서 요구된 특정 과일에 대한 판매, 미판매 금액이 조회되는 것을 확인할 수 있었다. 9-7. 과제 수행 개인 회고(1) 저번 과제에 이어서 API를 추가적으로 설계해 보면서 REST API 설계에 대해 익숙해 질 수 있었다.(2) 이번 스터디를 계기로 더 많은 API를 반환하는 것을 연습해 보면 더 좋을 것 같다고 생각했다. 10. [5일 차] - 클린 코드, Controller-Service-Repository로 계층 분리하기(계층형 아키텍처) (1) 관련 내용 수행 코드 : https://github.com/twojun/InFlearn_WarmingUp_Club_BE_0 10-1. 클린 코드(1) 클린 코드가 무엇인지 이를 통해 얻을 수 있는 장점(2) 안 좋은 코드가 쌓여가면 프로덕트의 생산성이 낮아지는 점을 인지할 수 있었다. 10-2. 계층형 아키텍처(1) Controller-Service-Repository 형태와 같이 각 계층이 서로에 맞게 분리되어 있는 설계 구조를 의미(2) 각 계층에서 수행되는 역할 정리 10-3. 회원 도메인에 대해서 계층형 구조로 개선 (1) 단순 사용자 정보 수정만이 아닌, 생성, 조회, 삭제 등 모든 비즈니스 포인트를 Controller-Service-Repository 계층 구조로 분리하는 작업 진행 10-4. 5일 차 학습 내용 개인 회고(1) 이번 학습을 통해 클린 코드의 중요성, 모든 역할을 하나의 계층에서 정의하는 것이 아닌 각각의 역할에 따라 계층을 나누고 코드를 분리하는 것이 가독성도 좋고 협업하기 좋은 코드라고 생각할 수 있었다. (2) 앞으로도 코드를 작성하면서 더 좋은 계층구조를 갖는 코드가 무엇인지 생각하고 코드를 작성할 필요성을 느끼며 반성할 수 있는 기회였다. 11. [5일 차] - 클린 코드 적용하기11-1. 주사위 게임 코드 리팩토링(1) 과제 수행 코드 : https://github.com/twojun/java8_core_study(2) 기존 주사위 게임 코드를 클린 코드로 변경해보는 과제였다. 11-2. 문제 접근 및 해결 방법 & 개인 회고(1) 아래의 코드가 만약 주사위의 눈의 수가 30 또는 100까지 늘어난다면? 요구사항 수정에 의한 코드 변경 파급력이 급격하게 커지게 된다. 변경에 의한 파급력이 최대한 작아지게, 또한 읽기 좋게 코드를 수정하려면 어떻게 해야 할까? 라는 생각을 가지고 코드를 작성했던 것 같다. 아래의 코드를 개선된 클린 코드로 리팩토링해 봐야겠다고 생각했다. (2) 본인은 Scanner보다는 BufferedReader를 사용하는 것이 더 익숙해서 코드에 BufferedReader를 적용시켰다. (3) 메서드, 클래스 단위로 나누어서 코드를 작성해도 좋지만 사용자로부터 최대 나올 수 있는 주사위 눈의 수, 게임 반복 횟수를 입력받고 관련 주사위 수가 몇 번 나왔는지 출력하면 되는 문제이기 때문에 별도의 클래스나 메서드로 나누지 않고 간단하게 자료구조(배열)을 확인해 문제를 풀었다. (4) 과제가 끝난 후 다른 분들 코드를 보면 메서드, 클래스 단위로 대부분 나누어 코딩하신 것 같아서 나만 너무 이상하게 코딩했나라는 생각을 했지만, 클린 코드의 의미를 되돌아 보면 읽기 쉬운 코드도 특징 중 하나이기에 최대한 간결하고 눈에 들어올 수 있도록 자료구조를 활용해 표현했지만 뭔가 부족한 느낌이 든다. 12. 1주차 총 회고(1) 스터디가 시작된지 1주일이 경과했다. 디스코드에서 보니 다들 열심히 하시는 분들이 많으신 것 같고 항상 열정적이신 코치님, 동료분들이 있어서 스터디하기 좋은 환경인 것 같다. (2) 열심히 참여해서 개인적인 성장에 한 걸음 더 다가서려고 한다.😄
백엔드
・
인프런워밍업
・
발자국
・
회고
・
스프링
2024. 02. 21.
1
[인프런 워밍업 클럽(백엔드, 0기)] - 개별 정리 : 자바 어노테이션
스프링으로 프로젝트를 하면서 자바 어노테이션을 항상 사용해 왔지만 아직 잘 모르는 부분이 많은 것 같아서 1일 차에 대한 과제 제출 기간은 지났지만, 추가적으로 인프런 블로그를 통해 다시 한 번 정리해 보고자 한다. (1) https://twojun-space.tistory.com/178본인 블로그에 내용을 별도로 정리했지만 한 번 더 리마인드해 보고자 한다. 1. 자바 어노테이션(Java Annotation)1-1. 정의(1) 어노테이션은 사전적 정의로는 "주석"이라는 의미를 가지고 있지만 자바에서의 어노테이션은 소스 코드에 추가할 수 있는 일종의 메타 데이터라고 볼 수 있다.(2) 애플리케이션 레벨에서 처리되어야 하는 대상이 아닌, 컴파일, 런타임 시점에 코드를 어떻게 처리해야 할지 알려주기 위한 정보로 볼 수 있겠다. 1-2. 장점(1) 코드 가독성, 컴파일 시점에서의 오류 체크코드 레벨에서 동일하게 작성되기 때문에 코드의 가독성이 좋고, 일부 어노테이션의 경우 컴파일 시점에 문법 에러(아래에서 설명할 @Override, @FunctionalInterface)를 잡아주기도 한다. (2) 중복 코드 제거중복되는 어노테이션의 경우 공통화시킬 수 있고 재사용이 가능하기 때문에 코드의 중복을 줄이고 효율적인 코드 작성이 가능하다. (3) 커스텀 어노테이션 (사용자 정의 어노테이션) 사용 가능직접 용도에 맞게 커스텀 어노테이션을 작성할 수 있다. 프로젝트를 진행함에 따라 각각 필요한 제약사항들을 별도로 정리해서 커스텀 어노테이션 구성이 가능하다. 1-3. 단점(1) 런타임 시 발생할 수 있는 오버헤드만약 런타임 시점에 자바의 리플렉션(Reflection) 등을 사용해서 처리되는 어노테이션이라면 이 부분을 처리하기 위한 별도의 오버헤드가 발생할 수 있다 (성능 상 문제) 2. 어노테이션의 종류살펴볼 어노테이션의 종류로 총 2가지가 있다.(1) 표준 어노테이션(빌트 인 어노테이션)(2) 메타 어노테이션 3. 표준 어노테이션(1) 표준 어노테이션의 경우 자바에서 기본적으로 제공하고 있는 어노테이션이다. 대표적으로 아래와 같이 3가지가 있다. 3-1. @Override(1) 현재 메서드가 부모 타입 클래스 또는 인터페이스의 메서드를 오버라이딩했음을 컴파일러에게 명시하는 역할을 수행한다. 만약 형식에 맞지 않게 오버라이딩되었다면, 컴파일러가 이를 인지하고 오류를 발생시킨다. 3-2. @Deprecated(1) 현재 메서드를 사용하지 않도록 유도한다. 만약 해당 어노테이션이 붙은 메서드를 사용하면 컴파일러가 오류를 발생시킨다. 3-3. @FunctionalInterface(1) 해당 인터페이스가 함수형 인터페이스임을 명시한다. 함수형 인터페이스의 경우 추상 메서드가 반드시 1개 존재해야 한다. 추상 메서드가 존재하지 않거나 2개 이상이라면 컴파일러가 오류를 발생시킨다. 4. 메타 어노테이션(Meta Annotation)(1) 메타 어노테이션이란 다른 어노테이션에서 사용될 수 있는 어노테이션을 의미하며 아래에서 작성할 커스텀 어노테이션(사용자 정의 어노테이션)을 생성할 때 주로 사용되는 어노테이션이다. 4-1. @Target(1) 어노테이션을 적용할 위치를 알려주는 어노테이션이다. (2) 예를 들어 @Target(ElementType.TYPE)의 경우 해당 어노테이션을 다른 어노테이션의 대상으로 사용할 수 있다는 의미이다. (3) 메타 어노테이션을 선언해 줄 때 사용되는 일반적인 방법 중 하나다.@Target({ ElementType.PACKAGE, // 패키지 선언 ElementType.TYPE, // 타입 선언 ElementType.CONSTRUCTOR, // 생성자 선언 ElementType.FIELD, // 멤버 변수 선언 ElementType.METHOD, // 메소드 선언 ElementType.ANNOTATION_TYPE, // 어노테이션 타입 선언 ElementType.LOCAL_VARIABLE, // 지역 변수 선언 ElementType.PARAMETER, // 매개 변수 선언 ElementType.TYPE_PARAMETER, // 매개 변수 타입 선언 ElementType.TYPE_USE // 타입 사용 }) 4-2. @Retention(1) @Retention의 경우 어노테이션이 적용되고 유지되는 범위를 설정하기 위해 사용되는 메타 어노테이션이다.@Retention(RetentionPolicy.RUNTIME) // 컴파일 이후에도 JVM에 의해서 참조가 가능하다. @Retention(RetentionPolicy.CLASS) // 컴파일러가 클래스를 참조할 때까지 유효하다. @Retention(RetentionPolicy.SOURCE) // 어노테이션 정보는 컴파일 이후 없어진다. 4-3. @Inherited(1) 해당 어노테이션이 적용된 경우 자식 클래스가 해당 어노테이션을 상속받을 수 있게 된다.(2) 따라서 부모 클래스에 선언된 @Inherited 어노테이션은 하위 클래스에서 자동으로 상속받는다. 4-4. @Repeatable(1) 반복 가능한 어노테이션을 정의할 때 사용될 수 있는 어노테이션이다. 5. 커스텀 어노테이션(Custom Annotation, 사용자 정의 어노테이션) 5-1. 정의, 사용 방법public @interface SimpleAnnotation { }(1) 자바에서는 위와 같이 @interface 키워드를 통해 커스텀 어노테이션을 정의할 수 있다. 5-2. 실제로 커스텀 어노테이션 적용해 보기@Retention(RetentionPolicy.RUNTIME) @Inherited @Target(ElementType.TYPE) @RestController @RequestMapping("/new") public @interface CustomMyAnnotation { String name() default "MemberController"; String value(); } @CustomMyAnnotation(name = "MemberController", value = "MemberController") @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @GetMapping("/list") public List getAllMemberList() { List allMemberList = memberService.findAllMembersList(); return allMemberList.stream() .map(member -> new MemberListResponseDto(member)) .collect(Collectors.toList()); } } 5-3. 자바의 리플렉션(Reflection)(1) 현재 어노테이션을 사용해서 코드의 가독성이 좋아짐은 물론 어노테이션 자체가 되게 많은 일을 대신 해주고 있는 것을 확인해 볼 수 있다. 이 부분은 자바의 리플렉션 기술들이 해결해 주고 있는데 추후에 리플렉션에 관한 내용을 블로그에 다시 한 번 정리해 볼 예정이다. 마지막으로 부족하지만 글을 읽어주신 분들께 감사드립니다!!
백엔드
・
백엔드
・
인프런워밍업
・
자바
・
어노테이션
・
스프링
2024. 02. 19.
1
[ 인프런 워밍업 클럽(백엔드, 0기)] - 0일 차 오리엔테이션 회고!
안녕하세요! 이번 인프런 워밍업 클럽 백엔드 스터디 0기에 참여하게 되었습니다.기존 Java, Spring, JPA로 백엔드를 공부했고, 그동안 배웠던 내용을 체화시켜야 할 기회가 필요했습니다.학습만 하고 체화시키지 않는다면 절대 본인의 지식이 될 수 없다고 생각하고 있기 때문입니다. 만약 학습한 내용을 바로 머릿속에 오래 남겨둘 수만 있다면 큰 행운인 것 같습니다. 하지만 저도 사람이기에 단순히 눈으로 보기만 한 내용은 기억에 오래 남지 못하는 것 같습니다. 저랑 비슷하신 분이 계실진 모르겠지만 배운 내용, 실습한 내용들을 본인의 GitHub나 개인 블로그에 잘 정리해 놓으면 상당히 기억에 오래 남고, 필요한 부분을 다시 찾아볼 수 있다는 점 때문에 저는 기록하는 것을 항상 좋아합니다! 제 루틴대로 배웠던 학습 내용들을 정리하고, 과제, 프로젝트 수행 부분 또한 별도로 블로그, GitHub에 정리할 예정입니다. 열정 가득한 코치님, 참가자분들과 함께 공부할 수 있게 되어 기쁜 마음입니다!백엔드 0기로 합류하시게 된 분들 모두 같이 파이팅했으면 좋겠습니다 😀 감사합니다 😀
백엔드
・
인프런
・
워밍업
・
백엔드
・
스프링
・
발자국
・
0기
・
화이팅!