1. K : Keep, 현재 만족하고 있는 부분 또는 계속 이어갔으면 하는 부분
2. P : Problem, 개선이 필요한 부분
3. T : Try, 문제에 대한 해결책 또는 다음에 시도해 볼 것

1. K

   (1) 프로젝트의 결과를 위해 목적지향적으로 개발했던 점을 가장 칭찬하고 싶다. 일정 테이블을 타이트하게 만들어서 개발할 때는 힘들었지만, 마지막에는 오히려 수월하게 마무리할 수 있어서 좋았다. 힘든 2주였지만, 많은 것을 배우고 느끼게 돼서 뿌듯하다.

 

   (2) 이전 토이프로젝트에서 QueryDSL을 한번 사용해보았던 경험을 바탕으로 이번 프로젝트에서는 보다 복잡한 쿼리를 QueryDSL로 성공적으로 작성하였다. 야놀자 현업에 계신 분께서 실제 현업에서도 이렇게 작성한다는 말에 뿌듯했다. 한번에 바로 짠하고 작성된 것은 아니지만, 이것저것 찾아보고 시행착오도 겪어보면서 QueryDSL에 대해 좀 더 깊게 이해하게 되었다.

 

   (3) 동시성 처리에 도전해 보았다. 이전 토이프로젝트에서는 QueryDSL이었다면, 이번에는 동시성처리에 도전해보았다. 처음에는 데이터소스를 분리해서 MySQL의 named lock을 이용해서 구현했지만, 이후에 KPT기간에 실제 현업에서 많이 사용하는 Redis의 redisson을 적용하는 것으로 리팩토링 함으로써 커머스 서비스의 구조를 엿볼 수 있었다. 사실, 야놀자 멘토님께서는 모든 객실을 야놀자에서 관리하지 않기 때문에 실제 야놀자는 동시성 처리는 하지 않는다고 들었습니다...


2. P

   (1) 테스트 코드 작성을 소홀히 하였다. 핑계겠지만, 타이트한 일정에 기능 구현하기 바빴던 터라 테스트 코드 작성을 소홀히 했다. 중간중간에 테스트 코드 작성이 미흡했을 때의 한계를 느꼈다. 당연히 될 거라고 생각해서 테스트 코드를 작성안했는데, 그 부분에서 오류가 나자 테스트 코드의 중요성을 다시 한번 느낄 수 있었다.

 

   (2) 코드 리뷰를 소홀히 했다. 개인적으로 코드 리뷰 하는 것을 재밌어 하는데, 시간이 부족했다(핑계다ㅜㅜ). 그래도 KPT 기간에 팀원들과 제대로 해보자고 해서, 조금이라도 맛을 보며 재밌게 해볼 수 있었다.


3. T

   (1) 파이널 프로젝트도 성공적으로 마무리 하자!

   (2) 테스트 코드 작성과 코드 리뷰를 꼼꼼히 해보자!

   (3) 파이널 프로젝트 하면서 새로운 기술을 도입하게 되더라도, 겁먹지 말고 도전적으로 공부하자!


 미니도 성공적으로 완료했다ㅎㅎㅎ. 그리고 무엇보다 지금 팀원들과 2주간 하면서 정들었는데, 바뀌어야 한다는 것이 너무 아쉽다...ㅜㅜ 덕분에 너무너무 즐겁게 프로젝트하게 되어서 팀원들 모두에게 감사하다. 마지막 파이널 프로젝트도 화이팅해서 마무리 잘 해보자!!!

1. K : Keep, 현재 만족하고 있는 부분 또는 계속 이어갔으면 하는 부분
2. P : Problem, 개선이 필요한 부분
3. T : Try, 문제에 대한 해결책 또는 다음에 시도해 볼 것

1. K

   (1) 모르는 기술에 대해 두려워하지 말자. 이번 프로젝트에 처음으로 Spring Security와 QueryDSL을 써보았다. 처음하다보니 두렵고 막막했는데, 하나하나씩 천천히 배우다 보면 별 것 없다는 것을 깨달았다. 새로운 것에 두려움을 버리자.

 

   (2) 2차때 가장 많이 들었던 생각은 '서비스도 생각하자' 였다. 기획서대로 구현이 아닌, 서비스적으로 고민해보고 설계를 진행했다. Entity 설계를 많이 바꿔서 나름 서비스 답게 구현했다. 내가 만드는 기능이 서비스에 어떻게 사용될지를 생각해보면서 구현하니 더 재밌었다.

 

   (3) 팀원들에게 도움이 되는 팀원이 되자. 팀원들이 물어볼 때, 친절하고 자세히 알려주자. 팀원과의 좋은 관계는 팀의 힘과 직결된다.

 

   (4) 다른 사람 코드를 보며 배우자. 더 깔끔하고 좋은 코드를 보며 따라하고 성장하자.

 

   (5) 2회차 이후에 적용해보려했던 Issue와 Code Review를 적용했다!


2. P

   (1) 핑계겠지만... 시간이 부족해서 Swagger를 사용해보지 못했다. 3차 끝나고도 바로 미니라 다음 프로젝트에 Swagger를 적용해볼 수 있을지는 모르겠지만, 이후에 습득해보자

 

   (2) Security에서 refreshToken을 적용하지 못했다. Redis를 이용해서 구현하고 싶었는데, 시간이 부족해서 적용하지 못했다. 보안이 취약한 서비스임.

 

   (3) Github commit을 좀 더 체계적으로 할 필요가 있다. commit 관리는 변경 관리이다. 지금은 필요성을 못느끼더라도 나중을 위해서 commit 관리를 하자.


3. T

   (1) Github Project를 사용해서 프로젝트 관리를 해보고 싶다. 미니프로젝트가 프론트엔드 사람과 같이하는 나름 중형의 프로젝트이므로 적용하면 좋을 것 같다!

   

   (2) Code Review를 좀 더 적극적으로 해보고 싶다. 같은 팀원들이 소극적으로 하기에 같이 소극적으로 되는 것 같다. 팀원들과 같이 얘기해서 적극적으로 하고 싶다.


작성하면서 보니까, 잘한점이 많아서 뿌듯했다!!! 미니 프로젝트도 화이팅!!!

1. K : Keep, 현재 만족하고 있는 부분 또는 계속 이어갔으면 하는 부분
2. P : Problem, 개선이 필요한 부분
3. T : Try, 문제에 대한 해결책 또는 다음에 시도해 볼 것

1. K

   (1) 이전 프로젝트를 진행한 후에 개선해야 할 점을 미리 문서로 정리한 후, 프로젝트 시작하기 전에 팀원들과 다같이 공유한 부분이 좋았다.

 

   (2) Java 및 Git commit 컨벤션 등 룰을 정해서, 마치 '한 사람'이 프로젝트를 구현한 것 처럼 보이게 해서 프로젝트에 짜임새를 더하였다.

 

   (3) RFP를 보고 구현 전에 사전 설계를 진행해서, 프로젝트의 변경 가능성을 최소화 하였습니다.


2. P

   (1) RFP에만 충실하기 위해 구현을 하였다. 물론 기획자가 아닌 개발자지만, '서비스가 어떻게 흘러갈까?' '다른 서비스는 어떻게 제공될까?' 등 구현하려는 서비스 자체의 흐름을 더 꼼꼼하게 파악할 필요가 있었다고 생각한다. 우리 팀은 서비스 자체에 집중하기 보다는 RFP에 나와있는 사항들을 빠짐없이 구현하는데에 더 초점을 두었던 것 같다. 다음 프로젝트 때는 서비스 자체부터 꼼꼼하게 파악하기 시작함으로써 더 완성도 있는 서비스를 구현하고 싶다.

 

   (2) 구현한 API를 github의 wiki에 저장해두었다. 그런데 만약 api가 조금 바뀐다던가 응답 구조가 바뀔 경우, 이 wiki를 모두 수정해야한다는 단점이 있었다. 이후에 알아보니 스웨거라는 툴을 이용해서 자동으로 api 명세서를 만들어주는 툴이 있었다. 다음에는 이를 적용시키면 더 좋을 것 같다.


3. T

   (1) Github의 issue를 사용해보고 싶다 issue를 통해 feature 브랜치를 만들어서 관리하고 싶다. PR을 보내면 자동으로 이슈와 브랜치가 닫히는 기능을 추가하면 프로젝트 작업 관리에 더 도움이 될 것 같다.

 

   (2) Github에서 코드리뷰를 더 꼼꼼하게 하면 좋을 것 같다. 지금까지는 merge하기 전에 줌에서 간단히 자기가 구현하거나 수정한 부분을 화면 공유해서 보여주고, merge를 했다. 그런데, 이렇게 화면 공유로 빠르게 지나가는 것보다 github에서 코드를 꼼꼼히 보면서 코드리뷰를 하면 더 좋을 것 같다.


이전 프로젝트보다 더 체계적으로 진행한 것 같아서 좋다. 이 다음 3차 프로젝트에서도 이 회고를 바탕으로 더욱 체계적인 프로젝트를 만들고 싶다.

설명 순서는 다음과 같습니다.

1. Stream이란
2. Stream의 특징
3. Stream의 장단점

1. Stream이란

   - 많은 수의 데이터를 다룰 때, 컬렉션이나 배열에 데이터를 담고 for문 또는 Iterator를 이용해서 코드를 작성했음. 그렇지만 이러한 방식은 가독성, 재사용성이 떨어지고, 데이터 소스마다 다른 방식으로 다뤄야하는 단점이 있음

   - 예를 들어, List를 정렬할 때는 Collections.sort()를 사용하고 배열을 정렬할 때는 Arrays.sort()를 사용해야 함

   - Stream은 데이터 소스가 무엇이던 간에 같은 방식으로 다룰 수 있도록 데이터 소스를 추상화하였고, 데이터를 다루는데 자주 사용되는 메소드들을 정의해 놓았음


2. Stream의 특징

   - 스트림은 데이터 소스를 변경하지 않음

      * 데이터 소스로 부터 데이터를 읽기만할 뿐, 원본 데이터 소스를 변경하지 않음

   - 스트림은 일회용임

      * 스트림은 한번 사용하면 닫혀서 다시 사용할 수 없음

   - 스트림은 작업을 내부 반복으로 처리함

      * 내부 반복이란 뜻은 반복문을 메소드 내부에 숨길 수 있다는 뜻임

      * 반복문을 숨김으로써 가독성이 높아짐

   - 지연된 연산

      * 스트림의 진행 순서는 생성 -> 중간연산 -> 최종연산으로 됨

      * 지연된 연산이란 최종연산이 수행되기 전까지 중간연산이 수행되지 않는다는 것

      * 최종연산이 수행되어야 비로소 스트림의 요소들이 중간연산을 거쳐 최종연산에서 소모됨

   - 병렬 처리가 쉽다

      * 병렬 처리를 하려면 단지 parellel() 메서드를 호출만 하면됨(다만 병렬처리가 항상 빠른 결과를 얻는 것은 아님)


3. Stream의 장단점

   - 장점

      ① 가독성이 높다

      ② 재사용성이 높다

      ③ 데이터소스에 관계없이 같은 방식으로 다룰 수 있다

      ④ 병렬 처리가 쉽다

   - 단점

      ① for문보다 성능이 대부분 떨어진다

         * 하지만, 복잡한 로직을 계산하는 비용이 순회하는 비용보다 크고 데이터의 양이 많다면 Stream의 성능은 for문과 비슷해지거나 더 좋아짐


Stream에 대해 알아볼 수 있었습니다.

 

'Java' 카테고리의 다른 글

JAR, WAR, EAR  (1) 2023.09.18
Garbage Collector  (0) 2023.09.15
JVM  (0) 2023.09.14
Abstract Class vs Interface  (0) 2023.09.13
[Java의 정석] Static이란?  (0) 2023.04.07

설명 순서는 다음과 같습니다.

1. JAR
2. WAR
3. EAR

1. JAR

   - Java ARchive의 약자

   - zip파일은 하나의 파일 안에 여러 개의 파일이 압축되어 들어있는 파일이며, 이러한 형태를 아카이브(Archive)라고함. 하나의 파일로 여러 파일을 편리하게 다루고 보관할 수 있고, 압축 덕분에 용량 또한 작아지게 되는 장점이 있음

   - JAR란 자바 애플리케이션을 실행하기 위한 여러 파일(클래스 파일, 이미지 파일, 소리 파일 등)을 압축한 파일

   - JAR는 그 자체로 실행할 수 있고, 다른 애플리케이션의 클래스 경로에 JAR를 추가해서 안에 있는 코드를 사용할 수 있게 할 수 있음

   - 이 때 포함된 파일들은 .class로 컴파일이 되는데, 그래서 윈도우에서 만든 jar파일을 맥에서도 사용할 수 있음


2. WAR

   - Web application ARchive의 약자

   - 자바의 웹 어플리케이션으로 이용되는 클래스 파일(servlet), 설정 파일(xml), JSP나 HTML, JAR 형식의 라이브러리 등이 압축되어 있는 파일

   - 웹 어플리케이션을 배포하기 위한 여러 파일을 압축한 파일

   - WAR는 단독으로 실행되지 않고, 웹 서버인 WAS에 의해 실행됨


3. EAR

   - Enterprise ARchive의 약자

   - Java Enterprise Edition에 쓰이는 파일 형식

   - 웹 애플리케이션 단위를 넘어서 실제 서버 배포를 위한 파일

   - 엔터프라이즈 애플리케이션에 필요한 JAR나 WAR 같은 모든 파일을 포함한 파일


JAR, WAR, EAR에 대해 알아볼 수 있었습니다.

'Java' 카테고리의 다른 글

Stream  (0) 2023.09.19
Garbage Collector  (0) 2023.09.15
JVM  (0) 2023.09.14
Abstract Class vs Interface  (0) 2023.09.13
[Java의 정석] Static이란?  (0) 2023.04.07

설명 순서는 다음과 같습니다.

1. Garbage Collector란?
2. Garbage Collection 대상
3. Garbage Collector의 청소 방식(Mark And Sweep)
4. Heap 메모리 구조
5. Garbage Collection 과정

1. Garbage Collector란?

   - 자바의 메모리 관리를 해주는 역할

   - JVM의 Heap 영역에 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체를 모아 제거해줌

   - C / C++ 에서는 Garbage Collector가 없어서 프로그래머가 수동으로 메모리 할당과 해제를 해줘야 했음. 그렇지만, Java에서는 Garbage Collector가 메모리 관리를 해주므로 오로지 개발에만 집중할 수 있다는 장점이 있음

   - 그렇지만, Garbage Collector가 메모리를 관리하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생되는 문제점이 있음. 이를 전문 용어로 Stop The World라고 하고 이 시간을 줄일수록 성능이 올라가며 이런 최적화 작업을 GC 튜닝이라고 함


2. Garbage Collection 대상

   - Garbage Collector는 ① Heap에서 사용되지 않는 객체를 찾고, ② 지움

   - 사용되지 않는 객체란 해당 객체가 어디에서도 참조되지 않는 객체를 의미함(Unreachable 상태)

   - 위 그림처럼 어디에서도 참조되지 않는 Heap의 객체를 Garbage Collector는 제거해야할 메모리로 인식하고 지워줌


3. Garbage Collector의 청소 방식(Mark And Sweep)

   - Mark And Sweep 방식은 Garbage Collector의 기초적인 청소 방식임

   - 과정

      ① Mark : Root Space로부터 그래프 순회를 통해 어떤 객체가 참조되고 있는지 찾아서 마킹함(청소 대상 마킹)

         * Root Space : Heap 메모리 영역을 참조하는 Method Area, static 변수, stack 등이 됨. 이 root부터 찾아가며 heap에 있는 객체가 참조되고 있는지 판별

      ② Sweep : 참조되고 있지 않은 객체(청소 대상)을 Heap에서 제거함(청소함)

      ③ Compact : 청소 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축


4. Heap 메모리 구조

   - Heap은 동적으로 생성된 객체들이 저장되는 공간으로, 가비지 컬렉션의 대상이 됨

   - Heap은 2가지 전제로 설계되었음

      ① 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다

      ② 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다

      -> 객체는 대부분 일회성이고, 메모리에 오래 남아있는 경우는 드물다는 뜻

   - 이러한 특성을 이용해서 Heap영역을 Young과 Old로 나눔

      ① Young

         * 새로 생성된 객체가 할당되는 영역

         * 대부분의 객체가 금방 Unreachable이 되기 때문에, Young에서 생성되었다가 사라짐

         * Young에 대한 가바지 컬렉션을 Minor GC라고 부름

      ② Old

         * Young에서 Reachable 상태를 유지해서 살아남은 객체가 복사되는 영역

         * Young보다 크게 할당되며, 그만큼 가바지 컬렉션은 적게 발생함

         * Old에 대한 가비지 컬렉션을 Major GC라고 부름

   - Young은 효율적은 GC를 위해 다시 Eden, Survivor0, Survivor1로 나뉨

      ① Eden : new를 통해 새로 생성된 객체가 위치. GC후 살아남은 객체들은 Survivor로 보냄

      ② Survivor 0/1 : 최소 1번의 GC 이상 살아남은 객체가 위치. Survivor 0/1 둘 중 하나는 꼭 비어있어야 함


5. Garbage Collection 과정

   (1) 처음 생성된 객체는 Young의 Eden 영역에 위치

   (2) 객체가 계속 생성되어 Eden이 꽉차게 되면 Minor GC가 실행

   (3) Mark를 통해 Reachable 객체를 탐색

   (4) Eden에서 살아남은 객체는 Survivor 0 또는 1 영역으로 이동

   (5) Eden 영역에서 Unreachable 객체의 메모리를 해제(청소)

   (6) 살아남은 객체들의 age값이 1 증가

   (7) Eden 영역이 다시 가득 차면 Minor GC를 실행하고(Survivor영역도 같이 청소), 이제 살아남은 객체를 모두 Survivor 1로 보냄

   (8) 이후 객체의 age가 임계값에 도달하면 이 객체를 Old로 보냄

   (9) Old 영역이 가득 차면 Major GC를 실행

   - Old 영역은 Young 영역에 비해 크기가 크기 때문에 GC가 10배 이상의 시간이 소요됨

   - 이렇게 Major GC가 일어날 때 성능이 나빠지는데, 이 때 성능을 높이기 위해 가비지 컬렉션 알고리즘이 발전함


Garbage Collector에 대해 알아볼 수 있었습니다.

'Java' 카테고리의 다른 글

Stream  (0) 2023.09.19
JAR, WAR, EAR  (1) 2023.09.18
JVM  (0) 2023.09.14
Abstract Class vs Interface  (0) 2023.09.13
[Java의 정석] Static이란?  (0) 2023.04.07

설명 순서는 다음과 같습니다.

1. JDK, JRE, JVM이란
2. JVM의 장점
3. JVM 구조

1. JDK, JRE, JVM이란

   - JDK : Java Debelopment Kit의 약자로, 자바로 개발할 때 필요한 도구들의 모음

   - JRE : Java Runtime Environment의 약자로, 자바 프로그램을 실행시킬 때 필요한 환경의 모음

   - JVM : Java Virtual Machine의 약자로, 자바 프로그램을 실행시키는 핵심적인 기기

   - Java 프로그램 실행 순서

      ① Java 소스코드(.java 파일)을 Java Compiler(javac)가 바이트코드인 .class파일로 컴파일

      ② JVM이 바이트코드를 기계어로 변환

      ③ 기계어 실행

 


2. JVM의 장점

   - 다른 언어는 작성한 코드를 특정 OS에서 컴파일 하면, 해당 OS에서만 실행가능한 프로그램이 만들어짐. 다른 OS에서는 실행이 불가능

   - 그렇지만, Java의 경우 어느 OS에서 컴파일된 바이트코드는 JVM만 있다면 다른 OS에서 실행이 가능함. 그래서 'Write Once Read Anywhere'라는 장점이 있음

   - 소스코드 -> 바이트코드 -> 기계어, 이렇게 되므로 두번 컴파일을 하기 때문에 속도의 문제가 발생하는데, JIT 컴파일러 방식으로 개선되어 속도에서도 개선을 이룸

   - JIT 컴파일러는 같은 코드를 매번 해석하지 않고, 실행할 때 컴파일을 하면서 해당 코드를 캐싱함


3. JVM 구조

   - 클래스 로더 : .class 파일을 필요에 따라 동적으로 로드하고 엮어서 JVM의 메모리 영역인 Runtime Data Areas에 배치함

   - 실행 엔진 : 런타임 데이터 영역에 배치된 바이트 코드를 명령어 단위로 읽어서 실행

   - 런타임 데이터 영역 : 프로그램을 실행할 때 사용되는 데이터들을 적재하는 영역

      ① 메서드 영역 : 바이트 코드(.class)를 처음 메모리에 올릴 때 초기화되는 대상을 저장하기 위한 공간. 이 영역은 클래스가 로드되고 종료될 때까지 저장됨. 이 영역에는 class 초기 정보 또는 static 변수나 메서드가 저장됨

      ② 힙 영역 : 런타임시 동적으로 생성되는 객체, 배열이 저장되는 공간

         * 만약 힙에 생성된 객체가 참조되지 않는다면, 이것을 쓰레기로 취급하고 Garbage Collector를 통해 제거됨

      ③ 스택 영역 : 메서드 호출마다 각각의 스택 프레임이 생성되고 이 안에서 사용되는 값을 임시로 저장하는 공간

      ④ PC 레지스터 : 현재 수행중인 JVM 명령어 주소를 저장하는 공간


JVM에 대해 알아볼 수 있었습니다.

'Java' 카테고리의 다른 글

JAR, WAR, EAR  (1) 2023.09.18
Garbage Collector  (0) 2023.09.15
Abstract Class vs Interface  (0) 2023.09.13
[Java의 정석] Static이란?  (0) 2023.04.07
[Java의 정석] JVM이란?  (0) 2023.04.01
1. 프로젝트 전체 구조
2. 내가 맡은 역할
3. 새롭게 알게된 점
4. 보완할 점

1. 프로젝트 전체 구조

   - MVC 패턴 : 요구 사항에 맞게 MVC 패턴으로 분리했다. Java 프로젝트지만, Spring에서 처럼 도메인에 따라 controller, service, repository와 dto, domain 패키지를 두어서 분리함.


2. 내가 맡은 역할

   - 여행 입력 기능 구현 : 여행(여행지 이름, 시작 날짜, 끝 날짜)를 입력받고 저장하는 기능을 구현하는 역할. 사용자에게 입력받은 dto를 서비스에서 받고, repository에서 파일로 저장하는 흐름을 구현하는 것.

TripService
TripRepository

   - 객체를 JSON or CSV 파일로 저장하는 기능과 JSON or CSV 파일을 객체로 바꾸는 기능 구현 : jackson과 opencsv 라이브러리를 이용해서 구현.

객체 -> JSON or CSV 파일
JSON or CSV 파일 -> 객체


3. 새롭게 알게된 점

   - builder 패턴 : 이전에는 알고만 있었고 직접 사용해본적은 없었는데, 이번 프로젝트 때 처음으로 적용해보았음. 유연성과 가독성을 확보할 수 있는 장점이 있음


4. 보완할 점

   - 첫 팀 프로젝트이다 보니, 어색하기도 하고 진행이 매끄럽지만은 않았던 것 같다. 그래도, 이제는 소통이 원할히 되는만큼 다음 프로젝트가 더 기대가 된다.

   - Git과 Github를 잘 알고 다룰줄 알아야 한다. 지금은 기본적인 명령만 쓰지만, 다음 프로젝트에서는 단 하나라도 다른 명령문을 써보자.

   - Github 커밋 메시지를 컨벤션에 따라 통일하는 것이 좋을 것 같다.

   - Java 코드 스타일 또한 컨벤션에 따라 통일하는 것이 좋을 것 같다.


한 주 동안 프로젝트하느라 고생 많았다!!!

+ Recent posts