블로그
전체 5#카테고리
- 백엔드
#태그
- 백엔드

2024. 05. 19.
0
인프런 워밍업 클럽 스터디 1기 BE 3주차 발자국
배포란 무엇인가배포최종 사용자에게 SW를 전달하는 과정현재는 우리 컴퓨터에 Spring, MySql 등이 서버가 설치되어 있다.우리 컴퓨터가 종료되어도 서버에 접속할 수 있는 방법전용 컴퓨터에 Spring, MySql 등을 설치하고 작성한 코드를 옮겨서 서버를 실행한다.이런 과정을 배포라고 한다.배포 방법AWS에서 무료로 전용 컴퓨터를 빌릴 수 있다.배포 준비profile 설정똑같은 서버 코드를 실행시키는데DB와 같은 설정을 실행되는 환경에 따라서 다른 설정으로 실행시키기 위한 설정우리 컴퓨터에서는 h2 DB전용 컴퓨터에서는 MySQL설정을 위해서는 application.yml을 수정해주면 된다.spring: config: activate: on-profile: local datasource: url: "jdbc:h2:mem:library;MODE=MYSQL;NON_KEYWORDS=USER" username: "sa" password: "" driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true dialect: org.hibernate.dialect.H2Dialect h2: console: enabled: true path: /h2-console --- spring: config: activate: on-profile: dev datasource: url: "jdbc:mysql://localhost/library" username: "root" password: 1234 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: none properties: hibernate: show_sql: true format_sql: true dialect: org.hibernate.dialect.MySQL8Dialect H2 Database개발 단계에서 많이 사용하는 경량 Database디스크가 아닌 메모리에 데이터를 저장할 수 있다.데이터가 휘발된다.개발 단계에서는 DB가 자주 변경되기 때문에 편하게 사용git 이란?코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램여러 명이서 개발을 수행할 때 코드를 쉽게 합치고 관리할 수 있다.GitHubgit으로 관리되는 프로젝트의 코드가 저장되는 원격 저장소GitHub에 저장하는 이유내 컴퓨터에 저장한 코드는 소실 될 수 있다.배포 과정에서 원격 저장소에서 코드를 쉽게 옮길 수 있다.git 기초 명령어**git init :** 프로젝트를 git이 관리하도록 해준다.**gti remote add origin [repository 주소]** : 원격 저장소와 git 프로젝트를 연결작성한 코드 원격 저장소에 올리기**git add .** : 코드를 올리기 위해 추가하는 명령어git status : 현재 add한 상황 확인 명령어**git commit -m “메시지”** : add한 코드를 메시지와 함께 묶는 커밋 명령어**git push** : 커밋한 코드를 원격 저장소로 보내는 명령어**git push —set-upstream origin master** : 최초로 push 하는 경우 1번 반드시 해줘야 하는 명령어.gitignoregit을 통해서 관리되기 싫거나 원격 저장소에 올리고 싶지 않은 파일을 관리하기 위한 파일파일명 또는 파일의 경로를 적어준다.build/ .gradle/ .idea/ AWS EC2Elastic Compute Cloud탄력적으로 사용할 수 있는 원격 컴퓨터언제든지 필요할 때 빌리고 반납할 수 있다.배포 시작EC2 접속방법1. 키 페어를 이용하는 방법먼저 키페어 파일의 보안을 설정해준다.chmod 400 경로/키페어명.pem ec2 접속 명령어ssh -i 경로/키페어명.pem ec2-user@IP 2. AWS 콘솔을 활용하는 방법AWS ec2 웹사이트에 접속해서 연결 버튼을 통해 연결한다.필요한 프로그램 설치하기코드를 가져오기 위한 git 설치서버를 구동하기 위한 java 설치데이터베이스 역할을 하는 MySQL 설치GitHub에서 코드 가져오기git clone [레포지토리 주소] EC2 Swap 설정무료로 사용하는 EC2인 t2.micro는 메모리가 적어서 성능이 떨어지기 때문에메모리가 부족할 경우 DISK를 사용하도록 하는 swap 설정이 필요하다.# swqp 메모리 할당 sudo dd if=/dev/zero of=/swapfile bs=128M count=16 # swqp 파일에 대한 권한 업데이트 sudo chmod 600 /swapfile # swap 영역 설정 sudo mkswap /swapfile # swap 파일 사용 설정 sudo swapon /swapfile # swap 성공 확인 sudo swapon -s 빌드하기# gradlew를 사용할 수 있도록 쓰기 권한 설정 chmod +x ./gradlew # 프로젝트 빌드(테스트 없이) ./gradlew build -x test 서버 실행하기java -jar build/libs/[빌드한 파일명.jar] --spring.profiles.active=dev 보안 그룹 편집하기보안 그룹에 접근 가능한 IP를 열어주어야 접근이 가능하다.보안 그룹 → 인바운드 규칙에서 열어줄 IP를 추가해주면배포된 사이트에 접근이 가능해진다. 백그라운드 실행시키기nohup 명령어ec2를 종료해도 서버를 종료시키기 않게 백그라운드로 실행시키기 위해서nohub 명령어를 사용한다.nohup java -jar build/libs/[빌드한 파일명.jar] --spring.profiles.active=dev & 실행 중인 프로그램 종료하기# 실행 중인 프로그램 목록 확인 ps aux | grep java # java가 들어가는 프로그램 확인 ps aux | grep java # 해당 프로그램 종료 kill -9 [프로그램 번호] 파일 확인 명령어# vim을 이용해 파일 열기 vi [파일명] # 터메널에서 파일 전체 출력 cat [파일명] # 파일의 끝 부분 출력 tail [파일명] # 끝 부분을 실시간으로 출력 tail -f [파일명]
백엔드

2024. 05. 12.
0
인프런 워밍업 클럽 스터디 1기 BE 두번째 발자국
학습 내용스프링 컨테이너의 의미와 사용 방법스프링 빈스프링은 스프링 서버 내부에 거대한 컨테이너를 만들고이 컨테이너 안에는 여러 클래스가 들어간다.이때 다양한 정보도 함께 들어 있고 인스턴스화도 이루어짐JdbcTemplate도 스프링 빈에 등록되어 있어서 의존성을 등록해준다.서버가 시작되면 일어나는 일스프링 컨테이너 시작기본적인 스프링 빈 등록우리가 설정한 스프링 빈 등록이때 필요한 의존성 자동 설정UserRepository는 JdbcTemplate을 가져오지 못한이유UserRepository가 스프링 빈이어야 하는데 UserRepository는 스프링 빈이 아니기 때문에UserRepository를 스프링 빈으로 등록하면 가져올 수 있다.@Service와 @Repository 어노테이션을 사용해 스프링 빈으로 등록스프링 컨테이너를 다루는 방법스프링 빈 등록하는 방법@Configuration클래스에 붙이는 어노테이션@Bean을 사용할 때 함께 사용해 주어야 함@Bean메소드에 붙이는 어노테이션메소드에 반환되는 객체를 스프링 빈에 등록@Component주어진 클래스를 컴포넌트로 간주이 클래스들은 스프링 서버가 뜰 때 자동으로 감지@Component 덕분에 우리가 사용했던 어노테이션이 자동감지Controller, Service, Repository가 모두 아니고 개발자가 직접 작성한 클래스를 스프링 빈으로 등록할 때 사용스프링 빈 주입받는 방법생성자를 이용해 주입받는 방식@Autowired 생략 가능Setter와 @Autowired 사용누군가 setter를 사용하면 오작동할 가능성 있음필드에 직접 @Autowired 사용테스트를 어렵게 만드는 요인@Qualifier@Primary vs @Qualifier사용하는 쪽이 직접 적은 @Qualifier이 우선적Spring Data JPA를 사용한 데이터베이스 조작SQL을 직접 작성하면 아쉬운 점문자열을 작성하기 때문에 실수할 수 있고 실수를 인지하는 시점이 느림컴파일 시점에 발견되지 않고 런타임 시점에 발견됨특정 데이터베이스에 종속적이게 됨반복 작업이 많아지며 테이블을 하나 만들 때마다 CRUD 쿼리가 항상 필요데이터베이스의 테이블과 객체는 패러다임이 다름JPA(Java Persistence API)객체와 관계형 DB의 테이블을 짝지어 데이터를 영구적으로 저장할 수 있도록 정해진 Java 진영의 규칙Hibernate: 말로 되어 있는 규칙을 코드로 구현한 것Hibernate(구현체)이 JPA를 구현내부적으로 JDBC 사용유저 테이블에 대응되는 Entity Class 만들기Java 객체 MySQL Table 매핑JPA 어노테이션@Entity: Spring이 User 객체와 user 테이블을 같은 것으로 바라봄@Id: 이 필드를 primary key로 간주@GeneratedValue: primary key는 자동 생성되는 값임@Column: 객체의 필드와 Table 필드 매핑JPA를 사용하기 위해서는 기본 생성자가 반드시 필요JPA 추가 설정ddl_auto: 스프링이 시작할 때 DB에 있는 테이블을 어떻게 처리할지 (create, create-drop, update, validate, none)format_sql: SQL을 보여 줄 때 예쁘게 포맷팅 할 것인가show_sql: JPA를 사용해 DB에 SQL을 날릴 때 SQL을 보여 줄 것인가dialect: 조금씩 다른 SQL을 수정해 줌Spring Data JPA를 이용해 자동으로 쿼리 날리기JPA 기능save: 주어지는 객체를 저장하거나 업데이트findAll: 주어지는 객체가 매핑된 테이블의 모든 데이터 가져옴findById: id를 기준으로 특정한 1개의 데이터 가져옴Spring Data JPA복잡한 JPA 코드를 스프링과 함께 쉽게 사용할 수 있도록 도와주는 라이브러리Spring Data JPA를 이용해 다양한 쿼리 작성하기By 앞에 들어갈 수 있는 구절 정리find: 1건을 가져옴, 반환 타입은 객체가 될 수도 있고 Optional이 될 수도 있음findAll: 쿼리의 결과물이 N개인 경우 사용, List 반환exists: 쿼리 결과가 존재하는지 확인, 반환 타입은 booleanBy 뒤에 들어갈 수 있는 기능 정리And / Or 조합 가능GreaterThan: 초과GreaterThanEqual: 이상LessThan: 미만LessThanEqual: 이하Between: 사이에StartsWith: ~로 시작하는EndsWith: ~로 끝나는트랜잭션과 영속성 컨텍스트트랜잭션쪼갤 수 없는 업무의 최소 단위트랜잭션 시작: start transaction;트랜잭션 정상 종료: commit; (SQL 반영)트랜잭션 실패 처리: rollback; (SQL 미반영)영속성: 모든 SQL을 성공시키거나 하나라도 실패하면 모두 실패시키는 속성트랜잭션 적용과 영속성 컨텍스트@Transactional스프링에서 트랜잭션 적용할 때 사용IOException과 같은 Checked Exception은 롤백이 일어나지 않음영속성 컨텍스트테이블과 매핑된 Entity 객체를 관리 및 보관하는 역할변경 감지(Dirty Check)영속성 컨텍스트 안에서 불러와진 Entity는 명시적으로 save하지 않더라도 변경을 감지해 자동으로 저장쓰기 지연DB의 INSERT / UPDATE / DELETE 문을 바로 날리는 것이 아니라 트랜잭션이 commit 될 때 한번에 날림1차 캐싱ID를 기준으로 Entity를 기억캐싱된 객체는 동일한 객체
백엔드

2024. 05. 07.
0
인프런 워밍업 클럽 스터디 1기 BE 4번째 과제
문제1과일 정보 저장 API{ "name": "사과", "warehousingDate": "2024-02-01", "price": 5000 } 위와 같은 정보를 받아서 저장할 수 있도록 fruit 테이블을 만들었다.create table fruit ( id bigint auto_increment, name varchar(30), warehousingdate date, price bigint, primary key(id) ); 그리고 이전에 구현했던 내용과 똑같이 INSERT문을 이용해 과일 정보 저장 API를 구현했다.public void save(Fruit fruit) { String sql = "INSERT INTO fruit (name, warehousingdate, price) VALUES (?, ?, ?)"; jdbcTemplate.update(sql, fruit.getName(), fruit.getWarehousingDate(), fruit.getPrice()); } 가격을 나타내는 price의 테이터 타입은 long을 사용했는데int를 사용하지 않고 long을 사용하는 이유는가격의 크기가 int의 범위를 초과할 수 있기 때문이다.문제2문제2는 과일이 팔린 경우 팔렸다는 정보를 저장하는 API를 구현하는 문제팔렸다는 정보를 저장하기 위해서 fruit 테이블에 sold라는 컬럼을 추가했다.create table fruit ( id bigint auto_increment, name varchar(30), warehousingdate date, price bigint, sold boolean default false, primary key(id) ); boolean 타입이고 default 값은 false인 sold 컬럼을 만들어서과일이 팔린 경우 해당 API를 호출하면 sold 컬럼을 true로 바꿔주도록 구현헀다.public void updateSold(Long id) { String sql = "UPDATE fruit SET sold = true WHERE id = ?"; jdbcTemplate.update(sql, id); } 문제3특정 과일의 팔린 금액과 팔리지 않은 금액을 조회하는 API 구현하기2가지의 방법으로 구현할 수 있다.1. 과일의 이름에 해당하는 모든 데이터를 조회해서 Service 단에서 금액을 계산하기FruitRepositorypublic List getStat(String name) { String sql = "SELECT name, price, sold FROM fruit WHERE name = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> new Fruit( rs.getString("name"), rs.getLong("price"), rs.getBoolean("sold") ), name); } FruitServicepublic FruitStatResponse getStat(String name) { List fruits = fruitRepository.getStat(name); long salesAmount = 0; long notSalesAmount = 0; for (Fruit fruit : fruits) { if (fruit.getSold()) { salesAmount += fruit.getPrice(); } else { notSalesAmount += fruit.getPrice(); } } return new FruitStatResponse(salesAmount, notSalesAmount); } 데이터가 다음과 같이 들어있을 경우원하는 결과를 조회할 수 있다.2. 팔린 금액과 팔리지 않은 금액을 조회하는 쿼리를 만들기public FruitStatResponse getStat(String name) { String sql = "SELECT SUM(CASE WHEN sold = true THEN price ELSE 0 END) salesamount, " + "SUM(CASE WHEN sold = false THEN price ELSE 0 END) notsalesamount " + "FROM fruit WHERE name = ?"; return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> new FruitStatResponse( rs.getLong("salesamount"), rs.getLong("notsalesamount") ), name); } SUM 함수를 사용해서 금액의 합을 계산할 수 있고CASE문을 사용하면 sold가 true인 금액을 조건으로 해서 계산할 수 있다. 이렇게 쿼리를 이용하면 다양한 조건의 데이터를 검색할 수 있기 때문에Service단에서 원하는 데이터를 분류하는 작업을 하지 않을 수 있다.SQL을 잘 알면 활용할 수 있는 방법이 무궁무진 하지만SQL도 알면 알수록 더 어려워지는 것 같다…
백엔드

2024. 05. 05.
0
인프런 워밍업 클럽 스터디 BE 1주차 발자국
JDK, JER, JVM 알아보기JVM(Java Virtual Machine)자바 소스 코드 파일을 컴퓨터가 이해하고 실행하기 위해서는 0과1로 이루어진 코드로 컴파일해야 한다.그런데 문제는 Windows, Mac, Linux와 같이 서로 다른 운영체제들은 이해하는 방식이 달라서 운영체제 마다 다르게 컴파일을 해줘야 한다.그래서 자바는 JVM이라는 녀석이 운영체제에 맞게 컴파일을 해주는 역할을 한다.JVM은 그루비, 스칼라, 코틀린 같은 다른 언어에도 사용된다.JDK > JRE > JVMJDK(Java Development Kit)는 자바 개발에 필요한 도구들을 모아놓은 패키지이고JDK 안에 JRE가 포함되고 JRE 안에 JVM이 포함되는 구조이다.JRE(Java Runtime Environment)는 자바 프로그램 실행에 필요한 라이브러리 파일들과실행환경을 위한 JVM을 가지고 있다.따라서 JDK를 설치하면 JRE와 JVM도 함께 설치되는 것이고Java의 버전은 JDK의 버전이라고 말할 수 있다.JDK의 종류JDK에는 많은 버전과 종류가 있고 성능과 비용에 차이가 있다.Oracle JDK는 Oracle에서 만든 JDK로 개인에게 무료이고 기업용은 유료이다.Open JDK는 Oracle JDK와 비슷한 성능이지만 기업용도 무료이다.Open JDK는 잘 몰랐는데 혹시나 상업용으로 자바 프로그램을 만든다면 Open JDK를 써야될 것 같다. HTTP와 APIHTTP(HyperText Transfer Protocol)두 개의 다른 컴퓨터인 클라이언트와 서버가 통신을 하기 위해서 만들어진 규칙으로규칙에 맞게 요청과 응답을 보내면 된다.HTTP 요청은 HTTP Method와 Path(경로)가 핵심이고데이터를 전달하기 위한 방법으로 쿼리와 바디가 있다.HTTP 응답의 핵심은 상태코드이다.HTTP MethodHTTP 요청의 행위나 방법을 나타내는 부분GET : 데이터 조회POST : 데이터 추가, 저장PUT : 데이터 수정DELETE : 데이터 삭제API(Application Programming Interface)HTTP 규칙을 통해서 데이터를 주고 받을 때특정 기능은 어떤 방식으로 요청하고 응답할 지를 결정하는데이처럼 특정 기능을 수행하기 위한 정해진 약속을 API라고 한다.예를 들면 어떤 메소드 그리고 어떤 경로로 요청을 보내고 어떤 데이터를 보내며 어떤 응답을 줄 지와 같은 약속을 말한다. GET, POST API 개발@RequestParamGet 메서드로 요청을 보낼 때 쿼리에 들어있는 데이터를 받을 수 있다.@GetMapping("/add") public int add(@RequestParam int number1, @RequestParam int number2) { return number1 + number2; } DTO로 받기쿼리의 파라미터들을 필드로 가지는 DTO를 만들어서 Controller 메서드의 매개변수로 받으면여러 개의 파라미터를 한번에 받을 수도 있다.Spring은 파라미터와 일치하는 필드를 가진 DTO에 매핑해서 객체로 만들어준다.@GetMapping("/add") public int add(AddRequest request) { return request.getNumber1() + request.getNumber2(); } @RequestBodyPOST 메소드는 바디에 데이터를 넣어서 요청을 보내는데이 때 바디에 들어있는 데이터를 객체로 만들어서 받기 위한 어노테이션@PostMapping("/multiply") public int multiply(@RequestBody Multiply request) { return request.getNumber1() * request.getNumber2(); } MySQL 사용하기도커를 이용해서 설치하기Mysql을 직접 설치하면 설정에 문제가 생겼을 때 MySQL을 삭제했다 다시 설치해야 되고도커를 이용하면 여러 개의 DB를 사용하게 될 경우 각각 컨테이너로 띄울 수 있어서도커를 이용하여 MySQL 설치해보았다.먼저 도커를 설치MySQL 이미지 다운로드docker pull mysqlMySQL 컨테이너 실행docker run --name -e MYSQL_ROOT_PASSWORD= -d -p 3306:3306 mysql:latest도커 데스크탑이 있다면 GUI를 이용해 실행할 수 있다.컨테이너 접속docker exec -it bashMysql 접속mysql -u root -p 좋은 코드(Clean Code)는 왜 중요한가?코드는 요구사항을 표현하는 언어현업에서 개발자는 수많은 코드를 읽어야 한다.그렇기 때문에 코드만 보고도 의미를 파악할 수 있는 것이 중요하다.프로그램이 커질 때 안좋은 코드가 쌓이면 점점 복잡해지고 그로 인해 생산성도 떨어진다.하나의 함수는 하나의 기능만 수행하는 것이 좋다.많은 기능을 가지고 있으면 코드가 길어지기 때문에 읽고 이해하기 어렵다.여러 명이 작업하고 수정하기 어렵고 테스트하기 힘들다.하나의 함수는 하나의 기능을 수행하도록 분리하는 것이 좋다. 과제어노테이션이란?소스 코드에 영향을 주지 않고 프로그램에 정보를 제공해주는 역할@ 를 붙여서 사용한다.JDK 1.5버전 부터 사용 가능@SpringBootApplication, @RestController, @GetMapping...람다식익명 클래스를 간결한 함수식으로 표현한 것함수형 프로그래밍을 사용하기 위해 추가되었다.함수형 인터페이스와 함께 사용된다.interface Add { int add(int x, int y); } // 익명 클래스 Add a = new Add() { public int add(int x, int y) { return x + y; } }; // 람다식 Add a = (x, y) -> {return x + y;}; 회고공부에 대한 의욕이 많이 떨어지고 있는 시기에 공부 의욕을 올리고 자극을 받기 위해서 이번 주부터 인프런 워밍업 클럽 스터디를 시작했다.처음 강의를 수강할 때는 알고있는 내용이라 생각되는 강의 내용이 많아서 빠르게 강의를 듣고 과제를 진행하는데 역시 쉽게 공부 의욕이 올라오지는 않았다.그래도 강의를 듣고 따라서 API도 만들어보니 예전 기억들이 떠오르면서 3일차부터 조금씩 집중력이 오르기 시작했다.다시 공부 의욕도 올라오고 하루에 시간을 잘 분배해서 계획을 세우고 계획에 맞게 생활을 시작할 수 있게 되었다.초반에는 집중력이 떨어지는 시간이 많았지만 다시 조금씩 집중력을 찾기 시작했으니 다음 주에는 더 많은 시간을 공부에 투자하고 집중력을 끌어올릴 수 있도록 해야겠다.
백엔드

2024. 05. 03.
0
인프런 워밍업 클럽 스터디 1기 BE 3번째 과제
람다 표현식이란?람다 표현식 줄여서 람다식이란 메서드를 간결한 함수식으로 표현한 것이다.그리고 함수형 프로그래밍을 구성하기 위한 함수식이라고 하는데람다식이 나오게 된 이유는 객체 지향 프로그래밍 언어인 자바에서함수형 프로그래밍을 사용하기 위해서 Java 8버전 부터 추가되었다.자바에서 메서드를 사용하려면 클래스를 정의하고 메서드를 작성해야 하지만람다식으로 표현하면 메서드의 이름과 반환타입을 생략할 수 있다.int add(int x, int y) { return x + y; } // 람다식으로 표현 // 메서드명과 반환타입 생략 가능 (int x, int y) -> { return x + y; } // 매개변수 타입도 생략 가능 (x, y) -> x + y; 람다식과 익명 클래스어떻게 클래스를 만들지 않고 메서드를 작성할 수 있는 걸까?자바에는 이름이 없는 클래스인 익명 클래스가 있는데익명 클래스는 클래스를 따로 정의하지 않고 바로 객체로 생성해 한번만 사용할 수 있다.이 익명 클래스를 짧게 표현하면 람다식이 되는 것이다.interface Add { int add(int x, int y); } // 익명 클래스 Add a = new Add() { public int add(int x, int y) { return x + y; } }; // 람다식 Add a = (x, y) -> {return x + y;}; 여기서 익명 클래스와 람다식을 대입 받는 변수가 필요한데이 변수는 인터페이스를 사용해야 하고이 인터페이스를 함수형 인터페이스라고 한다.함수형 인터페이스(functional interface)단 하나의 추상 메서드가 선언된 인터페이스를 함수형 인터페이스라고 한다.그리고 람다식은 함수형 인터페이스의 추상 메서드의 구현 부분을 짧게 표현한 것이 함수형 인터페이스의 추상 메서드를 통해서 타입을 추론할 수 있기 때문에 타입의 생략이 가능하다.@FunctionalInterface이 어노테이션을 인터페이스에 붙여주면 두 개 이상의 추상 메서드가 선언되지 않도록 컴파일러가 체크해줘서 실수를 줄일 수 있다. 참고https://inpa.tistory.com/entry/%E2%98%95-Lambda-Expression#
백엔드




