├── IDE └── intelij.md ├── README.md ├── algorithm └── algorithm.md ├── architecture ├── api_gateway.md ├── architecture.md ├── circuit_breaker.md ├── clean_architecture.md ├── continuous_deploy.md ├── monolithic.md ├── msa.md └── service_discovery.md ├── cheatsheet ├── sk_py.md └── sk_sql.md ├── database └── database.md ├── git └── gitflow.md ├── interview └── interview.md ├── java ├── annotations.md ├── data_structure.md ├── java.md └── libraries.md ├── js └── js.md ├── network └── network.md ├── oop └── oop.md ├── os ├── os.md └── os_med_test.md ├── rails └── tip.md └── spring ├── spring.md └── spring_intermediate.md /IDE/intelij.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ### 1. inteliJ 단축키 4 | https://opennote46.tistory.com/58 5 | 1. import 6 | > option + enter 7 | 8 | ### 2. 설정 9 | 1. 코드 수정 후 자동 반영 10 | https://dololak.tistory.com/575 11 | https://jojoldu.tistory.com/48 -> freemarker 정적 리소스 리로드 12 | 13 | 참고 14 | ~~~ 15 | spring.freemarker.cache=false 16 | spring.devtools.livereload.port=3000 17 | ~~~ 18 | 19 | 2. 부트스트랩 / 제이쿼리 적용하기 20 | ~~~html 21 | 22 | 23 | 24 | 25 | ~~~ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Dons wiki-dic 2 | 3 | 1. JAVA Language 4 | 5 | (1) **자바 언어 기본** 6 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/java/java.md) 7 | 8 | (2) 라이브러리 9 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/java/libraries.md) 10 | 11 | (3) 기타 자료구조 12 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/java/data_structure.md) 13 | 14 | (4) 어노테이션 15 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/java/annotations.md) 16 | 17 | 2. Spring Framework 18 | 19 | (1) 스프링 기본 20 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/spring/spring.md) 21 | 22 | (2) 프로젝트에서 쓰인 spring 23 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/spring/spring_intermediate.md) 24 | 25 | 3. OOP와 디자인 패턴 26 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/oop/oop.md) 27 | 28 | 4. 데이터베이스 29 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/database/database.md) 30 | 31 | 5. 네트워크 32 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/network/network.md) 33 | 34 | 6. OS 35 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/os/os.md) 36 | 37 | 7. GitFlow 38 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/git/gitflow.md) 39 | 40 | 8. Architecture 41 | 42 | #### 1) MSA 43 | - Monolithic Architecture 44 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/monolithic.md) 45 | 46 | - MSA 47 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/msa.md) 48 | 49 | - Circuit Breaker 50 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/circuit_breaker.md) 51 | 52 | - API Gateway 53 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/api_gateway.md) 54 | 55 | - Service Discovery 56 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/service_discovery.md) 57 | 58 | #### 2) Clean Architecture 59 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/clean_architecture.md) 60 | 61 | #### 3) 무중단 배포 62 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/architecture/continuous_deploy.md) 63 | 64 | 9. 자바스크립트 65 | [상세 보기](https://github.com/Donsworkout/techInterview/blob/master/js/js.md) -------------------------------------------------------------------------------- /algorithm/algorithm.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 알고리즘 4 | 5 | ## 자료구조 6 | 7 | ### 이진 탐색 트리 (Binary Search Tree) 8 | 9 | https://ratsgo.github.io/data%20structure&algorithm/2017/10/22/bst/ 10 | 11 | ### 힙 정렬 12 | 13 | https://zeddios.tistory.com/56 14 | 15 | -------------------------------------------------------------------------------- /architecture/api_gateway.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | 4 | ## API gateway 5 | > 앞단에서, 여러 API 서버의 end-point를 단일화 해 주는 것 6 | 7 | 8 | ### API gateway의 장점 9 | 1. 여러 마이크로서비스 라우팅 10 | > 각각 서비스마다 호출해줄 주소를 통일해 준다. 11 | 12 | 2. 보안 13 | > API gateway의 주소는 public 으로 열어두고, 각 서비스들은 private 으로 외부에서의 접근은 막는다. 14 | 15 | 3. 각 서비스의 공통 로직을 처리해 준다 16 | > 로깅, CORS, 모니터링, 인증 등 공통 기능을 API Gateway의 필터 기능으로 해결할 수 있다. 17 | -------------------------------------------------------------------------------- /architecture/architecture.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. MSA 4 | > 참고 : https://alwayspr.tistory.com/19 5 | 1. Monolithic 아키텍쳐 6 | 7 | 2. Microservice 아키텍쳐 8 | 9 | 3. Circuit Breaker 10 | 11 | 12 | 4. API Gateway 13 | 14 | 15 | 5. Service Discovery 16 | 17 | 18 | ## 2. Clean Architecture 19 | 20 | ## 3. 무중단 배포와 로드밸런서 21 | -------------------------------------------------------------------------------- /architecture/circuit_breaker.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Circuit Breaker 4 | > 직역하면 누전차단기라는 뜻 5 | 6 | 예를 들어 MSA 구조에서, 어떠한 요청을 보냈을때 요청을 받은 서버가 마비 상태라면 7 | 요청한 서버에도 장애가 전파될 수 있다. 이를 장애 전파라고 한다. 8 | 9 | **서킷 브레이커는 이러한 장애 전파를 막는다** 10 | 서킷 브레이커는 비정상을 감지하여 장애가 발생한 서비스로의 요청을 막고 11 | 다시 요청한 곳으로 응답을 돌려보낸다. 12 | 13 | Circuit Breaker의 에러 핸들링 방식은 구현체마다 다르지만, 14 | 대표적으로는 Default 값을 설정해 주는 것이다. 15 | 16 | 한 부분의 서비스가 마비되었는데도 미리 정의된 Default 값을 노출시켜 17 | 자연스러운 에러 처리가 가능하다. 18 | -------------------------------------------------------------------------------- /architecture/clean_architecture.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Clean Architecture 4 | https://medium.com/@younghyun/%ED%81%B4%EB%A6%B0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%8C%ED%8A%B81-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-vs-%EB%8F%84%EB%A9%94%EC%9D%B8-236c7008ac83 5 | 6 | ### 1. 프레임워크로부터 독립해라 7 | > 아키텍쳐는 프레임워크에 의존하면 안된다! 최소한의 노력으로 새로운 프레임워크를 적용할 수 있어야 한다. 8 | 9 | #### Comment 10 | 프레임워크가 주는 생산성과 클린 아키텍쳐와의 균형을 잘 찾는 것이 중요한것 같다. 11 | AOP, DI 같은 경우도 사실은 스프링 프레임워크의 기능인데, 이를 쓰지않고 개발하는 것은 곧 바퀴를 새로 만드는 꼴이 된다. 과유불급. 12 | 13 | ### 2. 세부 구현으로부터 독립해라 14 | > SW 시스템의 핵심 모듈은 UI, 데이터베이스, 프레임워크, 라이브러리 등의 변경에 영향을 받지 않아야 한다. 15 | 16 | 17 | ### 3. 내부 레이어는 상위/외부 레이어의 어떤 것도 알아서는 안된다 18 | > 그 결과로 모든 의존성은 내부 레이어를 향해야 한다. 19 | (보통 DB에 가까운 LEVEL) 20 | 21 | ### 4. Entity 와 Use Case 22 | > 아키텍처에 대해서 얘기할 때 이것들이 존재하는 레이어가 가장 중요하다. 23 | 그리고 이 레이어는 세부 (구현) 사항을 담고 있는 레이어의 변경에 영향을 받지 않아야 한다. 24 | 25 | ### 5. Adapter 와 Converter 의 필요성 26 | Adapter 와 Converter 는 각각의 레이어가 협력을 할 때 레이어 내부의 세부 사항이 다른 레이어로 전파되지 않도록 하는 역할을 한다. 27 | 28 | 즉, 각각의 레이어가 필요로 하는 그들만의 데이터 모델을 외부 레이어로 전달하거나 외부 레이어에서 받아 올 때 외부 또는 내부 레이어의 데이터 모델의 격리를 위해서는 외부 레이어의 데이터 모델을 내부 레이어의 데이어 모델로 변환하는 그리고, 내부 레이어의 데이터 모델을 외부 레이어의 데이터 모델로 변환하는 기능을 담당하는 녀석들이 필요한데 이 두 녀석이 Adapter 와 Converter 이다. 29 | 30 | 이를 통해 얻을 수 있는 것은 적절한 의존성이다. 이 둘이 레이어간 완충재 역할을 한다고 보면 되겠다. 그리고 이 녀석들을 통해 DDD에서 말하는 Bounded Context 가 좋은 형태로 구현된다고 볼 수도 있겠다. 31 | 32 | #### Comment 33 | 데이터 전달 시, 맘대로 계층을 뛰어넘지 말고 한 계층씩 거쳐 가라는 말인것 같다. 34 | 35 | ### 6. 의존성 역전의 법칙 (DIP) 36 | http://wonwoo.ml/index.php/post/1717 37 | > 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다. 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다. 38 | 39 | ***???? 무슨 말이지?*** 40 | 41 | 예를들어, 42 | 어떤 바이트 데이터를 읽어와 특정한 데이터로 결과를 반환하는 것으로 이야기를 해보자. 43 | 44 | **고수준 모듈** 45 | - 바이트 데이터를 읽어 와서 특정한 데이터로 결과를 반환한다. 46 | 47 | **저수준 모듈** 48 | - 파일에서 바이트 데이터를 읽어 온다. 49 | - Json 데이터로 결과를 반환한다. 50 | 51 | 52 | 의존성 역전의 법칙을 어기는 코드의 예 53 | ~~~java 54 | public class Response { 55 | 56 | private JsonConverter jsonConverter = new JsonConverter(); 57 | 58 | // 고수준 모듈 (JsonConverter 에게 의존하고 있다) 59 | public String response() { 60 | byte[] bytes = null; 61 | return jsonConverter.convert(bytes); 62 | } 63 | 64 | } 65 | 66 | // 저수준 모듈 67 | class JsonConverter { 68 | 69 | public String convert(byte[] bytes) { 70 | //json ... 71 | return "json"; 72 | } 73 | } 74 | 75 | ~~~ 76 | 77 | 이를 해결한 예 (인터페이스 사용) 78 | ~~~java 79 | public class Response { 80 | 81 | private Converter converter = new JsonConverter(); 82 | 83 | // JsonConverter 가 아니라 Converter에 의존한다 84 | public String response() { 85 | byte[] bytes = null; 86 | return converter.convert(bytes); 87 | } 88 | 89 | } 90 | 91 | interface Converter { 92 | 93 | String convert(byte[] bytes); 94 | 95 | } 96 | 97 | class JsonConverter implements Converter { 98 | 99 | @Override 100 | public String convert(byte[] bytes) { 101 | //json ... 102 | return "json"; 103 | } 104 | } 105 | ~~~ 106 | 107 | 여기다가 DI까지 추가하면 금상첨화 (스프링) 108 | 109 | ### 7. 경계(boundary) 간의 데이터 전달 110 | 레이어간 객체를 전달하는 것에는 항상 주의를 기울여야 한다. 전달되는 객체는 항상 고립되어야 함. 즉, 언어의 기본 형태를 사용해야 하고 감춰진 의존성을 가지면 안됨. 111 | 112 | ORM(Object Relational Mapping)같은 경우 데이터 레이어에 정의된 ORM 객체가 전 레이어를 돌아다닌다. -------------------------------------------------------------------------------- /architecture/continuous_deploy.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 배경지식 4 | ### 1. L4 스위치 5 | > L4 스위치 = 포트 + 로드밸런싱 6 | 7 | 로드밸런싱은, 동일한 역할을 수행하는 서버 그룹을 VIP (Virtual IP) 를 통해 관리하며, 8 | 서버로 향하는 트래픽을 일단 VIP를 가진 L4 스위치로 수신한 후 Round Robin 등 분배정책에 따라 적절한 서버에 분배해 주는 것을 말합니다. (부하 분산) 9 | 10 | * VIP (Virtual IP) 는 서버그룹의 대표 IP라 할 수 있습니다. 11 | 12 | #### 1.1 왜 L4 스위치를 사용하는가? 13 | 1. 부하를 분산하기 위해 14 | 예를 들어 한 서버에 웹 서비스(80)를 하는 서버가 있는데, 부하 문제로 서버를 증설해야 하는 상황이라고 가정하자. 15 | 그러나 서버를 여러대 두고 IP를 하나 더 할당하게 되면, 기본 서비스와 IP가 달라지는 문제가 발생한다. 16 | 17 | 이 때 사용하는 것이 L4장비의 **VIP** 이다. 18 | 19 | 예를 들어 기존에 사용하는 서버의 IP가 `128.x.x.1` 이라고 가정하자, 20 | 1. 이 IP를 L4장비의 VIP로 할당한다. `128.x.x.1 / 80` 21 | 2. 기존 서버에는 128.x.x.2 와 새로운 서버에는 128.x.x.3을 할당한다. 22 | 3. L4장비에 로드밸런싱이 가능하게 세팅합니다. 23 | 4. 그러면 이제 128.x.x.1 로 요청하는 응답에 대해서 L4가 처리하게 됨 24 | 5. hash, round-robin 방식 등을 이용하여 로드를 분산한다. 25 | 26 | 2. fail-over 기능 (실패 대비) 27 | L4에 fail over 기능을 이용 할 경우, 에러가 발생한 인스턴스 대신 다른 인스턴스가 대답하게 할 수 있다. 28 | 29 | ## 무중단 배포 30 | https://perfectacle.github.io/2019/04/21/non-stop-deployment/ 31 | 32 | ### 개요 33 | 먼저 우리가 일반적으로 생각하는 배포는 아래와 같다. 34 | 35 | 1. 새롭게 배포할 내용이 있으니, 포트 충돌 방지를 위하여 기존 운영되는 서버를 다운시킨다. 36 | 2. **[공사중]** 배너를 건다 37 | 3. 새롭게 배포될 서버를 띄운다. 38 | 39 | 개인 홈페이지 정도는 괜찮지만 핵심 서비스에 배포 때문에 새로운 서버를 띄우는데 오랜 시간이 걸린다면, 심각한 손실이 발생할 수 있다. (예를 들어 결제) 40 | 이를 방지하기 위해 무중단 배포가 필요하다. 41 | 42 | ### 무중단 배포의 조건 43 | - 두대 이상의 서버로 서비스해야 한다. (하나를 내리면 하나는 살아있어야 하기 때문) 44 | - 비용을 위해 배포시에만 두개의 서버를 운용해도 된다. 45 | 46 | ### 무중단 배포의 종류 47 | ### 1. Rolling Deployment 48 | ![elb-basic](https://user-images.githubusercontent.com/26560119/63570930-9de28300-c5b9-11e9-9d17-3a29d374c455.png) 49 | - 로드밸런서도 두개를 운용하는게 좋음 50 | 51 | 1. 배포할 서버 한대 (서버1) 를 로드밸런서에서 제외시킨다. 52 | 2. 제외된 서버1 에 배포한다. 53 | 3. 서버1의 배포가 끝나면, 다시 로드밸런서에 넣는다. 54 | 4. 배포가 아직 되지 않은 서버2를 로드밸런서에서 제외시킨다. 55 | 5. 제외된 서버2 에 배포한다. 56 | 6. 서버2의 배포가 끝나면, 다시 로드밸런서에 넣는다. 57 | 58 | 단점은 배포 시간이 오래걸리고, 59 | 누구는 이전 버전을 서비스 받고 누구는 다음 버전을 서비스받는 문제가 생긴다. 60 | 61 | ### 2. Blue / Green Deployment 62 | ![thumbs](https://user-images.githubusercontent.com/26560119/63571233-98d20380-c5ba-11e9-8142-76f762ce3feb.jpg) 63 | 64 | > Blue 는 실제 프로덕션 환경을 말하고, Green 은 새롭게 배포할 환경(alpha) 이다. 65 | 이 둘을 항상 띄워놓고 배포할때 사용하는것을 말한다. 66 | 67 | ### 장점 68 | 1. 새롭게 배포할 환경에만 배포하면 되기 때문에 속도가 빠르다. 69 | 70 | 2. 언제나 Green 환경도 준비되어 있으므로 만약에 잘못된 버전으로 배포했을 경우에 빠른 롤백이 가능하다. 71 | 72 | 3. 언제나 Green 환경이 준비되어있어야 하므로 비용도 두 배로 든다. 73 | 74 | ### 순서 75 | 76 | 1. 우선 기존의 서버그룹과 같은 서버그룹을 하나 더 만든다. 서버 버전도 동일하고 모든게 똑같지만 로드밸런서에 연결되어 있지는 않다. 77 | 78 | ![블루그린_여러그룹_1](https://user-images.githubusercontent.com/26560119/63576805-eef97380-c5c7-11e9-8287-02592a011485.png) 79 | 80 | 2. 복사한 서버그룹 내부의 서버들을 1.0.2버전으로 업데이트 진행한다. 여전히 로드밸런서에는 연결되어 있지 않다. 81 | 82 | ![블루그린_여러그룹_2](https://user-images.githubusercontent.com/26560119/63576807-ef920a00-c5c7-11e9-9767-200c819aea60.png) 83 | 84 | 3. 업데이트가 진행된 복사한 서버그룹을 로드밸런서에 연결한다. 85 | 86 | ![블루그린_여러그룹_3](https://user-images.githubusercontent.com/26560119/63576808-ef920a00-c5c7-11e9-829c-c55dc1a67463.png) 87 | 88 | 4. 기존에 존재하던 1.0.1버전 서버그룹을 로드밸런서에서 연결 해제한다. 이 상태부터 사용자들은 온전하게 1.0.2버전을 이용할 수 있게 된다. 89 | 90 | ![블루그린_여러그룹_4](https://user-images.githubusercontent.com/26560119/63577134-b4dca180-c5c8-11e9-86a9-1f0279483df3.png) 91 | 92 | 93 | - 업데이트를 진행하는 도중에도 서버의 수는 그대로 유지되기 때문에 기존 사용되던 그대로 서버를 업데이트 하면 된다. 따라서 부하가 걸릴 위험이 사라진다. 94 | 95 | - 만약 1.0.2버전에 문제가 있으면 아직 없애지 않은 1.0.1 버전의 서버그룹으로 로드밸런서를 연결해 주기만 하면 된다. 이후에 1.0.2 버전의 문제를 해결하고 다시 로드밸런서만 옮겨서 연결하면 된다. 96 | 97 | #### 회고 98 | 그러나 이같은 경우는 클라우드 환경이나 서버를 융통성있게 운용하는 환경에서나 가능하다. 물리 서버를 설치해놓고 평소에 그린환경의 서버그룹을 쓰지 않는다면 자원이 아깝다. (테스트서버를 그린환경으로 해놓고 쓰는 등의 효율적 운용이 필요) 99 | 100 | ### 2.1 Ngnix 를 이용한 무중단 배포 101 | ![997A14375A73F91D04](https://user-images.githubusercontent.com/26560119/64922359-70c86f80-d809-11e9-91d4-91ab359ae6c7.png) 102 | 103 | > Ngnix 는 스레드와 프로세스를 사용하는 Apache 와 달리, 비동기 이벤트 호출 방식을 사용하는 오픈소스 웹 서버 104 | 105 | 위의 그림에는 Ngnix가 리버스 프록시 (대리인) 서버로 사용되고 있다. 106 | 107 | 하나의 EC2 혹은 리눅스 서버에 Nginx 1대 와 스프링부트 jar를 2대 를 사용 108 | Nginx는 80(http), 443(https) 포트를 할당하고 109 | 스프링부트1은 8081포트로, 110 | 스프링부트2는 8082포트로 실행한다. 111 | 112 | 1. Ngnix 가 두 WAS 중, 하나에만 연결 시켜놓음 113 | 2. 연결되지 않은 놈을 배포 시키고 `ngnix reload` 를 통해, ngnix 가 바라보는 방향 변경 114 | 115 | 116 | ## 아키텍쳐 기본 117 | ### 1. NGINX 118 | > Apache 의 개선 버전의 **웹서버** 로 , 스레드 방식이 아닌 비동기 방식으로 처리한다. 119 | 가볍고 빠르며, 로드밸런싱과 리버스 프록시 기능도 지원한다. 120 | 121 | - 그러나 Health Check 결과에 따른 융통성 있는 로드밸런싱 불가 122 | 123 | ### 2. HAProxy 124 | > 하드웨어 로드밸런서 대체 위해 나온 고가용성 리버스 프록시 기반 SW 로드밸런서 125 | 126 | - 특정 API 에 대해 헬스체크 하고 문제가 있으면 포워딩 안함 (서킷 브레이킹 방식 제공) -------------------------------------------------------------------------------- /architecture/monolithic.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. Monolithic Architecture 4 | > 일반적인 서비스 구조, MSA가 아니면 monolithic이다. 5 | 6 | 예를들어, 모든 기능들이 뭉쳐있는 하나의 어플리케이션 서버와 데이터베이스로 이루어진 형태 7 | - 만약 아래와 같은 정도의 기능이라면 MSA로 굳이 나눌 필요는 없다. 8 | 9 | - 그러나 아래와 같이 수평적으로 어플리케이션이 확장되면서 많은 이슈가 생긴다. 10 | 11 | 12 | 그 문제들은 아래와 같다. 13 | 14 | ### 1. 빌드 시간이 길어진다 15 | 작은 규모에서는 문제 되지 않던 빌드 시간이 길어진다. 16 | 현재 CI / CD (지속적 통합 / 지속적 배포) 가 강조되면서 빌드/배포 시간을 줄이는 것이 중요하다. 17 | 18 | ### 2. 개발 언어에 종속적이다 19 | 상황에 맞게 유연한 기술을 사용하지 못함 20 | 개발 언어로 자바를 선택했으면 전체 서비스가 자바로 이루어 져야 함 21 | 22 | ### 3. 선택적 확장이 불가하다 23 | 원하는 서비스만 확장이 불가능하다. 24 | 한 부분의 기능만 업데이트 해도 되는데 전체를 빌드하고 배포해야 하는 상황이 발생한다. 25 | 26 | ### 4. 하나의 서비스가 모든 서비스에 영향을 준다. 27 | 한개 서비스에 트래픽이 몰리면, 서버 전체가 마비될 수 있는 상황이 발생할 수 있다. 28 | -------------------------------------------------------------------------------- /architecture/msa.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Microservice Architecture는 무엇일까 4 | > **정의 : 마이크로 서비스 아키텍처 스타일은 단일 응용 프로그램을 나누어 작은 서비스의 조합으로 구축하는 방법이다.** 5 | 6 | > 수평적으로 방대한 서비스를 단위 기능별로 분리하여 구조를 설계한 형태, 7 | 일반적으로 마이크로 서비스 간 [REST](https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html) 방식으로 호출한다. 8 | 9 | 10 | 11 | ## MSA의 장점 12 | ### 1. 빌드와 테스트 시간을 감소시킬 수 있다. 13 | CI / CD 에 적합하게, 짧은 시간 안에 원하는 서비스를 수정 및 배포할 수 있다. 14 | 15 | ### 2. [폴리글랏 프로그래밍](https://www.sciencetimes.co.kr/?news=%ED%8F%B4%EB%A6%AC%EA%B8%80%EB%9E%8F-%EC%84%A0%ED%83%9D%EC%9D%98-%EB%AC%B8%EC%A0%9C-%EC%95%84%EB%8B%88%EB%8B%A4)이 가능해진다 16 | 상황에 맞게 기술 스택을 유연하게 적용할 수 있다. 17 | 예를 들어 TPS(시간당 트랜잭션)가 높고, 읽기 작업이 많은 서비스에는 Node + Redis로 구현을 하고, 18 | 트랜잭션 및 안정성이 중요한 서비스에는 Spring + RDB를 적용할 수 있다. 19 | 20 | ### 3. 선택적이고 탄력적인 확장이 가능해 진다 21 | 필요한 서비스만을 scale out 할 수 있다. 22 | 23 | ### 4. 하나의 서비스에 문제가 생겨도, 다른 서비스에 문제를 발생시키지 않는다. 24 | 그러나 문제가 생긴 서비스를 호출 시에 문제가 발생할 수 있는데, 이는 [Circuit Breaker](https://github.com/Donsworkout/techInterview/blob/master/architecture/circuit_breaker.md)로 해결한다. 25 | 26 | 27 | ## MSA 구조 채택 시 문제점 28 | ### 1. **Performance issue** 가 있다 29 | Monololic에서 메서드로 서비스를 호출했다면, MSA는 http 통신을 이용하여 호출을 하게 된다. 30 | 따라서 Network IO에 관련한 오버헤드가 발생할 수 있다. 31 | 32 | ### 2. 데이터베이스 트랜잭션이 불편하다 33 | Spring에서는 [@Transactional](https://taetaetae.github.io/2017/01/08/transactional-setting-and-property/)이라는 어노테이션으로 트랜잭션 처리가 가능함. 34 | 그러나 서비스가 각각으로 나뉘게 되면, global 트랜잭션이 불편할 수 있다. 35 | 따라서 MSA에서는 서비스 간에 Global 트랜잭션이 일어나는 상황보다는, 36 | Local 트랜잭션이 주로 이루어지게 경계를 나누고 37 | 불가피하게 서비스 간에 트랜잭션이 필요하면 트랜잭션 로직을 추가해야 한다. 38 | 39 | > 이에 대한 해결책으로, 보상 트랜잭션이 많이 쓰인다. 예를들어 상품 재고 감소 API 가 있다면, 상품 증가 API 를 만들어서 해당 트랜잭션 실패시 보상 트랜잭션인 상품 증가 API를 호출하는 것이다. 그러나 이러한 상황은 아예 안 만드는게 좋다. 40 | 41 | ### 3. local sites 의 관리가 불편하다 42 | 로깅, 모니터링, 배포, 테스트, 클라우드 환경에서의 관리들이 다소 불편할 수 있다. 43 | 테스트 / 빌드 / 배포 자동화에는 jenkins, 44 | 모니터링에는 springboot admin 등을 사용한다. 45 | 46 | ## 서비스간의 상호작용 47 | 동기 : REST/JSON 48 | 비동기 : [MQ](https://www.icelancer.com/2016/12/message-queue.html) 49 | -------------------------------------------------------------------------------- /architecture/service_discovery.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Service Discovery 4 | > 보통 대용량 트래픽이 예상되는 서버에서는 가용성을 위해 5 | 하나의 인스턴스에 하나의 서비스를 올려두는 것이 아니라 6 | 두개 이상의 인스턴스에 동일한 서비스를 올린 후, 한쪽에서 문제가 발생하면 다른 인스턴스를 통해 로직을 수행한다. 7 | 8 | 이처럼 클라우드 환경의 Auto Scaling 이나, 확장 등의 이유로 9 | 인스턴스가 생성, 소멸 될 시 IP 주소가 변경되기도 한다. 10 | 따라서 비즈니스 로직은 이 상태를 알 수 없다. 11 | 만약 Auto Scaling으로 인스턴스가 하나 생성되었더라도 12 | 로직은 이를 스스로 알아차리고 생성된 인스턴스에 트래픽을 분산시킬 수 없다. 13 | 14 | 따라서 이러한 변화를 감지하는 역할이 **Service Discovery** 다. 15 | 16 | Service Discovery가 어떻게 진행되는지 살펴 본다면 아래와 같다. 17 | 18 | 1. 각 서비스가 실행(호출) 될 때, Service Registry에 IP,port 등의 서버 정보를 저장한다. 19 | 2. Client에서 HTTP 요청이 들어온다. 20 | 3. Router은 정해진 시간마다 주기적으로 Service Registry에 가서 서비스들의 서버 정보를 가져온다. 21 | 4. 요청이 들어온 URL을 해석해, Service Registry에서 가져온 서버 정보를 토대로 알맞는 서버로 라우팅을 시킴 22 | 23 | > 요청할때마다 Service Registry를 통해 서버 정보를 가져오지는 않고, 캐싱을 이용함 24 | 그리고 Service Registry는 주기적으로 인스턴스에 ping를 보내서 서버의 생존여부를 파악하고, 25 | 죽어있으면 Service Registry에서 정보를 지운다. 26 | 27 | 그리고 Service Registry에서 IP, PORT를 이미 가지고 있기 때문에 28 | 요청이 들어올 시, DNS 서버에 다녀오지 않아서 성능상에 이점이 있다. 29 | -------------------------------------------------------------------------------- /cheatsheet/sk_py.md: -------------------------------------------------------------------------------- 1 | ~~~python 2 | # 리스트 딥 카피 3 | import copy 4 | 5 | arr_org = [1, 2, 3, 4] 6 | arr_cpy = copy.deepcopy(arr_org) 7 | 8 | # 이차원 리스트 9 | n = 5 10 | arr = [[0] * n for _ in range(n)] 11 | 12 | # 리스트 소팅 (원래 기준) 13 | lst = ['conor', 'mcgregor', 'sexy', 'boy'] 14 | sorted_lst = sorted(lst) 15 | 16 | lst.sort() 17 | 18 | # 리스트 소팅 (리버스) 19 | lst.sort(reverse=True) 20 | 21 | # 리스트 소팅 (길이 기준대로) 22 | lst.sort(key=len) 23 | 24 | # 리스트 인덱스 알아보기 25 | lst.index('mcgregor') 26 | 27 | # 리스트 특정 원소 갯수 체크 28 | lst.count('sexy') 29 | 30 | # 리스트 특정 인덱스 삽입 31 | lst.insert(1, 'cain') 32 | 33 | # 리스트 특정 인덱스에 대해 삭제 34 | del lst[1] 35 | 36 | # 리스트 특정 값 삭제 37 | lst.remove('boy') 38 | 39 | # 딕셔너리 키, val, 아이템 순회 40 | dic = {'a': 10, 'b': 9, 'c': 9} 41 | 42 | for key in dic: 43 | print(key) 44 | 45 | for val in dic.values(): 46 | print(val) 47 | 48 | for key, val in dic.items(): 49 | print(key, val) 50 | 51 | # 딕셔너리 삭제 52 | del dic['a'] 53 | 54 | ~~~ -------------------------------------------------------------------------------- /cheatsheet/sk_sql.md: -------------------------------------------------------------------------------- 1 | 2 | # SQL 치트시트 3 | 4 | ## 빈출 SQL 5 | 6 | ### SELECT 기본 7 | 8 | #### 1. 정렬 9 | 10 | ~~~sql 11 | SELECT * FROM ANIMAL_INS 12 | ORDER BY ANIMAL_ID ASC 13 | 14 | SELECT * FROM ANIMAL_INS 15 | ORDER BY ANIMAL_ID DESC 16 | ~~~ 17 | 18 | #### 2. 정렬 (복수기준) 19 | 20 | ~~~sql 21 | SELECT * FROM ANIMAL_INS 22 | ORDER BY NAME ASC, DATETIME DESC 23 | ~~~ 24 | 25 | #### 3. 부정 26 | 27 | ~~~sql 28 | SELECT * FROM ANIMAL_INS 29 | WHERE INTAKE_CONDITION != "Aged" 30 | ~~~ 31 | 32 | #### 4. LIMIT 33 | 34 | ~~~sql 35 | SELECT NAME FROM ANIMAL_INS 36 | ORDER BY DATETIME LIMIT 1; 37 | ~~~ 38 | 39 | #### 5. MAX, MIN, COUNT 40 | 41 | ~~~sql 42 | SELECT MAX(DATETIME) FROM ANIMAL_INS 43 | 44 | SELECT MIN(DATETIME) FROM ANIMAL_INS 45 | 46 | SELECT COUNT(ANIMAL_ID) AS count FROM ANIMAL_INS 47 | ~~~ 48 | 49 | #### 6. DISTINCT 50 | 51 | ~~~sql 52 | # aggregation 과 DISTINCT 혼용 53 | SELECT COUNT(DISTINCT(NAME)) AS count FROM ANIMAL_INS 54 | 55 | # 그냥 중복 제거 56 | SELECT DISTINCT NAME FROM ANIMAL_INS 57 | ~~~ 58 | 59 | ### GROUP BY 60 | 61 | #### 1. 그룹 별 COUNT 62 | 63 | ~~~sql 64 | SELECT ANIMAL_TYPE, COUNT(ANIMAL_ID) AS count 65 | FROM ANIMAL_INS 66 | GROUP BY ANIMAL_TYPE 67 | ~~~ 68 | 69 | #### 2. 그룹 별 COUNT with 조건 70 | 71 | ~~~sql 72 | SELECT NAME, COUNT(*) AS COUNT 73 | FROM ANIMAL_INS 74 | WHERE NAME IS NOT NULL 75 | GROUP BY NAME 76 | HAVING COUNT(NAME) > 1 77 | ~~~ 78 | 79 | ### JOIN 80 | 81 | #### 1. LEFT JOIN 82 | 83 | > 왼쪽 테이블 엔트리 다 갖고감 84 | 85 | ~~~sql 86 | SELECT o.ANIMAL_ID, o.NAME 87 | FROM ANIMAL_OUTS AS o 88 | LEFT JOIN ANIMAL_INS AS i 89 | ON o.ANIMAL_ID = i.ANIMAL_ID 90 | WHERE i.ANIMAL_ID IS NULL; 91 | ~~~ 92 | 93 | #### 2. INNER JOIN with selection 94 | 95 | ~~~sql 96 | SELECT i.ANIMAL_ID, i.NAME FROM ANIMAL_INS as i 97 | INNER JOIN ANIMAL_OUTS as o 98 | ON i.ANIMAL_ID = o.ANIMAL_ID 99 | WHERE i.DATETIME > o.DATETIME 100 | ~~~ 101 | 102 | #### 3. 조인 응용 / LIKE / Where 복수조건 103 | 104 | ~~~sql 105 | SELECT i.ANIMAL_ID, i.ANIMAL_TYPE, i.NAME 106 | FROM ANIMAL_INS AS i 107 | INNER JOIN ANIMAL_OUTS AS o ON i.ANIMAL_ID = o.ANIMAL_ID 108 | WHERE i.SEX_UPON_INTAKE LIKE "Intact%" 109 | AND NOT o.SEX_UPON_OUTCOME LIKE "Intact%" 110 | ORDER BY i.ANIMAL_ID 111 | ~~~ 112 | 113 | -------------------------------------------------------------------------------- /database/database.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. 데이터베이스 풀 (pool) 4 | - 어플리케이션 스레드에서 DB Transaction 을 위해서는 DB connection이 필요하다. 5 | - Connection pool은 미리 Connection 을 여러개 만들어 놓고 스레드에게 빌려준다. 6 | - Thread는 Connection을 사용하고 사용 후 Pool 에 반환한다. 7 | - Connection이 없다면 대기하고, 가다렸다가 Connection 객체를 받는다. 8 | 9 | ![db-connection-02](https://user-images.githubusercontent.com/26560119/58722096-8f992680-8411-11e9-9276-5837b9e207f8.png) 10 | 11 | 12 | #### 장점 13 | - 매 연결마다 Connection 객체 생성 소멸 안해도 된다. 14 | - 그러므로 DB 접근 시간이 단축된다. 15 | - Connection 수를 제한하여 메모리와 DB 부하를 줄일 수 있다. 16 | 17 | > Thread Pool 도 있다. Thread 수가 Connection 보다 많은게 좋다고 한다. 18 | 모든 스레드가 디비 커넥션을 할 것이 아니기 때문. 19 | 스레드를 많이 사용할수록 당연히 메모리는 많이 먹는다. 20 | 21 | ## 2. 트랜잭션 (Transaction) 22 | > 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위 (로직 단위) 23 | 24 | - Commit : 트랜잭션이 완전히 끝남, 데이터베이스가 일관된 상태로 돌아옴 25 | - Rollback : 트랜잭션 중 결함이 발생하면 트랜잭션 전체를 취소함 (Undo) 26 | 27 | ### 트랜잭션의 성질 (ACID) 28 | 1) 원자성 (Atomicity) ALL OR NOTING 29 | 트랜잭션의 모든 연산들은 수행 완료되거나 아니면 아예 안한 상태를 보장해야 한다. 30 | 31 | 2) 일관성 (Consistency) 32 | 트랜잭션 완료 후에도 DB는 일관된 상태를 유지해야 한다 33 | 34 | 3) 독립성 (Isolation) 35 | 하나의 트랜잭션이 실행하는 도중 변경한 데이터는, 해당 트랜잭션이 완료되기 전까지 다른 트랜잭션이 참조하지 못한다. 36 | 37 | 4. 지속성 (Durability) 38 | 성공적으로 수행된 트랜잭션은 영원히 반영된다. 39 | 40 | ### 트랜잭션의 상태 41 | ![transaction-status](https://user-images.githubusercontent.com/26560119/58741705-3ce25d80-8457-11e9-8989-de963c642cce.png) 42 | 43 | - Commit / Aborted (undo) 상태가 DB가 보장하는 상태 44 | 45 | ### Isolation Level 46 | http://www.dbguide.net/db.db?cmd=view&boardUid=148216&boardConfigUid=9&boardIdx=138&boardStep=1 47 | 48 | 1. Read Uncommitted 49 | 커밋도 안했는데, 바뀐 값을 읽어올 수 있다. (UPDATE 직후) 50 | 51 | > 발생 문제점 : Dirty Read, Non-Repeatable Read, Phantom Read 52 | 53 | 2. Read Committed (READ 두번 할떄 한번 하고 그 중간에 UPDATE 간섭가능) 54 | 커밋이 완료된 데이터만 읽을 수 있다. 중간 간섭하는 TX2 가 커밋 되기 전에 읽으면 예전 데이터로 읽고, 커밋 후면 바뀐 데이터로 읽어온다. 55 | Dirty Read가 발생할 여지는 없으나, Read Uncommitted 수준보다 동시 처리 성능은 떨어진다. 56 | > 발생 문제점 : Non-Repeatable Read, Phantom Read 57 | 58 | 3. Repeatable Read 59 | 한번 읽은 값은 계속 그대로 읽는다. 60 | 트랜잭션이 완료되기 전까지는 처음느낌 그대로 ㄱ (다른 트랜잭션이 수정 불가) 61 | 한번 읽혀졌던 데이터에 걸린 LOCK 이 계속 유지된다. 62 | 63 | > 발생 문제점 : Phantom Read 64 | 65 | 66 | 4. Serializable 67 | Strict 2PL 같은거 68 | 69 | ### 격리성 관련 문제점 70 | 71 | 1. Dirty Read 72 | 커밋도 안된거 읽어서 롤백되면 당황하는 거 73 | 74 | 2. Non-Repeatable Read (리드하고 있는데 남이 와서 커밋해버림) 75 | 트랜잭션 내에서 다시 읽었는데 값이 바뀌어있음 (수정 / 삭제) 76 | 77 | 3. Phantom Read 78 | 없던 데이터가 생겨있음 (삽입) 트랜잭션 도중 새로운 레코드가 삽입될 수 있어서 그럼 79 | 80 | ## 3. 스키마 란? 81 | - 데이터베이스 구조 / 제약조건에 관해 전반적으로 명시해 놓은 것 82 | 83 | ![191456384EA616D008](https://user-images.githubusercontent.com/26560119/58744543-57303180-847f-11e9-885f-9cb844acd51c.jpeg) 84 | 85 | - 외부 스키마는 OFFSET 처럼 물리적 위치까지 나와있는 것. 86 | 87 | ## 4. 조인 88 | - 아래 링크 너무 굳 89 | https://github.com/WeareSoft/tech-interview/blob/master/contents/db.md#join 90 | 91 | 92 | ## 5. 파티셔닝 93 | - 내가 쓴 링크 94 | https://github.com/Donsworkout/cs_wiki/blob/master/database_system/22_a_parallel_dbms.md 95 | - 남이 쓴 링크 96 | https://github.com/WeareSoft/tech-interview/blob/master/contents/db.md#%ED%8C%8C%ED%8B%B0%EC%85%94%EB%8B%9D 97 | 98 | ### 5-1) 샤딩 심화 99 | 100 | - 샤딩은 **수평 파티셔닝** 이다. 101 | - JOIN 이나 일관성 유지 등에 약하다. 102 | - MongoDB는 데이터베이스 자체에서 샤딩 기능을 내장한다. 103 | - 데이터베이스 위치 (site) 는 추상화 되어 있다. 104 | - 당연히 물리적 샤딩 하면, 네트워크 IO 발생 105 | - Cubrid, Gizzard 는 미들웨어 샤딩 플랫폼 106 | 107 | ### 5-2) 샤딩의 단점, 주의사항 108 | 109 | - **두 개 이상의 샤드** (site) 에 대한 JOIN 연산을 할 수 없다. 110 | - auto increment (serial) 등은 샤드별로 달라질 수 있다. 111 | - shard key column 값은 update하면 안 된다(delete - insert 사용). 112 | - 하나의 트랜잭션에서 **두 개 이상** 의 샤드에 접근할 수 없다. 113 | - Scale up 을 항상 고려하자 114 | - 해시샤딩은 나중에 스케일업 시 해시함수 교체 비용 많이 든다 115 | - **샤드키를 잘 정하자** RANGE PARTITIONING 이면, 그 범위를 잘 정할것, 랜덤키도 가능 116 | 117 | ### 5-3) 샤딩 참고 118 | - 논리적 샤딩도 가능 119 | - UUID(universally unique identifier) 가 중요 120 | 121 | ## 6. 인덱스 122 | > 사용 이유 : READ FAST (검색 > 변경) 123 | 124 | - 인덱스 엔트리는 서치키로 레코드 서브셋을 찾고, 맨 아래 리프 노드에는 rid가 있다. 125 | 126 | ### 6.1. 데이터 엔트리의 정보 (리프 노드) 127 | ALTERNATIVE 1 : 128 | search key k를 포함하는 실제 데이터 레코드 (인덱스 파일 구성) 129 | heap, sorted 파일 구조 대신 쓰기도 한다. 130 | 131 | ALTERNATIVE 2 : 132 | : 133 | 유일키일 경우 하나의 rid Primary, Unique index 라고 부른다 134 | 135 | ALTERNATIVE 3 : 136 | : 137 | 유일키가 아닐경우 rid list Secondary index 라고 부른다. 138 | 139 | ### 6.2. 인덱스를 이용할때 최적의 조건 140 | - 테이블당 하나만 생성할 수 있는 clustered 인덱스가 가장 빠르긴 함 (실제 인접) 141 | - unclustered 도 rid 찾는것은 빠르지만, range query 일때 여러 페이지에서 레코드를 메모리로 올려야 해서 I/O cost 가 크다. 142 | - 풀스캔은 차라리 인덱스 안쓰는게 낫다. 143 | - 풀스캔 할 떄 인덱스는 버킷 찾으면 따로따로 디스크 블락을 불러 과도한 disk IO가 생김 144 | - 인덱스 안타는 풀스캔은 Multi Block IO를 한다. 한꺼번에 블락 끌어옴 145 | - B + tree 라면 fanout 을 높이는게 포인트, 따라서 인덱스 sKey 압축하기도 함 146 | - 따라서 복합 서치키도 너무 길면 fanout 줄여서 트리 업데이트가 더 자주 일어남 147 | - COUNT MIN AVG 등 직계함수는 INDEX ONLY 도 가능하다. 148 | 149 | ### 6.3. **Query workload** 150 | - 어떤 relation 이 쿼리에 참여했는지 151 | - 어떤 attr을 검색했는지 152 | - 어떤 attr이 select 나 join 연산에 참여했고, 해당 연산이 얼마나 selective 한지 153 | - 어떤 업데이트 연산을 사용했고, 어떤 attr에 영향을 미치는지 154 | 155 | ### 6.4. 어떤 인덱스를 쓸 것인가 156 | https://github.com/Donsworkout/cs_wiki/blob/master/database_system/8_overview_of_storage_and_indexing.md#7-%EC%96%B4%EB%96%A4-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%A5%BC-%EC%93%B8%EC%A7%80-%EC%84%A0%ED%83%9D%ED%95%98%EA%B8%B0\ 157 | 158 | ## 7. Slow Query 대처 159 | > **슬로우 쿼리 로그** 는 시간이 오래 걸렸던 쿼리를 로그로 저장해 놓은 것. FULL SCAN 이나 잘못된 인덱스 사용으로 발생하기도 한다. 160 | 161 | ### 7.1. Slow Query 원인 162 | - **쿼리 실행 계획** 체크하여 확인, 인덱스 잘못 쓴 경우가 많음 163 | - 서치키 or 복합서치키 prefix에 where 절 처음 조건이 오지는 않는지 체크 164 | - 버퍼 풀 사이즈가 너무 작지는 않은지 165 | - 어쨋든 로그 분석을 잘하자 166 | 167 | ## 8. Query Optimization 168 | 일단은 평소에 DB에 관련된 최적화가 이루어져있는지 체크하는 과정이 중요하다. 가장 간단하게 할 수 있는 Query 최적화가 있습니다. 169 | 170 | 그리고 평소에 Query 실행계획을 보면서 Query를 적용하기 전에 테스트하는 과정이 필요합니다. 171 | 172 | https://github.com/Donsworkout/cs_wiki/blob/master/database_system/12_overview_of_query_evaluation.md 173 | 174 | ### 8.1. 쿼리 평가 175 | > 쿼리 옵티마이저는 차선의 선택을 한다. 메타데이터 업데이트가 실시간은 아니기 때문 176 | 177 | ### 8.2. 쿼리 최적화의 interests 178 | 1) 주어진 Query에서 어떤 plan 들이 고려되어야 하는가? 179 | 2) 각 Plan의 Cost는 얼마인지 ? 180 | 181 | ### 8.3. 쿼리 최적화 과정 182 | 1. Access Path 선택 183 | - full scan or index! 184 | - prefix 조건을 확인해 보세요! 185 | 186 | 2. 관계연산을 위한 알고리즘 선택 187 | - Selection 188 | - RF 10% 100 페이지 10000 튜플일때, 클러스터는 100 IO 지만. 189 | unclustered 일때는 10000 IO 발생가능, FULL SCAN 요망 190 | - 이런식으로 selection 어떻게 할지 생각함 191 | - unclustered 라면 RF 5% 이상은 풀스캔이 낫다. 192 | 193 | - Projection 194 | - 여기서 가장 비싼 연산은 DISTINCT 195 | - 소팅이나 해시 기반으로 중복을 제거한다. 196 | 197 | - Join 198 | - https://github.com/Donsworkout/cs_wiki/blob/master/database_system/12_overview_of_query_evaluation.md#3-3-join 199 | - 인덱스를 이용하여 조인하면 더 빠름 200 | - 둘이 다 비교 안해도 조인칼럼 인덱스를 통해 튜플 찾으면 되니깐 .. 201 | - left deep plan 이 파이프라이닝을 이용하여 더 빠름 202 | 203 | 204 | ## 9. NoSQL - 주로 MongoDB vs RDBMS 205 | ### 9.1 MongoDB 의 특장점 206 | - Schema less (데이터의 유연한 변화) 207 | - Read, Write 성능 뛰어남 208 | - RDBMS의 한계, Scale Out 구조를 채택 209 | - **Scale out 시 AutoSharding을 지원한다.** 210 | - Json 구조, 가독성 211 | - WiredTiger storage 엔진은 트랜잭션 ACID 보장 212 | - JSON으로 바로 넣을 수 있다. 213 | - **삽입 부하가 큰 곳에 적절** 214 | - 위치 기반 데이터에 좋음 (Geospatial) 215 | 216 | ### 9.1.1 쓰면 좋을 상황 217 | - 데이터량이 많이 확장을 고려해야 하거나 218 | - RW 퍼포먼스가 좋아야 하거나 219 | - 요구사항에 따라 스키마가 변할 가능성이 많을때 220 | 221 | 222 | ### 9.2 MongoDB 단점 223 | - Document 자체 용량이 row 보다 큼 (3배가량) 224 | - 따라서 메모리 버퍼에도 올라가는 document가 적어 Disk I/O가 커진다. 225 | - Clustered Index 가 없다 226 | - ACID 등 안정성이 RDBMS보다 떨어짐 227 | 228 | ### 9.3 MongoDB 의 지형 인덱스와 쿼리 229 | - 위치 기반 기능이 존재한다. 230 | - MongoDB는 geosparial query를 지원한다. 231 | - Geospatial Indexes 를 지원한다. 232 | 233 | **지형 인덱스를 사용한 billRun** 234 | https://enzine.tistory.com/m/entry/MongoDB%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%A0-%EB%95%8C 235 | 236 | ### 실제 사례 연구: 결제 시스템 237 | - MongoDB를 데이터 저장소로 사용한 오픈소스 결제 솔루션인 BillRun 238 | 239 | - BillRun 시스템은 매월 5억건 이상의 통화 기록을 처리하는 이스라엘에서 가장 빠르게 성장하는 통신망 기업에서 사용되었다. 240 | 241 | - 스키마가 없는 설계 덕분에 새로운 통화 기록 유형을 시스템에 빠르게 도입할 수 있었다. 242 | 243 | - 새 필드 추가를 제한하거나 데이터 증가를 제한하지 않고도 BillRun은 이미 실무에서 테이블당 수 TB에 달하는 데이터를 다루었다. 244 | 245 | - 샤딩을 통해 예산을 다 쓰지 않고도 선형적, 수적인 증가가 가능했다. 246 | 247 | - 초당 2천건 이상의 통화 기록을 삽입할 때처럼 MongoDB 아키텍쳐는 삽입 부하가 높은 시스템에 적합하다. 248 | 249 | - 위치 기반 기능을 활용해 사용자의 사용 패턴을 분석하고 어디에 통신망 인프라를 투자할 것인지 정했다. -------------------------------------------------------------------------------- /git/gitflow.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 0. Git 기본 4 | 1. -u 키워드는 브랜치 명시 안하면, git push 할때 master로 푸시 하고 5 | 그냥 pull 할때는 origin의 master를 fetch하고 merge 하라는 뜻이다. 6 | ~~~ 7 | git push -u origin master 8 | ~~~ 9 | 10 | 2. **fetch** 11 | fetch는 merge 하지 않고 그냥 변경사항만 확인할때 사용한다. 12 | 이 때 가져온 최신 커밋 이력은 이름 없는 브랜치로 로컬에 저장됨 13 | 이 브랜치는 **'FETCH_HEAD'** 의 이름으로 체크아웃도 가능 14 | 15 | 16 | 이 상태에서 원격 저장소의 내용을 로컬 저장소의 'master'에 통합하고 싶은 경우에는, 17 | 'FETCH_HEAD' 브랜치를 merge 하거나 다시 pull 을 실행하면 됨 18 | 19 | 20 | 21 | ## 1. Clone 과 Fork의 차이 22 | > Fork와 Clone은 거의 동일, Fork는 깃허브에서 제공하는 기능이다. 23 | 단순 저장소 복제 -> **clone** 24 | 공동작업 기여 -> **fork** 25 | ### 1.1 Clone 26 | > 저장소를 그대로 복사하는 것 27 | ~~~ 28 | git clone '클론 주소' 29 | ~~~ 30 | ### 1.2 Fork 31 | fork 된 저장소는 clone 된 저장소와는 다르게 실제 오리지날 프로젝트와 연결되어있는 것이 가장 큰 차이점이다. 32 | 본인의 저장소에서 해당 프로젝트에 수정을 가하고 Pull Request 를 하였고, 33 | 오리지날 프로젝트가 이를 수용했을 경우 기여가 가능하다. 34 | 오리지널 저장소 변경 시, fork된 나의 저장소에도 변경이 적용된다. 35 | 36 | #### 일반적인 워크플로우 37 | 1. 오리지널 저장소 fork 38 | 2. fork 한 개인 repo에서 local로 clone 39 | 3. 로컬 repo에서 오리지널 저장소를 remote로 추가 40 | ~~~ 41 | git remote add upstream 'original.repo' 42 | ~~~ 43 | 44 | 출처: https://pasudo123.tistory.com/287 [unique individuals] 45 | 46 | ## 2. Merge / Rebase 47 | ### 2.1 Merge 48 | > 같은 조상(Base) 과 가장 말단 커밋 두개를 이용하는 3-way Merge 49 | 50 | 51 | 52 | ### 2.2 Rebase 53 | > 깨끗한 히스토리를 만들기 위해 사용한다. (브랜치 정리 등) 54 | 1. 원래의 상태 55 | 56 | 57 | 2. 아래 스크립트 실행 58 | ~~~ 59 | $ git checkout issue3 60 | Switched to branch 'issue3' 61 | $ git rebase master 62 | First, rewinding head to replay your work on top of it... 63 | Applying: pull 설명을 추가 64 | Using index info to reconstruct a base tree... 65 | :13: new blank line at EOF. 66 | + 67 | warning: 1 line adds whitespace errors. 68 | Falling back to patching base and 3-way merge... 69 | Auto-merging myfile.txt 70 | CONFLICT (content): Merge conflict in myfile.txt 71 | Failed to merge in the changes. 72 | Patch failed at 0001 pull 설명을 추가 73 | 74 | When you have resolved this problem run "git rebase --continue". 75 | If you would prefer to skip this patch, instead run "git rebase --skip". 76 | To check out the original branch and stop rebasing run "git rebase --abort". 77 | ~~~ 78 | 79 | 이때 커밋 한단계 한단계를 merge 하며 conflict를 해결하게 된다. 80 | rebase 의 경우 충돌 부분을 수정 한 후에는 commit 이 아니라 rebase 명령에 --continue 옵션을 지정하여 실행해야 함 81 | 82 | ~~~ 83 | $ git add myfile.txt 84 | $ git rebase --continue 85 | Applying: pull 설명을 추가 86 | ~~~ 87 | 88 | 89 | 90 | 이렇게 하면 issue3 브랜치는 rebase되어 master과 같은 베이스를 갖게 된다. 91 | 그리고 나서 아직 issue3가 적용되지 않은 master 브랜치를 fast forward 해준다! 92 | 93 | ~~~ 94 | $ git checkout master 95 | Switched to branch 'master' 96 | $ git merge issue3 97 | Updating 8f7aa27..96a0ff0 98 | Fast-forward 99 | myfile.txt | 1 + 100 | 1 files changed, 1 insertions(+), 0 deletions(-) 101 | ~~~ 102 | 103 | 104 | 105 | ## 3. Pull Request 106 | > 당장 merge가 아니라 책임자가 확인후 merge 하는 것, 코드리뷰나 push 권한이 없는 경우에 사용 107 | 108 | ### 일반적인 진행 순서 109 | 1. Upstream Repository를 자신의 저장소로 Fork(Origin Repository)한다. 110 | 111 | 2. Fork 한 Repository를 clone 하여 로컬에 내려받는다. 112 | 113 | 3. 로컬 repo에서 오리지널 저장소를 remote로 추가 114 | ~~~ 115 | git remote add upstream 'original.repo' 116 | ~~~ 117 | 118 | 4. 로컬에 개발용 branch(feature/xx 등) 를 만들고 작업 진행한다. 119 | 120 | 5. 작업 완료시 remote의 origin에 알맞는 branch에 push 한다. 121 | 122 | 6. 깃허브에서 Pull Request를 보낸다. (Compare & pull request) 123 | 124 | 7. 책임자가 승인 여부를 결정하고, 승인이 되었다면 merge 한다. 125 | 126 | 8. 로컬 저장소도 해당 변경사항 fetch 하고 merge 하여 동기화 시킨다. 127 | 128 | ## 4. Git 브랜치 종류와 gitflow 129 | https://gmlwjd9405.github.io/2018/05/11/types-of-git-branch.html 130 | 131 | ## 5. 커밋 메시지 이름 바꾸기 132 | ~~~ 133 | // 최근부터 최근에서 두번째 커밋 헤드까지를 rebase 134 | git rebase -i HEAD~2 135 | ~~~ 136 | 137 | 나오는 화면에서 맨 앞부분 edit 으로 바꾸고, 138 | 커밋 메시지 수정하면서 git rebase --continue 하면 하나하나 바꿀 수 있음 -------------------------------------------------------------------------------- /interview/interview.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Donsworkout/techInterview/cad6007d7d3cf5277a291e85d7e33ba58d6da14c/interview/interview.md -------------------------------------------------------------------------------- /java/annotations.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Annotations 4 | 1. @PathVariable 5 | > 파라미터에 실려오는 변수를 나타내는 어노테이션 (Post 방식은 해당 x) 6 | - 예시 7 | ~~~java 8 | @GetMapping("/{id}") 9 | public String show(@PathVariable Long id) { 10 | 11 | } 12 | ~~~ 13 | 14 | 2. @Configuration 15 | > IOC 컨테이너에게 해당 클래스가 Bean 설정(구성) 클래스라는 것을 알려준다. 16 | 17 | 3. @Bean 18 | > 개발자가 직접 제어 불가능한 외부 **라이브러리** 등을 Bean 으로 만들때 쓴다. 19 | ~~~java 20 | @Bean 21 | public Someclass someClass() { 22 | SomeClass a = new SomeClass(); 23 | a.method; 24 | return a; 25 | } 26 | ~~~ 27 | ~~~java 28 | @Bean(name="myClass") 29 | ~~~ 30 | 위처럼 해당 라이브러리 객체를 반환하는 method를 만들고, 31 | 그 위에 @Bean 어노테이션을 붙여 놓으면 된다. 32 | @Bean에 name을 따로 설정하지 않았으면 메서드가 Bean id로 등록된다. 33 | (위에서는 Bean ID가 'someClass') 34 | 35 | 4. @Component 36 | > 개발자가 직접 작성한 Class를 Bean으로 등록하기 위해 사용된다. 37 | @Component도 이름을 지정할 수 있다. 38 | ~~~java 39 | @Component(value="myClass") 40 | ~~~ 41 | 42 | 5. @Autowired 43 | > type을 기준으로 의존성을 주입할 수 있도록 해준다. 44 | IOC 컨테이너에 등록된, Service, Component 등의 어노테이션이 작성된 객체를 주입해 준다. 45 | 46 | 만약 다형성을 띄는 객체라면, 47 | ~~~java 48 | @Qualifier("Bean_이름") 49 | ~~~ 50 | 위와 같은 어노테이션으로 해당 자리에 주입될 Bean을 명시해 주어야 한다. 51 | 52 | 6. @UtilityClass 53 | > 유틸리티 클래스를 나타낸다. 특징은 생성자를 private 으로 바꿔서 static으로 쓰게끔 만들어 준다! 54 | ~~~java 55 | @UtilityClass 56 | public class TelegramUtil {} 57 | ~~~ 58 | 59 | 7. 커스텀 어노테이션 만들기 60 | > 인터페이스를 생성해 준다. 실제 구현한 코드는 아래와 같음 61 | ~~~java 62 | @Target(ElementType.FIELD) 63 | @Retention(RetentionPolicy.RUNTIME) 64 | public @interface TelegramField { 65 | int size(); 66 | int position(); 67 | } 68 | ~~~ 69 | 70 | > 그리고 클래스 실제 필드 선언에서 아래와 같이 사용하면 된다 71 | ~~~java 72 | @TelegramField(size=6, position=256) 73 | private String 거래_구분_코드; 74 | 75 | @TelegramField(size=20, position=262) 76 | private String 가맹점_번호; 77 | ~~~ -------------------------------------------------------------------------------- /java/data_structure.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Data Structures 4 | ### 1. Lists.newArrayList 5 | > 구아바 빌더는 유형 인수를 여러 번 입력하는 것을 절약한다. 6 | ~~~java 7 | List> list = Lists.newArrayList(); 8 | List> list = new ArrayList>(); 9 | ~~~ 10 | > 다이아몬드 연산자랑 같다고 보면 된다. 11 | ~~~java 12 | List> list = new ArrayList<>(); 13 | ~~~ 14 | 15 | ### 2. 자바 제네릭 - 다이아몬드 연산자 (Java 7 부터 지원) 16 | > cpp 의 템플릿과 비슷함 17 | 18 | java7 이전에는 아래와 같이 선언 후 사용했다. 19 | 20 | ~~~java 21 | //Case 1. 22 | List list = new LinkedList(); 23 | //Case 2. 24 | List list = new LinkedList(); 25 | ~~~ 26 | 27 | case 1 같이 쓰면 컴파일 에러는 안나지만, 런타임 에러가 발생하고, 28 | case 2 는 안전하지만, java 7 부터는 아래와 같이 작성이 가능 해 졌다. 29 | ~~~java 30 | List list = new LinkedList<>(); 31 | ~~~ 32 | 이렇게 다이아몬드를 쓰면, 굳이 뒤에 자료형을 명시할 필요가 없다. 33 | 34 | ### 3. 자바 Optional 35 | https://m.blog.naver.com/PostView.nhn?blogId=hehe5959&logNo=221002524184&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F 36 | > 존재할 수도 있지만 안할 수 도 있는 객체 (nullable 한 객체를 wrapping하고 있음) 37 | 제너릭도 사용가능하다. 38 | ~~~java 39 | Optional maybeOrder; 40 | // Order 타입의 객체를 감쌀 수 있는 Optional 타입의 변수 41 | Optional optMember; 42 | // Member 타입의 객체를 감쌀 수 있는 Optional 타입의 변수 43 | Optional
address; 44 | // Address 타입의 객체를 감쌀 수 있는 Optional 타입의 변수 45 | ~~~ 46 | 47 | ### 4. Map 과 MultiValueMap 은 무엇이 다를까? 48 | **A MultivaluedMap is:** 49 | A map of key-values pairs. Each key can have zero or more values. 50 | 51 | **A Map is:** 52 | An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. 53 | 54 | > 즉 MultiValueMap 은 한 key에 여러 value가 가능하고 55 | Map은 한 value만 가능하다. 56 | 57 | 중요한 특징중에 하나는 restTemplate의 exchange 메서드의 세번째 파라미터 request에는 무조건 MultiValueMap을 사용해야 한다. 58 | 59 | ~~~java 60 | MultiValueMap map= new LinkedMultiValueMap<>(); 61 | map.add("phone", "01087578935"); 62 | map.add("name", "김도현"); 63 | 64 | HttpEntity> request = new HttpEntity<>(map, headers); 65 | 66 | ResponseEntity> apiResponse = restTemplate.exchange(URL, HttpMethod.POST, request, new ParameterizedTypeReference>() {}); 67 | return apiResponse.getBody(); 68 | ~~~ 69 | 70 | ### 5. 배열과 리스트의 차이 71 | ### Array 72 | > 일반적으로 배열은 크기가 확정되어 있고 인덱스가 중요할 때, 효율이 좋아 많이 쓰인다. 73 | - 인덱스를 활용하여 빠른 조회가 가능하다. 74 | - 물리적으로 인접해 있어 cache hit (공간 지역성) 의 가능성이 높아진다. 75 | - 대신 리스트에 비해 기능이 없다. 76 | - 가변 배열을 쓰면 기존 배열 그대로 두고 새로운 길이로 배열 할당 후 데이터 복사하고 기존 배열을 삭제한다. 77 | - 요소 삭제시 메모리가 낭비된다. 78 | 79 | ### List 80 | > 인덱스가 중요하지 않을떄 빈틈없음 데이터의 적재가 가능 81 | - 순서가 있는 데이터의 모임 82 | - 배열의 index가 그 배열의 Key 라면, 리스트의 index 는 순서라는 의미 정도이다. 83 | - 데이터 추가 / 삭제가 많이 일어난다면 리스트가 적합하다. 84 | -------------------------------------------------------------------------------- /java/java.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. JDK / JRE / JVM 4 | 5 | ![jdk](https://user-images.githubusercontent.com/26560119/58600070-f0afe580-82bd-11e9-8c55-be299736b11b.jpg) 6 | 7 | 8 | #### JDK (개발킷, Java Development Kit) 9 | - JRE + 개발을 위해 필요한 도구 ex) javac (컴파일러), java 10 | 11 | #### JRE (실행용, Java Runtime Environment) 12 | - JRE (실행용) 는 자바 런타임 환경으로 하드웨어 위에 위치하는 계층이며 13 | 운영 체제에 상관없이 컴파일된 자바 프로그램을 실행될 수 있도록 돕는다. 즉 기반 OS를 추상화 해준다. 14 | 15 | > cf) RUNTIME 환경 16 | 컴퓨터 내에서 프로그램이 기동되면, 그것이 바로 그 프로그램의 런타임이다. (컴파일 다음단계) 17 | 18 | #### JVM (Java Virtual Machine) 19 | 20 | ![266F3C445805EF0A31](https://user-images.githubusercontent.com/26560119/58601083-3c648e00-82c2-11e9-808a-cd6537dfa07d.png) 21 | 22 | 23 | - 컴파일된 class 파일은 bytecode(중간언어) 로 만들어 지는데, bytecode를 OS에 맞는 기계어로 변환해주는 역할 (c++ 은 빌드때 바로 기계어로 감) 24 | > bytecode 는 컴파일 후 나오는 것으로 JVM 이 이해할 수 있는 코드 (클래스 파일) 25 | - JVM에 있는 클래스로더가 런타임때 바이트코드를 받아 자바 인터프리터 / JIT 컴파일러로 기계어로 해석하고 실행한다. 26 | 27 | - 이래서 자바가 OS 독립적이라고 하는 것이다. 28 | 29 | - JVM 의 구조에 대해 좀 더 살펴 보자면, 아래 그림 참고 고고 30 | 31 | 스크린샷 2019-05-30 오전 10 11 18 32 | 33 | 1) class loader 가 빌드된 자바 목적파일 (class / 바이트코드) 을 메모리로 로드한다. 34 | 35 | 2) Execution Engine이 적재된 바이트 코드를 읽어 기계어로 변환하는데, 처음에는 interpreter을 이용하여 한줄 씩 명령어를 실행하다가, 나중에는 JIT 컴파일러를 이용한다. 36 | 37 | > JIT 컴파일러는 적절한 시간에 전체 바이트코드를 기계어로 번역하고, 바이트 코드를 캐싱하여 뒤에 다시 같은 명령을 컴파일 하지 않도록 하여 성능을 높힌다. 38 | 39 | 3) **Garbage Collector (GC)** 40 | 41 | ![ㅇㅇㅇㅇ](https://user-images.githubusercontent.com/26560119/58604123-35dc1380-82ce-11e9-8c51-927b767a0365.png) 42 | 43 | - Runtume Data Area 의 Heap 메모리 영역에서 참조되지 않는 객체들을 탐색 후 제거한다. 44 | 45 | - Heap의 young 영역 (eden, survivor1/2) 에서 일어나는 Minor Gc가 있고, 46 | 47 | - Heap의 old 영역 (old. permanent) 에서 일어나는 Major GC가 있다. 48 | 49 | **자바 런타임 메모리 설명** 50 | 51 | - **Method Area :** 클래스, static 변수 등이 저장되는데, 이때 올라온 클래스에서 인스턴스를 생성하면 Heap 영역에 인스턴스가 생성되는 것이다. 52 | 53 | - **Heap Area :** 인스턴스 저장 54 | 55 | - **Stack Area :** 지역변수, 파라미터, 리턴 값 등이 저장된다. 56 | 57 | - **PC Register :** 스레드가 시작 될 때 생성, 현재 수행중인 JVM의 명령의 주소를 가진다. 58 | 59 | - **Native Method Stack :** : 자바 외의 언어로 작성된 네이티브 코드를 위한 스택이다. 즉, JNI(Java Native Interface)를 통해 호출하는 C/C++ 등의 코드를 수행하기 위한 스택으로, 언어에 맞게 C 스택이나 C++ 스택이 생성된다. 60 | 61 | #### GC 절차 62 | #### Minor GC 63 | 1) 최초 객체 생성시 Eden 영역으로, Eden이 꽉차면 Survivor1 영역에 그대로 복사된다. 64 | 이때 참조하고 있지 않은 객체는 삭제된다. 65 | 66 | 2) Eden 도 꽉 차고 survivor 1 영역도 꽉 차게 되면, 참조 검사를 하고 참조 되고 있는 객체만 survivor 2 영역에 복사한다. survivor 2 영역이 또 꽉 차면 Eden, survivor 2 영역에서 살아남은 친구들을 survivor 1으로 옮기고 죽은 애들은 삭제한다. 67 | 68 | > 이 과정은 일정 횟수 지속되는데, 이것은 Minor GC 라고 한다. 69 | 70 | 실제로 JVM은 각 Minor GC가 발생할 때 마다 Survivor Space의 포인터를 유지하고 있다가 단순히 survivor 1 에서 survivor 2 로 변경해 준다. minor GC의 알고리즘은 매우 속도가 빠르며 작은 크기의 메모리를 Collecting하는데 매우 효과적이다. Minor GC의 경우에는 자주 일어나기 때문에, GC에 소요되는 시간이 짧은 알고리즘이 적합하다. 71 | 72 | 3) 위 과정 중 일정 횟수이상 참조되고 있는 객체들을 survivor 2에서 Old 영역으로 복사한다. 73 | > survivor 영역 중 하나는 비어 있어야 한다. 74 | 75 | 4. 위 과정을 계속 반복하며, survivor 2 영역까지 차기 전에 Old 로 비워준다. 76 | 77 | > Minor GC 만으로도 heap 유지가 가능하도록 유도하는 것이 좋다. 78 | 79 | #### Major GC 80 | 81 | 1. Old 영역 모든 객체들을 참조되고 있는 지 검사하고 82 | 83 | 2. 참조되지 않는 객체들을 모아 한꺼번에 제거한다 (모든 쓰레드 중지) 84 | 85 | 3. Heap 메모리 중간중간 구멍을 없애기 위해 재구성을 하기도하는데, 옮기는 도중에 다른 쓰레드가 메모리 참조하지 못하도록 모든 쓰레드를 정지시킨다. 86 | 87 | => 결론 : GC를 잘 모니터링 해야 한다. (stop the world 조심) 88 | 89 | > Major GC의 Garbage Collection은 객체들이 Lived 상태로 있는지 여부를 파악하기 위해 모든 Thread의 실행을 잠시 멈추고 살아있는 객체를 표시하고 사용하지 않는 객체는 제거하여 heap을 정리한다. 이 Major GC는 Thread를 잠시 멈추게 되고 Mark and Sweep 작업을 위해 CPU에 부하를 가하게 되며 이러한 작업은 보통 Minor GC 에 비해 10배 이상의 시간을 사용하기 때문에 성능에 악영향을 주게 된다. 90 | 91 | #### 클래스 로더 92 | > JVM은 명령어를 클래스 파일에 저장한다. JVM 의 클래스 로더는 main 메서드가 호출될 메인 클래스부터 시작해서 필요할 때 클래스 파일을 로드한다. java.util.Scanner 같은 클래스를 이용하므로 이런 클래스도 로드하고, 이 클래스들이 각각 의존하는 클래스도 로드한다. 93 | 94 | ## 2. Java 언어의 다양한 특징 95 | 1. 자바는 변수를 사용하기 직전까지 변수 선인 시기를 늦추는 것을 좋은 방식으로 여긴다. 96 | 97 | 2. 상수는 final 키워드를 쓰며, 컴파일 타임에 할당되어 수정할 수 없다 (immutable) 98 | > 참고로 System.out.println 의 out은 System 클래스에 선언된 상수임 99 | ~~~java 100 | public static final PrintStream out 101 | ~~~ 102 | 103 | 3. 104 | 105 | ## 3. Java EE / SE / ME 차이 106 | ### 1) 자바 SE (Standard Edition) 107 | 데스크톱, 서버, 임베디드를 위한 표준 자바 플랫폼, SE가 다른 에디션의 기반이다. 108 | JDBC뜽 기본적인 기능이 들어가 있음 109 | 110 | ### 2) 자바 EE (Enterprise Edition) 111 | 자바를 이용한 서버측 개발을 위한 플랫폼 SE에 장애복구 및 분산 멀티미디어를 제공하여 대규모, 신뢰성 등을 보장한다. 112 | 113 | ### 3) 자바 ME (Micro Edition) 114 | 폰, 셋톰박스 등에서 java 이용할 수 있도록 만들어진 플랫폼 115 | 116 | ## 4. Wrapper Class 117 | 자바의 제너릭 클래스에는 불편한 제약이 하나 있는데, 118 | int, char 같은 기본 자료형을 타입 파라미터로 사용할 수 없다. 119 | (제너릭을 사용할때 타입 파라미터가 무조건 클래스이기 때문) 120 | 이에 대한 해결책으로 Wrapper Class 를 사용한다. 121 | 흔히 보는 Integer, Byte, Short, Long, Boolean 같은 것들이 이에 해당한다. 122 | 123 | ~~~java 124 | // ArrayList <- 이런 형태는 절대 불가 125 | ArrayList numbers = new ArrayList<>(); 126 | ~~~ 127 | 128 | 기본 타입과 Wrapper 클래스 사이는 자동 형 변환이 가능하다. 129 | 다른것은 별로 신경쓰지 않아도 되는데, Wrapper 클래스에서도 == 는 객체 참조를 비교한다는 사실을 잊지 말자 130 | 131 | ## 5. ClassPath (클래스패스) 132 | > 컴파일을 하면 java 파일에 선언된 클래스가 .class 파일 (bytecode)로 변환된다. 133 | javac 컴파일러는 항상 현재 디렉터리에서 파일을 찾지만, 자바 프로그램은 현재 디렉터리가 클래스패스에 있을때만 현재 디렉터리를 찾아본다, 그러나 따로 설정할 필요 없이 기본 설정으로 현재 디렉터리가 포함된다. (뻘짓만 안하면 가상머신이 클래스 로딩을 위해 클래스 파일 위치 찾는것에 무리가 없다는 내용) 134 | 135 | **결국 클래스패스는 JVM이 클래스 로딩을 위해 .class 파일을 찾기 위한 경로이다** 136 | - 클래스 파일을 파일 시스템에 저장하는 대신 JAR 파일이라는 아카이브 파일에 넣어서 사용할 수 있다. JDK의 일부인 jar 유틸리티로 이러한 아카이브를 만들 수 있다. 137 | 138 | - jar 파일을 사용하려면, 클래스 패스를 지정해서 해당 파일의 위치를 컴파일러와 JVM에 알려야 한다. 139 | 140 | ## 6. 인터페이스 141 | 사용자 클래스 - 서비스 제공 클래스 간의 **계약**을 표현하는것이 인터페이스이다. 142 | 인터페이스는 **구현(implements)** 하는 것이므로, 어떠한 필수 구현사항이 있다면 그것을 강제하는 느낌으로도 볼 수 있겠다. (구현 강제사항을 구현했는지는 컴파일러에서 검사한다) 143 | 말그대로 계약이자 협박인 것이다. 실제 좋은 아키텍처에서는 의존성을 느슨하게 만들기 위해, 서비스 사용자는 서비스의 구현체가 아닌 인터페이스를 의존하게 된다. 144 | 145 | **"너 이 메서드 구현 안하면, 컴파일 안해준다 .."** 146 | 147 | 그리고 Java 8 이 나오기 전까지는 인터페이스에는 실행 블록이 없는 추상 메서드만 선언이 가능했다. 그러나 지금은 디폴트 메서드나 정적 메서드 선언이 가능하다. 148 | 149 | ### 6.1 Java 8 에서 인터페이스에서 가질 수 있는 것들 150 | 1.1 상수 필드 151 | ~~~java 152 | public interface Parent{ 153 | public static final MAX_VALUE = 100; 154 | public static final MIN_VALUE = 0; 155 | } 156 | ~~~ 157 | 158 | 1.2 추상 메서드 159 | ~~~java 160 | public interface Parent{ 161 | // 상수 필드 162 | public static final MAX_VALUE = 100; 163 | public static final MIN_VALUE = 0; 164 | 165 | // 추상 메소드 166 | public abstract void run(); 167 | } 168 | ~~~ 169 | 170 | 1.3 디폴트 메서드 171 | ~~~java 172 | public interface Parent{ 173 | // 상수 필드 174 | public static final MAX_VALUE = 100; 175 | public static final MIN_VALUE = 0; 176 | 177 | // 추상 메소드 178 | public abstract void run(); 179 | 180 | // 디폴트 메소드 : 실행 내용까지 작성이 가능하다. 181 | public default void setState(boolean state){ 182 | 183 | if(state){ 184 | System.out.println("현재 상태는 정상입니다"); 185 | }else{ 186 | System.out.println("현재 상태는 비정상입니다"); 187 | } 188 | 189 | } 190 | } 191 | ~~~ 192 | 193 | 1.4 정적 메서드 194 | ~~~java 195 | public interface Parent{ 196 | // 상수 필드 197 | public static final MAX_VALUE = 100; 198 | public static final MIN_VALUE = 0; 199 | 200 | // 추상 메소드 201 | public abstract void run(); 202 | 203 | // 디폴트 메소드 : 실행 내용까지 작성이 가능하다. 204 | public default void setState(boolean state){ 205 | 206 | if(state){ 207 | System.out.println("현재 상태는 정상입니다"); 208 | }else{ 209 | System.out.println("현재 상태는 비정상입니다"); 210 | } 211 | 212 | } 213 | 214 | // 정적 메소드 215 | public static void change(){ 216 | System.out.println("상태를 변경합니다."); 217 | } 218 | } 219 | ~~~ 220 | 221 | ### 6.2 타입 변환 222 | 223 | 2.1. 자동 타입 변환(Promotion) 224 | 225 | ~~~java 226 | Interface interface = new 구현체(); 227 | // 위와같은 경우 인터페이스에 선언된 메서드만 사용이 가능하다 228 | ~~~ 229 | 230 | 2.2. 강제 타입 변환(Casting) 231 | 232 | 구현 객체가 인터페이스 타입으로 **자동 타입 변환** 되는 경우 233 | 인터페이스에 선언된 메소드만 사용이 가능한 반면, 234 | 235 | 인터페이스 구현 클래스에 선언된 필드와 메소드를 사용해야 하는 경우에는, 236 | **강제 타입 변환** 을 이용하여 다시 구현 클래스 타입으로 변환해야한다. 237 | 238 | ~~~java 239 | Interface interface = new 구현체(); 240 | 구현체 imp = (구현체) interface; 241 | ~~~ 242 | 243 | 강제 타입 변환시 instanceof 연산자로 확인하고 안전하게 강제 타입 변환을 할 것. 244 | 245 | ~~~java 246 | if (car instanceof Bus){ 247 | Bus bus = (Bus)car; 248 | } 249 | ~~~ 250 | 251 | ### 6.3 Runnable Interface 252 | > 스레드의 테스크를 정의하려면 Runnable 인터페이스를 구현해야 한다. 253 | Runnable Interface는 메서드(run)를 한개만 갖는다. 254 | 255 | ~~~java 256 | class ThreadTask implements Runnable { 257 | public void run() { 258 | for (int i = 0; i < 1000; i++) { 259 | System.out.println("Some Task"); 260 | } 261 | } 262 | } 263 | ~~~ 264 | 265 | 이 태스크를 새로운 스레드에서 실행하려면 Runnable 인터페이스 구현체를 스레드 변수에 담아 실행시키면 된다. 266 | 267 | ~~~java 268 | Runnable task = new ThreadTask(); 269 | Thread thread = new Thread(task); 270 | thread.start(); 271 | ~~~ 272 | 273 | ## 7. 자바의 자료구조 274 | ### 1. Array 275 | ~~~java 276 | String[] names = new String[100]; 277 | ~~~ 278 | **new 연산자로 배열 생성 시** 279 | - 숫자 타입의 배열은 0으로 채워진다 280 | - boolean 의 배열은 모두 false 로 채워진다. 281 | - 객체 배열은 null 참조 282 | 283 | ### 2. JAVA collection framework 284 | https://hackersstudy.tistory.com/26 285 | https://onsil-thegreenhouse.github.io/programming/java/2018/02/18/java_tutorial_1-22/ 286 | 287 | ![283](https://user-images.githubusercontent.com/26560119/64241191-2cea8600-cf3e-11e9-9b85-a3e9327e8cff.jpg) 288 | 289 | 290 | 291 | 292 | 293 | > 컬렉션 프레임워크에는 자료 구조의 구현체가 있다. 294 | 선택한 자료 구조에 독립적인 코드를 쉽게 작성할 수 있도록 컬렉션 프레임워크는 공통 인터페이스를 제공한다. 295 | 대표적으로는 사용 용도에 따라 List, Set, Map, Queue 으로 나눌 수 있다. 296 | 297 | ### 1. 자료구조 인터페이스의 특징 298 | > List, Set, Map, Queue 은 인터페이스이다. 299 | 300 | 1. List 301 | 구현 클래스 : ArrayList, LinkedList, Stack, Vector 302 | 간단 설명 : 순서가 있는 데이터의 집합, 데이터의 중복을 허용한다. 303 | 304 | 검색이 빠른 구현체는 **ArrayList** 305 | 노드간 삽입이 빠른 구현체는 **LinkedList** 306 | 307 | - ArrayList는 내부적으로 데이터를 배열에서 관리하며 데이터의 추가, 삭제를 위해 임시 배열을 생성해 데이터를 복사 하는 방법을 사용 하고 있기 때문에 삽입 삭제시 많은 복사가 일어나기 때문에 Cost 가 크다. 308 | 309 | **참고로** List 인터페이스는 리스트에서 n번쨰 요소에 접근하는 메서드를 제공한다. 310 | Collection 클래스에서 이러한 접근을 지원한다는 사실을 나타내려면, RandomAccess 라는 인터페이스를 구현해야 한다. 311 | **ArrayList**는 이러한 RandomAccess 인터페이스를 구현하지만, 312 | **LinkedList** 는 RandomAccess 인터페이스를 구현하지 않는다. 313 | 314 | 따라서 링크드리스트는 인덱스 접근이 불가하다는 사실을 기억! 315 | 2. Set 316 | 구현 클래스 : HashSet, TreeSet 317 | 간단 설명 : 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다. 318 | 319 | Set은 **순서** 가 없다는 것을 기억하자 320 | 그래도 Set은 Iterable 하기 떄문에 순회하여 값을 찾을 수 있다. 321 | 322 | Set 에서 적합한 용도는 해당 요소가 해당 집합에 포함되는지를 조사할때 유용하다. 323 | 324 | 평범한 싱황에서는 해시테이블을 이용하는 HashSet을 쓰면 되는데, 325 | 정렬된 순서대로 집합을 순회하려면, TreeSet 이 짱이다. 326 | 327 | TreeSet 은 이진검색트리 형태로 데이터를 저장하는데, 328 | 따라서 애초부터 정렬되어 트리에 저장된다, 329 | 이는 정렬과 검색에 뛰어난 성능을 보인다. 330 | TreeSet은 이진트리를 개선한 레드블랙 트리로 구현되었다. 331 | 332 | 예를 들어 아래와 같은 소스가 있다면, 중복 없이 오름차순으로 정렬된 형태로 출력된다. 333 | ~~~java 334 | Set set = new TreeSet(); 335 | 336 | ... ADD Integers to set 337 | 338 | Iterator it = set.iterator(); // 반복자 생성 339 | 340 | while (it.hasNext()) { 341 | System.out.println(it.next()); 342 | } 343 | 344 | ~~~ 345 | 346 | 3. Map 347 | 구현 클래스 : HashMap, TreeMap, HashTable 348 | 간단 설명 : 키(key)와 값(value)의 쌍으로 이루어진 데이터의 집합이다. 349 | 순서는 유지되지 않고, 키는 중복을 허용하지 않으며 값의 중복을 허용한다. 350 | 351 | 키를 정렬 순서로 방문해야 하는 이유가 없다면, HashMap 을 쓰는것이 낫다. 352 | 정렬 순서로 방문하려면 TreeMap 을 사용하면 된다. 353 | 354 | 4. Queue 355 | Queue 는 요소를 뒤에서만 삽입하고 앞에서만 제거할 수 있다. 356 | Deque 는 Double Ended Queue 의 약자로, 양끝에서 삽입 및 제거가 가능하다. 357 | 358 | 359 | 컬렉션 인터페이스는 모두 제너릭이며, 요소 타입에 대응하는 타입 파라미터를 받는다. 360 | 그리고 코드를 작성할 때 가능하면 인터페이스를 사용하는 것이 좋다. 361 | ~~~java 362 | List list = new ArrayList<>(); 363 | ~~~ 364 | 365 | #### 참고 ) Vector 와 ArrayList 의 차이 366 | #### Vector 367 | 1. Vector 은 사실 레거시 클래스! 368 | - 그러나 현재는 재구성 되어 Collection 프레임워크와 완벽 호환가능 369 | 2. **동적배열** 을 구현한다. 370 | 3. 배열과 같이 index로 접근한다. 371 | 4. 동기화되어 (한번에 한스레드) Thread-Safe 하다 372 | 373 | #### ArrayList 374 | 1. Collection 프레임워크 375 | 2. Vector과 마찬가지로 동적 배열 구현 376 | 3. 표준 배열보다는 느리지만, 많은 조작을 제공 377 | 4. 동기화 되어있지 않아서, 동기화 시키려면 syncronized 키워드 추가해야 함 378 | 379 | #### 차이점 380 | 1. 동기화 381 | Vector은 동기화, ArrayList 는 X (동시에 여러 스레드 접근가능) 382 | 383 | 2. Thread Safe 384 | 1번과 비슷한 맥락, ArrayList 는 스레드 프로그래밍의 경우에서는 명시적 동기화가 필요 385 | 386 | 3. Performance 387 | 당연히 동기화를 고려하지 않는 ArrayList가 빠름 388 | 389 | 4. 동적 사이즈 추가 갯수 다름 390 | - ArrayList는 기존배열 사이즈 대비 50% 만 증가하고 391 | - Vector은 사이즈 대비 100% 가 증가한다 392 | 393 | **따라서 스레드 환경이 아닐때는 걍 ArrayList 쓰면 된다.** 394 | ### 2. Iterator 395 | > 각 컬렉션에는 어떤 순서로 요소를 순회하는 메서드가 무조건 있다. 396 | Collection 의 부모 인터페이스인 Iterable는 다음과 같은 메서드를 제공한다 397 | ~~~java 398 | Iterator iterator() 399 | ~~~ 400 | 이 메서드는 모든 요소를 방문하는데 사용할 수 있는 반복자를 돌려준다. 401 | 아래처럼 활용 가능하다. 402 | 403 | ~~~java 404 | Collection coll = new 어쩌고; 405 | Iterator iter = coll.iterator(); // 반복자 반환 406 | while (iter.hasNext()) { 407 | String element = iter.next(); 408 | // logic 409 | } 410 | ~~~ 411 | 412 | 아니면 더 간단하게 아래처럼 향상된 for 문도 가능하다. 413 | 414 | ~~~java 415 | for (String element : coll) { 416 | //logic 417 | } 418 | ~~~ 419 | 420 | ### 3. Stack, Queue, Deque, Priority Queue 421 | - 스택은 한쪽 끝(top) 에서 요소를 추가하고 제거까지 하는 자료구조다 (LIFO) 422 | - 큐는 한쪽 끝(tail) 에서 요소를 추가하고, Head 에서 요소를 제거한다. 423 | - 스택 인터페이스는 없고 레거시 Stack 클래스만 있다 424 | - 위의 인터페이스 Stack, Queue, Deque 이 필요하지만 스레드 안전성을 신경쓰지 않아도 된다면, ArrayDeque 를 이용해 모두 구현할 수 있다. 425 | 426 | **Stack 을 구현할 때** push, pop 427 | **Queue 를 구현할 떄** add, remove 428 | 429 | 병렬 프로그래밍 상황에서는 스레드 안전 큐를 사용하고, 430 | 우선순위 큐는 요소를 무작위로 삽입해도 정렬된 형태로 꺼내게 된다. 431 | 즉 remove() 시 현재 가장 작은 요소를 얻는다는 뜻이다. (작업 스케줄링에 사용) 432 | 433 | ## 8. Java 의 장단점 434 | ### 장점 435 | - 운영체제에 독립적이다 (JVM 있음) 436 | - 객체지향 언어이다. (추상화 ,캡슐화, 상속, 다형성) 437 | - 자동으로 메모리 관리 해 준다 (JVM GC) 438 | - 멀티스레딩 API 가 있어 쉽게 구현할 수 있다. 439 | - 동적 로딩을 지원한다. 고치면 해당 클래스만 재컴파일 440 | 441 | ### 단점 442 | - 조금 느리다. (c++, c에 비해 느리단 말임, 당연히 portability 와 Trade-off) 443 | 444 | ## 9. 자바 언어 기타 445 | ### 1. final 과 static final 의 차이 446 | 1. static 447 | - 자바에서 static은 클래스 멤버를 설정하는 키워드이다. 448 | - JVM 클래스 로딩 (.class -> Java Runtime) 시, 클래스의 모든 정보가 JVM class 영역에 올라가므로 static 키워드를 썼다면 이때 static 맴버가 적재된다. 449 | - static 변수는 자바 메모리의 Method 영역으로 간다. 450 | 2. final 451 | - 상수, 메서드, 클래스에 사용가능하다. 452 | - 상수라면 값 고정, 메서드라면 오버라이딩 금지, 클래스라면 상속 금지 453 | 454 | 3. static final 455 | - 객체가 아니라 클래스에 존재하는 단 하나의 상수이다. 456 | - 해당 변수를 클래스 변수로 만들면서 값을 고정시키겠다 457 | ~~~java 458 | private static final Logger LOGGER = LoggerFactory.getLogger(sth.class); 459 | 460 | ### 2. DataInputStream / DataOutputStream 461 | https://hyeonstorage.tistory.com/239 462 | 463 | #### 입력 스트림 / 출력 스트림의 특징 464 | - 스트림은 - 바이트 스트림이라고 보면 된다. 465 | - 이러한 바이트는 네트워크나, 파일, 메모리 배열 등에서 읽어올 수 있다. 466 | - reader은 스트림을 소비하고, writer 은 스트림을 생산한다. 467 | - 원래는 스트림을 하나씩 소비하다가, 끝에 도달하면 -1 반환하는 방식이나 468 | - 소켓 통신 같은 경우에 한꺼번에 읽어올 수 도 있다. 469 | 470 | ### 3. throw 와 throws (아래 7번 참고) 471 | - throw 는 **예외 처리** 이고, throws 는 **전가** 이다. 472 | 473 | ~~~java 474 | public void getSth() throws Exception { 475 | if (stream.sthWrong()) 476 | throw new IOException(); 477 | } 478 | ~~~ 479 | - 아래 처럼 썼을때 getSth 메서드를 호출한 쪽에서 예외를 전가받아 책임져야 한다 480 | - throw에서 던질 수 있는 것은 Throwable 클래스를 상속받는 객체여야만 한다. 481 | 482 | ### 4. Reflection 483 | > 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법 484 | 동적으로 인스턴스를 생성한다. 485 | 486 | [BeanFactory](http://wonwoo.ml/index.php/post/1571) 라는 Spring Container 는 어플리케이션이 실행한 후 객체가 호출 될 당시 객체의 인스턴스를 생성하게 되는데 그 때 필요한 기술이 Reflection 이다. 487 | 488 | 아래 링크에 자세히 나와 있다. 489 | https://gyrfalcon.tistory.com/entry/Java-Reflection 490 | 491 | #### 4.1 객체 조사하기 492 | > 리플렉션을 이용하면 해당 객체의 필드와 타입을 나타내는 Field 객체를 얻을 수 있고, 해당 필드 값도 추출할 수 있다. 마찬가지로 Method 객체도 있어서 객체로 객체의 메서드를 호출할 수 있다. (대신 객체에 접근 가능하도록 setAccessible 해야 한다) 493 | 494 | 실제 리플렉션을 이용하여 보았다. 495 | 필드 전체를 돌면서 각 필드의 어노테이션 값들에 접근하고, 496 | 나아가 어떤 객체의 값을 설정하는 행위를 해 보았다. 497 | ~~~java 498 | private static boolean hasValidSize(T requestInst, Field field) { 499 | field.setAccessible(true); 500 | TelegramField telegramField = field.getAnnotation(TelegramField.class); 501 | 502 | try { 503 | if (telegramField.size() != field.get(requestInst).toString().length()){ 504 | LOGGER.error("{} 필드길이 에러", field.getName()); 505 | return false; 506 | } 507 | } catch (IllegalAccessException e){ 508 | LOGGER.error("필드에 대한 잘못된 접근입니다."); 509 | return false; 510 | } 511 | 512 | return true; 513 | } 514 | ~~~ 515 | 516 | ### 5. JAVA - ENUM 517 | http://blog.naver.com/PostView.nhn?blogId=kbh3983&logNo=220907314096&parentCategoryNo=&categoryNo=90&viewDate=&isShowPopularPosts=false&from=postView 518 | 519 | > 상수들을 모아놓은 **클래스** 이다. 메서드, 생성자를 모두 가질 수 있다. 520 | 런타임이 아닌 컴파일 타임에 모든 값을 알고 있어야 하기 때문에, 생성자가 private 로 제한된다. 싱글톤의 성질을 갖고 있다고 말할 수 있다. 521 | 522 | enum 선언하는 예를 보자 523 | ~~~java 524 | public enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE} 525 | ~~~ 526 | 527 | 위의 코드에서 enum 목록들은 모두 인스턴스이다. 528 | 인스턴스처럼 꺼내 쓰는것이다. 열거의 각 인스턴스는 한번만 생성됨을 보장받는다. 529 | 530 | 1. Enum 인스턴스의 생성은 기본적으로 thread safe하다. 531 | 532 | 2. Enum 싱글톤은 Serialization을 스스로 해결한다 533 | > 일반적인 싱글톤에서는 직렬화할 때, 싱글톤이 싱글톤이 아니게되는 문제가 발생한다. 534 | 왜냐하면 직렬화 하려면 readObject()를 구현해야하는데, readObject()는 매번 새로운 인스턴스를 리턴하기 때문이다. 이러한 문제를 해결하기 위해서 몇가지 단계가 필요하다. 535 | 536 | 1) 싱글톤 오브젝트를 직렬화 하기 위해 implements Serializable을 추가한다. 537 | 2) 모든 필드를 **transient** 로 선언한다 538 | (특정 멤버변수가 serialization이 되는 것을 막는 것) 539 | 3) readResolve() 메소드를 구현한다. 540 | 541 | 542 | 3. reflection 을 통한 공격에도 안전 543 | - setAccessible 하면 private field 에도 접근 가능한데, ENUM은 이에 대한 대비를 이미 하고 있음 544 | 545 | ### 6. Abstract Class VS Interface 546 | > 둘다 선언만 있고 구현은 없는 클래스이다. 즉, 인스턴스를 생성해 낼 수 없고 추상클래스를 상속받는 자식클래스나, 인터페이스를 구현하는 클래스만이 인스턴스를 생성해 낼 수 있다. 547 | 인터페이스는 어떠한 서비스의 필수 구현 사항 명세인 느낌이 강하다면, 548 | 추상클래스는 자식이 부모 클래스 메서드를 가져다 쓰거나, 오버라이드 해서 사용하려는 느낌이 더 강하다. 549 | 550 | **추상 클래스는 상속 개념이 들어간다는 것이 가장 큰 차이 -> 오버라이딩 (ISA)** 551 | 부모에서 끌어쓰는 내용이 없고, 기능 구현을 명세할 것이면 인터페이스가 더 적합하다. 552 | 553 | ### 7. 자바 Throwable - Exception 554 | ![Exception-Class](https://user-images.githubusercontent.com/26560119/63499839-a8424580-c503-11e9-8be9-45bbef0b1d6a.png) 555 | 556 | 557 | Throwable 을 상속받는 클래스는 Error, Exception 이다. 558 | 에러는 시스템 레벨에서 발생하는 것이기 때문에 보통 시스템 자체에 변화를 주어 해결해야 한다. 559 | 그러나 Exception은 개발자 선에서 처리할 수 있는 부분이다. 560 | 561 | **Exception**은 많은 자식을 가지고 있는데 이는 두가지 그룹으로 나눠질 수 있다. 562 | **RuntimeException**은 Checked 예외와 Unchecked 예외를 구분하는 기준이다. 563 | 564 | **Checked Exception** 은 컴파일 단계에서 확인하므로 반드시 컴파일 전에 예외처리가 필요하다. 565 | RuntimeException 빼고는 모든 예외가 이에 해당한다. 또한 Checked Exception 은 트랜잭션을 롤백하지 않는다. 미리 개발자가 인지하고 처리했을 것이라고 생각하기 때문인 것 같다. 566 | 대표적인 예로는 IOException이 있다. 567 | 568 | **Unchecked Exception** 은 무조건 RuntimeException 의 자식 클래스이다. 569 | 명시적 처리를 강제하지 않고 예외시 트랜잭션을 롤백한다. NullPointException /IllegalArgumentException / IndexOutOfBoundException 570 | / SystemException 등이 런타임 예외에 해당된다. 571 | 572 | 런타임 예외처리도 중요하지만, Checked Exception 발생 시에는 무조건 Catch 할때 아무 처리도 하지 않는것 보다는 특별한 처리를 해 줄 수 있도록 노력해야 한다. 573 | 574 | 575 | #### 참고 - Socket 사용 시 발생할 수 있는 에러 576 | 577 | 1. **SocketException** (Checked Exception) 578 | 579 | - 원인: read / write 시 상대방 socket close 된 경우 580 | 581 | 2. **IOException** - Broken pipe 등 (Checked Exception) 582 | 수신자가 송신받은 데이터를 제때 처리하지 못하는 상황 (네트워크가 느리거나 서버의 CPU가 max인 경우 등) 에서 송신자가 계속 보내는 경우 583 | 584 | 3. **SocketTimeoutException** (IOException 자손 클래스) 585 | 586 | ### 8. String, StringBuilder, StringBuffer 차이 587 | > 이 셋은 모두 문자열을 저장하고 관리하는 클래스이다. 뭐가 다를까? 588 | 589 | #### 1. String 590 | - String 은 **immutable** 하다. 591 | - 짧은 데이터 concat 같은 경우에 적절하다. 592 | - immutable 하므로 당연히 Thread-Safe 하다. 593 | - 그러나 concat 시 기존 String에 다른 String을 더하는 것이 아니라, 새로 아예 복사해서 만드는 것이기 때문에 연산할 문자열의 길이가 길 떄에는 **성능상** 사용하지 않는것이 좋다. 594 | 595 | #### 2. StringBuffer와 StringBuilder 596 | - StringBuffer와 StringBuilder 클래스가 제공하는 메서드는 서로 동일 597 | - String 과 달리 concat 시 기존 버퍼의 크기를 늘리는 방식으로 동작 598 | - StringBuffer 는 메서드별로 Synchronized Keyword 가 존재함 599 | => 동기화 지원 (Thread-Safe) 600 | - StringBuilder 은 동기화 미지원 601 | - 성능만 보면 StringBuilder 가 제일 좋지만, 보통 스레드 안전을 위해 StringBuffer을 쓰는게 나을 것 같다. 602 | 603 | 604 | ## 10. 병행 태스크 (The Parallel) 605 | ~~~java 606 | public interface Runnable { 607 | void run(); 608 | } 609 | ~~~ 610 | 611 | 이것은 Runnable 인터페이스이다. 612 | run 메서드에 들어 있는 코드는 Thread 안에서 실행된다. 613 | 614 | **Thread** 는 ***일련의 명령어를 실행하는 메커니즘*** 이다. 보통은 운영체제에서 제공하며, 별도의 프로세서나 같은 프로세서의 서로 다른 타임 슬라이스를 이용해 여러 Thread 가 동시에 실행된다. 615 | 616 | 단, 가벼운 작업은 스레드로 넣는것이 비효율적이다. 스레드 시작하는데 드는 오버헤드가 크기 때문이다. 강도 높은 계산일 경우에는 태스크별로 스레드를 사용하는 대신, 프로세서별로 스레드를 하나씩 사용해서 스레드 간 **스위칭 오버헤드** 를 피하는 것이 좋다. 617 | 618 | ### 1. Executor 619 | > Executor 클래스에는 다양한 유형의 실행자들을 만들어 내는 **팩토리 메서드**가 있다. 620 | **팩토리 메서드** 는 타입에 따른 객체의 생성을 생성자 자체가 아닌 팩토리 클래스에게 맡기는 것이다. 621 | #### 1) 유휴 스레드를 이용한 최적화된 스레드풀 제공 622 | ~~~java 623 | exec = Executor.newCachedThreadPool(); 624 | ~~~ 625 | 626 | #### 2) 고정 개수 스레드 풀 627 | ~~~java 628 | exec = Executor.newFixedThreadPool(스레드_개수); 629 | ~~~ 630 | 여기서 Thread 개수는 가용 프로세서 개수로 부터 구하면 된다. 631 | ~~~java 632 | int count = Runtime.getRuntime().availableProcessors(); 633 | ~~~ 634 | 635 | ### 2. 스레드 안전성에 영향을 주는 것들 636 | 637 | #### 1. 가시성 638 | > 캐싱 및 명령어 재배치는 의도하지 않은 결과를 만들 수 있다. 639 | 예를 들어 한쪽 스레드에서 어느 시점에 done 이라는 변수를 true 로 바꾸었을 경우, 다른 스레드에는 해당 변수가 캐싱 된 상태로 표시되기 떄문에 제대로 변경값이 탐지가 되지 않을 수 있음 640 | 641 | **이는 volatile 키워드로 해결 가능** 642 | - Java 변수를 Main Memory에 저장하겠다라는 것을 명시하는 것 643 | - 매번 변수의 값을 Read할 때마다 CPU 캐시에 저장된 값이 아닌 Main Memory에서 읽는 것 644 | - 또한 변수의 값을 Write할 때마다 Main Memory에 까지 작성하는 것 645 | - 당연히 성능과 Trade Off 가 있음 646 | - 여러 Thread 에서 사용시 문제 발생 가능성 있음, 메모리에 쓰는 중에 다른곳에서 덮어쓰고 이러면 부질 없음 647 | - 따라서 애초에 여러 Thread 에서 쓰려면 Syncronized 키워드 쓰는 것이 낫다 648 | 649 | #### 2. 경쟁조건 650 | > 1번에서 언급한 volatile 로는 충분하지 않다. 스레드 간에 경쟁이 있는데 중간에 자원 선점을 다른 스레드에게 뺏기면 의도치 않은 결과가 발생할 수 있다. 651 | 652 | #### 3. 락, 스레드 안전 자료 구조 등 653 | 1. 스레드 안전 자료 구조 654 | - 물론 Lock 을 이용하여 한번에 한 스레드만 자료구조에 접근 가능하도록 설정할 수 있으나 성능이 크게 떨어질 수 있다. 655 | - java.util.concurrent 패키지를 이용하면, 서로 블로킹 할 필요 없이 자료구조의 각기 다른 부분에 접근하여 동시성을 이용할 수 있다. 656 | 657 | 1.1 ) ConcurrentHashMap 658 | > 스레드 안전, 그러나 연산의 원자성을 보장하기 위해 compute 메서드를 써야 한다. 659 | compute 메서드에는 key와 새 값을 계산하는 함수를 전달해야 한다. (트랜잭션하고 비슷한 느낌, 전달되는 연산을 보장해 줌) 660 | 661 | 1.2 ) 블로킹 큐 .. 등등 여러가지 있음 662 | 663 | 2. 락 (Lock) 664 | 2.1) 재진입 가능 잠금 (명시적 잠금) 665 | ~~~java 666 | Lock countLock = new ReentrantLock(); 667 | int count; 668 | ... 669 | countLock.lock(); 670 | try{ 671 | count++; // 임계영역 672 | } finally { 673 | countLock.unlock(); // 잠금 해제 674 | } 675 | ~~~ 676 | 677 | 2.2) synchronized 키워드 (암시적 잠금) 678 | > 사실 명시적 잠금과 같은 의미 679 | ~~~java 680 | syncronized (obj) { 681 | // 임계 영역 682 | } 683 | ~~~ 684 | ## 11. Java 8 에서 추가된 기능 685 | ### 1. Stream API (반복에서의 더 고수준의 추상화) 686 | - 어떻게가 아니라 '무엇을' 에 관심있다. 687 | - 고수준 추상화로 최적화에 도움을 준다, 내부 로직을 API 가 결정 한다는 뜻 688 | - 파이프라인을 만드는데 필요한 API를 제공하게 되었다. 689 | - 기존에는 한 번에 한 항목을 처리했지만 작업을 고수준으로 추상화해 일련의 스트림으로 만들어 처리할 수 있다는 것 690 | - 스레드라는 복잡한 작업을 사용하지 않고도 **파이프라인식 병렬성**을 얻을 수 있게 된 것 691 | 692 | #### 스트림의 특징들 693 | 1. 스트림 연산은 원본을 변경하지 않는다. (iterate 하며 소비되는 특징을 가짐) 694 | - filter 메서드 같은 경우 기존 스트림에서 빼는 것이 아니라, 해당 요소가 없는 새로운 스트림을 돌려주는 방식임 695 | 2. 스트림은 가능한 연산을 지연 시켜둔다. 연산 결과가 필요하기 전까지는 실행되지 않는다 696 | 697 | #### 주의사항 698 | 아래와 같은 코드는 잘못된 코드이다 699 | ~~~java 700 | Stream words = wordList.stream(); 701 | words.forEach(s -> if (s.length() < 12) wordList.remove(s)); 702 | ~~~ 703 | 위의 코드는 스트림 원본을 손상시키고 있다. 704 | 중간 스트림은 지연 처리되기 떄문에 중간에 손상시키면 안된다. 705 | 706 | #### 스트림의 workflow 707 | 1. 스트림을 생성한다 708 | ~~~java 709 | Stream words = Stream.of("a","b","c"); 710 | ~~~ 711 | 2. 초기 스트림을 다른 스트림으로 변환하는 중간 연산을 지정한다. (여러 단계일 수 있음) 712 | ~~~ 713 | filter, map, flatMap, sorted, limit 등 714 | ~~~ 715 | 3. 지연되었던 연산을 적용한다. (이후 해당 스트림 재사용 불가) 716 | ~~~ 717 | forEach, toArray, reduce, collect, min, max, count, anyMatch 등 718 | ~~~ 719 | reduce 같은 경우는 스트림 합산이다 720 | ~~~java 721 | Optional vals = svalues.stream().reduce((x, y) -> x + y) 722 | // 이런 느씸 723 | ~~~ 724 | ~~~java 725 | import static java.util.stream.Collectors.toList; 726 | 727 | Map> transactionByCurrencies = 728 | transactions.stream() 729 | .filter((Transaction t) -> t.getPrice() > 1000) 730 | .collect(groupingBy(Transaction::getCurrency)); 731 | ~~~ 732 | 733 | 이처럼 반복문을 쓰지 않아도 되는 **함수형 코드 표현** 과 734 | **고수준의 병렬성 추상화**로 멀티코어를 잘 활용할 수 있도록 도와준다 735 | 736 | ### 2. 메서드와 람다(익명함수)를 1급 시민으로 737 | - 1급 시민은 파라미터로 넘겨질 수도 있고 반환될 수 도 있다. 738 | - 메서드를 파라미터로 전달가능 739 | ~~~java 740 | File[] hiddenFiles 741 | = new File(".").listFiles(File::isHidden); 742 | ~~~ 743 | - 악명함수를 이용하여 함수도 값으로 처리 744 | ~~~java 745 | (int x) -> x + 1 // x라는 인수로 호출하면 x + 1 을 반환 746 | ~~~ 747 | 748 | ### 3. Default Method 749 | > Java8에는 default 라는 새로운 키워드를 인터페이스 규격명세에 추가되어 있다. 750 | 하나의 예로 이전 버전의 자바에서는 List를 구현하는 모든 클래스가 sort 메서드를 구현해야 했지만 Java8부터는 디폴트 sort를 구현하지 않아도 된다. 751 | (인터페이스에 구현이 들어갈 수 있다.) 752 | 753 | ~~~java 754 | default void sort(Comparator c){ 755 | Collections.sort(this, c); 756 | } 757 | ~~~ 758 | 759 | ### 4. Optional Class 760 | > NullPointer 예외를 피할 수 있는 Optional 클래스도 제공한다. 761 | 이는 값을 갖거나 갖지 않을 수 있는 컨테이너 객체이다. 762 | 763 | - 값이 존재한다면 Optional 클래스는 값을 감싼다 764 | - 값이 없다면 Optional.empty메서드로 Optional을 리턴한다 765 | 766 | ### 5. CompletaleFuture 767 | https://m.blog.naver.com/PostView.nhn?blogId=horajjan&logNo=220328527952&proxyReferer=https%3A%2F%2Fwww.google.com%2F 768 | 769 | > 미래를 예약하는 값이나, 그냥 Future 에 비해 장점이 많다. 예를 들어 서로 독립적인 비동기 동작이든 아니면 하나의 비동기 동작이 다른 비동기 동작의 결과에 의존하는 상황이든 여러 비동기 동작을 조립하고 조합할 수 있다. 770 | 771 | 한 문장으로만 표현하자면, **람다 표현식** 과 **파이프라인 (.xx.yy)** 이 가장 큰 장점 772 | ~~~java 773 | ExecutorService executor = Executors.newSingleThreadExecutor(); 774 | 775 | CompletableFuture.runAsync(()->{ 776 | try{Thread.sleep(1000);} catch(Exception e){}; 777 | System.out.println("Hello!"); 778 | try{Thread.sleep(1000);} catch(Exception e){}; 779 | },executor) 780 | .thenRun(()->System.out.println("World")); 781 | 782 | System.out.println("async request is ready."); 783 | ~~~ 784 | 785 | 두개의 비동기 task 가 **자연스럽게 연결** 되었다. (A완료시 B실행) 786 | 787 | 1) Executor를 통해 비동기 task 가 수행될 쓰레드를 생성하고 788 | 2) CompletableFuture.runAsync를 통해 다른 쓰레드에서 비동기 식으로 동작할 로직를 선언하고 789 | 3) CompletableFuture.thenRun 를 통해 첫번째 task 가 완료된 이후에 연속적으로 동작할 로직을 선언함 790 | 791 | 따라서 장점을 따지자면 792 | - 태스크간 조합과 결합이 용이하다 (연속적 연결) 793 | - 여러 Completable Future 를 합쳐서, 마지막 놈 되는대로 결합가능 794 | - thenCompose 매소드는 첫 번째 연산의 결과를 두 번째 연산으로 전달한다 795 | - exceptionally 로 예외처리가 용이하다 796 | - 커스텀 Executor를 사용하여 스레드 풀의 크기를 조절하는 등 애플리케이션에 맞는 최적화된 설정을 만들 수 있다 (오버로딩 된 supplyAsync) 797 | 798 | ### 6. New date / time APIs 799 | 800 | ## 12. 객체 직렬화 (Serialization) 801 | http://woowabros.github.io/experience/2017/10/17/java-serialize.html 802 | > 자바 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 이야기합니다. 803 | 시스템적으로 이야기하자면 JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 같이 이야기합니다. 804 | 805 | - 클래스 직렬화를 원한다면 해당 클래스가 Serializable 인터페이스를 구현하면 된다. 806 | ~~~java 807 | public class A implements Serializable { 808 | 809 | } 810 | ~~~ 811 | 812 | - 보안 상의 문제나 기타 이유로 멤버변수의 일부를 제외하고 싶다면 transient를 통해 지정할 수 있다. 813 | 814 | ~~~java 815 | public class User implements Serializable { 816 | private String id; 817 | private transient String password; 818 | private String email; 819 | } 820 | ~~~ 821 | 822 | - 클래스에서 다른 클래스를 의존하는 경우 의존 클래스도 Serializable 인터페이스를 구현해야 직렬화할 수 있다. 823 | 824 | - JVM의 메모리에서만 상주되어있는 객체 데이터를 그대로 **영속화(Persistence)** 가 필요할 때 사용된다. 825 | 826 | - CSV, JSON 등으로도 직렬화가 가능하다 827 | 828 | - CSV, JSON, 프로토콜 버퍼 등은 시스템의 고유 특성과 상관없는 대부분의 시스템에서의 데이터 교환 시 많이 사용됩니다. 829 | 830 | - **자바 직렬화 형태** 는 자바 시스템 간의 데이터 교환을 위해서 존재한다 831 | 832 | - 자바 직렬화의 장점 833 | > 자바 직렬화는 자바 시스템에서 개발에 최적화되어 있습니다. 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화 가능하다 834 | 835 | - 역직렬화시 데이터 타입이 자동으로 맞춰지기 때문에 편리 836 | - 역직렬화가 되면 기존 객체처럼 바로 사용할 수 있음 837 | 838 | - 주의점 839 | 840 | - 역직렬화가 되지 않을 때와 같은 예외처리는 필수 841 | - 용량이 크기 때문에 새롭게 스타트하는 서비스 같은 경우에는 생산성을 위해서 자바 직렬화를 그대로 이용한다고 해도 트래픽이 지속적으로 증가할 때에는 JSON 형태 또는 다른 형태의 직렬화로 바꿔주는 것 고려 -------------------------------------------------------------------------------- /java/libraries.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Libraries 4 | 1. swagger2 5 | [확인하기](https://lng1982.tistory.com/314) 6 | > API 문서화 / 테스팅 라이브러리 7 | 8 | 2. logback 9 | [확인하기](https://taetaetae.github.io/2017/02/19/logback/) 10 | > 로깅 라이브러리, 성능 좋음, 스프링부트에서 기본 제공중 11 | lombok의 @Slf4j 어노테이션 사용가능 12 | 13 | ~~~java 14 | import com.example.demo.domain.User; 15 | import com.example.demo.repository.UserRepository; 16 | import lombok.AllArgsConstructor; 17 | import lombok.extern.slf4j.Slf4j; 18 | import org.springframework.web.bind.annotation.GetMapping; 19 | import org.springframework.web.bind.annotation.PostMapping; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | @AllArgsConstructor 24 | @RestController 25 | @Slf4j 26 | @RequestMapping("/api/users") 27 | public class ApiUserController { 28 | private final UserRepository userRepository; 29 | 30 | @GetMapping("") 31 | public String getAllUsers(){ 32 | return "200 success"; 33 | } 34 | 35 | @PostMapping 36 | public User create(String name, String info){ 37 | User user = new User(name, info); 38 | try { 39 | return userRepository.save(user); 40 | }catch (RuntimeException ex) { 41 | log.warn(ex.getCause().getMessage()); 42 | return user; 43 | } 44 | } 45 | } 46 | ~~~ 47 | 3. freemarker 48 | > 템플릿 엔진 49 | 아래는 application.properties 관련 설정 50 | ~~~ 51 | spring.freemarker.template-loader-path=classpath:/templates 52 | spring.freemarker.suffix=.ftl 53 | ~~~ 54 | pom.xml 55 | ~~~xml 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-freemarker 60 | 2.1.3.RELEASE 61 | 62 | 63 | ~~~ -------------------------------------------------------------------------------- /js/js.md: -------------------------------------------------------------------------------- 1 | ## JavaScript 기본 2 | https://opentutorials.org/course/743/4650 3 | 4 | > 자바스크립트는 본래 웹 페이지를 동적으로 제어하기 위해 만들어진 언어 5 | 6 | ### 1. ECMAScript 7 | 자바스크립트 표준안, ESX 로 표현된다. 8 | 9 | ### 2. Features / Grammar 10 | 1. == 와 === 11 | - == 은 값이 같은지 비교 12 | - === 은 값, 타입 등이 같은지 모두 비교 13 | - == 은 java 의 equals, === 은 java 의 == 이라고 볼 수 있음 14 | 15 | 2. if / while / for 등 일반적인 조건문 / 반복문 다 있음 16 | 17 | ### 3. Hoisting 18 | > 끌어올리기, 호이스트는 변수의 정의가 범위에 따라 선언과 할당으로 분리되는 것을 말한다. 19 | 함수 내에서 변수가 정의되었다면, 선언이 함수의 최상위로 20 | 함수 밖 전역에서 변수가 정의되었다면, 선언이 전역 context 의 최상위로 변경된다. 21 | 22 | 1. 변수 호이스팅 23 | 24 | **코드로 보자** 25 | ~~~js 26 | // 1) 27 | // 아래의 함수는 에러가 나지 않는다. 28 | function() { 29 | console.log(x); 30 | var x = 100; 31 | } 32 | 33 | // 2) 34 | // 아래와 같이 선언과 할당이 분리되어 35 | // 선언이 최상위 맥락으로 올라가는 것인 Hoist 36 | function() { 37 | var x; 38 | console.log(x); 39 | x = 100; 40 | } 41 | ~~~ 42 | 43 | 1번 함수에서는 오류가 나지 않는다 (선언을 자바스크립트 엔진이 가장 최우선으로 해석) 44 | 그러나 값은 100이 아니라 undefined 로 출력된다 (할당은 런타임에 되기 때문) 45 | 46 | 2. 함수 호이스팅 47 | > 함수 선언이 함수 실행보다 뒤에 있더라도 자바스크립트 엔진이 함수 선언을 끌어올린다. 48 | 아래와 같은 상황에서 "foooooo" 는 정상적으로 출력된다. 49 | ~~~js 50 | foo(); 51 | function foo() { 52 | console.log("foooooo"); 53 | } 54 | // > foooooo 55 | ~~~ 56 | 57 | > 그러나 할당의 경우에는 Hoisting 이 안된다는 것을 기억하지 58 | ~~~js 59 | foo(); 60 | var foo = function(){ 61 | console.log("foooooo"); 62 | } 63 | // > Syntax Error! 64 | ~~~ 65 | 66 | ### 4. 익명함수와 IIFE (immediately-invoked function expression) 67 | 68 | #### 익명함수 69 | > 이름이 없는 함수, 자바스크립트에서는 이름 없는 함수 리터럴을 변수에도 할당이 가능하다. 70 | ~~~js 71 | const add = function (a, b) { return a + b }; 72 | ~~~ 73 | 74 | 그러나 아래와 같은 선언은 불가하다. 75 | 선언부가 없으면 이를 사용할 맥락이나 이를 할당해줄 변수가 무조건 필요하다. 76 | *(Hoisting을 할건지, 아니면 지금 바로 쓸껀지)* 77 | ~~~js 78 | function (a, b) { return a + b } 79 | // Uncaught SyntaxError: Unexpected token ( 80 | ~~~ 81 | 82 | 그래서 익명 함수를 쓰려면 아래 두가지 경우로 쓸 수 있다. 83 | ~~~js 84 | // 1. 변수에 함수 리터럴 할당하기 85 | const add = function (a, b) { return a + b }; 86 | 87 | // 2. 즉시 사용하기 (IIFE - 아래 참조) 88 | (function(a, b) { return a + b })(1, 2); 89 | ~~~ 90 | 91 | #### IIFE (immediately-invoked function expression) 92 | > 정의와 동시에 즉시 실행되는 함수 93 | 94 | 함수를 즉시 실행시킨다. 95 | IIFE 의 일반적인 형태는 아래와 같다. (함수 리터럴을 괄호로 감싼 형태) 96 | ~~~js 97 | function() {console.log("donsdev")}; // 함수 리터럴 98 | (function() {console.log("donsdev")})(); // IIFE 99 | ~~~ 100 | 101 | ### 5. 클로저 (Closure) 102 | 103 | > 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 클로져라고 한다 104 | 105 | 먼저 **일급 함수** 에 대한 이해가 필요하다. 106 | 자바스크립트는 일급 함수를 지원하므로 함수를 변수에 저장하거나, 파라미터를 함수로 넘기고, 함수에서 함수를 반환하는 것이 가능하다. 107 | 108 | 아래를 참고하자 109 | 110 | ~~~js 111 | var global_name = "홍길동"; 112 | 113 | function makePrinter() { 114 | var outer_name = "김철수"; 115 | 116 | function printName() { 117 | var inner_name = "김영희"; 118 | console.log(global_name); 119 | console.log(outer_name); 120 | console.log(inner_name); 121 | } 122 | 123 | return printName; 124 | } 125 | 126 | var print = makePrinter(); 127 | print(); 128 | ~~~ 129 | 130 | 결과 131 | ~~~ 132 | 홍길동 133 | 김철수 134 | 김영희 135 | ~~~ 136 | 137 | 아래 부분에서 print 변수에 할당된 것이 **클로저** 이다. 138 | ~~~js 139 | var print = makePrinter(); 140 | ~~~ 141 | 142 | 여기서 포인트는 print() 실행시, outer_name 을 그대로 가지고 출력한다는 것이다. 143 | 따라서 함수 안에 있는 함수인 클로저는 자신을 포함하고 있는 맥락(외부함수)의 인자, 지역변수를 기억하고 있다 라는 것이다. (makePrinter() 를 했는데도 살아있다) 144 | 이러한 변수들을 **자유 변수** 라고 한다. 145 | 146 | 클로저가 생성될 시점, 그 맥락의 지역 변수들을 자유 변수로 만드는 것을 (뭔가 그 상태 그대로 급냉하는 느낌) **캡쳐(capture)** 라고 한다. 이러한 자유변수들은 외부 접근에 의해 참조할 수 없으며, 오직 해당 closure을 이용해서만 접근할 수 있다. 객체 지향의 private 멤버 변수 같은 느낌을 가진다. 147 | 148 | From MDN : 149 | > 클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경(Scope)을 ‘기억한다’ 150 | 151 | **또 다른 예** 152 | 153 | ~~~js 154 | function getClosure() { 155 | var text = 'variable 1'; 156 | return function() { 157 | return text; 158 | }; 159 | } 160 | 161 | var closure = getClosure(); 162 | console.log(closure()); // 'variable 1' 163 | ~~~ 164 | 165 | getClosure 함수는 함수를 반환한다. 그리고 **반환된 함수**는 getClosure 의 스코프에서 선언된 변수를 참조하고 있다. 또한 참조된 변수는 함수 실행이 끝나고 반환되었다고 해서 사라지지 않았고 아래 함수의 사용에서 제대로 된 값을 반환하고 있다. 166 | 167 | 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다. 이러한 메커니즘을 클로저라고 한다. 168 | 169 | 여기서 반환된 함수가 **클로저** 이다. 170 | 171 | ### 6. var, let, const 172 | 173 | #### 1. var 174 | - function-scoped 175 | > 함수 안까지만 확장되는 스코프 176 | ~~~js 177 | // var 변수가 호이스팅 되어 정상적으로 j가 출력된다. 178 | for(var j=0; j<10; j++) { 179 | console.log('j', j) 180 | } 181 | console.log('after loop j is ', j) 182 | // after loop j is 10 183 | 184 | 185 | // 아래의 경우에는 function 스코프까지만 확장되어 186 | // 함수 밖에서 i 값을 참조할 수 없다. 187 | function counter () { 188 | for(var i=0; i<10; i++) { 189 | console.log('i', i) 190 | } 191 | } 192 | counter() 193 | console.log('after loop i is', i) 194 | // ReferenceError: i is not defined 195 | ~~~ 196 | 197 | var은 변수 재선언이 되고, 호이스팅 때문에 아래와 같은 문제가 있었다. 198 | ~~~js 199 | // 이미 만들어진 변수이름으로 재선언했는데 아무런 문제가 발생하지 않는다. 200 | var a = 'test' 201 | var a = 'test2' 202 | 203 | // hoisting으로 인해 ReferenceError에러가 안난다. 204 | c = 'test' 205 | var c 206 | ~~~ 207 | 208 | 따라서 생긴것이 let 과 const 이다. 209 | #### 2. let / const 210 | - let 은 변수 재선언이 불가하고, 재할당은 가능하다. 211 | - const 는 재선언 및 재할당 둘다 불가하다. 212 | 213 | let, const가 hoisting이 아예 발생하지 않는것은 아니다. 214 | var이 function-scoped로 hoisting 이 되었다면, 215 | let, const는 block-scoped 단위로 hoisting이 일어난다. 216 | 217 | ~~~js 218 | c = 'test' // ReferenceError: c is not defined 219 | let c 220 | ~~~ 221 | 위에 코드에서 ReferenceError가 발생한 이유는 호이스팅이 발생하지 않은 것이 아니라 **tdz(temporal dead zone)** 때문이다. 222 | 또한 const 는 선언과 동시 할당이 필수이다. 223 | 224 | ### 7. ES6 에서 추가된 기능 225 | https://jsdev.kr/t/es6/2944 226 | 227 | ES6 에서 추가된 주요 기능 228 | 1. Arrows (화살표 함수) 229 | ~~~js 230 | var evens = [2, 4, 6, 8,]; 231 | 232 | // Expression bodies (표현식의 결과가 반환됨) 233 | var odds = evens.map(v => v + 1); // [3, 5, 7, 9] 234 | var nums = evens.map((v, i) => v + i); // [2, 5, 8, 11] 235 | var pairs = evens.map(v => ({even: v, odd: v + 1})); // [{even: 2, odd: 3}, ...] 236 | 237 | // Statement bodies (블럭 내부를 실행만 함, 반환을 위해선 return을 명시) 238 | nums.forEach(v => { 239 | if (v % 5 === 0) 240 | fives.push(v); 241 | }); 242 | ~~~ 243 | 244 | 2. Classes 245 | ES6 클래스는 기존 프로토타입 기반 객체지향 패턴을 더 쉽게 사옹할 수 있도록 함 246 | 247 | ~~~js 248 | class SkinnedMesh extends THREE.Mesh { 249 | constructor(geometry, materials) { 250 | super(geometry, materials); 251 | 252 | this.idMatrix = SkinnedMesh.defaultMatrix(); 253 | this.bones = []; 254 | this.boneMatrices = []; 255 | //... 256 | } 257 | update(camera) { 258 | //... 259 | super.update(); 260 | } 261 | get boneCount() { 262 | return this.bones.length; 263 | } 264 | set matrixType(matrixType) { 265 | this.idMatrix = SkinnedMesh[matrixType](); 266 | } 267 | static defaultMatrix() { 268 | return new THREE.Matrix4(); 269 | } 270 | } 271 | ~~~ 272 | 273 | 3. Let, Const 274 | - var의 스코프는 전체 외부 함수까지이다. 275 | - let은 변수를 선언한 블록과 그 내부 블록들에서 유효 276 | 277 | 4. Iterator / Generator 278 | https://infoscis.github.io/2018/01/31/ecmascript-6-iterators-and-generators/ 279 | 280 | > 많은 프로그래밍 언어는 컬렉션에서 위치를 추적하기 위해 변수가 필요한 for 루프를 사용하여 데이터를 반복하는 것에서 컬렉션의 다음 항목을 반환하는 Iterator 객체를 사용하는 방식으로 전환했다. 281 | Iterator를 사용하면 데이터 컬렉션을 쉽게 처리할 수 있어 ES6 에서는 Iterator를 JavaScript에 추가했습니다. 282 | Iterator는 새로운 Array 메서드 및 새로운 타입의 컬렉션 (Set 및 Map)과 결합하여 데이터를 효율적으로 처리할수 있는 핵심 요소이며, 이러한 부분은 JavaScript의 여러곳에서 찾아볼 수 있다. 283 | 또한 Iterator와 함께 작동하는 새로운 for-of 루프가 있으며, Spread (...) 연산자에서도 Iterator를 사용할 수 있다. 284 | 그리고 Iterator는 비동기 프로그래밍을 더 쉽게 만들수 있게 한다. 285 | 286 | 287 | 288 | 5. Proxy 289 | > Spring AOP 처럼 사용 가능 290 | ~~~js 291 | // Proxying a function object 292 | var target = function () { return 'I am the target'; }; 293 | var handler = { 294 | apply: function (receiver, ...args) { 295 | return 'I am the proxy'; 296 | } 297 | }; 298 | 299 | var p = new Proxy(target, handler); 300 | p() // 'I am the proxy'; 301 | ~~~ 302 | 303 | 6. Promises 304 | > Promise는 미래에 생성되는 값을 나타내는 일급 객체이다. 305 | 306 | 7. Reflect API 307 | ~~~js 308 | class Greeting { 309 | constructor(name) { 310 | this.name = name; 311 | } 312 | 313 | greet() { 314 | return `Hello ${name}`; 315 | } 316 | } 317 | 318 | function greetingFactory(name) { 319 | return Reflect.construct(Greeting, [name], Greeting); 320 | } 321 | 322 | greetingFactory('a'); // Greeting {name: "a"} 323 | ~~~ -------------------------------------------------------------------------------- /network/network.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. OSI7 계층 4 | https://kwongyo.tistory.com/7 5 | > 컴퓨터 네트워크 통신과 프로토콜을 계층으로 나누어 설명한 것 6 | 7 | ![osi-7-layer](https://user-images.githubusercontent.com/26560119/64315569-60381e00-cfed-11e9-8ba3-c56d84afc151.png) 8 | 9 | - 각 계층은 하위 계층의 기능만을 이용하고, 상위 계층에게 기능을 제공한다. 10 | - 일반적으로 하위 계층들은 하드웨어로, 상위 계층들은 소프트웨어로 구현된다. 11 | - 네트워크 관리자는 어떤 문제의 원인이 어디에 있는지 범위를 좁힐 수 있다 12 | - 언제나 그렇듯 역할과 책임의 분리 (추상화) 13 | - 각 계층의 전달 단위는 프레임, 패킷, 세그먼트지만 데이터는 같고 헤더 정보만 다르다 (MAC, IP, PORT 등) 14 | - 아레 계층으로 가면서 헤더가 붙는다, application header -> TCP header -> IP header -> Ethernet header .. 15 | 16 | 1. 물리 계층 (Physical Layer) 17 | - 장치와 전송 매체 간에 인터페이스의 특성을 규정한다. 18 | - 비트 스트림으로 상대방에게 송신한다. 19 | - 네트워크 케이블, 주파수 등 연결과 관련된 HW 적인 Feature 이다. 20 | - 전송 단위는 Bit 이다 21 | 22 | 2. 데이터 링크 계층 (Data-link Layer) 23 | - **동일 네트워크 내** 의 노드간 데이터 전송을 나타낸다. 24 | - CRC 기반의 오류, 흐름 제어가 들어간다. (약하게) 25 | - 2계층의 흐름 제이는 두 노드 간 속도만 고려한다. 26 | - 오류 제어는 트레일러를 이용함 27 | - 네트워크 내의 노드 간 구분 주소는 MAC 28 | - Ethernet 헤더에 MAC 주소가 있다. 29 | - 대표적인 데이터링크 계층 프로토콜은 Ethernet 30 | - 저비용 / 비 연결성, 비 신뢰성 31 | - IEEE 802.11 은 이더넷의 단점을 보완 (로컬 site 간의 연결) 32 | - LTE는 재전송도 보장해 준다. 33 | - 데이터 전송 단위는 Frame (Bit -> Frame, Frame -> Bit) 34 | 35 | 3. 네트워크 계층 (Network Layers) 36 | - MAC 주소 가지고는 인터넷 통신불가, **네트워크 간 통신** 이 필요 37 | - 여러개의 노드를 거칠때마다 경로를 찾아주는 역할을 하는 계층 (Routing) 38 | - 라우팅, 흐름 제어, 세그멘테이션(segmentation/desegmentation), 오류 제어, 인터네트워킹(Internetworking) 39 | - 논리적인 주소 구조(IP), 곧 네트워크 관리자가 직접 주소를 할당하는 구조를 가짐 40 | - 데이터 전송 단위는 Datagram(Packet) 이다. 41 | 42 | 4. 전송 계층 (Transport Layer) 43 | - 가장 중요한 특성은 **신뢰성 보장**, 흐름 / 혼잡 / 오류 제어가 가능하다. 44 | - 오류제어는 세그먼트를 재전송 한다. 45 | - 흐름 제어의 경우, 2계층과는 다르게 통신하는 모든 hop을 고려한다. 46 | - 데이터 전송 단위는 Segment 인데, 순서 번호가 포함되어 있어 수신 측에서 조립이 가능하다 (UDP는 안됨) 47 | - TCP Header 에 포트 정보 (프로세스) 가 들어간다. 48 | - 연결은 비연결형 일 수 있고, 연결형 일 수도 있다. 49 | - 가장 잘 알려진 전송 계층의 예는 TCP이다. 50 | 51 | 5. 세션 계층 (Session Layer) 52 | - 사용자 위주의 추상화된 연결서비스 제공 53 | - 연결을 유지하기 위해서는 세션이 필요하다. 54 | - 응용 프로그램간의 대화(세션)을 유지하고 관리 55 | - 전송 모드 결정 (Half-Duplex, Full-Duplex emd) 56 | - 물리적 연결이 아닌 어플리케이션간의 세션을 구축하고 관리한다. 57 | 58 | 6. 표현 계층 (Presentation Layer) 59 | - 응용 계층의 다양한 데이터 형식을 전송형태의 구문으로 변환 60 | - JPEG, TIFF, GIF(그래픽 포맷), MPEG, QUICKTIME(동영상 포맷), MIDI(음악 포맷), RTF, ASCII, EBCDIC(텍스트 포맷)등을 받아들이고 공통 형식으로 반환 61 | - 데이터 암호화 / 데이터 압축 담당 62 | 63 | 7. 응용 계층 (Application Layer) 64 | - 사용자에게 서비스를 제공하며, 하위 계층에 정보나 명령을 전달한다. 65 | - 사용자가 직접 눈으로 보고 실제로 작업을 하는 계층이다. 66 | - telnet, HTTP, FTP, WWW, SMTP, POP 67 | 68 | ## 2. TCP / UDP 69 | > 네트워크 계층 중 전송(Transport) 계층에서 사용하는 프로토콜 70 | 71 | ### 1. TCP 72 | **신뢰성** 보장이 아주 중요한 키워드이다. 73 | 74 | tcp-virtual-circuit 75 | 76 | - 인터넷 상에서 세그먼트를 보내기 위해 IP와 함께 사용하는 프로토콜이다. 77 | - TCP와 IP를 함께 사용하는데, IP가 주소를 찾아주면 TCP는 흐름 제어, 혼잡 제어 등 신뢰성을 보장한다. 78 | - 흐름제어 (**Host to Host** / 송신측이 수신측보다 과하게 빠른 문제 해결) 79 | - 데이터를 송신하는 곳과 수신하는 곳의 데이터 처리 속도를 조절하여 수신자의 버퍼 오버플로우를 방지하는 것 80 | - 송신하는 곳에서 감당이 안되게 많은 데이터를 빠르게 보내 수신하는 곳에서 문제가 일어나는 것을 막는다. 81 | - 혼잡제어 (**Host to Network** / **네트워크**의 과부하 조절) 82 | - 네트워크 내의 패킷 수가 넘치게 증가하지 않도록 방지하는 것 83 | - 정보의 소통량이 과다하면 패킷을 조금만 전송하여 혼잡 붕괴 현상이 일어나는 것을 막는다 84 | - **연결형 서비스이다** 85 | - 3-way handshaking과정을 통해 연결을 설정하고, 4-way handshaking을 통해 연결을 해제한다. 86 | - https://github.com/WeareSoft/tech-interview/blob/master/contents/network.md#tcp%EC%9D%98-3-way-handshake%EC%99%80-4-way-handshake 87 | - 전이중(Full-Duplex), 점대점(Point to Point) 방식이다. 88 | - 전이중 89 | - 전송이 양방향으로 동시에 일어날 수 있다. 90 | - 점대점 91 | - 각 연결이 정확히 2개의 종단점을 가지고 있다. 92 | - UDP보다 속도가 느리다. 93 | 94 | #### 흐름제어와 혼잡제어 방법 95 | 96 | 1. 흐름제어 97 | 98 | 1. Stop And Wait 99 | 100 | > 매번 전송한 패킷에 대해 확인응답을 받아야 다음 패킷 전송 101 | 102 | 2. Sliding Window 103 | 104 | > 수신측 응답에 따라 윈도우 (버퍼) 를 이용하여 흐름을 제어한다. 105 | 106 | 107 | ### 2. UDP 108 | **비연결형 프로토콜** 이라는 점에 주목 109 | 110 | udp-datagram 111 | 112 | - 4계층 프로토콜이긴 한데 IP만 보고 움직임 113 | - 패킷 단위로 전송 114 | - TCP 처럼 연결형이 아니라, 데이터 순서 보장 X (지맘대로 감) 115 | - 그대신 빠름 (스트리밍에 적합) 116 | - UDP헤더의 CheckSum 필드를 통해 최소한의 오류만 검출한다. 117 | - 흐름제어(flow control)가 없어서 패킷이 제대로 전송되었는지, 오류가 없는지 확인할 수 없다. (성능 중시) 118 | 119 | ## 3. 3-way handshake / 4-way handshake 120 | ### 1. 3-way handshake (연결 시작) 121 | 122 | ![222D873E5815FD142E](https://user-images.githubusercontent.com/26560119/64319805-359f9280-cff8-11e9-970a-b95c6d6bff14.jpeg) 123 | 124 | 1. A : SYN (포트 열어라 새끼야) 125 | 2. B : ACK (알겠어), SYN (근데 너도 포트 열어) 126 | 3. A : ACK (OK 나도 열었어) 127 | 128 | ### 2. 4-way handshake (연결 종료) 129 | 130 | ![2301313E5815FF5A27](https://user-images.githubusercontent.com/26560119/64319806-359f9280-cff8-11e9-8967-3e58713cb604.png) 131 | 132 | 1. A : FIN (얀결 끊자) 133 | 2. B : ACK (OK, 끊자는 메시지 받았어) ... 일 처리하던거 마무리 134 | 3. A : ... 대기중 135 | 4. B " FIN (나 연결 끊었어) 136 | 5. A : ACK (OK 나도 좀만 기다리다 끊을게) 137 | 6. A : TIME WAIT 138 | 139 | ## 4. HTTP 140 | > HTTP => Hyper Text Transfer Protocol 141 | 인터넷에서 데이터를 주고받을 수 있는 프로토콜, 142 | 웹 서버와 클라이언트 간의 통신을 하기 위한 통신 규약 143 | 144 | ### 1. 주요 특징 145 | - HTTP 는 웹에서만 사용하는 프로토콜이며, TCP/IP 기반이다. 146 | - HTTP는 비연결성 프로토콜이다 147 | - 비연결성의 단점보완을 위해 Cookie와 Session 등장 148 | - 응답은 html 뿐 아니라 json, xml 등으로도 받을 수 있다. 149 | 150 | ### 2. HTTP Method 151 | 1. GET 152 | - 데이터가 URL에 노출된다. 153 | ~~~ 154 | www.urladdress.xyz?name1=value1&name2=value2 155 | ~~~ 156 | - **무언가를 가져오는 요청 (select), 상태변화 X** 157 | - HTTP 패킷의 Body는 비어 있는 상태로 전송한다. 158 | 즉, Body의 데이터 타입을 표현하는 'Content-Type' 필드도 HTTP Request Header에 들어가지 않는다. 159 | - 브라우저 캐싱을 지원하여 빠르다 160 | 161 | 2. POST 162 | - 요청 정보를 HTTP 패킷의 Body 안에 숨겨서 서버로 전송한다. 163 | - **서버의 값이나 상태를 바꾸기 위한** 용도의 메서드 164 | - Insert, Update, Delete 165 | - Request Header의 Content-Type에 해당 데이터 타입이 표현됨 166 | application/octet-stream , text/plain, multipart/form-data 등 167 | 168 | 3. HEAD 169 | - Get Response 헤더 정보만 받아오겠다. 170 | - 특정 리소스를 GET 으로 요청하는 경우에 어떤 헤더들이 반환되는지를 요청 171 | - 예를 들어, 큰 용량의 리소스를 다운로드 받을지 말지 결정하기 위해서 사전 요청하는 용도로 사용할 수 있습니다. 172 | 173 | 4. PUT 174 | - 요청된 자원을 수정(UPDATE) 및 생성(CREATE) 한다 175 | - 정확히는 멱등함수와 비슷하게, 지정 위치에 덮어쓰는 느낌이다. (없으면 삽임한다) 176 | - 자원내 모든 필드영역 업데이트 (DB 1 ROW 전체 수정) 177 | - 만약 일부만 전달할 경우, 그외의 필드 모두 null or 초기값 처리 178 | - 따라서 PUT 잘못쓰면 골로간다 179 | - 보안 위협 180 | 181 | 5. PATCH 182 | - PUT과 유사하게 요청된 자원을 수정(UPDATE)할 때 사용한다. 183 | - PUT의 경우 자원 전체를 갱신하는 의미지만, PATCH는 해당자원의 일부를 교체하는 의미로 사용. 184 | 185 | 6. DELETE 186 | - 자원 삭제 187 | - 보안 위협 188 | 189 | 7. OPTIONS 190 | - 요청한 URL이 어떤 http 메서드를 지원 하는지 체크할 때 사용한다 191 | - response 헤더에 Allow 에 가능한 메서드가 적혀온다 192 | - 보안 위협 193 | 194 | 8. TRACE 195 | - 받은 메시지를 다시 돌려보낸다. 196 | 197 | 9. CONNECT 198 | - 프록시에 사용하기 위해 예약된 메서드이다 199 | - 프록시 서버의 기본적인 동작은 클라이언트로부터 전달받은 리퀘스트를 서버로 전달하고, 서버에서 받은 응답을 클라이언트에 전달하는 역할을 한다. 200 | - 프록시의 사용 목적은 네트워크 캐싱, 조직내의 특정 웹사이트 액세스 방지, 액세스 로그 획득 등이 있다. 201 | 202 | ### 3. HTTP Request / Response 헤더 203 | > 요청의 경우 일단 헤더 앞에는 `GET / HTTP/1.1` 이런식으로 적혀있다. 204 | 응답의 경우 헤더 앞에는 `HTTP/1.1 200 OK` 라고 적혀있음 205 | - HTTP 헤더 - 일반 헤더 (General Header) 206 | - 요청 및 응답 메시지 모두에서 사용 가능한 일반 목적의(기본적인) 헤더 항목 207 | - 주요 항목 208 | - **Date**: HTTP 메시지를 생성한 일시 209 | - `Date: Sat, 2 Oct 2018 02:00:12 GMT` 210 | - **Connection**: 클라이언트와 서버 간 연결에 대한 옵션 설정 211 | - `Connection: close` => 현재 HTTP 메시지 직후에 TCP 접속을 끊는다는 것을 알림 212 | - `Connection: Keep-Alive` => 현재 TCP 커넥션을 유지 213 | - **Cache-Control** 214 | - `Cache-Control: no-store` => 캐시 안쓴다 215 | - `Cache-Control: no-cache` => 모든 캐시를 쓰기 전에 서버에 이 캐시 진짜 써도 되냐 물어보라는 뜻 216 | ... 이 외에도 몇가지 있음 217 | - **Pragma** 218 | - http 1.0 레거시, 캐시 컨트롤이랑 같음 219 | - **Trailer** 220 | - http 헤더 뒤에 임의 추가 가능 221 | ~~~ 222 | HTTP/1.1 200 OK 223 | Content-Type: text/plain 224 | Transfer-Encoding: chunked 225 | Trailer: Expires 226 | 7\r\n 227 | Mozilla\r\n 228 | 9\r\n 229 | Developer\r\n 230 | 7\r\n 231 | Network\r\n 232 | 0\r\n 233 | Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n 234 | \r\n 235 | ~~~ 236 | - HTTP 헤더 - 엔터티 헤더 (Entity Header) 237 | - 요청 및 응답 메시지 모두에서 사용 가능한 Entity(콘텐츠, 본문, 리소스 등)에 대한 설명 헤더 238 | - 주요 항목들 239 | - **Content-Type**: 해당 개체에 포함되는 미디어 타입 정보 240 | - 컨텐츠의 타입(MIME 미디어 타입) 및 문자 인코딩 방식(EUC-KR,UTF-8 등)을 지정 241 | - 타입 및 서브타입(type/subtype)으로 구성 242 | - `Content-Type: text/html; charset-latin-1` => 해당 개체가 html으로 표현된 텍스트 문서이고, iso-latin-1 문자 인코딩 방식으로 표현됨 243 | - **Content-Language**: 해당 개체와 가장 잘 어울리는 사용자 언어(자연언어) 244 | - **Content-Encoding**: 해당 개체 데이터의 압축 방식 245 | - `Content-Encoding: gzip, deflate` 246 | - 만일 압축이 시행되었다면, Content-Encoding 및 Content-Length 2개 항목을 토대로 압축 해제 가능 247 | - **Content-Length**: 전달되는 해당 개체의 바이트 길이 또는 크기(10진수) 248 | - **Content-Location**: 해당 개체가 실제 어디에 위치하는가를 알려줌 249 | - **Content-Disposition**: 응답 Body를 브라우저가 어떻게 표시해야 할지 알려주는 헤더 250 | - inline인 경우 웹페이지 화면에 표시되고, attachment인 경우 다운로드 251 | - `Content-Disposition: inline` 252 | - `Content-Disposition: attachment; filename='filename.csv'` 253 | - **Content-Security-Policy**: 다른 외부 파일들을 불러오는 경우, 차단할 소스와 불러올 소스를 명시 254 | - *XSS 공격*에 대한 방어 가능 (허용한 외부 소스만 지정 가능) 255 | - `Content-Security-Policy: default-src https:` => https를 통해서만 파일을 가져옴 256 | - `Content-Security-Policy: default-src 'self'` => 자신의 도메인의 파일들만 가져옴 257 | - `Content-Security-Policy: default-src 'none'` => 파일을 가져올 수 없음 258 | - **Location**: 리소스가 리다이렉트(redirect)된 때에 이동된 주소, 또는 새로 생성된 리소스 주소 259 | - 300번대 응답이나 201 Created 응답일 때 어느 페이지로 이동할지를 알려주는 헤더 260 | - 새로 생성된 경우에 HTTP 상태 코드 `201 Created`가 반환됨 261 | - `HTTP/1.1 302 Found Location: /` 262 | - 이런 응답이 왔다면 브라우저는 / 주소로 redirect한다. 263 | - **Last-Modified**: 리소스를 마지막으로 갱신한 일시 264 | - HTTP 헤더 내 요청 헤더 (Request Header) 항목 265 | - 요청 헤더는 HTTP 요청 메시지 내에서만 나타나며 가장 방대하다. 266 | - 주요 항목들 267 | - **Host**: 요청하는 호스트에 대한 호스트명 및 포트번호 (***필수***) 268 | - Host 필드에 도메인명 및 호스트명 모두를 포함한 전체 URI(FQDN) 지정 필요 269 | - 이에 따라 동일 IP 주소를 갖는 단일 서버에 여러 사이트가 구축 가능 270 | - **User-Agent**: 클라이언트 소프트웨어(브라우저, OS) 명칭 및 버전 정보 271 | - **From**: 클라이언트 사용자 메일 주소 272 | - 주로 검색엔진 웹 로봇의 연락처 메일 주소를 나타냄 273 | - 때로는, 이 연락처 메일 주소를 User-Agent 항목에 두는 경우도 있음 274 | - **Cookie**: 서버에 의해 Set-Cookie로 클라이언트에게 설정된 쿠키 정보 275 | - **Referer**: 바로 직전에 머물었던 웹 링크 주소 276 | - **If-Modified-Since**: 제시한 일시 이후로만 변경된 리소스를 취득 요청 277 | - **Authorization**: 인증 토큰(JWT/Bearer 토큰)을 서버로 보낼 때 사용하는 헤더 278 | - 토큰의 종류(Basic, Bearer 등) + 실제 토큰 문자를 전송 279 | - **Origin** 280 | - POST 요청 주소 281 | - 여기서 요청을 보낸 주소와 받는 주소가 다르면 **CORS 에러** 가 발생 282 | - 응답 헤더의 **Access-Control-Allow-Origin**와 관련 283 | - 다음 4개는 주로 HTTP 메세지 Body의 속성 또는 내용 협상용 항목들 284 | - **Accept**: 클라이언트 자신이 원하는 미디어 타입 및 우선순위를 알림 285 | - `Accept: */*` => 어떤 미디어 타입도 가능 286 | - `Accept: image/*` => 모든 이미지 유형 287 | - **Accept-Charset**: 클라이언트 자신이 원하는 문자 집합 288 | - **Accept-Encoding**: 클라이언트 자신이 원하는 문자 인코딩 방식 289 | - **Accept-Language**: 클라이언트 자신이 원하는 가능한 언어 290 | - 각각이 HTTP Entity Header 항목 중에 `Content-Type, Content-Type charset-xxx, Content-Encoding, Content-Language`과 일대일로 대응됨 291 | - HTTP 헤더 내 응답 헤더 (Response Header) 항목 292 | - 특정 유형의 HTTP 요청이나 특정 HTTP 헤더를 수신했을 때, 이에 응답한다. 293 | - 주요 항목들 294 | - **Server**: 서버 소프트웨어 정보 295 | - **Accept-Range** 296 | - **Set-Cookie**: 서버측에서 클라이언트에게 세션 쿠키 정보를 설정 (RFC 2965에서 규정) 297 | - **Expires**: 리소스가 지정된 일시까지 캐시로써 유효함 298 | - **Age**: 캐시 응답. max-age 시간 내에서 얼마나 흘렀는지 알려줌(초 단위) 299 | - **ETag**: HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그 300 | - **Proxy-authenticate** 301 | - **Allow**: 해당 엔터티에 대해 서버 측에서 지원 가능한 HTTP 메소드 리스트 302 | - 때론, HTTP 요청 메세지의 HTTP 메소드 OPTIONS에 대한 응답용 항목 303 | - OPTIONS: 웹서버측 제공 HTTP 메소드에 대한 질의 304 | - `Allow: GET,HEAD` => 웹 서버측이 제공 가능한 HTTP 메서드는 GET,HEAD 뿐임을 알림 (405 Method Not Allowed 에러와 함께) 305 | - **Access-Control-Allow-Origin**: 요청을 보내는 프론트 주소와 받는 백엔드 주소가 다르면 *CORS 에러*가 발생 306 | * 서버에서 이 헤더에 프론트 주소를 적어주어야 에러가 나지 않는다. 307 | * `Access-Control-Allow-Origin: www.zerocho.com` 308 | * 프로토콜, 서브도메인, 도메인, 포트 중 하나만 달라도 CORS 에러가 난다. 309 | * `Access-Control-Allow-Origin: *` 310 | * 보안 박살 311 | * 유사한 헤더로 `Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Headers` 등이 있다. 312 | ### 4. HTTP Keep-Alive 313 | HTTP 는 비연결 방식으로 연결을 매번 만들고 끊는 구조이다. 314 | 이는 많은 비용이 드므로, HTTP 1.1 부터는 Keep-Alive (연결 유지) 를 제공한다. 315 | 316 | - HTTP/1.1부터 지원하는 기능으로 TCP 연결을 재사용하는 기능이다. 317 | - Handshake 과정이 생략되므로 성능 향상을 기대 할 수 있다 (TCP 소켓 세션 유지) 318 | - 모든 TCP 세션을 무한정 유지할 수는 없으므로 Timeout 및 Max 설정을 통해 관리되어야 한다. 319 | - 연결된 Socket에 IO 의 Access가 마지막으로 종료된 시점부터 320 | 정의된 시간까지 Access가 없더라도 세션을 유지하는 구조이다. 321 | - 정의된 시간내에 Access가 이루어진다면 계속 연결된 상태를 유지할 수 있게 된다. 322 | 323 | ### 5. HTTP Status Code 324 | 325 | #### 100 - 199 : 정보성 상태 코드 326 | 327 | - 100 : 요청의 시작 부분 일부가 받아들여졌으며, 클라이언트는 나머지를 계속 이어서 보내야 함을 의미함 328 | 329 | - 101 : 요청자가 서버에 프로토콜 전환을 요청했으며, 서버에서 이를 승인하는 중을 의미함 330 | 331 | #### 200 - 299 : 성공 상태 코드 332 | 클라이언트가 요청을 보내면, 요청은 대게 성공함. 서버는 대응하는 성공을 의미하는 각각의 요청에 대응한다. 333 | 334 | - 200 : 요청은 정상이고, 본문은 요청된 리소스를 포함하고 있다. (OK) 335 | 336 | - 201 : 어떠한 생성 작업을 요청받았으며, 생성 작업을 성공하였다. (CREATED) 337 | 338 | - 202 : 요청은 받아들여졌으나, 아직 동작을 수행하지 않은 상태로 요청이 적절함을 의미함 339 | 340 | - 203 : 요청을 성공하였지만, 요청에 대한 검증이 되지 않은 상태를 의미함 341 | 342 | - 204 : 요청을 성공하였지만, 제공할 내용이 없음을 의미 343 | 344 | - 205 : 204와 동일하지만 새로고침등을 통해 새로운 내용등을 확인할것을 추가로 의미 345 | 346 | - 206 : 요청의 일부분만 성공하였음을 의미 347 | 348 | #### 300 - 399 : 리다이렉션 상태 코드 349 | 클라이언트에 요청에 대해 적절한 다른 위치를 제공하거나, 대안의 응답을 제공한다. 350 | 351 | - 300 : 클라이언트가 동시에 여러 응답을 가리키는 URL을 요청한 경우 응답 목록과 함께 반환된다.(ex] 어떠한 HTML에 문서에 대한 영문페이지와 불어페이지를 요청) 352 | 353 | - 301 : 요청한 URL이 옮겨졌을 때 사용. 옮겨진 URL에 대한 정보와 함께 응답되어야 한다. 354 | 355 | - 302 : 301과 동일하나, 클라이언트는 여전히 옮겨지기전 URL로 요청할것을 의미 356 | 357 | - 303 : 요청받은 행동 수행을 위해서는 다른 URL로 요청 해야함을 의미 358 | 359 | - 304 : 이전의 동일한 요청과 비교하여 변화가 없음을 의미 (단시간에 반복된 동일 요청에 대한 대응 코드) 360 | 361 | - 305 : 직접적인 요청이 아니라 반드시 프락시(우회경로)를 통해 요청되어야 함을 의미 362 | 363 | - 307 : 302와 동일하며, HTTP Method도 변경없이 요청하여야 함을 의미 364 | 365 | #### 400 - 499 : 클라이언트 에러 상태 코드 366 | 클라이언트의 잘못된 요청에 대한 대응 코드 367 | 368 | - 400 : 클라이언트가 올바르지 못한 요청을 보내고 있음을 의미 (BAD REQUEST) 369 | 370 | - 401 : 요청을 위해서는 권한 인증등을 요구함을 의미 (NOT AUTHORIZED) 371 | 372 | - 403 : 요청이 서버에 의해 거부 되었음을 의미 (FORBIDDEN) 373 | 374 | - 404 : 요청한 URL을 찾을 수 없음을 의미 (NOT FOUND) 375 | 376 | - 405 : 요청한 URL이 Method를 지원하지 않음을 의미 (ex] POST요청에 대한 응답을 하는 URL에 GET으로 요청) (NOT ALLOWED) 377 | 378 | #### 500 - 599 : 서버 에러 상태 코드 379 | 올바른 클라이언트 요청에 대해 서버의 문제로 응답 할 수 없음을 의미 380 | 381 | - 500 : 서버에 오류가 발생하여 응답 할 수 없음을 의미 382 | 383 | - 501 : 클라이언트 요청에 대한 서버의 응답 수행 기능이 없음을 의미 384 | (ex : 서버가 지원하지 않는 새로운 Method를 사용하여 요청 - GET2, POST2...) 385 | 386 | - 502 : 프락시나 게이트웨이등의 서버에서 응답하며, 서버의 모(엄마)서버에서 오류가 발생하였음을 의미 387 | 388 | - 503 : 현재 서버가 유지보수 등의 이유로 일시적인 사용 불가함을 의미 389 | 390 | - 504 : 서버에서 다른 서버로 요청을 보냈으나, 응답 지연이 발생하여 처리가 불가함을 의미 391 | 392 | - 505 : 서버가 지원할 수 없거나 올바르지 못한 프로토콜로 요청을 받았음을 의미 393 | 394 | ### 6. CORS란 (Cross Origin Resource Sharing) 395 | > 웹 서버에게 보안 cross-domain 데이터 전송을 활성화하는 cross-domain 접근 제어권을 부여한다. 396 | - 배경 397 | - 처음 전송되는 리소스의 도메인과 다른 도메인으로부터 리소스가 요청될 경우 해당 리소스는 cross-origin HTTP 요청에 의해 요청된다. 398 | - 보안 상의 이유로, 브라우저들은 스크립트 내에서 초기화되는 cross-origin HTTP 요청을 제한한다. 399 | - 예를 들면, XMLHttpRequest는 same-origin 정책을 따르기에 XMLHttpRequest을 사용하는 웹 애플리케이션은 자신과 동일한 도메인으로 HTTP 요청을 보내는 것만 가능했다. 400 | - 웹 애플리케이션을 개선시키기 위해, 개발자들은 브라우저 벤더사들에게 XMLHttpRequest가 cross-domain 요청을 할 수 있도록 요청했고 이에 따라 CORS가 생겼다. 401 | - 과정 402 | - CORS 요청 시에는 미리 OPTIONS 주소로 서버가 CORS를 허용하는지 물어본다. 403 | - 이때 Access-Control-Request-Method로 실제로 보내고자 하는 메서드를 알리고, 404 | - Access-Control-Request-Headers로 실제로 보내고자 하는 헤더들을 알린다. 405 | - Allow 항목들은 Request에 대응되는 것으로, 서버가 허용하는 메서드와 헤더를 응답하는데 사용된다. (preflight) 406 | - Request Header 의 Origin과 Allow가 일치하면 CORS 요청이 이루어진다. 407 | 408 | > - [https://zamezzz.tistory.com/137](https://zamezzz.tistory.com/137) 409 | 410 | ### 7. HTTPS / HTTP2 411 | #### 1. HTTPS 412 | > HyperText Transfer Protocol over Secure Socket Layer 413 | 414 | - HTTPS는 소켓 통신에서 일반 텍스트를 이용하는 대신에, 웹 상에서 정보를 암호화하는 SSL이나 TLS 프로토콜을 통해 세션 데이터를 암호화한다. 415 | 416 | - HTTPS의 원리 417 | - 공개키 알고리즘 (공개키는 암호화에, private 키는 복호화에) 418 | 1. 사용자의 데이터를 공개키로 암호화 (공개키를 얻은 인증된 사용자) 419 | 2. 서버로 전송 (데이터를 가로채도 개인키가 없으므로 복호화할 수 없음) 420 | 3. 서버의 개인키를 통해 복호화하여 요청 처리 421 | 422 | - 사용자 인증 방법 423 | - 클라이언트가 서버에 접속한 직후에, 서버는 클라이언트에게 이 인증서 정보를 전달한다. 클라이언트는 이 인증서 정보가 신뢰할 수 있는 것인지를 검증 한 후에 다음 절차를 수행하게 된다 (SSL 인증서에 공개키 포함) 424 | - 그리고 SSL 인증서 안에는 CA (인증서 발급 조직) 가 있는데, 브라우저가 미리 CA 리스트를 파악하고 있고, 여기에 있는 것이 공인된 CA 다. 425 | 426 | #### 2. HTTP2 427 | > 웹 페이지 로드 시 리소스가 예전에 비해 많이 커지면서 이에대한 부분을 더 효율적으로 만들어주는데 초점을 맞춤 428 | 429 | 1. Binary Framework 430 | 431 | 스크린샷 2019-09-16 오후 2 29 55 432 | 433 | - 기존 text 기반 Header 와 Body 대신 HTTP/2 는 전송에 필요한 메시지들을 Binary 단위로 구성하여 더 작은 프레임으로 쪼개서 관리하고 송신한다. 434 | 435 | 기존에 텍스트 기반으로 Header 와 Data 가 연결되고 있던 1.1 이하 버전과 다르게 HTTP/2 는 전송에 필요한 메시지들을 Binary 프레임 단위로 구성하며 필요 정보를 더 작은 프레임으로 쪼개서 관리한다. 436 | 437 | 2. Multiplexing 개선 438 | - 멀티플렉싱이란 한 connection 에서 여러개의 요청을 동시에 송/수신 할 수 있도록 하는 것 439 | - 기존 HTTP/1.x 에서는 순차 전송하거나 병렬 요청 응답을 위해서는 여러 연결이 필요했음 440 | 441 | 442 | 443 | VS 444 | 445 | 446 | 447 | 이것이 가능한 이유는 HTTP2 는 패킷을 Frame 단위로 세분화하여 순서에 상관없이 받는쪽에서 ***조립*** 하도록 설계하였기 때문이다 448 | 449 | 3. Header Compression 450 | 헤더 압축 지원 451 | 452 | 4. Server Push 453 | 454 | 455 | 456 | - HTTP/1.1에서 클라이언트는 요청한 HTML 문서를 수신한 후 HTML 문서를 해석하면서 필요한 리소스를 재 요청한다. 457 | 458 | - 그러나 HTTP/2에선 Server Push기법을 통해서 클라이언트가 요청하지도 않은 (HTML문서에 포함된 리소스) 리소스를 서버가 직접 Push 해주는 방법으로 클라이언트의 요청을 최소화 해서 성능 향상을 이끌어 낸다. **이벤트 기반**으로 동작한다. 459 | 460 | 461 | ### 5. HTTP **VS** Socket 462 | #### HTTP 463 | - Half Duplex 464 | - 서버 - 클라이언트간 상태를 유지하지 않는다. 465 | - 따라서 서버 요청 처리후 다시 TCP Connection 을 맺어주어야 함 466 | - 요청 - 응답 - close (keep alive 가능) 467 | 468 | #### TCP Socket 469 | - 요청 - 응답 - 요청 - 응답 - 강제종료 470 | 471 | ## 5. 쿠키와 세션 472 | - HTTP 프로토콜에서 상태를 유지하기 위한 기술로 쿠키와 세션이 있다. 473 | ### 쿠키 (Cookie) 474 | - 클라이언트에 저장되는 Key, Value 475 | - 이름, 값, 유호 시간, 경로 등을 포함하고 있다. 476 | - 클라이언트의 상태 정보를 브라우저에 저장하여 참조한다. 477 | 478 | #### 구성 요소 479 | - 쿠키의 이름(name) 480 | - 쿠키의 값(value) 481 | - 쿠키의 만료시간(Expires) 482 | - 쿠키를 전송할 도메인 이름(Domain) 483 | - 쿠키를 전송할 경로(Path) 484 | - 보안 연결 여부(Secure) 485 | - HttpOnly 여부(HttpOnly) 486 | 487 | 488 | 489 | ### 세션 (Session) 490 | 1. 웹브라우저가 서버에 Request 491 | 2. 서버가 해당 웹브라우저(클라이언트)에 유일한 ID(Session ID)를 부여함 492 | 3. 서버가 응답할 때 HTTP 헤더(Set-Cookie)에 Session ID를 포함해서 전송 493 | 4. 쿠키에 Session ID를 JSESSIONID 라는 이름으로 저장 494 | `Set−Cookie: JSESSIONID=xslei13f` 495 | 5. 웹브라우저는 웹브라우저를 닫기까지 다음 요청 때 부여된 Session ID가 담겨있는 쿠키를 HTTP 헤더에 넣어서 전송 496 | `Cookie: JSESSIONID=xslei13f` 497 | 6. 서버는 세션 ID 기반으로 응답 498 | 499 | ### 쿠키와 세션의 차이점 500 | #### 1. 저장 위치 501 | 쿠키 : 클라이언트 502 | 세션 : 서버 503 | #### 2. 보안 504 | 쿠키 : 클라이언트에 저장되므로 보안에 취약하다. 505 | 세션 : 쿠키를 이용해 Session ID 만 저장하고 이 값으로 구분해서 서버에서 처리하므로 비교적 보안성이 좋다. 506 | #### 3. 라이프사이클 507 | 쿠키 : 만료시간에 따라 브라우저를 종료해도 계속해서 남아 있을 수 있다. 508 | 세션 : TimeOut 도 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다. 509 | #### 4. 속도 510 | 쿠키 : 클라이언트에 저장되어서 서버에 요청 시 빠르다. 511 | 세션 : 실제 저장된 정보가 서버에 있으므로 서버의 처리가 필요해 쿠키보다 느리다. 512 | 513 | ## 6. 주소창에 URL 입력 시 일어나는 일들 514 | 1. 브라우저의 url 파싱 515 | ~~~java 516 | http: // 통신 규약 517 | www.example.com =//주소 518 | :80 // 포트, 입력 x 시 표준 HTTP 포트 [http 80, https 443] 사용 519 | /path/to/myfile.html // 웹 서버에서 자원에 대한 경로 (라우팅) 520 | ?key1=value1&key2=value2 (파라미터) 521 | ~~~ 522 | 523 | 2. DNS 서버 검색 524 | 1. 브라우저 캐시에 남아 있으면, 바로 해당되는 서버 IP를 반환하고 525 | 2. ISP의 DNS 해석기에게 주소를 해석하여 IP로 반환시킨다 526 | 527 | 3. ARP Request (2계층 Data-Link) 528 | 1. IP 주소로는 해당 지역 라우터까지 접근 가능 529 | **라우터** 에서는 IP 주소에 해당하는 컴퓨터가 누군지 알아내기 위해 MAC 주소가 필요 530 | 2. 클라이언트는 가장 먼저 ARP 캐시에 확인 531 | 3. 캐시 (ARP 테이블) 에 없다면 ARP요청 패킷을 해당 IP 라우터에 브로드캐스트로 전송 532 | 4. 해당되는 수신자만 자신의 논리주소와 물리주소를 넣어 응답 패킷을 유니캐스트로 전송 533 | 534 | 4. TCP Connection (Client -> Server) 535 | - 네트워크 4계층 (Transport, ip와 port 기반 TCP 소켓 연결) 536 | 537 | - 소켓은 통신을 원하는 프로세스에 할당되는 자원이며 서로다른 site의 두 프로세스가 네트워크를 통해 서로 통신할 수 있는 통신 접속점 (포트 기반) 538 | - 아래는 TCP/IP 4계층 539 | 540 | 541 | 1. 3 way handshake (연결) 542 | 2. 4 way handshake (해제) 543 | 544 | 5. http Request 송신 545 | - http 메시지 송신 (GET, POST 등 메서드 / 수신자 / 요청 자원 등 포함) 546 | 547 | 6. 서버 처리 (웹 서버, 웹 어플리케이션 서버) 548 | - Tomcat 같은 서블릿 컨테이너가 받아서 동적 처리 549 | - 서블릿 doGet doPost .. 디스패쳐서블릿 .. 페이지 컨트롤러 - 비즈로직 - 뷰리졸버 550 | 7. TCP Connection (Server -> Client) 551 | 552 | 8. 서버 측 http Response 송신 553 | 554 | 9. 클라이언트는 http Response 를 받아서 사용자에게 노출 555 | 556 | ## 7. REST 557 | https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html 558 | 559 | **Representational State Transfer** 560 | > **URI(Uniform Resource Identifier)** 를 통해 **자원(Resource)** 을 명시하고, HTTP Method (POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 **행위(CRUD operation)** 을 명시하고 표현(html, json ...) 하는 것 561 | 562 | **무언가를 지우는 일** 563 | ~~~ 564 | post/delete/1 565 | ~~~ 566 | 이렇게 쓰는것이 아니라 헤더에 method 를 명시하고 567 | ~~~ 568 | post/1 569 | ~~~ 570 | 이렇게 지우는 행위를 표현하는 것이 RESTful 571 | 572 | 573 | ## 8. 소켓 / 전문 통신 574 | 575 | ### 1. 소켓 576 | > 두 프로세스간 네트워크를 통해 통신을 수행할 수 있도록 양쪽에 생성되는 링크의 단자 577 | 네트워크 4계층 (Transport)의 TCP/IP와 관련되어 있음 (연결형 서비스) 578 | - TCP : 패킷 전달 규약 (전달받은 패킷 재조립, 손상 시 재전송 받음 - 흐름제어) 579 | - IP : TCP는 경로에 대한 규약은 아니기 때문에 라우팅 관련 IP와 같이 사용됨 580 | - 통신을 위해서는 즉, 라우팅을 위한 IP와 프로세스간 구분을 위한 PORT가 필요함 581 | 582 | ### 2. 전문 583 | > Fixed Length Format 584 | https://downman.tistory.com/153?category=669234 585 | - Parsing은 안해도 됨 / 바이너리 데이터로 송수신 586 | - fixed length format 이란 전문을 구성하는 field 들의 길이가 입력받을 수 있는 최대사이즈로 고정시키는 방식 587 | > ex) 이름은 최대 32byte 까지, 주소는 100byte 까지 항목의 길이를 fix 시키는 것 588 | **자바에서는 Fixed Length 를 구현하는것이 다소 까다로움 C언어 같은 struct 자료구조를 제공하지 않기 때문에, 아래와 같은 방식으로 진행해야 한다.** 589 | https://cofs.tistory.com/282 590 | 1. 수신한 바이너리 데이터를 byte 배열로 할당 591 | 2. 미리 정의된 프로토콜에 따라 데이터의 위치를 찾아서 원하는 부분에 활용 592 | 593 | ### 3. 스프링에서의 소켓통신 구현 594 | #### 클라이언트 595 | ~~~java 596 | public void clientSocket(byte[] data) { 597 | try { 598 | //IP주소와 포트번호를 입력하여 Socket 통신을 시작합니다. 599 | Socket sock = new Socket("127.0.0.1", 8200); 600 | 601 | //Socket으로부터 outputStream을 얻습니다. 602 | OutputStream os = sock.getOutputStream(); 603 | 604 | //등록한 OutputStream을 DataOutputStream 방식으로 사용 605 | DataOutputStream dos = new DataOutputStream(os); 606 | 607 | //byte[] 파일을 object 방식으로 통째로 전송합니다. 608 | oos.write(data); 609 | 610 | // 스트림과 소켓은 잘 닫아준다. 611 | oos.close(); 612 | os.close(); 613 | sock.close(); 614 | 615 | } catch (SocketTimeoutException e){ 616 | 617 | // 타임아웃 되었을때 618 | timeoutErrorHandler(e); 619 | 620 | } catch (IOException e) { 621 | 622 | // IOException 처리는 강제한다. 623 | e.printStackTrace(); 624 | } 625 | 626 | } 627 | 628 | ~~~ 629 | 630 | #### 서버 631 | ~~~java 632 | public static void serverSocketListener (){ 633 | int port = 8200; 634 | //Server측에서 사용할 포트번호를 설정한 후 Socket 서버 개방 635 | ServerSocket sock = new ServerSocket(port); 636 | 637 | //Client로부터 소켓 신호를 기다림 638 | Socket socket = sock.accept(); 639 | 640 | //Socket로부터 InputStream을 등록 641 | InputStream is = socket.getInputStream(); 642 | 643 | //등록한 InputStream을 DataInputStream방식으로 사용 644 | DataInputStream dis = new DataInputStream(is); 645 | 646 | //미리 데이터를 수신할 버퍼 생성 647 | byte[] buffer = new byte[1156]; 648 | 649 | //미리 지정해 놓은 버퍼에 전송된 byte[] 데이터를 수신 650 | dis.readFully(buffer); 651 | 652 | dis.close(); 653 | is.close(); 654 | socket.close(); 655 | sock.close(); 656 | } 657 | 658 | ~~~ 659 | 660 | 661 | - **DataInputStream / DataOutputStream** 662 | https://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html 663 | 664 | 1. 외부 라이브러리가 아니라 자바의 스탠다드 라이브러리다 665 | 666 | 2. DataInputStream 을 사용하면 애플리케이션이 기계에 독립적인 방법으로 기본 입력 스트림에서 원시 Java 데이터 유형을 읽을 수 있다. (8가지 다양한 자료형으로 읽고 쓸 수 있음) 667 | 668 | 3. 두 클래스는 각각 생성자에서 InputStream과 OutputStream을 받아들임 (API 확인) 669 | 생성자의 arguments 값으로 InputStream, OutputStream을 받아들인다는 의미는 그 하위 클래스들을 받아들인다는 뜻 670 | 671 | 4. JAVA9 이라면 위 클래스 쓰지 않아도 아래와 같은 코드도 가능 672 | ~~~java 673 | InputStream is; 674 | byte[] array = is.readAllBytes(); 675 | ~~~ 676 | - **java.io의 주요 클래스** 677 | 2-1) InputStream : 678 | 바이트 단위로 데이터를 읽는다 679 | 2-2) OutputStream : 680 | 외부로 데이터를 전송한다 681 | 682 | ### 3. BufferedInputStream / BufferedOutputStream 683 | > BufferedInputStream / BufferedOutputStream을 사용하면 편리하고 효율적인 입출력을 할 수 있다. 684 | 685 | BufferedInputStream을 통하여 원하는 자료를 1바이트 단위로 읽는 read() 메소드를 수행하면 시스템 내부적으로 버퍼를 준비하고 이 버퍼를 이용하여 지정된 파일로부터 버퍼의 크기만큼 한꺼번에 많은 데이터를 가져온다. 686 | 687 | 이렇게 채워진 버퍼로부터 1 바이트씩 읽어들여 프로그램으로 전달하게 된다. 688 | 이때, 1 바이트씩 읽어들이는 작업은 파일로부터 읽어오는 것이 아닌 준비된 시스템 버퍼에서 읽어오게 되므로, 파일 입력으로 인한 성능 저하를 최소화 할 수 있다. 689 | 690 | BufferedOutputStream 역시 마찬가지로 데이터를 1 바이트씩 출력하면 파일이 아닌 준비된 시스템 버퍼에 출력을 쌓는다. 691 | 버퍼가 모두 채워지거나 close(), flush() 명령을 만나면 버퍼의 모든 내용을 하드 디스크 파일에 출력한다. 692 | 693 | 따라서, BufferedOutputStream 역시 하드 디스크 파일에 대한 출력을 최소화 하여 효율을 향상 시킬 수 있다. 694 | 695 | 결론적으로 사용자가 BufferedInputStream과 BufferedOutputStream을 이용하여 프로그램을 작성하면 1 바이트씩 읽고 쓰는 모든 작업이 하드 디스크 파일이 아닌 내부적인 버퍼를 대상으로 발생하며, 필요에 따라 버퍼와 하드 디스크 파일간에 입출력이 간헐적으로 발생하므로 전체적인 입출력 성능이 동적으로 향상될 수 있다. 696 | 697 | 698 | 699 | ### 4. String 으로 바이트 데이터 만들기 700 | > 보통 은행이나 기타 금융쪽 시스템은 C / C++ 기반인 경우가 많음 701 | 따라서 정해진 buffer로 적절히 끊어서 전송해야 하기 때문에, byte[] 형식으로 변환한 후 socket에 실어서 전송해야 한다. 702 | ~~~java 703 | byte[] res = text.getBytes(StandardCharsets.UTF_8); 704 | ~~~ 705 | 1. **getBytes()** 메소드는 소켓통신 등 특정 상황에서 스트링을 바이트 배열로 만드는 메소드이고, 수신 측에서는 이를 바이트 배열로 읽고 디코딩하면 원본 String을 얻을 수 있다. 706 | 707 | ### 4.1. Byte - String / String - byte 708 | ~~~java 709 | String str1 = “Hello World!”; 710 | 711 | // 변수 str1의 바이트 값 712 | 713 | // 72101108108111328711111410810033 714 | 715 | bytes[] buffers = str1.getBytes(); 716 | 717 | … 718 | 719 | // 바이트 배열 자체의 문자열 값 720 | 721 | // [B@ca0b6 722 | 723 | String buffersArrayString = buffers.toString(); 724 | 725 | … 726 | 727 | // 바이트 배열을 문자열로 변환한 값 728 | 729 | // Hello World! 730 | 731 | String str2 = new String(buffers); 732 | 733 | ~~~ -------------------------------------------------------------------------------- /oop/oop.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. 객체 지향 프로그래밍 4 | 5 | ### 1-1) 객체 지향의 4갸지 원칙 6 | 1. **추상화 (Abstraction)** 7 | 필요로 하는 속성이나 행동을 추출하여 추상화 시키는 것 8 | ex) Class / Instance 9 | 10 | 2. **캡슐화 (Encapsulation)** 11 | > Message-passing의 한 부분이다, 접근 지정자의 형태로 나타남 (private, protected) 12 | 객체들간 메시지를 통해 소통하고 상대방의 디테일은 알 필요가 없다는 객체지향 원칙이다. 13 | 14 | 캡슐화의 장점 15 | 1. 낮은 결합도 16 | 객체간 소통시 세부사항 알 필요 없음 17 | 18 | 2. 정보 은닉 19 | 정보 손상 가능성 낮춤 (public -> private) 20 | 21 | 3. **상속 (Encapsulation)** 22 | > Generalization / Specialization 23 | 24 | - 재사용의 관점 + 캡슐화의 일종 25 | - 슈퍼클래스로 자식 클래스를 외부로 부터 은닉하는 것이다. 26 | - in Kind of 관계가 성립되지 않으면 불필요한 속성이나 연산을 물려받게 된다. 27 | 28 | 4. **다형성** 29 | 이름은 같으나 시그니쳐가 다르오 30 | > 하나의 메소드나 클래스가 여러 가지 형태로 사용될 수 있는 것 31 | **자바** 에서는 한 타입(Super Class / Interface) 의 참조변수로 32 | 여러 타입의 객체 (Sub Class, 구현체) 를 참조할 수 있도록 함 33 | 34 | - 오버로딩 / 오버라이딩 35 | - 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함 (인터페이스, 상속) 36 | 37 | **다형성을 쓰는 이유** 38 | - 전략 패턴과 같이 유연한 프로그래밍이 가능하다. 39 | - 추상화를 지켜며, 유지보수의 측면에서 좋다 40 | 41 | 출처: https://arabiannight.tistory.com/entry/302 [아라비안나이트] 42 | 43 | ~~~java 44 | // 부모 클래스 45 | public abstract class Pet { 46 | public abstract void talk(); 47 | } 48 | // 자식 클래스 49 | public class Cat extends Pet { 50 | public void talk(){ System.out.println("야옹"); } 51 | } 52 | public class Dog extends Pet { 53 | public void talk(){ System.out.println("멍멍"); } 54 | } 55 | public class Parrot extends Pet { 56 | public void talk(){ System.out.println("안녕"); } 57 | } 58 | ~~~ 59 | 60 | 4-1) 오버라이딩 (Overriding) 61 | - 슈퍼클래스에서 정의한 함수를 자식 클래스에서 덮어씌우는 것 62 | - 자바의 abstract 함수가 그 예 63 | - 즉 클래스 외적인 개념 64 | 65 | 4-2) 오버로딩 66 | - 같은 클래스 내에서, 메소드 이름은 같지만 시그니처 (파라미터 유형 갯수 등) 이 다름 67 | 68 | 69 | ## 2. 디자인 패턴 70 | > 바퀴를 다시 발명하지 마라, 71 | 각기 다른 SW가 서로간의 공통되는 설계 문제가 존재하며 이를 해결하는 방법론 72 | 73 | ### GoF (Gang of Fouts) 디자인 패턴의 분류 74 | 1. 생성 (Creational Pattern) 패턴 75 | - 객체 생성에 관련된 패턴 76 | - 객체의 생성과 조합을 캡슐화해 특정 객체가 생성되거나 변경되어도 프로그램 구조에 영향을 크게 받지 않도록 유연성을 제공한다. 77 | - 싱글턴이 생성 패턴에 포함 78 | 79 | 2. 구조 (Structural) 패턴 80 | - 클래스나 객체를 조합해 더 큰 구조를 만듬 81 | 82 | 3. 행위 (Behavior) 패턴 83 | - 객체나 클래스 사이의 책임 분배와 관련된 패턴 84 | - 한 객체가 혼자 수행할 수 없는 작업을 여러개의 객체로 어떻게 분배하는지. 그렇게 하면서도 객체간 결합도는 최소화 한다. 85 | - Strategy(전략패턴) 가 여기에 포함 86 | 87 | ### 싱글턴 패턴 (Singleton) 88 | - 전역 변수를 쓰지 않고, 객체를 하나만 생성하게 한다. 89 | - getInstance 형태로 프로그램 어디에서나 끌어쓸 수 있다. 90 | - 스레드 상황에서 문제가 발생할 수 있는데 이는 static 변수로 바로 멤버변수에 할당하면 된다. 91 | 92 | ~~~java 93 | public class Printer { 94 | // static 변수에 외부에 제공할 자기 자신의 인스턴스를 만들어 초기화 95 | private static Printer printer = new Printer(); 96 | private Printer() { } 97 | // 자기 자신의 인스턴스를 외부에 제공 98 | public static Printer getPrinter(){ 99 | return printer; 100 | } 101 | public void print(String str) { 102 | System.out.println(str); 103 | } 104 | } 105 | ~~~ 106 | 107 | ### 전략 패턴 (Strategy) 108 | - 상황에 따라, 비슷하면서도 조금씩 다른 행위을 주고 싶을때 사용한다. 109 | - 인터페이스는 하나요, 인터페이스 생성될떄 그 구현체를 선택하는 형태이다. 110 | - 인터페이스를 전략 인터페이스라고 부르고, 111 | - 구현체들을 전략 클래스라고 부른다. 112 | - 구현체들은 같은 이름의 함수를 가지고 있고 액션은 다르다. 113 | 114 | 먼저 전략 인터페이스는 아래와 같이 구현체의 공통 메솓드로! 115 | ~~~java 116 | public interface Strategy { 117 | void runStrategy(); 118 | } 119 | ~~~ 120 | 121 | 전략 인터페이스를 구현한 클래스는 아래와 같다. 122 | ~~~java 123 | public class StrategyGun implements Strategy{ 124 | @Override 125 | public void runStrategy() { 126 | // TODO Auto-generated method stub 127 | System.out.println("탕! 타탕! 탕탕!"); 128 | } 129 | } 130 | ~~~ 131 | 132 | 전략을 사용할 컨텍스트가 필요하고 133 | ~~~java 134 | public class Solider { 135 | void runContext(Strategy strategy) { 136 | System.out.println("배틀 그라운드 시작"); 137 | strategy.runStrategy(); 138 | System.out.println("배틀 종료"); 139 | } 140 | 141 | } 142 | ~~~ 143 | 그리고 전략을 생성하고 컨텍스트에 주입니다. 144 | ~~~java 145 | public class Client { 146 | public static void main(String[] args) { 147 | Strategy strategy = null; 148 | Solider rambo = new Solider(); 149 | // 인터페이스에 생명력 부여 150 | strategy = new StrategyGun(); 151 | 152 | rambo.runContext(strategy); 153 | 154 | System.out.println("\n"); 155 | strategy = new StrategyGrenade(); 156 | 157 | rambo.runContext(strategy); 158 | } 159 | } 160 | ~~~ 161 | 162 | ### 팩토리 메서드 패턴 163 | > 객체의 생성 코드를 별도의 클래스/메서드로 분리하는 패턴 164 | 165 | #### 팩토리 메서드 패턴의 개념과 적용 방법 166 | 167 | 1. 객체 생성을 전담하는 별도의 Factory 클래스 이용 168 | 스트래티지 패턴과 싱글턴 패턴을 이용한다. 169 | - 생성 Factory 클래스는 파라미터를 받아서 상황에 맞는 객체를 얻어온다. 170 | 2. 상속 이용: 171 | 하위 클래스에서 적합한 클래스의 객체를 생성 172 | 스트래티지 패턴, 싱글턴 패턴과 템플릿 메서드 패턴을 이용한다. 173 | 174 | ## 3. 객체 지향의 5대 원칙 (SOLID) 175 | > High Cohesion - Loose Coupling 원칙을 객체 지향애 도입한 것, 재사용은 극대화 시키되 수정은 최소화 하는것이 목표 ㄴ 176 | 177 | ### 1. 객체지향 5원칙 178 | 1. SRP (Single Responsibility Principle) 단일 책임 원칙 179 | 2. OCP (Open Closed Principle) 개방 폐쇄 원칙 180 | 3. LSP (Liskov Substitution Principle) 리스코프 치환 원칙 181 | 4. ISP (Interface Segregation Principle) 인터페이스 분리 원칙 182 | 5. DIP (Dependency Inversion Principle) 의존 역전 원칙 183 | 184 | ### 1.1 객체지향 5원칙 상세 185 | #### 1. SRP (Single Responsibility Principle) 186 | **단일 책임 원칙** 187 | > 클래스의 역할과 책임을 명확하게 하고, 추상화의 정도를 지켜야 한다. 188 | 189 | #### 2, OCP (Open Closed Principle) 190 | **개방 폐쇄 원칙** 191 | > 소프트웨어는 확장에는 열려있고, 주변의 변화에 대해서는 닫혀 있어야 한다. 192 | 193 | 기존 제휴사와의 서비스에서 비슷하게 다른 제휴사의 서비스를 추가할 때, 기존 코드의 수정은 불가피하지만, 최대한 프로그램의 수정은 줄이되 확장은 용이하도록 설계해야 한다. 194 | 이와 관련하여 적절한 예는, **인터페이스** 이다. 195 | 196 | ![99B9E433599E5A9E07](https://user-images.githubusercontent.com/26560119/64069260-a6524380-cbe1-11e9-9114-0cd5fc828605.png) 197 | 198 | 인터페이스나 상위 클래스 (상속) 은 세부 구현과 다른 모듈의 의존성을 약화시키는 완충장치이다. 199 | 200 | #### 3. LSP (Liskov Substitution Principle) 201 | **리스코프 치환 원칙** 202 | > 서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다. 203 | (의미론적으로 sub type ISA base type 이 되어야 한다는 뜻) 204 | 205 | LSP(리스코프 치환 원칙)은 인터페이스와 클래스 관계, 상위 클래스와 하위 클래스 관계를 얼마나 잘 논리적으로 설계 했느냐가 관건이다. (상속을 제대로 구현했는지) 206 | 그리고 **상속 == 확장** 이라는 것을 기억하자. 207 | 208 | #### 4. ISP (Interface Segregation Principle) 209 | **인터페이스 분리 원칙** 210 | 211 | > 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다. 212 | (상황과 관련있는 메서드만 지원해야 한다.) 213 | 214 | ISP(인터페이스 분리 원칙)은 SRP(단일 책임 원칙)과 다른 해결책을 제시하는 것이다. 215 | 216 | SRP(단일 책임 원칙) => 클래스를 쪼개서 기능별로 클래스 자체를 분리 217 | 218 | ISP(인터페이스 분리 원칙) => 인터페이스 정제 및 최소화 219 | 220 | 221 | 222 | #### 5. DIP (Dependency Inversion Principle) 223 | **의존 역전 원칙** 224 | 225 | "고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화 된 것에 의존해야 한다." 226 | "추상화 된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화 된 것에 의존해야 한다." 227 | "자주 변경되는 구체(Concrete) 클래스에 의존하지 마라" - 로버트 C. 마틴 228 | 229 | > 자신보다 변하기 쉬운 것에 의존하지 마라. 230 | 231 | 구체적으로 추상클래스 또는 상위클래스는 구체적인 구현클래스 또는 하위클래스에게 의존적이면 안된다. 구체 클래스는 자주 변경되기 때문에 이에 의존하게 되면 의존하는 고차원 클래스들을 모두 수정해야 한다. 지양하자 232 | -------------------------------------------------------------------------------- /os/os.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## Unix File System 4 | 5 | > 부트블록, 슈퍼블록, i-node, 데이터블록 영역을 가지며, 운영 체제에서 보조 기억 장치와 그 안에 저장되는 파일을 관리하는 시스템의 통칭. 보조 기억 장치에 저장된 각 파일과 그 구조 Unix의 모든 파일은 파일명과 하나의 유일한 *inode* 를 가짐 6 | 7 | ### 1. 유닉스 파일 시스템의 구성 8 | 9 | http://www.jidum.com/jidums/view.do?jidumId=481 10 | 11 | #### 계층구조 12 | 13 | 1. Boot Block 14 | 15 | 운영체제 부트, 초기화와 관련된 Bootstrap 프로시저를 저장 16 | 17 | 2. Super Block 18 | 19 | 전체적인 파일 시스템의 상태에 대한 meta-data 20 | (크기, 상태, metadata structure 에 관한 포인터 등) 21 | 22 | 3. Bitmap Block 23 | 24 | i-node 와 data-block 의 할당 현황 표시 25 | 26 | 4. i-node 27 | 28 | 파일과 디렉토리 각각에 대한 속성 정보 영역 29 | 30 | 5. Data Block 31 | 32 | 파일과 디렉토리의 실제 데이터를 저장하는 영역 33 | 34 | #### 유닉스 파일 시스템 유형 35 | 36 | 1. 일반파일 37 | 38 | 사용자가 정의한 실행가능한 파일 (텍스트, 바이너리) 39 | 40 | 2. 디렉토리 파일 41 | 42 | 디렉토리에 포함되어 있는 여러가지 파일들, 디렉토리에 관련한 정보 등을 저장하는 논리적 영역 43 | 44 | 3. 특수파일 45 | 46 | 주변 장치, 파이프와 소켓 같은 프로세스간의 상호 통신 및 표준입출력 시스템 호출 47 | 48 | 4. i-node 49 | 50 | 각 파일에 대한 정보를 기억하는 **구조체** 51 | 52 | #### i-node 의 개념과 구성요소 53 | 54 | 55 | 56 | 위의 그림처럼 흔히 말하는 심링크는 inode 를 두번 걸쳐서 (첫번째 inode 는 원본 파일에 대한 포인터를 가지고 있음) 원본 파일 데이터를 메모리에 사상하는 것이고, 하드 링크 파일은 원본과 직접 연결되는 inode 룰 통해 원본을 바로 자려올 수 있다. 57 | 58 | ## OS / Kernel 59 | 60 | ### 운영체제란? 61 | 62 | > 각 유저 프로세스에 가상의 컴퓨터들을 적절히 제공하며, 63 | 사용자와 하드웨어 간의 인터페이스 소프트웨어라고 할 수 있다. 64 | 65 | 주요한 특징은 아래와 같다. 66 | 67 | (1) Resource Manager (자원관리) 68 | 69 | - HW Resources : 말그대로 하드웨어 자원 (메모리, CPU, IO장치 등) 70 | 71 | - SW Resources : File Management (파일 시스템을 관리한다) 72 | 73 | (2) API (Application Programing Interface) 74 | 75 | 응용 프로그램 등등을 위한 여러가지 서비스를 지원한다. 76 | 77 | ### Kernel 이란? 78 | 79 | > OS의 API 기능을 담당하는 부분이다. 80 | 운영체제의 다른 모든 부분에 필요한 서비스를 제공한다. 81 | 82 | 흔히 말하는 System Call 이 Kernel 서비스에 대한 인터페이스이고, 83 | 운영체제 위의 많은 Application 들은 System Call 을 이용하여 Kernel 이 제공하는 서비스들을 받을 수 있다. 84 | 85 | - 하드웨어 자원을 프로세스에 적절히 분배 86 | 87 | - 메모리 제어 88 | 89 | - System Call 처리 90 | 91 | ### System Call? 92 | 93 | > OS가 제공하는 서비스를 어플리케이션에 제공하는 인터페이스 94 | 95 | #### 1. 시스템콜 종류 96 | 97 | 1. 프로세스 제어 (생성, 종료, 시그널) 98 | 99 | 2. 파일 및 IO 관리 100 | 101 | - 생성 / 종료 102 | - 열기 / 닫기 103 | - read / write 104 | 105 | 3. 통신 106 | 107 | 4. 프로세스간 통신 (IPC) 108 | 109 | ## Thread / Process 110 | 111 | ### Program 112 | 113 | > 어떤 작업을 위해 실행할 수 있는 파일 114 | 115 | ### Process 116 | 117 | > 프로그램의 인스턴스 (실행된 프로그램 / 운영체제로 부터 자원을 할당받는) 118 | ref) 자원 : CPU시간, 주소공간, 메모리 119 | 120 | - 각 프로세스는 별도의 주소 공간에서 실행되며 영향을 주지 않는다 121 | - 프로세스간 통신을 하려면 IPC (파이프, 소켓 등)를 사용해야 한다. 122 | - 최소 1개의 스레드는 있어야 한다. 123 | 124 | ### Thread 125 | 126 | ![thread](https://user-images.githubusercontent.com/26560119/58751383-b5d5c980-84d8-11e9-9739-6c2a9644e72b.png) 127 | 128 | - 스택만 따로 할당받고 코드 / 데이터 / 힙 공간은 공유한다. 129 | - **프로세스 내** 의 여러 흐름 (분산처리) 130 | - 스택과 레지스터는 별도로 131 | 132 | ### Java Thread 133 | 134 | - 일반 쓰레드와 비슷하지만, 주체가 OS가 아니라 JVM이다. 135 | - 자바 스레드는 JVM에 의해 스케줄되는 **실행 단위 코드 블록**이다. 136 | - 스레드 코드를 작성하고, JVM에게 요청하면 된다. 137 | - Runnable 인터페이스 구현 or Thread 상속 138 | - 즉, 개발자는 자바 스레드로 작동할 스레드 코드를 작성하고, 스레드 코드가 생명을 가지고 실행을 시작하도록 JVM에 요청하는 일 뿐이다. 139 | 140 | ### Java ThreadLocal 141 | 142 | - 자바 ThreadLocal 클래스는 오직 한 Thread 에 의해 읽고 쓰여질 수 있는 변수를 생성할 수 있도록 한다. 143 | 144 | - 때문에 만일 두 쓰레드가 같은 코드를 실행하고 이 코드가 하나의 ThreadLocal 변수를 참조하더라도, 이 두 쓰레드는 서로의 ThreadLocal 변수를 볼 수 없다. 글자 그대로 쓰레드의 지역변수이다. (Thread Block 의 지역변순) 145 | 146 | ## 멀티프로세서 vs 멀티스레드 147 | 148 | > 멀티스레드가 더 좋겠지.. 149 | 150 | ### 1. 좋은 이유 151 | 152 | 1. 자원의 효율성 증대 153 | 154 | - 프로세스 간의 Context Switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐시 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크기 때문 155 | - 스레드는 프로세스 내 메모리 공유하기 때문에 간단하고, 자원도 덜 든다. 156 | 157 | 2. 처리비용 감소 / 응답시간 단축 158 | 159 | - IPC 필요 없으니 통신 오버헤드 줄어듬 160 | - 스레드 Context Switching 은 Stack 만 갈아치우면 되니 훨씬 빠름 161 | - 스레드는 PCB에 프로세스에 비해 적게 저장 (스택 및 간단한 정보만 저장) 162 | - 따라서 PCB 관련 오버헤드도 적음 163 | 164 | ### 2. PCB (Process Control Block) 165 | 166 | 프로세스 제어 블록(Process Control Block, 줄여서 PCB)은 특정한 프로세스를 관리할 필요가 있는 정보를 포함하는, 커널의 자료구조이다. PCB는 운영 체제가 **프로세스** 를 표현한 것이라 할 수 있습니다. 167 | 168 | #### PCB 내 표현되는 정보 169 | 170 | 1) 프로세스 식별자(Process ID) 171 | 172 | 2) 프로세스 상태(Process State) : 173 | 생성(create), 준비(ready), 실행 (running), 대기(waiting), 완료(terminated) 174 | 175 | 3) 프로그램 계수기(Program Counter) : 176 | 프로그램 계수기는 이 프로세스가 **다음에 실행할 명령어** 의 주소를 가리킵니다. 177 | 178 | 4) CPU 레지스터 및 일반 레지스터 179 | 180 | 5) CPU 스케줄링 정보 : 우선 순위, 최종 실행시각, CPU 점유시간 등 181 | 182 | 6) 메모리 관리 정보 : 해당 프로세스의 주소 공간 등 183 | 184 | 7) 프로세스 계정 정보 : 페이지 테이블, 스케줄링 큐 포인터, 소유자, 부모 등 185 | 186 | 8) 입출력 상태 정보 : 프로세스에 할당된 입출력장치 목록, 열린 파일 목록 등 187 | 188 | 9) 포인터 : 부모프로세스에 대한 포인터, 자식 프로세스에 대한 포인터, 프로세스가 위치한 메모리 주소에 대한 포인터, 할당된 자원에 대한 포인터 정보 등. 189 | 190 | 191 | ### 3. Context Switching 192 | 193 | > 현재 진행하고 있는 Task(Process, Thread)의 상태를 저장하고 다음 진행할 Task의 상태 값을 읽어 적용하는 과정을 말합니다. 참고로 프로세스 마다 PCB가 있습니다. 194 | 195 | 196 | 197 | 1. Context Switching이 발생하게 되면 많은 Cost가 소요된다. 198 | 199 | - Cache 초기화 200 | - Memory Mapping 초기화 201 | - Kernel은 메모리 접근을 위해 항상 실행되어야 함 202 | 203 | 2. 작동 방식 204 | 205 | - Task의 대부분 정보는 Register에 저장되고 PCB(Process Control Block)로 관리되고 있습니다. 206 | - 현재 실행하고 있는 Task의 PCB 정보를 저장하게 됩니다. (Process Stack, Ready Queue) 207 | - 다음 실행할 Task의 PCB 정보를 읽어 Register에 적재하고 CPU가 이전에 진행했던 과정을 연속적으로 수행을 할 수 있습니다. 208 | - PCB를 저장하고 가져올때는 CPU가 아무런 일도 하지 못하게 된다. (오버헤드) 209 | - 컨텍스트 스위칭을 하는 주체는 스케줄러이다. 210 | 211 | 3. 컨텍스트 스위칭이 일어나는 상황 212 | 213 | - I/O interrupt 214 | - CPU 사용시간 만료 215 | - 자식 프로세스 Fork 216 | 217 | 218 | ## Thread Safe 219 | 220 | > 멀티스레드 환경에서 여러 스레드가 동시에 하나의 객체 및 변수(공유 자원)에 접근할 때, 의도한 대로 동작하는 것을 말한다. 221 | 222 | - 공유자원에 접근하는 임계영역을 동기화 기법으로 제어해야 함 (상호배제) 223 | - 동기화 기법은 Mutex, Semaphore 등이 있다. 224 | - 재 진입성 (동시에 어떤 스레드가 와도 같은 결과 보장) 을 보장해야 한다. 225 | - 뮤텍스, 세마포어는 운영체제 커널의 동기화 방법이다. 226 | - 커널모드 변경하면 성능이 저하된다. 227 | 228 | ## 뮤텍스와 세마포어 229 | 230 | https://worthpreading.tistory.com/90 231 | 232 | ### 뮤텍스 233 | 234 | - 임계 영역을 가진 스레드들의 러닝타임이 겹치지 않도록 처리 (동시사용 불가) 235 | - 프로세스나 스레드가 뮤텍스 객체를 한번에 하나만 소유가능 236 | 237 | ### 세마포어 238 | 239 | - 세마포어는 OS내부 커널의 한 저장장치 값 (바이너리 일 수도 있고, 아닐수도 있음) 240 | - 이 값을 통해 자원이 사용중인지 알 수 있다. 241 | - 자원을 사용하고 있다면 기다리고, 없다면 드루간다. 242 | - 세마포어를 사용하는 프로세스는 세마포어 값을 확인하고, 자원을 사용하는 동안에는 그 값을 변경함으로써 다른 세마포어 사용자들이 기다리도록 해야함 243 | - 현재 공유자원에 접근할 수 있는 쓰레드, 프로세스의 수를 나타내는 값을 두어 상호배제를 달성하는 기법 244 | 245 | ### 세마포어와 뮤텍스의 차이 246 | 247 | - 세마포어는 뮤텍스가 될수 있지만, 뮤텍스는 세마포어가 될 수 없다 248 | - 간단히 보자면 뮤텍스는 boolean(상태), 세마포어는 int(카운터) 249 | - 뮤텍스는 항상 열쇠 1개이고, 세마포어는 여러개 가질 수 있기 때문에 250 | 세마포어의 열쇠가 1개라면 뮤텍스와 같습니다. 251 | - 세마포어는 파일시스템 상 파일형태 (값) 로 존재, 뮤텍스는 프로세스 범위 252 | - 즉, 프로세스가 사라질 때 뮤텍스는 clean up 됩니다. 253 | - 세마포어는 소유할 수 없는 반면, 뮤텍스는 소유할 수 있습니다. 254 | 255 | ### 모니터 256 | 257 | - 상호배제를 구현한 프로그램, java 가 이 방식을 사용 258 | - 모니터에는 한 프로세스 만이 접근 가능함 259 | - 무조건 모니터를 통해 자원을 할당받고 사용할 수 있음 260 | 261 | #### wait / notify 262 | 263 | 1. wait 264 | 265 | - 현재 thread 야, 가지고 있던 Lock 을 풀고 대기해라 266 | 267 | 2. notify 268 | 269 | - wait 하고 있는 thread 를 깨운다 270 | 271 | ### Critical Section 272 | 273 | 임계 구역으로 프로세스 또는 스레드들이 공통 변수들에 접근, 및 수정하고 테이블을 갱신하며, 파일의 읽기, 쓰기 작업들을 수행하는 영역을 말한다. 즉 race condition이 발생하는 영역을 뜻한다. 이미 한 스레드가 Critical Section에 들어갔을 때 다른 스레드들은 이 곳으로의 접근을 막아야한다. 274 | 275 | 한 프로세스 혹은 한 스레드가 메모리의 어떤 부분을 접근하고 있을 때 다른 프로세스 혹은 스레드가 그 부분을 접근하여 값을 변경하면 안된다. 따라서 그 부분을 막기 위해 우리는 동기화를 해야한다는 개념이 나오는 것이다. 276 | 277 | ## 가상 메모리 278 | 279 | http://www.jidum.com/jidums/view.do?jidumId=473 280 | 281 | > 가상 메모리란 어떤 프로세스를 실행할때, 프로세스 전체가 메모리에 다 적재되지 않고도 실행이 가능하도록 하는 기법이다. 부분부분 올려서 쓰는것. 282 | CPU - RAM 관계에서 Cache 같은 역할 수행 283 | 284 | - 효과적인 멀티 프로그래밍 가능 285 | 286 | - 물리적 공간보다 더 큰 프로세스의 실행이 가능 287 | 288 | - 시스템의 다중 프로그래밍 수준 향상 -> 많은 프로그램 동시 수행 - > 이용률, 처리율 상승 289 | 290 | - 기억공간의 제약 감쇠 -> 물리적 기억장치의 효율적인 사용 291 | 292 | ### 1. 메모리 단편화 293 | 294 | https://jeong-pro.tistory.com/91 295 | 296 | > 메모리를 효율적으로 사용하지 못하는 상황을 나타낸다. 297 | 298 | 1. 내부 단편화 299 | 300 | 어떠한 프로세스가 사용해야 하는 메모리는 1kb인데, 실제 할당된 메모리 블럭은 4kb일 경우 사실상 3kb 의 메모리가 낭비되는 것이다. 301 | 302 | 2. 외부 단편화 303 | 304 | 어떠한 프로세스가 메모리 블럭을 사용하고 반납 했을때, 해당 공간이 작게 작게 비어서 큰 놈이 한번에 들어가지 못하는 것이다. (연속으로 비어있지 않아서 발생하는 문제) 305 | 306 | ### 2. 단편화 해결방안 307 | 308 | 1. Paging 309 | 310 | 물리 메모리를 사용할 때, 페이지를 고정크기의 프레임 단위로 나눕니다. 311 | 가상 메모리도 같은 프레임단위인 페이지로 나누어 프레임과 페이지를 페이지 테이블을 통해 맵핑하여, 312 | **연속적인 물리메모리** 가 아니더라도 원하는 크기의 프레임을 사용할 수 있도록 하는 기능이다. 313 | 314 | 따라서 외부 단편화 문제는 해결되겠지만, 여전히 페이지 단위에 따라 메모리 공간이 낭비되는 내부 단편화 문제가 발생한다. 315 | 페이지를 더 작은 단위로 쪼개면 내부 단편화 문제가 해결될 수 도 있지만, 그만큼 Page Mapping 이 자주 발생하기 떄문에 주의해야 한다. 316 | 317 | 2. Segmentation 318 | 319 | 세그멘테이션 기법 같은 경우는 같은 페이지 사이즈로 가상 메모리 영역을 나누는 것이 아니라, 각각 다른 사이즈인 **세그멘트** 로 나누게 된다. 사용 시 마다 다른 단위로 메모리를 할당해야 하므로 미리 메모리 영역을 나누어 놓을 수 없다. 320 | 321 | 따라서 내부 단편화 문제는 해결되었지만 (수요에 따라 메모리 공간 효율적으로 세팅) 미리 얼마나 뜯어갈 지 예측할 수 없으므로, 메모리 사용 후 반납 시 외부 단편화 문제로 중간에 메모리 공간들이 뻥뻥 뚤려 있을 수 있다. 322 | 323 | ### 3. 페이지 폴트 324 | 325 | > 프로세스가 필요한 페이지가 있는데, 지금 가상메모리에서 프레임에 매핑이 아직 되지 않는 상태에서 페이지 폴트가 난다. 326 | 327 | #### 대응 328 | 329 | 1. CPU는 물리 메모리에서 찾는 페이지가 없으면, TRAP 을 발생시켜 커널 모드로 진입한다. 330 | 331 | 2. 커널은 CPU 동작을 잠깐 멈춘다. 332 | 333 | 3. 페이지 테이블을 확인하여, 해당되는 페이지가 스왑파일 어디에 위치하는지 확인하고 혹시 없다면 프로세스를 중지한다. 334 | 335 | 4. 페이지 테이블에 엔트리가 있다면, 물리 메모리에 빈 프레임이 있는지 확인한다. 336 | - 의문점 : 빈 프레임이 없다면? (아래에서 답변) 337 | 338 | 5. 비어있는 프레임에 가상 메모리의 페이지를 맵핑하고, 페이지 테이블을 최신화 한다. 339 | 340 | 6. 중단되었던 CPU를 다시 시작한다. 341 | 342 | #### Q. 빈 프레임이 없다면 ? 343 | 344 | 페이지 교체 알고리즘을 써서 대응한다! 345 | 여기서 나오는 방식이 FIFO, LRU, LRU Approximation 등이 있다. 346 | 347 | 1. First In First Out (FIFO) 348 | 349 | 가장 먼저 들어간 놈을 교체시킨다 350 | 351 | 2. Least Recently Used (LRU) 352 | 353 | 사용된지 오래된 놈 교체 354 | 355 | **쓴지 오래된놈은** 뒤로 보내서 꽉 차면 교체되게 만들고 356 | **방금 쓰인애는** 앞으로 보내서 프레임에서 교체되는 것을 방지한다. 357 | 358 | 3. LRU Approximation 359 | 360 | LRU 와 교체의 기준은 같지만, 대신 bit 를 하나 사용하여 기회를 한번 더 주는것이다. 361 | 교체 후보로 선정되면 1이였던 Bit 을 0으로 바꾸고, 362 | 한번더 선정되면 얄짤없이 교체하는 방식이다. 363 | 364 | ## 지역성 (Locality) 에 대하여 365 | 366 | ### 지역성의 이해 367 | 368 | > 프로세스가 메모리를 참조할 때, 이리저리 균일하게 참조하는 것이 아니라 한 순간에 물리적으로 메모리의 한 부분을 집중적으로 참조하는 성질이다. 369 | 370 | 이것은 Cache Hit 이나, Page Fault 에 모두 관련되어 있는 이야기이다. 371 | 복잡하게 생각하기 보다는, 그냥 프로세스가 메인 메모리 까지 안가고 캐시에서 원하는 정보를 찾으면 좋은 것이고, 또 가상 메모리까지 안가도 메인 메모리에서 끝내면 좋은 것을 말하는 것이다. 372 | 373 | ### 지역성의 종류 374 | 375 | 1. 시간적 지역성 376 | 377 | 최근에 참조된 메모리 주소가, 조만간 또 참조될 가능성이 높다는 것 378 | (LRU 등) 379 | 380 | 2. 공간적 지역성 381 | 382 | 최근에 참조된 메모리 근처 (실제 물리적으로 근접) 에서 또 참조될 가능성이 높다는 것 383 | (배열 등) 384 | 385 | 3. 순차 지역성 386 | 387 | 데이터가 순차적으로 액세스되는 경향 (공간 지역성의 일부로 설명되기도 함) 388 | 389 | ## DMA (Direct Memory Access, Cycle Stealing) 390 | 391 | http://www.jidum.com/jidums/view.do?jidumId=470 392 | 393 | > 메모리 버퍼, 포인터, 카운터를 사용하여 장치 제어기가 CPU의 도움 없이 DMA컨트롤러를 이용하여 데이터를 직접 메모리로 전송하는 입출력 방식 (IO 장치 작업을 CPU 도움 없이 한다) 394 | 395 | ## 데드락 (DeadLock) 396 | 397 | - 첫 번째 스레드는 두 번째 스레드가 들고 있는 객체의 락이 풀리기를 기다리고 있고, 두 번째 스레드 역시 첫 번째 스레드가 들고 있는 객체의 락이 풀리기를 기다리는 상황을 일컷는다. 398 | 399 | - 모든 스레드가 락이 풀리기를 기다리고 있기 때문에, 무한 대기 상태에 빠지게 된다. 이런 스레드를 교착상태에 빠졌다고 한다. 400 | 401 | ### 교착상태의 4가지 조건 402 | 403 | 1. 상호 배제(mutual exclusion) 404 | 한 번에 한 프로세스만 공유 자원을 사용할 수 있다. 405 | 좀 더 정확하게는, 공유 자원에 대한 접근 권한이 제한된다. 자원의 양이 제한되어 있더라도 교착상태는 발생할 수 있다. 406 | 407 | 2. 들고 기다리기(hold and wait) = 점유대기 408 | 프로세스가 자기한테 할당된 자원을 가진 상태에서 다른 자원 요구 및 대기 가능 (욕심쟁이) 409 | 410 | 3. 선취(preemption) 불가능 = 비선점 411 | 프로세스가 어떤 자원의 사용을 끝낼 때까지 그 자원을 뺏을 수 없다. 412 | 413 | 4. 대기 상태의 사이클(circular wait) = 순환대기 414 | 두 개 이상의 프로세스가 자원 접근을 기다리는데, 그 관계에 사이클이 존재한다. 415 | 416 | ### 교착상태 방지 417 | 418 | > 4가지 조건들 가운데 하나를 제거하면 된다. 419 | 420 | - 공유 자원 중 많은 경우가 한 번에 한 프로세스만 사용할 수 있기 때문에(예를 들어, 프린트) 1번 조건은 제거하기 어렵다. 421 | 422 | - 대부분의 교착상태 방지 알고리즘은 4번 조건, 즉 대기 상태의 사이클이 발생하는 일을 막는 데 초점이 맞춰져 있다. 423 | 424 | -------------------------------------------------------------------------------- /os/os_med_test.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 운영체제 과제 4 | 5 | ### Chapter 8 **DeadLocks** 6 | 7 | #### 8.4 8 | 9 | 데드락을 방지하는 가능한 방법은 우선순위가 높은 단일의 요청을 그렇지 않은 요청들 보다 무조건 먼저 처리하는 것이다. 예를 들어, 만약 다수의 스레드들이 동기화 되어야 하는 오브젝트들 (A..E) 에 한꺼번에 접근을 시도한다면, 데드락에 걸릴 수 있다. (동기화 방식은 뮤텍스, 세마포어, 조건 변수 등등을 포함한다) 우리는 A..E 이외의 6번째 오브젝트인 F를 추가함으로서 데드락을 예방할 수 있다. 한 스레드가 A..E 의 어떠한 오브젝트의 lock 을 획득하고 싶다면, 첫째로 F에 대한 lock 을 획득해야 한다. 이러한 해결 방식은 *봉쇄* 방식이라고 불리는데 봉쇄 방식은 F에 lock이 걸려있다면, A..E의 lock 이 봉쇄되는 방식이다. 10 | 이러한 계획을 환형 대기와 비교하라 11 | 12 | **A)** 이러한 방식은 효울적인 방식이 아니다. 이는 너무 많은 오브젝트들이 대기해야 한다. 13 | 14 | #### 8.6 15 | 16 | 컴퓨터 시스템이 한 달에 5000개의 작업을 실행하는데 데드락 예방이나 데드락 회피 계획이 없다고 가정해 보자. 데드락은 한달에 두번씩 일어나고, 작업자가 직접 데드락당 10개의 작업들을 종료하고 재 실행 시켜야 한다. 각 작업은 2달러의 가치를 가지고 있고, 종료된 작업들은 중단 되었을때 절반정도 완료되는 경향을 가지고 있다. 17 | 18 | 시스템 프로그래머는 시스템에 설치되어 있는 데드락 회피 알고리즘 사용시 소요되는 실행 시간이 작업 당 평균 실행 시간보다 10% 높다는 것을 발견했다. 해당 컴퓨터는 30% 의 여유 시간을 가지고 있기 때문에 turnaround time 이 평균 20% 정도 증가하지만, 여전히 매달 5,000개의 작업을 처리할 수 있다. 19 | 20 | a) 데드락 회피 알고리즘을 설치한다면, 그 이유는 무엇인가? 21 | 22 | **A)** 데드락 회피는 어떠한 데드락 상황이든 회피 가능을 보장한다. 또한 해당 컴퓨터는 데드락 회피 알고리즘 설치 후에도 작업 부하 처리가 가능하기 때문에 설치할 수 있다. 23 | 24 | b) 데드락 회피 알고리즘 설치를 반대한다면, 그 이유는 무엇인가? 25 | 26 | **A)** 한달에 두 건정도 데드락이 발생하고 하나당 적은 비용이 발생하므로, 굳이 알고리즘을 설치 할 필요는 없다. 27 | 28 | #### 8.11 29 | 30 | 단 하나의 스레드가 존재하는데, 데드락이 발생할 수 있는가? 31 | 32 | **A)** 절대 발생할 수 없다. 교착 상태의 필요조건인 상호 배제, 점유대기, 비선점, 환형대기 모두 2개 이상의 스레드가 존재해야 성립 가능한 조건이다. 33 | -------------------------------------------------------------------------------- /rails/tip.md: -------------------------------------------------------------------------------- 1 | ### 레일즈 앱에 마크다운 업로드 기능 추가하기 2 | 3 | 예전부터 마크다운을 여기 데브로그에 추가하려고 마음을 엄청 먹고 있었는데, 바빠서 미루다가 이제서야 마크다운 에디터를 추가해 버렸다. 지금 쓰고 있는 이 글도 마크다운으로 작성중이다. 원래는 마크다운이 위지윅보다 글 쓸때는 약간 불편하다고 생각했지만, 마크다운으로 쓰다 버릇 하니 마크다운이 너무 편하고 포맷팅도 깔끔한 것이 느껴진다. 4 | 5 | #### 1. 마크다운 파싱해 주는 젬 설치하기 6 | 7 | 알아보니 Redcarpet 이라는 젬도 있지만, 둘 다 읽어보니 사용법은 대략 비슷한거 같고 나는 깃헙 지킬에서 쓰는 Kramdown 이라는 모듈을 사용해 보기로 했다. 8 | 9 | https://github.com/gettalong/kramdown 10 | 11 | 언제나 그렇듯이 Gemfile에 아래 문장을 추가한다. 12 | ~~~ruby 13 | gem 'kramdown' 14 | ~~~ 15 | 16 | 그리고 언제나 그렇듯 `bundle install` 17 | 18 | #### 2. 사용법은 초간단 19 | 20 | 그냥 아래와 같이 쓰면 된다..ㅋㅋㅋㅋㅋ 진짜 레일즈는 너무 사용자 친화적이다 21 | 22 | ~~~ruby 23 | require 'kramdown' 24 | 25 | Kramdown::Document.new(text).to_html 26 | ~~~ 27 | 28 | 여기 데브로그에서 쓴 코드를 인용하자면, 아래와 같다. 29 | 나는 데브로그 show 액션에서 사용했고 아래의 `markdown_text` 는 데브로그 테이블의 칼럼이자, 마크다운 텍스트 내용이다. 30 | 아걸 그냥 `Kramdown::Document` 클래스 생성자에 넣고, 생성된 객체를 to_html 메서드로 변환하여 주면 끝이다. 31 | 32 | ~~~ruby 33 | def show 34 | @post = Devlog.find_by(id: params[:id]) 35 | if @post.markdown_text.present? 36 | @markdown = Kramdown::Document.new(@post.markdown_text).to_html 37 | end 38 | end 39 | ~~~ 40 | 41 | 아무튼 변수에 담긴 html 텍스트를 화면에 뿌려주면 잘 나올 것이다. 42 | 43 | #### 3. 스타일링 44 | 45 | 근데 이대로 화면에 뿌려보면, 무언가 깃허브 마크다운만큼 안이쁘다. 46 | 그러면 이쁘게 꾸미면 된다. 아래에 깃허브 마크다운 css 파일이 있다. 47 | 48 | https://github.com/sindresorhus/github-markdown-css 49 | 50 | 위 링크 디렉토리에 있는 css 파일을 잘 긁어서 적절한 곳에 잘 붙여넣고, 51 | 마크다운 텍스트가 들어갈 구역의 클래스에 `.markdown-body` 클래스를 이쁘게 박아주면 된다. 52 | 53 | 아래를 참고하도록 하자 54 | 55 | ~~~html 56 |
57 | <%= @markdown.html.safe %> 58 |
59 | ~~~ 60 | 61 | 끝! 깃허브 처럼 이쁘게 나온다. -------------------------------------------------------------------------------- /spring/spring.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | 3 | ## 1. Why SpringBoot? 4 | 5 | ### 스프링부트의 특징 6 | - Embedded Tomcat (WAS, Servlet Container) 제공 7 | - 사실 AutoConfiguration 맥락에, 톰캣 객체 생성 및 연결 준비 등도 들어감 8 | - DispatcherServlet 도 자동설정 됨 9 | - 즉 서블릿 컨테이너 만들고 서블릿 넣어주는일을 자동으로 해준다는 말 10 | - 의존성 관리 11 | - Maven pom.xml 에서 의존 라이브러리의 버전을 일일이 지정하지 않아도 된다. 12 | (등록된 라이브러리에 한해 스프링 부트가 *권장 버전* 을 관리한다) 13 | - @SpringBootApplication 어노테이션으로 xml 설정 대체 14 | - @SpringBootApplication 는 @ComponentScan 과 @EnableAutoConfiguration 을 포함하고 있다. 15 | - @ComponentScan 은 프로젝트 패키지에 있는 Bean을 찾아서 등록한다. 16 | - @EnableAutoConfiguration 로 클래스패스 내 의존성 관련 자동 설정 17 | - 스프링부트는 Bean 을 두단계로 등록한다. 18 | 1. @ComponentScan 19 | 2. @EnableAutoConfiguration 20 | - ContextLoaderListener / DispatcherServlet / CharacterEncodingFilter 설정은 Spring Boot 에서는 추가하지 않아도 된다. 21 | 22 | - 독립실행 가능한 어플리케이션 지향 (JAR도 독립실행 가능) 23 | - mvn package를 하면 실행 가능한 JAR 파일 “하나가" 생성 됨. 24 | - 이는 spring-maven-plugin이 해주는 일 (패키징) 25 | - 스프링 부트는 JAR 파일들을 읽어들이는 로더를 제공한다. 26 | - JAR 런쳐를 사용해서 main 함수가 있는 JAR 파일을 실행한다. 27 | 28 | ### 핵심 장점 29 | 1. 의존성 관리 30 | 31 | 2. 임베디드 톰캣 (독립 실행 가능한 어플리케이션) 32 | - 톰캣 위에 war 를 얹지 않아도, 스프링부트는 jar를 읽을 수 있도록 기능을 제공한다. 33 | - 내장 톰캣도 제공하면서, jar 도 실행가능 하도록 하므로 독립실행이 가능하다. 34 | 35 | 3. Auto Configuration (@EnableAutoConfiguration) 36 | > Spring Boot Auto Configuration 은 추가된 jar 의존성을 기반으로 Spring application을 자동적으로 설정하는 것을 시도한다. 예를 들어 HSQLDB 가 클래스패스에 있다면 어떤 데이터베이스 연결 빈을 정의하지 않아도 자동적으로 in-memory 데이터베이스에 접근할 것이다. 37 | - @SpringBootApplication 에 @EnableAutoConfiguration 이 포함되어 있다. 38 | - AutoConfiguration 을 담당하는 결국은 @Configuration 기반이다 39 | - spring.factories 에 명시되어 있는 클래스들에 한해 자동설정을 적용한다. 40 | - 알아서 조건에 따라 설정 Bean 을 생성하고 적용한다. 41 | 42 | 4. 어노테이션 기반 Component Scan (@Component) 43 | > 현재 패키지 이하에서, @Component 어노테이션이 붙은 클래스들을 찾아 Bean 으로 등록한다. (제외도 가능) 44 | - 예를 들어 @Controller 어노테이션도 내부를 까보면 @Component 가 들어있다. 45 | 46 | ## 2. Servlet 과 JSP 47 | ### 1. 서블릿 (Servlet) 48 | > 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 Spec 49 | 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다. 50 | 자바로 구현된 [CGI](https://ko.wikipedia.org/wiki/%EA%B3%B5%EC%9A%A9_%EA%B2%8C%EC%9D%B4%ED%8A%B8%EC%9B%A8%EC%9D%B4_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4) 라고 말할 수 있다. 51 | 52 | #### 1.1 서블릿의 특징 53 | 54 | - HTML 을 사용하여 요청에 응답한다. 55 | - **Java Thread** 를 이용하여 동작한다. 56 | - MVC 패턴에서 Controller로 이용된다. 57 | - HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다. 58 | - HTML 변경 시 Servlet을 재컴파일해야 하는 단점이 있다. 59 | 60 | #### 1.2 서블릿 동작 방식 61 | 993A7F335A04179D20 62 | 63 | 1. 클라이언트가 HTTP 요청시 이를 Servlet Container (WAS) 로 전송 64 | 65 | 2. 이를 전송받은 Servlet Container 는 ***HttpServletRequest, HttpServletResponse*** 의 객체들을 생성한다. 66 | 67 | 3. **web.xml** 은 사용자가 요청한 URL을 분석하여 어느 서블릿에 대해 요청을 한 것인지 찾습니다. (한개의 서블릿 당 한개의 컨트롤러 사상) 68 | 69 | 4. 해당 서블릿 스레드 (객체 아님) 에서 service 메소드를 호출한 후 요청의 POST, GET 여부에 따라 doGet() 또는 doPost()를 호출 70 | 71 | 5. doGet() or doPost() 메소드는 동적 페이지를 생성한 후 HttpServletResponse 객체로 응답. 72 | 73 | 6. 응답이 끝나면 HttpServletRequest, HttpServletResponse 소멸 74 | 75 | 76 | ### 2. 서블릿 컨테이너 (aka WAS) 77 | > 서블릿 컨테이너는 서블릿을 관리하며 네크워크 통신, 서블릿의 생명주기 관리, 스레드 기반의 병렬처리를 대행한다. 가장 대표적인 것으로는 아파치 톰캣(Tomcat)이 있다. 78 | 79 | ### 3. WS vs WAS (Apache VS Tomcat) 80 | 81 | **웹서버** 는 클라이언트의 요청을 기다리고 요청에 대한 데이터를 만들어서 응답하는 역할을 한다. 이때 데이터는 정적인 데이터(html, css, 이미지등)로 한정된다. 말그대로 미리 정해진 자원들을 응답해 주는 것이다. 82 | 83 | **WAS** 클라이언트의 요청이 있을 때 ***내부 프로그램을 통해 결과를 만들어내고*** 이것을 다시 클라이언트에게 돌려주는 역할을 한다. 84 | 이는 WS의 기능 일부와 웹 컨테이너의 결합으로 다양한 기능을 컨테이너에 구현하여 다양한 역할을 수행한다. 85 | 86 | 예전에는 static file 은 웹서버를 통해 제공하고, 동적인 기능들만 WAS 를 쓰는것이 효율적이라는 말이 있었는데, 톰캣은 5.5부터 **Httpd** 의 native모듈을 사용해서 스태틱파일을 처리하는 기능을 제공한다. 87 | 88 | 이 경우 아파치와 톰캣이 같은 모듈을 사용하는 셈이니 성능에서 차이가 날 이유가 없다. 실제 테스트 한 결과를 봐도 톰캣에서 아파치 Native 모듈을 사용하는 것이 순수하게 아파치 Httpd만 사용하는 것과 비교해서 성능이 전혀 떨어지지 않는다. 89 | 90 | ### 4. JSP (Java Server Page) 91 | > 이는 웹 서버 어플리케이션의 발전속에 응답의 표현을 위해 자연스럽게 등장했다. 92 | 93 | 기존 서블릿 같은 경우 HttpServletResponse 객체에게 응답 html을 주려면 아래와 같이 상당히 귀찮은 작업이 필요했다. 94 | ~~~ java 95 | public class HelloServlet extends HttpServlet { 96 | 97 | public void doGet(HttpServletRequest req, 98 | HttpServletResponse res) 99 | throws ServletException,IOException { 100 | 101 | 102 | 103 | res.setContentType("text/html; 104 | charset=UTF-8"); 105 | 106 | PrintWriter out = res.getWriter(); 107 | 108 | out.println(""); 109 | out.println(""); 110 | out.println("Hello World!!"); 111 | out.println(""); 112 | out.println(""); 113 | out.close(); 114 | 115 | } 116 | 117 | } 118 | ~~~ 119 | 120 | 그래서 등장한 도구가 JSP (루비의 ERB 같은 느낌이라고 보면 된다) 121 | ~~~jsp 122 | <% @page import="java.util.Calendar" %> 123 | <% @page contentType="text/html; charset=UTF-8"%> 124 | <% String str = String.format("%tF",Calendar.getInstance()); %> 125 | 126 | 127 | 129 | Insert title here 130 | 131 | 132 | 오늘은 <%= str %>
한시간만 참으면 점심.... 133 | 134 | 135 | ~~~ 136 | 137 | 아무튼 이렇게 기존 방식보다 html 작성이 훨씬 빠르게 되었다. 138 | 내부적으로는 JSP 파일은 Tomcat이 Servlet으로 바꾸어서 돌린다고 한다. 139 | 140 | ## 3. 컨테이너 그리고 IOC / DI 141 | #### 3.1 스프링 컨테이너 란? 142 | 컨테이너는 보통 인스턴스의 생명주기를 관리하며, 143 | 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것이다. 144 | 컨테이너는 개발자가 작성한 코드의 처리과정을 위임받은 존재이다. 145 | 예를들어 서블릿 컨테이너는 서블릿을 생성하고 스레드를 이용해 사용자의 요청을 처리한다. 146 | 147 | 이와 마찬가지로, 스프링에도 의존성 주입을 이용하여 어플리케이션 컴포넌트들을 관리하는 컨테이너가 있다. 이것이 바로 Spring Container 이다. 148 | 149 | #### 3.2 IOC / DI 150 | 그리고 컨테이너는 아래와 같은 특징을 가진다 151 | 152 | 1. **IOC (Inversion Of Control - 제어의 역전)** 153 | 154 | 개발자는 보통 객체지향 프로그래밍을 하면 New 연산자, 인터페이스 호출, 팩토리 호출방식으로 객체를 생성하고 소멸시킨다. 155 | IOC란 이렇게 원래 개발자의 의무인 인스턴스의 생성부터 소멸까지의 객체 생명주기 관리를 컨테이너가 해 주는것을 말한다. 156 | 157 | 2. **DI (Dependency Injection - 의존성 주입)** 158 | 159 | IoC를 실제로 구현하는 방법으로서 의존성있는 컴포넌트들 간의 관계를 개발자가 직접 코드로 명시하지 않고 컨테이너인 Spring이 런타임에 찾아서(getBean) 의존성을 주입해 주는 것이다. 160 | 161 | - 인터페이스에 알맞는 Bean 을 주입하는 방법을 많이 사용한다. 162 | - 생성자 주입이 권장된다 (final 선언으로 immutable / 과한 책임의 가시성) 163 | 164 | 165 | #### 3.2 스프링 컨테이너의 종류 166 | 1. **BeanFactory** 167 | 168 | DI의 기본사항을 제공하는 가장 단순한 컨테이너이다. 169 | BeanFactory 는 빈을 생성하고 분배하는 책임을 지는 클래스 170 | 빈 자체가 필요하게 되기 전까지는 인스턴스화를 하지 않는다 (lazy loading) 171 | 172 | 2. **ApplicationContext** 173 | 174 | 빈팩토리와 유사한 기능을 제공하지만 좀 더 많은 기능을 제공한다. 175 | 176 | - 국제화가 지원되는 텍스트 메시지를 관리해 준다. 177 | 178 | - 이미지같은 파일 자원을 로드 할 수 있는 포괄적인 방법을 제공해준다. 179 | 180 | - 리스너로 등록된 빈에게 이벤트 발생을 알려준다. 181 | 182 | - Lazy Loading이 아니라 컨텍스트 초기화 시점에 모든 싱글톤 빈을 미리 로드한다. 183 | 184 | ## 4. AOP 와 Proxy 185 | 186 | https://minwan1.github.io/2017/10/29/2017-10-29-Spring-AOP-Proxy/ 187 | > 모듈을 쉽게 사용할 수 있도록 해주는 것이라고 보는것이 편함 188 | 특정 로직이 수평으로 흐른다면, 수직으로 원하는 흐름을 꽂아주는 방식이다. 189 | 핵심로직을 구현한 코드를 컴파일하거나, 컴파일된 클래스를 로딩하거나, 또는 로딩한 클래스의 객체를 생성할 때, Proxy 객체를 통해 호출할 때 AOP가 적용됨 190 | 191 | ### AOP 기본 192 | #### 1. AOP 용어 193 | 1. **Advice** 194 | 언제 공통 관심 기능을 비즈니스 로직에 적용할 지 정의 195 | *예를들어,* '메서드를 호출 하기전에 트랜잭션 시작' 기능을 적용한다는 것을 정의하고 있는 것 196 | 197 | 2. **Joinpoint** 198 | Advice 를 적용 가능한 지점을 의미. 199 | 메소드 호출, 필드값 변경 등이 Joinpoint에 해당 200 | 201 | 3. **Pointcut** 202 | Joinpoint의 부분집합으로서 실제로 Advice가 적용되는 Joinpoint를 나타냄 203 | 스프링에서는 정규 표현식이나 AspectJ의 문법을 이용하여 Poincut을 재정의 할 수 있습니다. 204 | 205 | 4. **Weaving** 206 | Advice를 비즈니스 로직에 적용하는 행위 207 | 208 | 5. **Aspect** 209 | 여러 객체에 공통으로 적용되는 기능 210 | 트랜잭션, 보안 등이 Aspect의 좋은 예 211 | 212 | #### 2. Weaving 방식 213 | 214 | 1. 컴파일시에 Weaving하기 215 | 2. 클래스 로딩 시에 Weaving하기 216 | 3. 런타임시에 Weaving하기 217 | 218 | > 1,2 번 같은 경우는 AspectJ라이브러리를 추가하여 구현할때 사용됨. 219 | 런타임시 위빙같은 경우는 Spring-AOP 에서 사용하는 방식으로, 소스코드나 클래스 자체를 변경하는 것이 아니라 **프록시 객체** 를 사용하여 모듈을 Weaving 하고 비즈니스 로직을 실행한다. 220 | 221 | ***Proxy 를 이용한 런타임 위빙*** 222 | 223 | ![스프링AOP](https://user-images.githubusercontent.com/26560119/63500528-f441ba00-c504-11e9-94cb-1aa87120984c.jpg) 224 | 225 | #### 3. Spring-AOP 226 | > 스프링은 자체적으로 프록시 기반의 런타임 AOP를 지원하고 있다. 227 | 따라서 11-2 에서 살짝 설명한 것과 같이, 228 | Spring-AOP는 ***메서드 호출*** Joinpoint 만을 지원함. 229 | 만약에 ***필드값 변경*** 과 같은 Joinpoint 를 사용하고 싶다면, AspectJ와 같이 다양한 Joinpoint를 지원하는 AOP프레임워크를 사용해야 한다. 230 | 231 | 또한 스프링은 3가지 방식으로 AOP를 제공한다. 232 | 233 | - XML 스키마 기반의 POJO클래스를 이용한 AOP구현 234 | - AspectJ에서 정의한 @Aspect 애노테이션 기반의 AOP구현 235 | - 스프링 API를 이용한 AOP구현 236 | 237 | **어떠한 방식을 사용하더라도 Proxy를 통한 메서드 호출만 AOP가 적용된다는것을 알아두자** 238 | 239 | #### 4. 프록시를 생성하는 방식 240 | > 어쨌든 실행해야 하는 비즈니스 로직이 있는 클래스에 대해 무조건 Bean 객체가 생성되는데, 스프링 컨테이너가 지정한 Bean 객체에 대한 프록시 객체를 생성하고, 원본 Bean 객체 대신에 Proxy 객체를 사용하게 된다. 이때 프록시 객체를 생성하는 방식은 인터페이스 여부에 따라 두가지 방식으로 나뉜다. 241 | 242 | 1. JDK Dynamic Proxy 243 | - 이는 인터페이스 기반으로 프록시 객체를 생성하기 때문에, 인터페이스에 정의되어있지 않은 메서드에는 AOP가 적용되지 않는 점을 주의해야 한다. 244 | 245 | 2. CGLIB 246 | - 인터페이스를 따로 구현하고 있지 않는 클래스는 CGLIB 방식으로 프록시를 생성한다. 247 | 이는 대상 클래스를 상속 받아 프록시를 구현하게 된다. 따라서 클래스가 final 인 경우는 프록시를 생성할 수 없고 private method 같은 경우에는 AOP 의 혜택을 받을 수 없다. 248 | 249 | 250 | ### Spring @Transactional 이 적용되지 않는 사례들 251 | > 스프링의 @Transactional annotation 은 Proxy Mode 와 AspectJ 모드로 동작한다. 252 | 일반적으로 많이 사용되는 것은 Proxy Mode 인데, 아무래도 Bean 이 아니라 프록시 객체를 이용하는 방법이다 보니, 의도치 않게 @Transactional 어노테이션이 동작하지 않는 사례들이 있다. 253 | 254 | 1. **private method에 @Transactional 달았을때** 255 | 256 | Service Bean 에서 메서드를 호출하는 것이 아니라, Proxy 객체가 메서드를 호출하게 되므로 당연히 @Transactional 어노테이션이 적용되지 않는다. 257 | 이 부분은 SonarLint 같은 정적 코드분석기도 알려주는 부분이라 발견하기 쉽다. 258 | 259 | 2. **메서드 안에서 내부 메서드 call** 260 | 261 | self call 에 관한 부분이다. 262 | 내부 클래스에서의 동일 메소드를 호출 할 때에는 Proxy 객체가 아닌 this 를 이용해 메소드를 호출하기 때문이다. 프록시로 특정 메서드를 불러냈어도 그 메서드 흐름 안의 internal method 는 Bean 이 호출한다. 263 | 따라서 프록시 객체에 의해 동작하는 Spring-AOP는 내부 method를 호출하는지 까지는 관심이 없다. 처음 프록시로 불러낸 메서드까지가 Proxy 관할 구역임 264 | 265 | *아래와 같은 코드는 무용지물이다. 266 | 프록시는 자신이 호출한 메서드 그 하나만 인식하는 것이다.* 267 | 268 | ~~~java 269 | @Transactional 270 | public void cancel(String orgFlwNo) { 271 | cancelTransaction(orgFlwNo); 272 | } 273 | 274 | public void cancelTransaction(String orgFlwNo) { 275 | TradeRepository.cancelTrade(orgFlwNo); 276 | userPointRepository.savePoint(CURRENT_USER_ID) 277 | } 278 | ~~~ 279 | 280 | *당연히 아래와 같은 코드도 무용지물이다. 281 | 어차피 프록시가 호출하지 않을 메서드이기 때문 (태어날때부터 self call이 예견되어 있다.)* 282 | ~~~java 283 | public void cancel(String orgFlwNo) { 284 | cancelTransaction(orgFlwNo); 285 | } 286 | 287 | @Transactional 288 | public void cancelTransaction(String orgFlwNo) { 289 | TradeRepository.cancelTrade(orgFlwNo); 290 | userPointRepository.savePoint(CURRENT_USER_ID) 291 | } 292 | ~~~ 293 | 294 | 295 | 헷깔릴 수도 있는데, 프록시는 메서드를 불러주는 대리인이다. 296 | 대리인은 말그대로 다른 클래스에서 호출하는 것과 마찬가지다. 297 | 298 | 위 코드에서 cancel 메서드는 외부에서 부르게 되는 시나리오의 메서드이고, 아래 cancelTransaction은 cancel 내부에서 호출하고 실행해야 의미가 있는 내부 메서드이다. 299 | *(위의 예제는 임시로 12.1 의 이유로 public scope로 되어 있음)* 300 | 301 | 따라서 proxy 입장에서 내부에서 호출해야만 하는 메서드에 아무리 @Transactional 을 달아봐야 외부인인 proxy 는 내부 메서드 cancelTransaction 의 흐름을 가로챌 기회가 없는 것이다. 302 | 303 | 3. **Try Catch 구문 안에서 사용할때** 304 | 305 | @Transactional 어노테이션은 비즈니스 로직 실행 뒤 Exception을 인식하고 처리한다. 306 | 따라서 로직 안에서 try - catch 를 해버리면 @Transactional이 예외를 인식하기도 전에 메서드 내부에서 예외를 catch 하게 되어 예외시 ROLLBACK이 불가능하다. 307 | 308 | ## 5. Spring MVC 동작 원리 309 | 310 | ![99D9B34B5C9C5B501C](https://user-images.githubusercontent.com/26560119/64938537-3c9c8f80-d899-11e9-8760-dbdbdd26ba17.png) 311 | 312 | 1. 웹 어플리케이션이 실행되면 Tomcat(WAS) 에 의해 배포서술자 `web.xml` 로딩 313 | 314 | 2. WAS 는 `web.xml` 에 등록되어 있는 ContextLoaderListener 생성 315 | - 자동으로 IoC container (ApplicationContext) 초기화 316 | - Servlet 을 사용하는 시점에 ServletContext 에 ApplicationContext 등록 317 | - Servlet 이 종료되는 시점에 ApplicationContext 삭제 318 | 319 | 3. 위에서 생성된 ContextLoaderListener는 `root-context.xml` 을 로딩 320 | - `root-context.xml` 은 Service , Repository 와 같은 bean 을 설정함 321 | 322 | 4. Root Spring Container 구동 323 | - ContextLoaderListener 가 `root-context.xml` 의 설정 기반으로 Root Spring Container 구동 324 | 325 | 4. 사용자 요청 받음 326 | - 최초의 클라이언트 요청이라면 DispatcherServlet 객체 생성 327 | 328 | 5. 두번째 Spring Container 구동 (By DispatcherServlet) 329 | - 두번째 스프링 컨테이너에는 컨트롤러 Bean 들이 들어 있고, 기존 root container 클래스를 상속받는다. 330 | - DispatcherServlet 객체는 `WEB-INF/config` 폴더에 있는 331 | servlet-context.xml` 파일을 로딩하여 두번째 스프링 컨테이너를 구동 332 | - servlet-context.xml을 보면 어노테이션을 스캔하여 bean 객체로 등록함을 볼 수 있음 (@Controller) 333 | - DispatcherServlet 이 **두번쨰 스프링 컨테이너** 를 구동 한다는 사실 기억할 것 334 | 335 | 6. DispatcherServlet 의 `doService()` 호출 336 | 1. `doService()` 에는 사용자의 요청을 처리하기 위한, Handler 과 Adapter 을 찾아 호출하기 위해 `doDispatch()` 호출 337 | 2. `doDispatch()` 에서는 HandlerMapping 을 통해서 요청에 맞는 Controller 의 HandlerMethod 를 찾고, HandlerMethod 를 호출할 수 있는 HandlerAdapter 찾음 338 | 3. HandlerAdapter 가 HandlerMethod 호출 339 | 340 | 7. Controller 요청 처리 후, Controller 는 ModelAndView , View 리턴 341 | 342 | 8. 리턴받은 View 는 ViewResolver가 먼저 받아 해당 view가 존재하는지 검색 343 | 344 | 9. DispatcherServlet은 ViewResolver 로 부터 JSP 등 최종 표시 결과를 받아서 최종 결과를 사용자에게 전송 345 | 346 | ## 6. JPA vs MyBatis 347 | 348 | ### 6-1) 영속성 (Persistence) 349 | 350 | - 데이터를 생성한 프로그램의 생명이 다하더라도, 데이터는 남아 있는 것 351 | - 따라서 우리는 데이터베이스(DISK) 를 통해 영속성을 부여한다. 352 | - Persistence Layer 는 데이터에 영속성을 부여해 주는 계층이다. 353 | - 여기서 JDBC 없이 영속성을 갖게 해 주는 도구가, Persistence Framework 354 | 355 | ![spring-jdbc-layer](https://user-images.githubusercontent.com/26560119/58633311-03a8d100-8323-11e9-81bf-1e18a68a6b34.png) 356 | 357 | ### 6-2) SQL Mapper 과 ORM 358 | Persistence Framework 는 두가지가 있다. 359 | #### 1. SQL Mapper 360 | - SQL **<- mapping ->** Object 필드 361 | - 대표적인 예로는 Mybatis 이고, 실제 SQL을 명시해 주어야 한다. 362 | - 직접 SQL을 많이 만져야 하는 쿼리가 있는 경우에 좋다. 363 | - XML 파일에 쿼리 쓰고 @Autowired 하는 방식 364 | > SQL Mapper의 Query는 xml로 관리되어지기 때문에 유지보수 과정에서 문제가 발생했습니다. 빌드 과정에서 오류를 발생시키지 않기 때문에 최악에는 SQL Query과 관련된 모든 Controller/Business/DAO Layer를 찾아서 유지보수 해야했습니다. 365 | 366 | 367 | #### 2. ORM (Object - Relation Mapping) 368 | - 객체와 RDB 테이블의 데이터를 자동으로 매핑해 주는 도구 369 | - SQL Query 대신 직관적인 method 로 트랜잭션 할 수 있다. 370 | - SQL을 자동으로 생성한다. 371 | - Persistence API 라고 할 수 있다. 372 | - Hibernate 는 JPA 의 구현체이다. 373 | 374 | #### 2-1) JPA 그리고 Hibernate 375 | overall_design 376 | 377 | - JPA 는 자바 어플리케이션에서 데이터베이스를 사용하는 방식을 정의한 인터페이스이다. 378 | - Hibernate 는 JPA를 구현한 구현체이다. 379 | 380 | #### 3. ORM의 장점과 단점 381 | #### 장점 : 382 | - 객체지향적인 코드로 직관적이고, 비즈니스 로직에 더 집중할 수 있다. 383 | - DBMS 에 종속적이지 않다. 384 | - 재사용 및 유지보수의 편리성이 증가한다. 385 | - JPA 경우 @Query 어노테이션을 사용하여 SQL을 직접 쓸 수 있으나, 복잡한 것 뺴고는 JPQL 이용하도록 함 386 | 387 | #### 단점 : 388 | - JPA의 내장 메소드로 해결되지 않는 쿼리가 많다. 389 | - 자주 사용되는 대형 쿼리는 별도의 튜닝이 필요한 경우가 있다. 390 | - 최적화된 SQL 쿼리를 사용할때는 MyBatis 가 낫다. (배우기 어렵) 391 | - 아래 링크 참조 392 | https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html 393 | - ORM에 대한 개발자들의 생각 394 | https://okky.kr/article/286812 395 | 396 | ## 7. JAR vs WAR 397 | > class < jar < war < ear 398 | 399 | ### 5-1) JAR (Java Application Archive) 400 | - java class 파일 및 리소스파일(이미지, 텍스트 등)의 컨테이너이다. 401 | - jar 파일이 독립실행 되려면, 클래스 중 하나가 기본 클래스로 정의된다. 402 | - 실행 가능한 jar 파일은 아래 명령어로 실행된다. (spring 지원) 403 | ~~~ 404 | java -jar foo.jar 405 | ~~~ 406 | 407 | ### 5-2) WAR(Web Application aRchive) 408 | - 웹 어플리케이션을 저장하고 압축해 놓은 파일 409 | - html, JSP, 서블릿 소스 등이 컴파일 되어 저장되어 있다. 410 | - war는 WAS 위에서 돌아갈 수 있다. 411 | - Tomcat 위에 얹어서 디플로이한다. 412 | 413 | ## 7. 외장 톰캣 vs 내장 톰캣 414 | - 웹 서버 위에서 다른 WAS 과 함께 운영해야 한다면 외장 톰캣 415 | - 아니면 기존 레거시가 있거나 .. 416 | - 그럴필요 없다면 내장 톰캣을 써도 좋다. 417 | - D2 Naver 의 동영상 플랫폼 개발 팀도 embed 톰캣을 쓰더라 418 | https://d2.naver.com/helloworld/5626759 419 | https://zepinos.tistory.com/51 420 | ## 8. 스프링 Log 421 | - 스프링은 LogBack, Log4j 등 여러 로그 라이브러리를 지원한다. 422 | - Logback 이 Log4j 보다 10배이상 빠르고 메모리 효율성도 좋단다. 423 | 424 | ### Log Level (강한 로그 순서대로) 425 | 1) FATAL : 가장 크리티컬한 에러 426 | 2) ERROR : 에러 427 | 3) WARN : 에러는 아니지만 주의할 것 428 | 4) INFO : 일반 정보 429 | 5) DEBUG : 일반 정보를 좀 더 상세히 (옵션을 켜야 보임) 430 | 6) TRACE : 에러 시 경로 추적 (스택 트레이스 같은 것) 431 | 432 | ## 9. Maven vs Gradle 433 | 434 | - 둘다 빌드 툴이다. 435 | - 라이브러리 Dependency 를 관리한다. 436 | > Gradle 이 더 좋아보임 (출시 시기도 늦고 ANT, MAVEN 장점만을 모았다고 함) 437 | 438 | ### GRADLE 439 | - XML 기반의 Maven 빌드 설정보다 Gradle의 빌드 설정의 가독성이 더 좋다. 440 | - Gradle의 빌드 성능이 Maven의 빌드 성능보다 더 뛰어나다 441 | - **Groovy 기반의 DSL(domain-specific language)로 Gradle의 빌드 스크립트를 직접 작성할 수 있다.** 442 | 443 | ## 10. Spring TEST 444 | 445 | - 레일즈는 RSpec, Capybara 등 라이브러리 존재 446 | - 카피바라로는 패스트원 할떄 로그인, 메뉴진입 등 기본적인 View 기반 테스트 진행 447 | 448 | > 스프링부트는 처음 빌드 설정파일에 spring-boot-starter-test 넣으면 다 설치됨. 449 | 아래와 같은 것들이 포함된다고 한다. 450 | 451 | - JUnit — 자바 표준 단위 테스트 프레임워크 452 | - Spring Test — 스프링 부트 애플리케이션 테스트 지원을 위한 유틸리티 453 | - AssertJ — 어셜선 라이브러리 454 | - Hamcrest — 유용한 매처를 지원하는 객체 라이브러리 455 | - Mockito — 자바 모킹 프레임워크 456 | - JSONassert — JSON 어셜션 라이브러리 457 | - JsonPath — JSON 구조를 탐색할 때 유용한 라이브러리 458 | 459 | ## 11. JpaRepository save vs saveAll 460 | - save는 트랜잭션 하나에 한개 insert 461 | - saveAll은 트랜잭션 하나에 여러개 insert 462 | -> 트랜잭션 절약 463 | - saveAll 은 Batch 개수 설정도 가능 464 | spring.jpa.properties.hibernate.jdbc.batch_size=4 465 | 466 | ## 12. 스프링 배치 467 | - 일괄처리라는 뜻을 가지고 있음 468 | - WAS에서 대용량 처리로 인한 과부하 방지 469 | - 단발성 대용량 처리에 용이 (특정 시간 대용량 데이터 처리) 470 | - SpringQaurtz 등 스케줄러와 같이 쓰는 경우가 많음 471 | 472 | ### 스프링배치 어플리케이션의 조건 473 | - 대용량 데이터 - 배치 어플리케이션은 대량의 데이터를 가져오거나, 전달하거나, 계산하는 등의 처리를 할 수 있어야 합니다. 474 | - 자동화 - 배치 어플리케이션은 심각한 문제 해결을 제외하고는 사용자 개입 없이 실행되어야 합니다. 475 | - 견고성 - 배치 어플리케이션은 잘못된 데이터를 충돌/중단 없이 처리할 수 있어야 합니다. 476 | - 신뢰성 - 배치 어플리케이션은 무엇이 잘못되었는지를 추적할 수 있어야 합니다. (로깅, 알림) 477 | - 성능 - 배치 어플리케이션은 지정한 시간 안에 처리를 완료하거나 동시에 실행되는 다른 어플리케이션을 방해하지 않도록 수행되어야합니다. 478 | 479 | https://jojoldu.tistory.com/324 480 | -------------------------------------------------------------------------------- /spring/spring_intermediate.md: -------------------------------------------------------------------------------- 1 | [목록으로](https://github.com/Donsworkout/techInterview/blob/master/README.md) 2 | ## SpringBoot in Project 3 | 4 | ### 1. 스레드 / 스레드 풀 5 | https://postitforhooney.tistory.com/entry/JavaThread-Java-Thread-Pool%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-Thread%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0Thread-Runnable 6 | 7 | 1. 스레드 8 | > 스레드(thread)는 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말한다. 일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있다. 이러한 실행 방식을 멀티스레드(multithread)라고 한다. 9 | 10 | 2. implements Runnable **VS** extends Thread 11 | > Runnable 은 자바의 다중상속에 대한 문제를 해결해 준다. 12 | 13 | 3. 스레드 풀 14 | https://limkydev.tistory.com/55 15 | 16 | - 병렬 작업 처리가 많아지면 Thread의 개수가 증가되고 어플리케이션의 성능이 저하됨 17 | 18 | - Thread Pool은 스레드를 미리 만들어 놓음 19 | 20 | - Thread Pool은 작업 처리에 사용되는 Thread를 제한된 개수만큼 정해 놓고 작업 큐(Queue)에 들어오는 작업들을 하나씩 Thread가 맡아 처리함 21 | 22 | \- Thread Pool도 과유불급이다. 너무 많이 만들어 놓으면 메모리 낭비 발생 23 | 24 | ### 2. ThreadPoolTaskExecutor 를 이용한 멀티쓰레드 구현 25 | https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/task/TaskExecutor.html 26 | > TaskExecutor 라는 이름의 인터페이스를 사용하여 Thread의 개수를 자동으로 조절하고 ThreadPoolTaskExecutor 를 추상화하는 execute() 메소드를 사용해 멀티쓰레드로 작업을 처리합니다. 27 | 28 | #### void execute(Runnable task) 29 | *Execute the given task.* 30 | ~~~ 31 | The call might return immediately if the implementation uses an asynchronous execution strategy, or might block in the case of synchronous execution. 32 | ~~~ 33 | 34 | execute() 함수의 인자로는 Runnable 인터페이스를 구현한 구현체가 들어가게 됨 35 | execute 는 Executor 인터페이스의의 메소드이다. 36 | 37 | ~~~ 38 | Interface Executor - Interface TaskExecutor 39 | // 부모 인터페이스 - 자식 인터페이스 40 | ~~~ 41 | 42 | ThreadPoolTaskExecutor 는 위의 인터페이스를 구현하는 구현체이다. 43 | 그리고 Interface AsyncListenableTaskExecutor 도 구현하고 있어 비동기 방식으로 작동한다. 44 | 45 | ~~~java 46 | taskExecutor.execute(ctx.getBean(실행할.class)); 47 | ~~~ 48 | 그리고 위의 코드는 실행할 Bean의 run method 를 자동으로 실행한다. 49 | 50 | 51 | 설정 파일 예시 (/config/ThreadConfig.java) 52 | ~~~java 53 | @Configuration 54 | public class ThreadConfig { 55 | @Primary 56 | @Bean 57 | public TaskExecutor taskExecutor() { 58 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 59 | executor.setCorePoolSize(50); 60 | executor.setMaxPoolSize(100); 61 | executor.setThreadNamePrefix("default_task_executor_thread"); 62 | executor.initialize(); 63 | return executor; 64 | } 65 | } 66 | ~~~ 67 | 68 | ### 3. CompletableFuture 69 | 70 | Java7 부터는 Future 인터페이스를 통해서, 비동기 프로세스를 수행할 수 있었다. 71 | Future 클래스는 비동기 계산이 끝났는지 확인할 수 있는 isDone, 타임아웃 기간을 결정하고 결과를 출력하는 get 메소드 등이 있다. 72 | 73 | JAVA8 에서는 복잡한 비동기처리를 선언형으로 이용할 수 있는 CompleteableFuture 를 제공하며, Stream API 나 Optional 같이 람다표현식과 파이프라인을 사용하여 비동기 작업을 조합할 수 있습니다. 74 | 75 | 일부 상황에서는 굳이 CompletableFuture 를 쓸 필요가 없어보이지만, 76 | 병렬스트림과 달리 이를 이용한 방법은 executor 를 커스터마이징 할 수 있다. 77 | 78 | https://m.blog.naver.com/PostView.nhn?blogId=2feelus&logNo=220714398973&proxyReferer=https%3A%2F%2Fwww.google.com%2F 79 | 80 | #### 장점 81 | 82 | 1) 명시적 쓰레드 선언없이 쓰레드를 사용할수 있다. 83 | 84 | 2) 함수형 프로그래밍방식으로 비동기적으로 동시성/병렬 프로그래밍을 가능하게 함으로서 의도를 명확하게 드러내는 함축적인 프로그래밍을 가능하게 한다. 85 | 86 | 3) 각 테스크마다 순서적 연결을 할수도 있고, 테스크의 예외처리도 가능하다. 87 | 88 | 4) 태스크간 결합이 용이함 89 | 90 | 91 | 92 | ~~~java 93 | Stream.of(PartnerCode.values()) 94 | .forEach( partner -> 95 | completableFutures.add( 96 | CompletableFuture.supplyAsync(() -> 97 | getUserInfoForView(userCi, partner)) 98 | .exceptionally(e -> { 99 | LOGGER.info(e.toString()); 100 | return new UserInfoForView().setPartnerInfo(partner.getPartnerCode()); 101 | }))); 102 | 103 | 104 | completableFutures.stream() 105 | .forEach(future -> 106 | userInfoList.add(getUserInfoForViewFromFuture(future)) 107 | ); 108 | ~~~ 109 | 110 | 111 | ### 4. Properties -> Yaml 112 | > yml 파일은 계층 구조를 표현할 수 있는 장점이 있고, 113 | config 클래스를 따로 정의했다면, prefix, 필드명을 yml 파일 명세와 잘 일치시키면 자동으로 설정값을 주입할 수 있다. 게다가 List 나 Map 같은 구조로 설정 값을 주입시킬 수 있다. 114 | 115 | 1. pom.xml 파일에 의존성 추가 (spring-boot-configuration-processor) 116 | ~~~xml 117 | 118 | org.springframework.boot 119 | spring-boot-configuration-processor 120 | 2.1.6.RELEASE 121 | 122 | ~~~ 123 | 124 | 2. yml 파일 명세 125 | ~~~yml 126 | #Hana 127 | socket: 128 | serverAddress: 127.0.0.1 129 | serverPort: 8082 130 | timeout: 131 | checkRequest: 2000 132 | useRequest: 2000 133 | cancelRequest: 2000 134 | delivery: 2000 135 | checkSave: 2000 136 | ~~~ 137 | 138 | 3. 설정 클래스 명세 139 | ~~~java 140 | @Setter 141 | @Getter 142 | @Component 143 | // prefix yaml 파일 명세와 잘 맞출 것 144 | @ConfigurationProperties(prefix="socket") 145 | public class SocketConfig { 146 | private String serverAddress; 147 | private int serverPort; 148 | // timeout의 하위 attr 들을 맵 형태로 매핑할 수 있다. 149 | private Map timeout; 150 | } 151 | 152 | ~~~ 153 | 154 | ### 5. 여러 Yaml 설정파일 추가하기 155 | > SpringApplicationBuilder 를 활용해 간단하게 설정할 수 있다. 156 | ~~~java 157 | @SpringBootApplication 158 | public class MyApplication { 159 | 160 | private static final String PROPERTIES = 161 | "spring.config.location=" 162 | +"classpath:/application.yml" 163 | +",classpath:/config.yml"; 164 | 165 | public static void main(String[] args) { 166 | new SpringApplicationBuilder(MyApplication.class) 167 | .properties(PROPERTIES) 168 | .run(args); 169 | } 170 | 171 | } 172 | ~~~ 173 | 174 | ### 6. SpringApplicationBuilder 175 | [SpringApplicationBuilder 공식문서 확인](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/builder/SpringApplicationBuilder.html) 176 | 177 | ***그냥 앱 실행이라면 아래 방법이 제일 편함*** 178 | ~~~java 179 | public static void main(String[] args) { 180 | SpringApplication.run(MyApplication.class, args); 181 | } 182 | ~~~ 183 | 184 | ***그러나 실행시 Fluent builder API를 사용하기 위해 SpringApplicationBuilder 을 사용한다*** 185 | + 체인 방식의 메서드 Call 을 지원한다. 186 | + 계층을 표현할 수 있다 187 | 188 | ~~~java 189 | new SpringApplicationBuilder() 190 | .showBanner(false) 191 | .sources(Parent.class) 192 | .child(Application.class) 193 | .run(args); 194 | ~~~ 195 | 196 | ***아무튼 앱을 실행하는데에는 아래와 같은 방법들이 있다.*** 197 | ~~~java 198 | @SpringBootApplication 199 | public class Application { 200 | public static void main(String[] args) { 201 | // 방법 1 - static 202 | SpringApplication.run(Application.class); 203 | 204 | // 방법 2 - make instatnce 205 | SpringApplication app = new SpringApplication(Application.class); 206 | app.run(args); 207 | 208 | // 방법 3 - Builder 209 | new SpringApplicationBuilder() 210 | .sources(Application.class) 211 | .run(args); 212 | } 213 | } 214 | ~~~ 215 | 216 | ### 7. Spring Retry 217 | https://github.com/spring-projects/spring-retry 218 | https://www.baeldung.com/spring-retry 219 | 220 | > Spring Retry 는 실패한 작업에 대해 재시도 할 수 있도록 도와준다. 221 | 이는 로직 등 개발자의 실수에 의한 에러보다는 일시적인 에러에 적합하다 (네트워크 장애 등) 222 | 장애가 발생할 수 있는 메서드 위에 **@Retryable** 어노테이션을 이용하여, 특정 예외에 맞는 재시도 횟수, 재시도 BackOff 시간 등을 설정할 수 있다. 223 | 224 | 1. pom.xml 의존성 추가 225 | ~~~java 226 | 227 | org.springframework.retry 228 | spring-retry 229 | 1.1.5.RELEASE 230 | 231 | ~~~ 232 | 233 | 2. Configuration에 @EnableRetry 어노테이션 추가 234 | ~~~java 235 | @Configuration 236 | @EnableRetry 237 | public class AppConfig { ... } 238 | ~~~ 239 | 240 | 3. 일시적 장애가 우려되는 메서드에 @Retryable 어노테이션 추가 241 | ~~~java 242 | @Service 243 | public interface MyService { 244 | @Retryable( 245 | value = { SQLException.class }, 246 | maxAttempts = 2, 247 | backoff = @Backoff(delay = 5000)) 248 | void retryService(String sql) throws SQLException; 249 | ... 250 | } 251 | ~~~ 252 | 253 | 4. 지정된 재시도 횟수만큼 시도했는데 실패했을때 대한 failback 메서드 작성 254 | > 첫번째 인자로 발생한 예외를 넘겨주고, 그 뒤에는 순서대로 원래 메서드의 인자를 적어주면 된다. failback 매서드의 리턴값은 원래 메서드의 리턴값 형식과 같다. 255 | ~~~java 256 | @Service 257 | public interface MyService { 258 | ... 259 | @Recover 260 | void recover(SQLException e, String sql); 261 | } 262 | ~~~ 263 | 264 | 5. 테스트 등 필요하면 RetryTemplate 이용한다. 265 | ~~~java 266 | @Configuration 267 | public class AppConfig { 268 | //... 269 | @Bean 270 | public RetryTemplate retryTemplate() { 271 | RetryTemplate retryTemplate = new RetryTemplate(); 272 | 273 | FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); 274 | fixedBackOffPolicy.setBackOffPeriod(2000l); 275 | retryTemplate.setBackOffPolicy(fixedBackOffPolicy); 276 | 277 | SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); 278 | retryPolicy.setMaxAttempts(2); 279 | retryTemplate.setRetryPolicy(retryPolicy); 280 | 281 | return retryTemplate; 282 | } 283 | } 284 | 285 | ~~~ --------------------------------------------------------------------------------