블로그
전체 52024. 06. 04.
1
[인프런 워밍업 스터디 클럽 1기] BE 스터디 참여 후기
인프런 워밍업 클럽 1기 백엔드 과정의 참여했던회고 및 후기에 대한 내용입니다. 처음으로 프로젝트나 스터디를 마무리한 후에 최종적으로 써보는 회고록입니다.약 4주 간의 스터디를 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!해당 강좌를 통해서 과제를 진행하고 미니프로젝트를 구현하면서대강 알고 있던 수준을 넘어 성장을 할 수 있는 토대를 마련할 수 있었던 거 같습니다. 신청유튜브와 다양한 인터넷 강의를 통해 관심 있는 내용만 선택적으로 공부해왔습니다. 그러나 실제 현업에서 사용하는 기술이나 개발자로서 중요한 이론에 대해서는 간략하게만 알고 있었고, 정확한 내용은 잘 알지 못한 상태였습니다. 그러던 중, 운 좋게 인프런에서 '워밍업 클럽' 홍보 배너를 확인하게 되었습니다. 이 강의를 통해 필수 기술을 체계적으로 학습할 수 있고, 진도표를 통해 계획적으로 진행할 수 있다는 점이 꾸준히 실력을 쌓는 데 큰 도움이 될 것이라 생각하여 도전하게 되었습니다.또한, 디스코드를 통해 여러 교육생들과 커뮤니티가 형성되어 실시간으로 질문할 수 있고, 자신의 정보를 공유하며 공부했던 내용을 기록하는 등 열정 넘치는 모습들이 눈에 띄었습니다. 이러한 열정적인 분위기 속에서 다른 교육생들에게 뒤처지지 않기 위해 이전 기수의 교육생들이 작성한 회고록이나 과제 내용을 참고하며 스터디에 집중하고 적응하기 위해 노력했습니다.진행스터디 진행이번 강의를 통해 백엔드의 주 언어인 Java에 대해 기존에 알고 있던 내용을 바탕으로 하여, 서버의 정의부터 기본적인 API 작성, DB 연동, 배포에 이르기까지 서버 개발의 전체 사이클을 경험할 수 있었습니다. 기존에 공부했던 내용이 많아 비교적 쉽게 접근할 수 있을 것이라 생각했으나, 실제로 강의를 진행하면서 제가 제대로 알고 있던 내용이 많지 않다는 것을 깨달았고, 여러 부분에서 부족함을 느꼈습니다. Java의 기본 문법부터 시작해, Spring Boot를 활용한 RESTful API 개발, JPA를 사용한 데이터베이스 연동, 그리고 AWS를 통한 배포에 이르기까지, 서버 개발의 전 과정을 마치 처음부터 다시 배우는 듯한 자세로 강의 내용에 집중하며 하나하나 이해하면서 스터디를 진행했었습니다. 기록의 중요성이번 스터디를 통해 개발자로서 중요한 덕목 중 하나인 기록의 중요성을 다시금 깨닫게 되었습니다. 주차별 과제를 블로그에 정리하고, 주차별 회고록을 작성하면서 공부한 내용을 공유했습니다. 이 과정을 통해 학습한 지식을 더욱 확실하게 이해하고 기억할 수 있었습니다. 또한, 몰랐던 부분이나 더 공부해야 할 내용들을 알게 되었습니다. 주차가 거듭될수록 이전 내용에 대해 헷갈리거나 지식이 겹쳐 혼란스러웠던 부분들을 기록해둔 회고록이나 과제 내용을 보며 빠르게 해결할 수 있었습니다. Q&A 시간의 소중함격주로 진행된 라이브 Q&A 시간을 통해 스터디를 하면서 막힌 부분이나 궁금한 점에 대해 질문하고 답을 얻으면서 지식을 채워나갈 수 있었습니다. 또한, 다른 러너들의 질문을 들으며 생각지 못한 다양한 방면에서 지식을 얻을 수 있었습니다. 과제를 진행하면서 코치님께서 주신 코멘트와 추가로 공부해보면 좋을 내용을 통해 스터디에 더욱 열심히 임할 수 있었고, 성장할 수 있는 동력을 얻은 것 같습니다. 📃 과제 진행 링크과제 1~7주차 블로그 정리📃 나의 주차별 회고록BE 1주차 회고록BE 2주차 회고록BE 3주차 회고록BE 4주차 회고록 마무리인프런 워밍업 클럽을 진행하면서 가장 첫 번째 목표는 완주하는 것이었습니다. 공부를 하다 보면 나태해지기 쉬웠기 때문에, 스터디를 끝까지 마치는 것이 목표였습니다. 스터디를 진행하면서 다른 러너분들이 적극적으로 질문하고, 과제나 회고록을 작성하며, 자신이 찾은 유튜브나 기술 블로그 링크를 공유하는 열정을 보면서 더욱 열심히 참여할 수 있었습니다.스터디를 참여하면서 개발자로써 간접적으로나마 프로젝트에 사용하는 기술에 대한 학습을 하여 블로그에 작성을 하고, 그 내용을 토대로 프로젝트를 구현하고, 이를 끝마치면 회고록을 작성하여 개발의 서사를 작성하는 습관을 길렀다고 생각이 들 정도로 유익했던 거 같습니다. 스터디가 마무리되면서 다시 홀로 공부를 시작하게 되었지만, 이전에 진행했던 스터디의 열정을 잃지 않도록 꾸준히 노력해야겠다는 다짐을 하게 되었습니다. 이번 스터디를 참여하신 모든 스터디원 분들과 해당 프로그램을 기획하신 인프랩 임직원분들께 감사드리며이 시간을 활발하게 이끌어주신 코치님께 감사의 인사를 전달드립니다.
백엔드
・
인프런
・
인프런워밍업클럽
・
스터디1기
2024. 05. 26.
0
[인프런 워밍업 스터디 클럽 1기] BE 4주차 회고록
네 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 네 번째 회고록입니다.학습 내용build.gradle빌드 스크립트라고 불린다.gradle을 이용하여 프로젝트를 빌드하고 의존성을 관리하기 위해 작성되었다.현재는 groovy 언어를 사용해 작성되어있고, kotlin 언어를 사용할 수도 있다. 플러그인plugins { id 'java' id 'org.springframework.boot' version '3.1.11' id 'io.spring.dependency-management' version '1.1.4' } org.springframework.boot 플러그인스프링을 빌드했을 때 실행 가능한 jar 파일이 나오게 도와준다.스프링 애플리케이션의 실행을 도와준다.이 외의 플러그인들이 적용될 수 있도록 해준다.io.spring.dependency-management 플러그인외부 라이브러리, 프레임워크의 버전 관리의존성 처리하는 데 사용java 플러그인java 프로젝트 개발 시 필요한 기능 추가JVM 언어 Gradle 플러그인의 사용할 수 있는 기반 마련 그룹group = 'sample' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' }group프로젝트 그룹빌드 결과물에 프로젝트 그룹에 대한 정보가 들어있다.version프로젝트 버전sourceCompatibility프로젝트가 사용하고 있는 JDK 버전 레포지토리repositories { mavenCentral() }외부 라이브러리/ 프레임워크를 가져오는 장소 설정 의존성(dependencies)dependencies { // Spring boot implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' // test testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' // lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' //mysql runtimeOnly 'com.mysql:mysql-connector-j' }사용하는 라이브러리/프레임워크 표시implementation : 해당 의존성을 항시 사용한다.runtimeOnly : 코드를 실행할때에만 의존성을 사용한다.testImplementation : 테스트코드를 컴파일하거나 실행할 때 항시 사용한다.Spring과 SpringBoot의 차이점간편한 설정스프링은 강력한 기능을 제공한다.ex) IoC/DI, AOP, PSA ..기능을 사용하기 위해 xml 설정을 해야했는데 양이 많았다. -> 어노테이션 기반의 설정으로 변경하고 기본적으로 필요한 것들은 모두 자동 설정간단한 의존성 관리Spring을 사용할 때는 개발에 필요한 라이브러리/프레임워크를 모두 기입해야했다.의존성 관리가 힘들기에 starter로 묶어서 관리강력한 확장성Springboot 내부에 tomcat이 있기에 따로 설정할 필요가 없다.MSA에 적합한 모니터링application.yml 파일YAML 문법Yet Another Markup Language(또 다른 마크업 언어)YMAL Ain't Markup Language(마크업 언어가 아니다)확장자 : .yaml 또는 .ymlkey : value 형식으로 데이터를 정의한다.각 계층은 들여쓰기를 통해 구분하게 되며, 이를 통해 중복을 제거할 수 있다.value에는 참/거짓, 숫자, 문자열이 들어갈 수 있다.value에는 배열도 들어갈 수 있다. - 를 활용한다.#을 이용하면 주석을 사용할 수 있다.application.propertiesdev profile 사용application-dev.properties 파일 생성Lombokgetter/setter, 생성자와 같은 반복되는 보일러 플레이트 코드(boiler plate code)를 제거할 수 있다.dependencies 추가compileOnly 'org.projectlombok:lombok'annotationProcessor 추가annotationProcessor 'org.projectlombok:lombok'Spring Boot 2.7.x -> 3.0.x 변경점java 최소 버전이 17로 업그레이드스프링 프로젝트, third-party library 버전 업그레이드AOT 기초 작업AOT(Ahead Of Time) : 빌드 시 스프링 애플리케이션을 분석하고 최적화하는 도구애플리케이션 시작 시간과 메모리 사용량을 줄일 수 있게 해준다.javax -> jakarta 패키지로 변경모니터링 기능 강화 과제 내용이번 프로젝트에서는 출퇴근 사내 시스템으로써, 회사 내 팀과 직원 관리, 출퇴근 관리, 그리고 연차 관리 기능을 설계하였습니다. 기본적인 기술 스택으로는 Java 17 / Springboot 3.x.x으로 구성하여 팀 관리에서는 팀 이름을 필수로 등록하고 팀 정보를 조회할 수 있는 기능을 구현했습니다. 직원 관리에서는 직원의 이름, 매니저 여부, 입사 날짜, 생일을 등록하고, 직원 정보를 조회할 수 있게 했습니다. 출퇴근 관리에서는 직원의 출근 및 퇴근 기능을 구현하였으며, 직원의 근무 시간을 날짜별로 조회할 수 있도록 하였습니다. 연차 관리에서는 직원이 연차를 신청하고, 남아있는 연차를 조회할 수 있는 기능을 제공했습니다. 특히, 연차 신청 시 팀마다 다른 등록 기간을 적용하여 유연성을 높였습니다. 📋 미니 프로젝트 Github : commuting-system회고이번 프로젝트를 통해 팀, 직원, 출퇴근, 연차 관리를 통합적으로 설계하는 경험을 쌓았습니다. 팀 관리에서는 팀의 필수 정보를 명확히 정의하고, 팀 조회 기능을 통해 팀 운영의 투명성을 높였습니다. 직원 관리에서는 직원의 기본 정보를 체계적으로 관리할 수 있게 되었고, 매니저 여부와 같은 역할 분류를 통해 조직의 구조를 명확히 파악할 수 있었습니다. 출퇴근 관리에서는 출퇴근 예외 처리와 날짜별 근무 시간 조회 기능을 통해 직원들의 근태를 정확히 관리할 수 있었습니다. 연차 관리에서는 연차 신청과 조회 기능을 통해 직원들이 연차를 효율적으로 사용할 수 있도록 했습니다. 팀마다 다른 연차 등록 기간을 적용함으로써 조직의 유연성을 높였습니다. 이 프로젝트를 통해 데이터의 일관성을 유지하면서도 다양한 요구 사항을 충족시키는 설계의 중요성을 깨달았습니다. 또한, 시스템 통합의 복잡성을 이해하고, 사용자 편의성을 고려한 기능 설계의 필요성을 다시 한 번 느꼈습니다.
백엔드
・
인프런워밍업스터디클럽
・
4주차
・
회고록
2024. 05. 19.
0
[인프런 워밍업 스터디 클럽 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주차
・
회고록
2024. 05. 12.
1
[인프런 워밍업 스터디 클럽 1기] BE 2주차 회고록
두 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 두 번째 회고록입니다.학습 내용static이 아닌 코드를 사용하려면 인스턴스화를 해야합니다.하지만, 학습에서 진행했던 UserController는 jdbcTemplate를 의존하여 사용하고 있습니다.이를 가능케 하는 것은 @RestController 어노테이션으로 의해 의존이 가능해지고 해당 클래스를 스프링 빈으로 등록시킵니다. 스프링 빈서버가 시작되면, 스프링 서버 내부에 거대한 컨테이너를 만듭니다.해당 컨테이너 안에는 클래스가 들어가게 되고, 다양한 정보(이름, 타입) 도 함께 들어가고, 인스턴스화도 이루어집니다.서버가 시작되면 코드의 구현 순서에 대해 살펴보겠습니다.스프링 컨테이너(즉, 클래스 저장소)가 시작됩니다.기본적으로 생성되어있는 스프링 빈들이 등록됩니다.사용자가 설정한 스프링 빈이 등록됩니다.필요한 의존성이 자동으로 설정이 됩니다. 여기서 스프링 컨테이너를 사용하는 이유를 살펴보면 2가지의 스프링 프레임워크의 특성 때문입니다.첫 번째는 제어의 역전(IOC) 이다. 말 그대로 메서드나 객체의 호출 작업을 개발자가 결정하는 것이 아닌, 외부(스프링 컨테이너)에서 결정되는 것을 의미입니다. 객체의 의존성을 역전시켜 객체간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 해서 가독성 및 코드 중복, 유지 보수를 편하게 할 수 있도록 도와줍니다.두 번째는 의존성 주입(DI) 로 객체를 직접 생성하는 것이 아닌 외부에서 생성할 후 주입시키는 방식을 의미한다.이를 통해 모듈 간의 결합도가 낮아지고 유연성을 높일 수 있습니다. 스프링 빈으로 등록하는 방법여기서 중점적으로 사용하는 어노테이션에 대해 살펴보겠습니다. @Configuration클래스에 붙이는 어노테이션@Bean을 사용할 때 함께 사용외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다.@Bean메서드에 붙이는 어노테이션메서드에서 반환되는 객체를 스프링 빈에 등록한다.외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다.@Service, @Repository개발자가 직접 만든 클래스를 스프링 빈으로 등록할 때 사용한다.@Component주어진 클래스를 컴포넌트로 간주한다.해당 클래스들은 스프링 서버가 뜰 때 자동으로 감지된다. @Component 사용컨트롤러, 서비스, 레포지토리 X개발자가 직접 작성한 클래스를 스프링 빈으로 등록 시에 사용되기도 한다. 스프링 빈 주입 방법생성자를 활용하여 주입하는 방법setter와 @Autowired를 사용하는 방법필드에 직접 @Autowired를 사용하는 방법 JPA(Java Persistence API)데이터를 영구적으로 보관하기 위해 Java 진영에서 정해진 규칙영속성 : 서버가 재시작되어도 데이터는 영구적으로 저장되는 속성 ORM(Object-Relational Mapping)객체와 관계형 DB의 테이블을 짝짓는 방법HibernateJPA를 구현(implement)해서 코드로 작성한 구현체내부적으로 JDBC를 사용한다 JPA 어노테이션@Entity : 스프링이 객체와 테이블을 같은 것으로 바라본다.Entity 뜻 : 저장되고, 관리되어야 하는 데이터@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;@Id : 위 필드를 primary key로 간주@GeneratedValue : primary key는 자동 생성되는 값GenerationType.IDENTITY : MySQL의 auto_increment 전략과 매칭JPA를 사용하기 위해서는 기본생성자가 꼭 필요하다 @Column(nullable = false, length = 20, name = "name") private String name;@Column : 객체의 필드와 Table의 필드를 매칭한다.null 여부, 길이 제한, DB Column 이름 등을 사용@Column 어노테이션을 생략할 수도 있다. 트랜잭션(Transaction)쪼갤 수 없는 업무의 최소 단위 모든 SQL 한번에 성공 or 하나라도 실패하면 모두 실패 트랜잭션 명령어start transaction; : 트랜잭션 시작하기commit; : 트랜잭션 정상 종료(SQL 반영)rollback; : 트랜잭션 실패 처리(SQL 미반영) 트랜잭션 적용 방법@Transactional public void saveUser(UserCreateRequest request) { userRepository.save(new User(request.getName(), request.getAge())); }SELECT 쿼리만 사용한다면 readOnly 옵션 사용 가능@Transactional(readOnly = true) public List getUsers() { return userRepository.findAll().stream() .map(UserResponse::new) .collect(Collectors.toList()); } ❗ 주의사항IOException 과 같은 Checked Exception은 롤백이 일어나지 않는다. 영속성 컨텍스트테이블과 매핑된 Entity 객체를 관리/보관하는 역할스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨나고, 트랜잭션이 종료되면 영속성 컨텍스트가 종료특징변경 감지(Dirty Check)영속성 컨텍스트 안에 불러와진 Entity는 명시적으로 save 하지 않더라도, 변경을 감지해 자동으로 저장된다.@Transactional public void updateUser(UserUpdateRequest request) { User user = userRepository.findById(request.getId()) .orElseThrow(IllegalArgumentException::new); user.updateName(user.getName()); }쓰기 지연DB의 insert/update/delete SQL문을 바로 날리는 것이 아닌, 트랜잭션이 commit될때 모아서 1번만 날린다.1차 캐싱ID를 기준으로 Entity를 기억한다.캐싱된 객체는 완전히 동일하다.(객체 주소도 같다) JPA 연관관계ex) 사람(person)과 실거주 주소(address)사람 1명은 1개의 실거주 주소만을 가지고 있다.@OneToOne연관관계의 주인을 설정한다.(mappedBy 사용한다.)연관관계의 주인 효과상대 테이블을 참조하고 있으면 연관관계의 주인이다.연관관계 주인이 아니면 mappedBy 사용연관관계의 주인의 setter가 사용되어야만 테이블이 연결@Transactional public void savePerson() { Person person = personRepotiory.save(new Person()); Address address = addressRepotiory.save(new Address()); person.setAddress(address); } 연관 관계의 주의점트랜잭션이 끝나지 않았기에, 한 쪽만 연결해두면 반대쪽의 값은 알 수 없다. @Transactional public void savePerson() { Person person = personRepotiory.save(new Person()); Address address = addressRepotiory.save(new Address ()); person.setAddress(address); System.out.println(address.getPerson); //null 반환 }이를 방지하기 위해 setter 한 번에 둘을 같이 이어준다.public void setAddress(Address address) { this.address = address; this.address.setPerson(this); } 다대일,일대다관계@ManyToOne을 단방향으로 사용할 수 있다.@JoinColumn연관관계의 주인이 활용할 수 있는 어노테이션필드의 이름이나, null 여부, 유일성 여부, 업데이트 여부 등을 지정할 수 있다.다대다관계(N : M 관계)@ManyToMany구조가 복잡하고, 테이블이 직관적으로 매핑되지 않기 때문에 사용하지 않는 것을 지양한다.cascade 옵션한 객체가 저장되거나 삭제될 때, 그 변경이 폭포처럼 흘러서 연결되어 있는 객체도 함께 저장되거나 삭제되는 기능orphanRemoval 옵션객체간의 관계가 끊어진 데이터를 자동으로 제거하는 옵션 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List userLoanHistories = new ArrayList();지연 로딩(Lazy Loading)연결되어 있는 객체를 꼭 필요한 순간에 데이터를 로딩한다. @OneToMany의 fetch() 옵션 연관관계의 장점각자의 역할에 집중하게 된다.새로운 개발자가 코드를 읽을 때 이해하기 쉬워진다.테스트 코드 작성이 쉬워진다.연관관계 사용 시 주의 사항지나치게 사용하면 성능 상의 문제가 발생할 수 있다.도메인 간의 복잡한 연결로 인해 시스템을 파악하기 어려워질 수 있다.요구 사항 등 여러 부분을 고민해서 연관 관계 사용을 선택해야한다. 과제 내용Day 4Day2에서 진행했던 GET API와 POST API를 구현했었는데, 그 당시에는 database를 사용하지 않은 방법으로 과제에서 주어진 조건에 맞게 답을 출력했었습니다. 이번 과제에서는 DB를 활용하여 정보를 저장하고, 수정할 수 있는 로직을 구현해야했습니다.Layer를 분리해서 진행을 할 수 있지만, 간단하게 문제의 답만 도출하기 위해서 Controller Class에 구현을 진행했었습니다.그렇기 때문에 Spring Data JPA가 아닌 JDBCTemplate를 활용하여 진행했습니다. JPA를 통한 DB 로직을 구현하는 것만 주구장창 했어서, 직접 쿼리문을 작성해서 진행하는 JDBCTemplate를 사용하는 방법에 대해 알 수 있었던 거 같습니다.📋 4일차 미션 : GET API와 POST API 구현 Day 5클린 코드는 코드를 아름답게 만드는 것이 아닌 코드의 질을 향상 시키는 데 중요하다는 것을 알았습니다.클린 코드를 구현하기 위해서 명확하고 간결하게 코드를 구현하여 버그를 줄이고, 그로 인한 개발 속도를 향상시킬 수 있습니다.또한, 잘 작성된 코드는 시간이 흘러도 이해하기 쉽기에, 유지 보수가 간편합니다. 이로 인해 개발자로서 팀 프로젝트를 진행할 시에팀 커뮤니케이션을 원활하게 진행할 수 있도록 도움을 줄 수 있다는 것을 알게 되었습니다.📋 5일차 미션 : 클린 코드 구현 회고스프링 프레임워크의 핵심 개념인 제어의 역전(IOC)과 의존성 주입(DI)을 통해 더 나은 코드 작성과 유지 보수의 용이섬에 대해 알게 되었습니다. 또한 어노테이션들을 활용하여 클래스를 스프링 빈으로 등록하고, 스프링 컨테이너가 이를 관리함으로써, 필요한 의존성을 자동으로 설정할 수 있다는 사실을 배웠습니다. JPA를 통한 데이터의 영속성 관리와 ORM을 통한 객체와 DB의 매핑에 대해 이론적으로 정립할 수 있는 계기되었던 거 같습니다.서비스를 구성하는 데 가장 중요한 @Transactional 어노테이션을 사용하여 데이터의 일관성을 유지하는 방법을 쉽게 공부하면서 더티 체크, 쓰기 지연 등 특성에 대해 알 수 있었던 거 같습니다.객체와 DB를 효과적으로 설계할 수 있도록 연관관계를 설계하는 방법을 배움으로써 사용할 때의 주의사항과 성능 문제를 방지하기 위한 전략에 대해 알게 되면서 이를 통해 효과적이고 용이한 애플리케이션 개발을 할 수 있는 토대를 마련할 수 있었던 거 같습니다.
백엔드
・
인프런워밍업스터디클럽
・
2주차
・
회고록
2024. 05. 04.
0
[인프런 워밍업 스터디 클럽 1기] BE 1주차 회고록
첫 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 첫 번째 회고록입니다. 학습 내용스프링 프로젝트를 시작하는 방법과 네트워크, HTTP, API에 대한 기본적인 개념에 대해 학습하였습니다.HTTP는 데이터를 주고 받는 표준이고, 행위와 자원은 HTTP 요청을 보내기 전에 약속을 해야합니다.HTTP Method는 GET, POST, PUT, DELETE 가 있습니다. 예시로 GET는 HTTP 요청을 받는 컴퓨터에게 요청하는 행위입니다.GET 요청의 경우 /portion 이라는 요청 받는 path와 ?의 구분기호로 세부 조건인 쿼리스트링 작성합니다.GET /portion?color=red&count=2POST 요청의 경우 데이터를 저장하는 것으로 바디를 사용합니다.POST /oak/leatherDELETE는 데이터를 삭제하기 위해 쿼리스트링을 사용하고, PUT은 데이터를 수정하기 위해 바디를 사용합니다. POST API는 HTTP Body를 활용해서 데이터를 받습니다.데이터를 보낼 때는 JSON(객체표기법)을 활용합니다.key : 'value' 형태로 Java 문법 상 Map 형태와 유사합니다.@PostMapping("/multiply") public int multiplyTwoNumbers(@RequestBody CalculatorMultiplyRequest request){ return request.getNumber1()* request.getNumber2(); }위의 예시의 주요 어노테이션은 아래와 같습니다.@PostMapping : HTTP Method가 POST 이고, 요청 경로인 /path인 API를 생성합니다.@RequestBody : HTTP Body로 들어오는 JSON 파라미터로 데이터를 전달하는 객체인 DTO로 바꿔줍니다. DTO에는 JSON의 key 값이 명시되어야하며, 각 속성은 key 값과 동일하게 value도 타입에 맞게 작성합니다. Database는 데이터를 구조화시켜 저장합니다. 마치 엑셀과 비슷하게 표처럼 구조화하여 저장합니다.여기서 구조화된 데이터를 조회하는 언어를 SQL 이라고 합니다.SQL문의 예시는 아래와 같습니다.// DB 생성 create database [데이터베이스 이름]; // DB 조회 show databases; // DB 삭제 drop database [데이터베이스 이름]; // DB 사용 use [데이터베이스 이름]; // TABLE 조회 show tables; // TABLE 생성 create table [table 이름] ([필드 이름] [타입] [부가 조건], [필드 이름] [타입] [부가 조건], ... primary key([필드 이름]) ); // TABLE 삭제 drop table [table 이름];테이블 자체를 생성, 삭제, 변경, 초기화 하는 것을 DDL(Data Definition Language) 라고 합니다. 테이블의 데이터를 조작하는 것을 일명 C.R.U.D 라고 부릅니다.테이블 데이터를 조작하는 SQL문을 DML(Data Manipulation Language) 라고 합니다.데이터 삽입insert into [table 이름]([필드 이름1], [필드 이름2], ...) values (값1, 값2, ...);데이터 조회select * from [db 이름]; select [필드 이름1], [필드 이름2] from [db 이름];조건 데이터 조회select * from [db 이름] where [조건];데이터 업데이트update [table 이름] set 필드1=값, 필드2=값,... where [조건];❗ 조건문을 작성하지 않으면 모든 데이터가 바뀌니 항상 주의하자!데이터 삭제delete from [table 이름] where [조건];❗ 조건문을 작성하지 않으면 모든 데이터가 삭제되니 항상 주의하자! 과제 내용Day 1HTTP 요청을 보내기 위한 Method 중 하나인 GET API 를 만들기 위해서 어노테이션을 사용했었습니다.이를 통해 어노테이션을 사용하는 이유는 무엇인지, 또한 나만의 어노테이션을 만드는 방법에 대해 학습하게 되었습니다.처음에는 클래스 위에 붙은 @ 어노테이션은 의미를 생각하기보다는 레이어에 맞는 동작을 하기 위해서 알맞는 어노테이션을 사용할 수 있도록 암기하는 것으로만 생각하고 공부했었습니다. 자바에서 제공하는 표준 어노테이션을 다양하게 찾아봤으며, 코드가 작동되면서 reflection을 이용하여 코드를 직접적으로 호출하지 않고 코드를 제어할 수 있는 다양한 기술의 집합체라는 것을 알게 되었습니다.그리고, 유저가 직접 만드는 어노테이션을 구현해보면서 메타 어노테이션 즉, 내가 만드는 어노테이션의 유지 기간, 위치를 결정할 수 있도록 결정할 수 있는 사용자 친화적인 조작을 할 수 있다는 것을 알게 되었습니다.📋 1일차 미션 : 어노테이션의 개념과 특징 Day 2GET, POST API를 활용한 과제인데 일반적으로, GET을 사용할 때는 URL 뒤에 query를 사용하는 방식, POST를 사용할 때는 body를 사용하는 방식으로 볼 수 있습니다. 하지만 부득이하게 데이터의 양이 많이 복잡하다면 쿼리 파라미터로 받는 방식(GET)보다는 body 로 받는 방식(POST)로 변경하는 방향이 좋다는 것을 알았습니다.또한, LocalDate 타입을 string 형태로 받아 치환을 해줬는데, 스프링부트 2.x.x 버전에서 @DateTimeFormat을 활용하여 localDate를 바로 받을 수 있는 방법도 알게 되어, java 문법의 변수가 아닌 스프링에 친화적인 어노테이션을 활용하여 구현할 수 있도록 많이 접해보고 공부해야겠다는 생각이 들었습니다.📋 2일차 미션 : GET API와 POST API Day 3람다식의 등장한 이유와 람다식과 익명 클래스의 관계에 대한 내용을 중점적으로 공부하는 것이었습니다.위의 내용을 공부하면서 함수형 프로그래밍과 @FunctionalInterface, stream API와 메서드 레퍼런스에 대한 내용에 대한 연관성도 함께 예시를 만들어보면서 공부했습니다. 위의 내용은 코딩테스트를 해본 사람이면 한 번 쯤은 실습해봤을 내용이라서 쉽게 내용을 이해할 수 있을 것이라고 생각했습니다.하지만 필자의 경우 문법에 대한 내용보다는 코드를 구현할 줄만 알았습니다. 해당 내용을 공부하니 왜 만들어졌는지, 자바에서는 버전을 올라가면서 메서드를 쉽게 구현할 수 있도록 점차 단순화시키고 간결하게 표현할 수 있다는 것에 대해 면밀하게 알 수 있었습니다.📋 3일차 미션 : 익명 클래스와 람다식 회고기초 지식보다는 실제 프로젝트를 구현하기 위한 기술에 대한 내용에 중점을 두고 공부를 했었는데, 백엔드 개발을 하기 위한 서버 지식과 Java, Spring에 관한 내용을 다시 처음부터 하나씩 이해하면서 다시금 지식을 쌓을 수 있었던 거 같습니다.또한, 강의만 듣는 게 아닌 과제를 해결하면서 강의에 대한 이해와 구현할 수 있는 능력을 키우면서 나 자신의 부족한 점과 다른 방식으로 구현할 수 있을 수 있을까라는 여러 방법에 대해 골똘하게 생각할 수 있는 계기가 되었던 거 같습니다.
백엔드
・
인프런워밍업스터디클럽
・
1주차
・
회고록