[인프런 워밍업 클럽 스터디 1기] BE 3주차 회고
세번째 발자국
인프런 워밍업 클럽 스터디에 참여하여 일주일을 보낸 후 쓰는 세번째 회고록.
학습 내용
Section 5 - 책 요구사항 구현하기
연관관계
두 개 이상의 테이블 또는 객체 간의 관계를 정의하는 방법
엔티티 간 객체지향적 모델링 가능
연관관계의 주인 효과
상대 테이블을 참조하고 있으면 연관관계의 주인
연관관계의 주인이 아니면 MappedBy를 사용
연관관계의 주인의 setter가 사용되어야만 테이블 연결
JPA 연관관계
1:1 관계
@OneToOne
한 엔티티가 하나의 엔티티와만 연관된 경우
두 엔티티 모두
@OneToOne
설정주인이 아닌 곳에
mappedBy
붙여야 함
N:1 관계
@ManyToOne
여러 엔티티가 한 개의 엔티티와 연관된 경우
연관관계의 주인은 무조건 N (숫자가 많은 쪽)
N쪽(Many)에
@ManyToOne
을 설정하고 1쪽(One)에@OneToMany
를 설정@ManytoOne
은 단방향으로 사용 가능@JoinColumn
연관관계의 주인이 활용할 수 있는 어노테이션
필드의 이름이나 null 여부, 유일성 여부, 업데이트 여부 등을 지정
N:M 관계
@ManyToMany
여러 엔티티가 여러 개의 엔티티와 연관된 경우
구조가 복잡하고 테이블이 직관적으로 매핑되지 않아 사용하지 않는 것이 좋음
casade 옵션
한 객체가 저장되거나 삭제될 때, 그 변경이 폭포처럼 흘러 연결되어 있는 객체도 함께 저장되거나 삭제되는 기능
orphanRemoval 옵션
객체 간의 관계가 끊어진 데이터를 자동으로 제거하는 옵션
Section 6 - 생애 최초 배포 준비하기
배포
최종 사용자에게 SW를 전달하는 과정
전용 컴퓨터에 우리의 서버를 옮겨 실행시키는 것
전용 컴퓨터에 코드를 옮기고 필요한 프로그램을 설치해 최종 사용자가 접속할 수 있도록 하는 것
profile
같은 서버 코드를 실행시키지만, 실행 설정을 다르게 하고 싶을 때 사용
DB 설정, 외부 API 키 등의 환경 구성을 다르게 할 수 있음
local -> H2 DB, dev -> MySQL DB
application.yml
에서---
로 옵션 구분
H2 DB
경량 데이터베이스로, 개발 단계에서 많이 사용함
디스크가 아닌 메모리에 데이터를 저장 가능
개발단계에서는 수정사항이 많아 데이터가 휘발되는 것이 장점으로 작용
ddl-auto
옵션을create
로 설정하면 테이블이 자동 생성/삭제가 되어 편리함
git
코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램
github
git으로 관리되는 프로젝트의 코드가 저장되는 저장소
코드는 어떠한 이유로든 소실될 가능성이 있기 때문에 백업용으로 사용
프로젝트 공유, 협업, 배포 등에 활용 가능
git 명령어
git init
git 초기화
해당 프로젝트를 git이 관리하겠다는 의미
git remote add orign [각자의 주소]
현재 프로젝트의
git
저장소를 주어진 주소로 설정
git add .
작업 디렉토리의 모든 (변경된) 파일을 스테이징 영역(commit의 대상)으로 추가 (택배 상자에 파일 담기)
.
대신[파일 이름]
을 넣으면 특정 파일만 추가 가능
git status
git
상태 확인 (택배 상자 안에 담긴 내용 확인)
git commit -m "메시지"
스테이징 영역의 상태를 버전으로 기록 (택배를 포장하고 송장 붙이기)
commit
을 해주면commit
한 곳으로 언제든지 돌아올 수 있어 코드의 추가, 삭제가 자유로움commit
메시지에는 적고 싶은 내용(어떤 코드인지, 업데이트 내용 등)
git push
원격 저장소(github)에 코드 변경분을 업로드 (택배 상자 github에 보내기)
git pull
원격 저장소의 코드를 다운로드
.gitignore
git을 통해 관리하고 싶지 않거나 원격 저장소에 올리고 싶지 않은 파일을 관리하기 위한 파일
파일의 경로나 파일 이름을 적어둠
AWS(Amazon Web Service)
가입하면 우리가 배포할 전용 컴퓨터를 대여 가능
지역을 한국으로 변경
EC2 (Elastic Compute Cloud)
탄력적으로 사용할 수 있는 원격 컴퓨터
탄력적 : 원격으로 언제든 생성/제거 가능
인스턴스 = 우리가 빌린 컴퓨터
인스턴스 시작을 누른 후 설정
이름 및 태그 : 우리가 빌릴 컴퓨터의 이름 지정
애플리케이션 및 OS 이미지 : 기본적으로 Amazon Linux 2 AMI(아마존에서 관리하는 리눅스 운영체제)
인스턴스 유형 : 우리가 빌릴 컴퓨터 사양
키 페어(로그인) : 빌린 컴퓨터에 접속할 때 필요한 보안 파일
네트워크 설정 : 빌린 컴퓨터에 접속할 때 접근을 허용할 IP, 포트 등을 설정하는 보안 그룹 생성
스토리지 구성 : 빌릴 컴퓨터의 디스크 용량 결정
Section 7 - 생애 최초 배포하기
EC2 접속
키 페어를 이용하는 방법
다운로드 받은 키 페어(pem key)
키 페어 파일의 보안을 설정 :
chmod 400 경로/키페어명 .pem
chmod
: 접근 권한 변경 (400)
ssh 접속 :
ssh -i 경로/키페어명.pem ec2-user@IP
AWS 콘솔을 활용하는 방법
AWS EC2 웹사이트에 접속해 연결 버튼 누르기
리눅스 명령어
mkdir
: 폴더를 만드는 명령어ls
: 현재 위치에서 폴더나 파일을 확인하는 명령어ls -l
: 더 자세한 정보 확인drwxrwxr-x
d: 폴더(디렉토리)
r: 읽는 권한, w: 쓰는 권한, x: 실행 권한
rwx / rwx / r-x : 소유자 권한 / 소유 그룹 권한 / 아무나 접근할 때의 권한
2 : 폴더에 걸려 있는 바로가기 개수
ec2-user : 폴더 소유자의 이름
ec2-user : 폴더 소유 그룹의 이름
6 : 파일의 크기(byte)
Dec 5 06:00 : 파일의 최종 변경 시각
folder1 : 파일 이름
cd
(change directory): 폴더 안으로 들어가는 명령어cd ..
: 상위 폴더로 이동
pwd
(print working directory): 현재 위치를 확인하는 명령어rmdir
: 특정 폴더(디렉토리)를 제거하는 명령어
서버 설정 및 배포
Git, Java, MySQL 설치
코드를 가져오기 위한 Git
서버를 구동할 Java
사용할 데이터베이스 MySQL
리눅스에서 스프링 배포 프로그램 설치
Github에서 코드 가져오기
git clone [저장소 주소]
Swap 설정
메모리가 부족할 경우 일부 디스크를 사용하도록 하는 설정
무료로 사용하는 EC2는 메모리가 적기 때문
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
: swap 메모리 할당sudo chmod 600 /swapfile
: swap 파일에 대한 권한 업데이트sudo mkswap /swapfile
: swap 영역 설정sudo swapon /swapfile
: swap 파일 사용 설정sudo swapon -s
: swap 성공 확인
빌드
chmod +x ./gradlew
: gradLew를 사용할 수 있도록 쓰기 권한 설정./gradlew build -x test
: gradle을 이용해 프로젝트 빌드 (테스트 코드 실행 X)
서버 실행
java -jar build/libs/[빌드한 파일명.jar] --spring.profiles.active=dev
Jar 파일을 실행만 했는데 서버가 동작하는 이유 : Spring Boot에 톰캣이 내장되어 있기 때문
톰캣 : 웹 애플리케이션 서버의 한 종류. 들어온 요청을 형식에 맞추어 스프링에 전달
ctrl+c
: 무언가를 중단하는 신호(실행중인 서버 중단)./gradlew clean
: 현재 빌드되어 있는 결과물 제거
foreground vs background
foreground
우리가 보고 있는 프로그램(현재 보이는 화면의 프로그램)
background
우리가 보고 있지 않은데 실행 중인 프로그램
ec2 접속을 종료해도 서버가 종료되지 않도록 하려면 서버를 background로 동작하게 해야 함
nohup [명령어] &
background 서버 다운
ps aux
: 현재 실행중인 프로그램 목록을 확인ps aux | grep java
:java
가 들어가는 프로그램을 확인(각 프로그램의 고유 번호 확인)kill -9 프로그램번호
: 해당 프로그램을 종료
DNS 적용
가비아 회원가입 후 도메인 구매
도메인 네임 등록 : 구매한 도메인과 빌린 EC2 서버 연결
타입 : A
호스트 : www
값/위치 : EC2에서 빌린 인스턴스의 IP
방화벽 설정
접근 가능한 IP 혹 포트 설정
Section 8 - Spring Boot의 이모저모
build.gradle
빌드 스크립트
gradle을 이용해 프로젝트를 빌드하고 의존성을 관리하기 위해 작성
plugins
: 프로젝트에 적용하고 싶은 플러그인 추가group
: 프로젝트의 그룹version
: 프로젝트의 버전sourceCompatibility
: 프로젝트가 사용하고 있는 JDK 버전repositories
: 외부 라이브러리나 프레임워크를 가져오는 장소 설정dependencies
: 우리가 사용하는 라이브러리/프레임워크 표시tasks.named('test')
: 테스트를 수행할 때 사용할 프레임 워크
Spring Boot의 특징(Spring과의 차이점)
간편한 설정
xml
대신 어노테이션 기반의 설정 가능기본적으로 필요한 것을 모두 자동 설정
간단한 의존성 관리
의존성을 필요한 것끼리 묶어
starter
로 관리필요한 라이브러리나 프레임워크 하나 하나 적을 필요 없음
강력한 확장성
starter
추가만으로 필요한 기술을 도입할 수 있음
application.yml
YAML 문법 사용
.yaml
또는.yml
: YAML의 확장자기본적으로 key : value 형식으로 데이터 정의
각 계층은 들여쓰기를 통해 구분 (이를 통해 중복 제거)
value로 들어갈 수 있는 타입 : 참/거짓, 숫자, 문자열(큰 따옴표 사용)
배열은
-
사용
#
로 주석 표현
application.properties
applicatoin.yml 대신 사용 가능
key : value 형식으로 데이터 기록
들여 쓰기를 통해 중복을 제거할 수는 없음
application-프로파일 이름.properties
파일을 새로 만들어 profile 설정가독성 떨어짐
lombok
생성자, getter, setter, equals, toString 등 반복되는 보일러 플레이트 코드(boiler palte code)를 자동으로 생성해줌(반복되는 코드 제거)
lombok 도입을 위한 설정
lombok 의존성 추가
IntelliJ lombok 플러그인 추가
intelliJ Annotation Processor 설정
과제
6일차 과제 - Controller 3단 분리하기
https://shimmer-exoplanet-946.notion.site/6-18433147fcf443ad8597ac6b4fac8c43?pvs=4
문제 1번은 과제 4에서 만들었던 코드를 Controller - Service - Repository로 분리하는 과제였다. 수업 때 배운대로 API와 HTTP를 담당하는 부분만 Controller에 남겨두고 분기 처리나 로직을 담당하는 부분은 Service로, SQL을 이용해 DB와 통신을 담당하는 부분은 Repository로 분리해 주었다.
문제 2번은 Repository를 DB에 데이터를 저장하는 MysqlRepository와 메모리에 데이터를 저장하는 MemoryRepository로 분리하는 과제였다. 기존 코드가 SQL을 이용해 DB에 데이터를 저장하는 방식이었으므로 그대로 MysqlRepository로 옮겨주고, MemoryRepository의 경우 List<Fruit>
을 만들어 메모리에 과일에 대한 정보들을 저장했다. 기존 함수에서 id가 필요한 부분이 있었는데, mysql에서 id는 자동으로 생성되기 때문에 MemoryRepository에만 변수 num
을 0으로 초기화해두고 createFruit가 호출될 때마다 1씩 증가하게 하여 id 대신 사용했다.
문제 2개 모두 수업 시간에 했던 방식에서 크게 달라지지 않아 무난하게 해결했다. 확실히 코드를 계층별로 분리해두니 각 계층의 역할이 명확하게 보이고 코드가 간결해져 보기 편했다.
7일차 과제 - JPA 적용하기
https://shimmer-exoplanet-946.notion.site/7-9e89cd27e6284807b1f448d6934b30fe?pvs=4
문제 1은 과제 #6에서 만들었던 기능들을 JPA를 이용하도록 변경하는 것이었다. 수업에서 배운대로 Fruit 객체에 @Entity 어노테이션을 붙이고 각 필드를 테이블의 속성과 매핑되도록 적절한 어노테이션을 붙여주었다. 그후 FruitService에서 SQL을 문자열로 하나하나 타이핑하는 것이 아니라 JPA 함수를 이용해 DB와 통신하도록 수정하고, 추가적으로 필요한 함수는 FruitRepository 인터페이스에 선언해주었다.
문제 2는 과일의 이름을 받아 지금까지 가계를 거쳐간 해당 과일의 개수를 세는 기능을 만드는 것이었다. 테이블에서 특정 이름을 가진 레코드의 개수를 세면 되는 것이라 countByName
을 이용하여 원하는 값을 구했다. postman으로 테스트할 때 406 Not Acceptable 에러가 발생했는데, FruitCountResponse에 getter
를 추가해주니 정상 작동했다.
문제 3은 아직 판매되지 않은 과일 중 특정 금액 이상 혹은 특정 금액 이하의 과일 목록을 받아오는 기능을 만드는 것이었다. findAllByPriceGreaterThanEqual / findAllByPriceLessThanEqual
을 이용해 특정 가격 이상/이하의 과일들을 가져온 후, Fruit의 isPurchase 함수를 이용해 팔린 과일인지 확인하여 팔리지 않은 과일들만 넣은 리스트를 반환해주었다.
세 문제 모두 수업에서 배운 내용을 그대로 사용하거나 간단한 응용만 하는 방식이라 할 만 했다. 다만 stream과 같은 기능이 익숙하지 않아 해당 부분에서 발생한 에러를 해결하거나 특정 기능을 사용하는 방법을 찾기 위해 구글링을 해야 했다. 수업을 들으면서도 느꼈지만 자바 공부를 좀 더 해야겠다.
회고
다른 일들이 많이 겹쳐 공휴일이 끼어 있는데도 바쁜 한 주를 보냈다. 덕분에 저번주에 배운 내용을 다시 한번 복습하고 정리하겠다는 다짐은 지켰지만, 후반부 강의도 조금 밀려 늦게 들었고 따로 공부해보려던 것은 못한 점이 아쉽다. 이번주 강의는 새로운 개념을 익히기 보다는 배포 과정을 체험해보는 것에 가까웠던 점이 다행이었다. 강의를 따라하는 게 다지만 강사님의 화면과 다른 부분이 조금씩 있어 따로 찾아봐야 했는데, 그래도 진도를 마치고 배포까지 해내고 나니 굉장히 뿌듯하고 자신감이 붙었다. 처음에는 잘 사용하지 않는 리눅스나 AWS 부분에 대한 막연한 두려움이 있었는데 강의에서 세세히 설명해주니 어렵게만 느껴졌던 것들이 이해가 돼서 좋았다.
이번주로 스터디는 마무리되고 남은 것은 미니 프로젝트와 마무리 강의들 뿐이다. 다음주는 미니 프로젝트를 할 수 있는 부분까지만이라도 수행해보고, 시간이 된다면 강의에서 배운 것들을 전체적으로 복습하려 한다. 또한 스터디가 끝나더라도 한 주의 회고를 작성하는 것은 계속하는 습관을 들여보려 한다. 발자국을 작성하는 것은 이번 스터디를 통해서 처음 해봤는데, 한주동안 배운 내용을 한번씩 정리하는 것이 많은 도움이 되었다. 작성을 하는 동안 지난 한주를 돌아보며 아쉬운 점을 개선할 방법을 찾아보고, 다음주에 대한 계획을 세우게 되는 것도 좋았다. 이 마음가짐을 쭉 유지해서 스터디가 끝난 이후에도 계속해서 체계적으로 공부를 할 수 있도록 노력해야겠다.
댓글을 작성해보세요.