-
feature 개발 진행하면서 알게된 것들 책, 영상, 자료를 먼저 보고 파악한 내용이 아닌 실제 필요한 기능 개발을 하면서 알게된 것들 : 정말 소중한 경험을 하면서 얻게된 것들을 당분간 남길 것 같음 Jackson json 파싱 기준(예제) 자바빈 규약을 지켜야함 : NoArgsConstructor, setter/getter [] 일 경우 array로 할지, List로 할지는 마음대로 하면 됨 { "id": 123, "name": "Pankaj", "permanent": true, "address": { "street": "Albany Dr", "city": "San Jose", "zipcode": 95129 }, "phoneNumbers": [ 123456, 987654 ], "role":...
-
working 프로젝트에 투입되기 전 배경지식을 얼른 캐치하는 것이 좋음 : 기획 배경, 사용 플로우(직접 사용해보기), API/테이블 목록, 정의, ERD 파악하기 다른 분의 코드를 보니깐 딱 든 생각은 컨벤션의 중요성과 문서화의 중요성(혹은 주석이라도 남기기)임 : 후임자가 코드를 보는데 아무런 설명이 없다면 생산성에 엄청난 악영향을 끼치게 됨 API의 사용처, 객체의 역할, 메소드 각각에 대한 주석 등이 굉장히 생산성에 영향을 미친다는 것을 알게됨 스프링 MVC @RestController redirect @Controller와 달리 redirect를 시키기위해서 HttpServletRequest(JavaEE)를 인자로 받아서 redirect 시켜줘야함 직접적인 JavaEE...
-
MySQL 데이터 타입 성능을 위해서 꼭 맞는 데이터를 고르기 : 공간 낭비(읽어오는 시간, 공간까지도 낭비) 숫자 unsigned : 양수(+)만 타입 크기 참고 BIT(N) 1 ~ 64bit까지 지정 크게 잡고 작은 수를 넣을 경우 0으로 채워짐 TINYINT 1byte SMALLINT 2byte INT 4byte BIGINT 8byte FLOAT 4byte DOUBLE 8byte DECIMAL 지정 시 : (M, N), Mbyte(정확한 소수점을 저장할 때 사용) M 길이로 N개 남은 수부터는 소수점으로, 문자 타입 크기 참고 CHAR(N)...
-
java 팩토리메소드 패턴 객체를 만드는 공장을 생성해두는 것 왜? 특정 조건에 의해 생성되는 인스턴스(같은 상위클래스의 하위클래스)가 다를 때 구체적인 클래스로 인스턴스 생성하는 코드 작성하지않고 생성 권한을 위임 받은 아이에게 요청하면 결합도를 낮출 수 있기 때문(구체적인 클래스를 명시해서 직접 생성하기보다 맞는 조건이 있으면 생성, 없으면 예외 발생이 되도록 할 수도 있음) 조금 더 나아가면 싱글턴일 때 팩토리 혹은 인스턴스 관리자에게 인스턴스를 특정 조건값을 주고 가져오게 할 수도 있음 : 여기에 더 추가하자면 인스턴스들에게 물어봐서 특정 조건값에...
-
test spock 사용해보기 기존에 자바 코드(+spring)를 테스트할 때는 JUnit(unit test), Mockito(integration test)을 사용해서 테스트를 했는데, 워크샵에서 groovy로 테스트 코드를 작성하는 것을 보고 무엇인지 보았더니 Spock 였음 /* build.gradle Spock 추가 : mvnrepo(Core Module) : 스프링 환경에서 테스트 하는 것이 아니므로 Core만 */ dependencies { testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4' } junit과 비교했을 때 Spock는 어떤 특징을 가지는지 알아보았음 POJO 테스트 /* 테스트 대상 코드 */ public class Person { private static NameRule rule...
-
java 병렬로 연산하기 ExecutorService API 쓰레드풀에 일정 개수의 쓰레드를 만들어두고 처리하는 방식의 API : limit 개수만큼 동시에 처리함 ExecutorService executor = Executors.newFixedThreadPool(5); List<Future<String>> results = new ArrayList<>(); for (int i = 0; i < 30; i++) { results.add(executor.submit() -> { Thread.sleep(5000); return Thread.getCurrrentName() + ", end time : " + LocalDateTime.now(); }); } for (Future<String> result : results) { System.out.println(result.get()); } executor.shutdown(); Stream API(java8) 하나의 task를 여러개 task로 쪼개고, 처리한 후 하나로 합치는 형태로 처리...
-
오늘의 회고 드디어 시스템 파악하기 시작! 모르는 것은 모른다고 말하고 배우는 자세를 취하면 아무리 실력 없더라도 안좋게 보지는 않을까 생각함. 그리고 입사해서 느낀 것은 글로 정리하는건 역시나 중요하다는 것 사내 위키에 시스템에 대한 히스토리 정리, 설명이 잘 되어 있다보니 파악하기가 수월하였음 명패에 쓴 “기본으로 돌아가자” 문구처럼 모르겠으면 거기서 헤매기보다 처음부터 훑어보면서 어디를 모르는지 체크부터 하도록 해야겠다. 오늘 공부 못한만큼 내일 많이 해야지~~~ 데이터베이스 upsert 데이터베이스에 저장되어있는 데이터가 있을 경우(unique key값 기준) update, 없을 경우 insert...
-
git git flow(+operation) fork flow : master, develop, feature, release, hotfix 브랜치로 구성하고, 저장소는 upstream, origin, local으로 구성함 브랜치 : master가 현재 운영, develop은 기능 개발 시 출발점이 되는 브랜치, feature는 각 기능 개발 때 사용되는 브랜치(develop에서 branch 생성), release는 다음 release될 브랜치, hotfix는 긴급하게 수정해야하는 상황이 발생했을 때 master로부터 브랜치를 따서 수정 후 merge 배포를 진행함(절대적인 것은 아님! - 각 팀의 운영 노하우에 따라 조금씩 수정될 수 있음) 저장소 : upstream을 prod로 사용하고 origin은...
-
데이터베이스 트랜잭션 격리 수준(Lock 정책) 멀티쓰레드 환경에서 트랜잭션이 지켜야하는 트랜잭션 간의 간섭 금지(Isolation)와 속도 트레이드오프 발생 : 격리 수준 특징을 알아야 도메인 특징에 따라 알맞는 격리 수준을 골라 트레이드오프 상황을 벗어날 수 있을 것이라 생각됨 데이터베이스마다 다르기 때문에 어떤 격리 수준이 있는지는 알아봐야함 명칭 설명 발생할 수 있는 문제점 read uncommited 커밋되지 않은 데이터 변경까지도 다른 트랜잭션에서 읽기 가능 phantom read, non-repeatable read, dirty read read commited 커밋된 데이터 변경을 읽을 수 있음 phantom read,...
-
절차지향 vs 객체지향 프로그래밍 입사 첫날 운 좋게도 객체지향의 사실과 오해 저자이자 배민찬 개발자이신 조영호님의 특강을 들을 수 있었다. 절차지향과 객체지향적인 설계와 코드를 비교해가며 각각의 특징과 장단점에 대해 들을 수 있는 시간이었다. 절차지향 데이터를 관리하는 클래스와 로직을 처리하는 클래스가 분리되어 있음 : 객체는 단지 데이터를 getter/setter 하는 용도로 밖에 사용되지않음 중앙 집중형 코드가 완성됨 : 역할에 따라 로직을 처리하지않고, 데이터를 가진 객체들이 한 곳에서 모여서 절차지향적으로 처리되다보니 변경사항이 생겼을 때 유연하지못함 객체지향 데이터(상태값)와 로직 처리를...
-
REST 도대체 REST가 무엇인가? 이전까지는 그냥 아키텍쳐 스타일, API를 디자인할 때 지켜야하는 원칙들의 모음이라고만 얼핏 알고 있었음 그러니 누가 설명해달라고 했을 때 선뜻 이게 무엇이다라는 말을 하지 못하겠음 그 말은 즉슨 내가 잘 모른다는 사실 그래서 REST에 대해서 나름의 정의를 머리에 가지기 위해 여러 글들을 찾아보게 됨 REST 원칙들이 무엇인지는 알아도, REST가 왜 고안되었는지는 알아도 정작 REST의 REpresentational State Transfer에 대해 관심을 가져보지 않음 REST 알아보기 특정 리소스의 상태 정보를 전달하는 것을 말함 : HTTP...
-
디자인패턴 템플릿 메소드 패턴 전체적인 흐름(로직)은 같으나 일부분 구현 클래스마다 유연성을 부여해주는 문제 해결 방법 : 중복되는 코드를 줄이고 흐름은 일괄적으로 하되 유연성을 부여할 수 있는 방법, 해당 유연성 부여 메소드는 외부 인터페이스로 공개하지않음 public abstract class Car { private boolean isStart; public Car { isStart = false; // 명시적 } public void drive() { if (!isStart) { start(); isStart = true; } System.out.println("붕붕"); } abstract void start(); } public class ManualCar extends Car {...
-
스테이트 패턴 객체의 상태가 변경됨에 따라 다르게 행동할 수 있음 : 상태 자체를 객체화하는 것이라고 이해됨 - 상태를 추상화 시킴, 상태에 따라 할 수 있는 일이 많아지고 조건문이 엄청 세분화 되어질 때 분리시켜서 관리하도록 하는 것이 좋을 듯 상태 별로 같은 행동(코드 중복 제거), 상태 별로 코드 관리(코드 관리에 편함) 볼링 게임 구현할 때 사용했던 패턴이었음 : 상태 자체가 실질적으로 쓰러뜨린 핀(입력된 값)이 유효한 값인지 아닌지 해당 프레임의 상태값이 무엇인지 정할 수 있었음 예제로 되새겨보는...
-
톰캣은 어떻게 동작하나* 갑자기 궁금해져서 여러 자료를 통해서 알아보게 됨 HTTP 메세지 추상화(자바의 abstract와 다른 뜻의 추상화) 객체 생성 요청 처리할 서블릿 찾기 - web.xml(Deployment Descriptor) 참고, 스프링MVC도 초기에 xml을 사용했지만 어노테이션 - 리플렉션 API로 xml 사용을 하지않아도 되도록 함 컨테이너에 요청 - 인스턴스 생성 or 리턴 처리 후 응답 서블릿 컨테이너 서블릿은 자바의 HTTP 처리 추상화 표준 : 서블릿을 구현하여 서버 개발자가 HTTP 요청에 대한 처리 응답을 만들 수 있음, JavaEE 마다 각 서블릿...
-
디자인패턴 평소 전략 패턴을 사용해서 객체 간의 디펜던시를 끊고 개발을 많이 하면서 디자인패턴의 효용성에 대해서 알게 되었음 이전에는 이런 것까지 알아야해? 했지만 지금은 알고 있으면 문제 상황에서 해결할 수 있는 방법 하나쯤을 더 알고 있는 것이 아닐까 라는 생각이 듦 그래서 하루 하나씩 디자인패턴에 대해서 알아보고자 함 : 다 외우겠다는 것은 아니지만 이해는 하고 있자는 취지! 디자인 패턴 종류 전략 패턴 싱글턴 패턴 스테이트 패턴 템플릿 메소드 패턴 옵저버 패턴 커맨드 패턴 데커레이터 패턴 팩토리...
-
sync/async, blocking/non-blocking Java9도, Spring5도, nodejs도 얘기할 때 가장 큰 토픽이 async/non-blocking이라고 하던데 정확히 구분을 할 수 없어 공부해야겠다는 생각이 들었음 헷갈리는 부분 두 그룹의 구분해서 이해하기 blocking/non-blocking : 시스템 콜에 대한 결과 반환 전까지 대기(wait), 처리가 완료되지않아도 결과가 반환되어 제어권이 넘어와서 다음 처리를 할 수 있음 sync/async : 호출하는 쪽에서 작업 완료 여부를 신경씀(완료 확인을 계속함)과 작업 완료 여부 신경쓰지않고 호출한 함수에 맡겨버림(완료 처리는 콜백함수로 호출받은 쪽에서 완료 후 처리함) 참고자료 HomoEfficio - Blocking-NonBlocking-Synchronous-Asynchronous nesoy...
-
트리 말 그대로 나무형태 구조 : 뻗아나가는 계층적인 구조, 루트 노드(오직 1개), 브랜치 노드, 리프 노드(더 이상 자식노드가 없는) 사용하는 곳 : (빠른)검색 관련(이진 탐색) 탐색(순위) 방법 : 중간 노드를 기준으로 이름이 정해짐, 자식 노드(왼/오)는 각각이 트리일 수 있음 전위 : 중간 노드 - 왼쪽 노드 - 오른쪽 노드 순 중위 : 왼쪽 노드 - 중간 노드 - 오른쪽 노드 순 후위 : 왼쪽 노드 - 오른쪽 노드 - 중간 노드 순 직접 구현 배열...
-
6개월 코드스쿼드 과정을 모두 끝내고… 처음엔 어떻게 보낼까 생각했던 6개월이 점점 가면 갈수록 시간이 빠르게 느껴졌고, 이전에는 생각치 못했던 실력을 가지게 됨을 느꼈다. 어떻게보면 짧은 시간이지만 또 어떻게보면 6개월이라는 시간은 굉장히 길다. 절대 시간은 적지만 그 시간을 제대로만 활용해도 엄청난 시간이 될 것이라는 믿음을 가지고 계속해서 공부를 해나갔다. 마스터들의 도움, 같이 공부하는 동료들의 도움들로 인해 쉽게 얻기 힘든 것들의 가치와 그것들을 얻게 되었다. 어제 코드스쿼드 생활의 마지막 장식으로 면접을 보고 부산을 내려오게 되었다. 부산 내려오는...
-
Jvm 메모리 힙 영역 힙 : 객체가 저장되는 곳, 쓰레드 간 공유 영역, gc의 청소 대상 - 참조되지않는 객체(메모리 회수) 추상적인 가비지 컬렉터 지식을 조금 더 구체화 하고 싶었음 가비지 컬렉터 조금 더 알아가기 GC가 청소할 때는 ‘stop-the-world’로 자바 어플리케이션의 동작을 일시적으로 멈추고 청소함 : 청소 작업 쓰레드 이외의 쓰레드는 동작 멈춤 GC 성능 튜닝 : ‘stop-the-world’ 시간 줄이는 것에 집중, 어플리케이션 처리 일시정지가 길어지는만큼 처리 속도가 느리게 보임 메모리 청소 시에 부분 부분 청소를...
-
Java API ArrayList vs LinkedList 많이 쓰는 자료구조지만, 개념적으로 차이도 이해하고 있지만 익숙하다고해서 ArrayList만 사용하지않나? 제대로 사용하기위해서 코드를 눈으로 봐야겠다싶었음 개념적 차이 ArrayList는 배열로, LinkedList는 객체 간 연결을 통해 리스트를 만듦 ArrayList는 탐색에 유리 : 인덱스 LinkedList는 제일 앞, 뒤 확장에 유리 : 삽입이 빈번할 때 유리 API 코드 확인 LinkedList /* head와 tail을 알고 있음 */ transient Node<E> first; transient Node<E> last; /* 꼬리에 붙임 */ public boolean add(E e) { linkLast(e); return true;...
-
INDEX 테이블 읽기 속도를 높여주는 자료구조 속도 비교해보기 200만건 데이터 bulk insert 하기 bulk insert 할 때 foreign key가 있다면 foreign key 체크가 기본적으로 설정되어있어(참조 무결성) insert 하는 데에 많은 시간이 듦, 감사합니다 호눅스 bulk insert 한글이 깨지는 현상이 있다면 : 아래 bulk insert 토픽 참고 /* 데이터베이스 캐릭터셋 설정 */ > show variables like 'c%'; /* 테이블 생성 */ > SET foreign_key_checks=0; DROP TABLE IF EXISTS user; CREATE TABLE user ( id int not...
-
HTTP’S’ HTTP의 단점과 HTTP’S’ HTTP : 클라이언트가 서버에 민감한 정보를 요청 메세지에 실어보내야할 때 평문으로 데이터를 보냄, 설령 Base64와 같이 간단한 인코딩 방식으로 변환했다고 하더라도 인코딩 방법만 알면 금방 디코드 되기 쉬움 HTTPS : 보안 개념이 더해진 HTTP(Secure Socker Layer) - SSL 프로토콜이 추가됨 인증된(안전한) 서버라는 것을 인증, 민감한 데이터를 암호화 SSL(TLS) : 안전하게 데이터를 주고 받을 수 있게 해주는 프로토콜, HTTP 아래 계층(기반 프로토콜) 어떻게 ‘안전하게’? 데이터 암호화 : 민감한 데이터를 평문으로 보내지않고, 암호화해서...
-
간단하게 HTTP/2 알아보기 HTTP의 단점과 HTTP/1.1의 해결방법 그리고 단점 무거운 헤더 : 헤더를 통해 전달되는 데이터(key-value) 모두 무거운 존재 - 해당 값들을 모두 서버에 보내줘야하고, 서버는 또 필요한 헤더를 설정해서 클라이언트에 보내줘야함 3way handshake를 거쳐 형성되는 TCP 커넥션을 한번의 리소스를 응답받은 뒤 끊어버림 : 주고 받아야할 리소스가 많아질수록 커넥션이 많이 필요하게됨 - 그만큼 커넥션을 맺기위한 사전 작업 또한 계속해서 하게됨 HTTP(TCP 기반) : 직렬적(순서대로), 여러 리소스가 있으면 요청하고 응답받고 순서대로 하나씩 진행 HTTP/1.1 해결 방법...
-
JPA ORM으로 테이블 복잡도 줄이기 성능 상의 이점을 보기 위해서 두 테이블로 나누지않고 하나의 테이블에 관련 정보를 모음 : JOIN 하지않고 그냥 SELECT 하기위해서 @Embedded와 @Embeddable로 복잡도 줄이기 : 객체 분리해서 모듈 형태로 관리하기 - 하나의 큰 판(CarInfo)과 여러 모듈(Car, Owner) 테이블 mysql> desc carinfo; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name |...
-
도커 리눅스 컨테이너 기술을 활용함 : 사용 하는 것에 있어서 추상화 시킨 것으로 이해함 - 사용할 때 커맨드 인터페이스로 명령(docker run, images 등) 왜 경량화인가? 왜 고립되었다고 하는가? (단번에 이해하기 어려운 기술일 것 같아서 계속해서 봐야할 듯) 가상화랑은 다르게 호스트 OS에 게스트 OS를 설치하지않음 : 호스트 커널을 공유함 자원을 같이 쓰되 고립된 환경에서 사용함 개발, 배포, 운영 단계에 반복적으로 해야할 수 있는 일을 이미지화 시켜서 생산성을 향상 시킴 개발 환경을 세팅한다면 jdk 설치, 빌드툴 설치,...
-
트랜잭션과 스프링 트랜잭션 격리성을 보장하면서도 성능을 가져가야함 동시에 실행되는 트랜잭션은 서로 영향을 미치면 안됨(상황에 따라 어느 수준까지 영향을 미치지 않을 것인가 정해야함 - Lock 정책) - 예를 들어 T1이 SELECT한 데이터를 T2가 UPDATE를 했을 때 T1이 다시 SELECT 하면 다른 값이 읽히는 그런 영향(Repeatable Read 불가 - 각 락 정책에 따라 발생할 수 있는 문제가 있음) 데이터 정합성 수준에 따라 Lock 정책을 정하면 됨 : 기본적으로 데이터베이스마다 설정되어있는 정책이 있음 mysql> show variables like 'tx_isolation';...
-
데이터 캐시하기(2) - 스프링 캐시 추상화, redis 글로벌 캐시 스프링 캐시 추상화 - AOP, 캐시 매니져 AOP : @Cacheable, @CacheEvict 캐시 관련 코드를 비즈니스 로직에서 덜어낼 수 있도록 어노테이션(포인트컷)을 설정해두면 프록시? CGLib? 어찌되었건 캐시 동작(read, write) @Cacheable : 캐시 서비스를 메소드 단위로 설정 어노테이션 name : 캐시 이름 메소드 파라미터(key), 리턴 데이터(value) : 파라미터가 없을 경우 기본 키 값을 생성, 파라미터가 여러개인 경우 key=”#파라미터명” 으로 설정, 객체일 경우 key=”#객체.필드명” (SpEL) @Cacheable("item") public Item findByName(String name)...
-
데이터 캐시하기(1) - 성능 차이보기 데이터 캐시의 필요성 : 고정적인 데이터나 매번 변경되지않아도 되는 데이터에 대해 DBMS에 매번 요청(Read)하지말고 캐시해둘 필요성이 있음 자바 캐시와 관련된 스펙 : JSP107(JCache) - API 표준(javax.cache) 캐시 제공 벤더에 상관없이 캐시할 수 있도록 만들어진 API : 캐시 쪽에서의 JDBC Map으로 구현 : key-value 캐시 스펙 구현체 : EhCache(JCache Provider) JSR : 자바 스펙에 추가된 기술에 대한 설명 공식 문서 캐시 종류 로컬 캐시 : 어플리케이션 내부 메모리 사용 글로벌 캐시...
-
오늘 하루 배운 것 부족한 부분은 정말 많다! 물론 이전에도 느꼈지만 면접보면서 부끄러운 순간이 정말 많았다 이정도까지 몰랐나싶을정도로…. 부족한 부분이 뭔지 알았으니깐 공부해야겠다 추상화한 프레임워크 사용한다고 정작 중요한 데이터베이스 경험이 그렇게나 없다니… 한참 멀었다는 생각 객체지향 개발자지만 서버 개발자임을 잊지말아야함 모든 것을 객체로 풀 수 있다는 생각보다 다른 지점에 해결점이 없나 생각해봐야함 경험이 부족하다는 탓보다 경험을 해보려고 노력하는 것이 중요함을 느끼게 됨 한단계 더 나아가려고 이미 건너온 길을 놓치고 있다는 생각이 들었음 면접 준비를 하면서.....
-
JPA, Spring lazy loading 실제 사용할 때까지 연관관계에 있는 객체를 실제로 데이터 찾고(커넥션) 초기화 하지않음 : 메모리를 아낄 수 있고, 커넥션을 하지않으니 효율적(쓸데 없이 테이블 JOIN을 하지않아도 되는 것임) 대신 원 타입을 상속받은 프록시 객체(가짜)가 할당되어있음 : 해당 객체를 처음 사용(최초 1회 - 메모리 상)하려고할 때 그제서야 데이터베이스에서 데이터를 찾고 객체 초기화를 함 컬렉션을 그대로 get받아도 초기화하지않다가 컬렉션.get(idx)를 할 떄 초기화 : 아래 예시를 보면 hibernate에서 만들어낸 컬렉션 이름이 나옴 - 쿼리도 여전히 날리지않음 영속성...
-
정리해보기 객체지향 객체지향 : 분업화, 하나의 세상을 이루기위해서 하나의 존재만이 있는 것이 아니라 여러 존재들이 협업하면서 세상을 이룸, 협업이 필요하다면 필요한 객체가 다른 객체에 메세지를 보내 요청함, 파일로 코드를 분리한 것과는 전혀 다른 개념임(저장 공간만 달리할 뿐 하나로 처리하는건 마찬가지) 객체지향의 장점 : 역할 별로 객체를 나누다보니 어떤 한 기능을 수정할 때 담당 객체의 코드만 수정해주면 됨 - 변경점이 하나로 모임, 변경사항이 생기더라도 유연하게 대처할 수 있음(코드 간의 의존성이 적기때문에 - 물론 객체지향적인 프로그래밍을 했다면),...
-
Spring-data-JPA 상태 기본적으로 트랜잭션 내에서 JPA/Hibernate가 관리하냐 마냐의 상태 - 관리 대상이 아니면 영속화와는 상관없이 gc 대상 객체일 뿐, 중간 계층이 존재함(성능적인 장점이 있음 - 커넥트를 여러번 하지않음) transient : 관리한 적이 없는 상태, 일반 객체(ID가 없음) persistence : 관리하고 있는 상태, 1차 캐시 대상, 트랜잭션 내에서 얘를 찾으면 SELECT 쿼리 날리는 대신 캐시한 객체를 리턴해줌 detached : 트랜잭션이 끝나고 Persistence Context가 제거된 상태, 관리한 흔적으로 맵핑 데이터는 있으나 일반 객체 removed : 트랜잭션 내에서...
-
Stream API groupingBy Stream의 원소()들을 특정 기준에 따라 그룹핑하는 함수 : 리턴 타입 - Collector<T, ?, Map<K, List>> groupingBy는 인자로 Function 타입(함수형 인터페이스)을 받음 : T타입으로 받아서 R타입으로 리턴(R apply(T t)) public static void main(String[] args) { List<Item> items = Arrays.asList( new Item(SHOES, "nike shoes"), new Item(SHOES, "adidas shoes"), new Item(SHOES, "nike shoes2"), new Item(FOOD, "떡볶이"), new Item(FOOD, "연어"), new Item(CLOTHES, "hazzys"), new Item(CLOTHES, "polo") ); Map<String, List<Item>> groupItem = items.stream() .collect(groupingBy(Item::getItemKind)); groupItem.keySet() .stream() .map(itemKind...
-
Spring-data-JPA ORM을 쓰면 도메인 모델 개발 쿼리를 직접 생성하지않음(물론 아예 하지않는 것은 아님 - 필요에 의해 제공 기능으로 쿼리 생성까지 할 수 있음) : SQL 방언까지 신경쓰지않아도 됨(java-ims에서 prod/dev 환경에 따라 다른 RDBMS를 사용했지만 손쉽게 전환이 가능했던 이유) UserDao 혹은 UserRepository와 같이 데이터베이스 접근하는 역할을 만들어줌 : Connection 자원 할당, 해제 등 관리를 개발자가 하지않음 /* 도메인 모델 없이 개발하기 */ String url = "jdbc:postgresql://localhost:5432/springdata"; String username = "jinbro"; String password = "pass"; try (Connection...
-
스프링부트 환경설정 알아보고 dev/prod 환경에 따른 설정하기 외부에서 어플리케이션 환경설정하기 주로 사용되는 방법은 application.properties 파일에 설정을 함 key-value 형태로 정의해두면 어플리케이션 내에서 사용할 수 있음 : 설정값 가져오는 방법(1) - @Value로 다양한 외부에서 환경설정 방법이 있어서 적용 우선순위가 있음 스프링부트가 기본적으로 어플리케이션 구동 시 필요한 설정을 이미 해둔 것이 있음 : 우선순위가 가장 낮음 - 기본 설정된 key-value 살펴보기 jar 실행 시 커맨드라인으로도 환경설정을 할 수 있음 : properties 파일로 선언하는 것보다 적용 우선순위가 높음(훠어어얼씬...
-
Stream API 하나씩 사용해보기 flatMap map과 flatMap 차이 : map은 1:1로 변환하는 함수라면, flatMap은 N:1 변환하는 함수(배열 -> 스트림으로 변환할 때 사용) stream에 진행 함수에 들어가는 값(input)이 배열인 것을 하나하나 떼어놓을 때 Stream.of( new String[]{"a", "b", "c", "d", "e"}, new String[]{"f", "g", "h", "i", "j"} ) .flatMap(Arrays::stream) .map(str -> str.charAt(0)) .filter(ch -> ch > 'a') .collect(toList()) .forEach(ch -> System.out.print(ch + " ")); sorted 감싸져있는 콜렉션 원소들을 정렬함 primitive type의 경우 대소 관계를 비교(정수)할 수 있음,...
-
Stream API Stream API : 콜렉션에 저장된 요소(데이터)에 대해 어떤 처리를 하기위해 만들어진 API forEach로 하면 안되나? 코드 간결해지면서도 Lazy한 처리가 가능(최종 결과내는 메소드를 사용하지않으면 그때까지 처리를 하지않음), *기존 콜렉션에 대해서는 조작하지않으면서도 원하는 결과값을 얻어낼 수 있음, 병렬처리를 쉽게할 수 있음(API에 있음) 데이터 변경보다는 데이터 처리가 주목적 IntSummaryStatistics 최댓값, 최솟값, 평균 등 기본적으로 필요한 값에 대해 매번 구하려고 Stream API 쓰는게 아니라 하나의 객체만 리턴하도록 하면 됨 어떤 값에 대해 최대, 최소, 평균 등을 구할...
-
데이터베이스 트랜잭션과 MySQL 트랜잭션 : 복수 쿼리로 처리해야할 때 하나의 작업으로 묶는 것, 단일 작업으로 만들어내는 것 오토커밋모드와 단일 쿼리 : MySQL, PostgreSQL 등 몇몇 RDBMS는 오토커밋모드가 기본설정인데, 단일 쿼리의 경우 오토커밋 대상 COMMIT과 ROLLBACK : 트랜잭션(모든 쿼리) 성공 시 커밋(완료, 저장소 적용), 하나의 쿼리라도 실패 시 롤백(이전 상태로 되돌리기, 저장소 상태 되돌림) CREATE TABLE과 COMMIT : CREATE TABLE(DDL) 쿼리는 바로 커밋(다른 트랜잭션에서 읽을 수 있음) 트랜잭션이 가져야할 특성 원자성 : 더이상 쪼갤 수 없음,...
-
기초도 못하면서 응용 잘하는 사람 한명도 본 적 없다 기초부터 잘하자 객체지향 객체지향이 뭘까 만들려고 하는 가상세계에 마스터가 모든 것을 처리하는 것이 아니라 여러 존재가 모여 협업하는 세상 객체와 객체 간에는 협력을 함, 협력은 자동적으로 하는게 아니라 메세지에 의해 요청하는 것, 다른 객체는 요청만 할 뿐 처리에 대해 어떠한 관여도 할 수 없음 : 전적으로 담당 객체의 권한 - 그렇기때문에 객체 고유의 상태값 또한 바깥으로 가져올 수 있는 설계를 해서 안되고 조작도 마음대로 하지못하도록 만들어야함...
-
웹서버 캐시해보기(2) 기간 만료되지 않았지만 갱신하기 패스별로 캐시를 하기때문에 리소스 이름에 파라미터를 붙여줘서 다시 캐시하도록 함 그렇다면 서버에 쌓인 기존 리소스 처리는? nginx에서 캐시 설정을 해줄 때 기간을 설정하기때문에 지워짐(실제로는 누가 지우지?) 생각해볼 수 있는 문제 : 자주 변경될 수 있다면 제한된 범위 내에서 파라미터를 설정해주기(완전한 랜덤값으로 설정하면 그만큼 많은 파일이 서버에 캐시될 수 있기 때문에 - 그런 상황을 만나봐야알겠지만..) 비정기적으로 변경될 수 있는 정적인 리소스에 대해서는 파라미터를 달아줌으로써 클라이언트가 오래된 캐시 데이터를 그대로 가져다가...
-
HTTP 웹 구성요소들이 대화를 하기위해 만들어진 프로토콜(약속) 클라이언트 - 서버 상호운용성을 중요시 함 : 버젼업이 되더라도 하위호환성 있게 기존의 것은 그대로 유지 TCP/IP 기반 : 하지만 리소스 1개에 대한 트랜잭션 후 연결을 끊고, 다시 연결을 만들어 트랜잭션 진행(커넥션 생성 반복으로 오버헤드 발생하는 것을 대체하는 방법이 있긴 함 - keep alive), URL에 명시된 주소와 포트(80이라면 생략 - 웹 클라이언트 default)로 TCP/IP 프로토콜 메세지 작성 -> 연결 -> HTTP 통신 MIME 타입 : Multipurpose Internet Mail Extentions,...
-
[프로젝트 개발] 오픈 API 사용하기 - 네이버 Geocoder를 활용한 주소 검색 API API 적용할 곳 도로명 주소를 입력하고, 상세주소는 유저가 마커를 찍으면 좌표가 나오는데 좌표를 가지고 변환하는 형식으로 아니면 도로명 주소를 입력했을 때 상세주소 입력하도록 API 살펴보기 Maps API에 모듈 형태로 제공함 : 변환하는 역할의 모듈인 Geocoder를 사용함 geocoder api docs API 사용해서 데모만들기 & 데이터 보관 생각해보기 코드 좌표값을 받아 저장해두고 리뷰 글을 열 때 좌표에 맞는 위치 보여주기 하면 될 듯 : Coordinate...
-
서버 성능 및 안정성 향상을 위해 고려해볼 수 있는 아키텍쳐 리버스 프록시 서버 앞 단에 위치하여 요청을 몸빵 하는 역할 : 단순 몸빵만 하는 것이 아니라 효율적인 처리와 보안성을 높여줄 수 있음 캐시 가능 : 정적인 자원에 대해 캐시를 해뒀다가 이후 구성요소로 가지않고도 바로 응답해줄 수 있는 장점이 있음 서버 보안 : WS, WAS 보안(감추기 가능) Nginx의 경우 리버스 프록시 역할을 할 수 있음 (Nginx가 아니더라도 다른 웹서버에서도 지원) 로드밸런싱 처리를 분산하기위해 N대의 웹서버, 톰캣을...
-
[프로젝트 개발] spring-security 리팩토링 커스텀 필터를 스프링빈으로 등록하기 : 스프링빈 컨테이너 - circular dependency 발생과 해결 커스텀 필터에서 스프링빈을 사용해야하므로 필터를 스프링빈으로 등록해야할 필요성이 생김 : 빈으로 등록하고 Config에서 @Autowired를 받으려고 했으나 필터 생성과정에서 AuthenticationManager를 등록해줘야하는데, Config에서 Manager 빈을 가지고 있으므로 Config가 빈으로 생성되지 못하면 Manager 빈을 가져오지 못하는 문제가 발생함 커스텀 필터는 매니져가 필요하고 매니져는 Config가 생성되어야 가져올 수 있다보니 결국 어느 한 쪽도 온전히 생성되어 빈으로 등록되지 못한 상황이라 로그에는 circular dependency라며 찍히고...
-
[프로젝트 개발] spring-security OAuth, JWT, HttpOnly Cookie favicon.ico로 redirect 되는 현상 security가 적용되기때문에 ignore 설정해주면 됨 @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers("/h2-console/**") .antMatchers("/js/**") .antMatchers("/css/**") .antMatchers("/favicon.ico"); } 자원 요청에 대해서 모두 ignore 하도록 위의 방법은 모든 필터에 대한 설정, 필터마다 설정하기위해서는 필터를 생성할 때 RequestMatcher를 생성해서 설정해주면 됨(processPath와 skipPath 지정할 수 있음) 인증서버 프로바이더마다 다른 인증 확인 방법 - Template 분리 객체 사용 분산 효과 서비스 프로바이더의 인증 확인 방식에 변경이 생겼을...
-
[프로젝트 개발] spring-security JWT 인증과정 HTTP Only 쿠키 서버에서 쿠키를 설정할 때 HTTP Only로 설정한다면 브라우저 콘솔에서는 해당 쿠키의 값을 볼 수 있지만 자바스크립트 API로 호출하면 빈 문자열이 리턴됨(설정된 것이 없음) HTTP 통신 과정에서만 사용됨 서버 측에서의 설정 application.properties에서도 설정가능하지만 쿠키 전체에 대한 설정이라 해당 쿠키에 대해서만 설정한다면 쿠키 객체에 설정해줘야함 : 각각의 상태값 Cookie cookie = new Cookie(COOKIE_NAME_AUTH, generator.generate(account)); cookie.setHttpOnly(true); response.addCookie(cookie); JWT 만료기간 체크 현재는 씨큐리티에 많은 시간을 쏟고 있는 관계로 리프레시 토큰에 대해...
-
[프로젝트 개발] spring-security OAuth2 - jwt 리팩토링 다른 객체의 상태값을 get해서 바깥에서 상태를 가지고 무언가를 만드는 작업을 하지말고 해당 객체에 메세지를 보내서 일 시키기 get해서 가공하는 쪽으로 가면 코드의 의존성이 커지기때문에 get해오는 쪽에서 변경이 생기면 가공하는 쪽에서도 변경이 생기게 됨 현재의 방법(전략)이 앞으로 고정될 것이라고 생각하고 코딩하면 안됨 : 언제든지 변경이 생길 수 있다는 점을 생각하고 코딩하기 한가지 방법으로 고정시켜두면 테스트하기도 힘들어질 때가 있음 : DI할 수 있도록 코딩을 해두면 테스트하기 편한 전략으로 교체할 수...
-
서블릿과 스프링 그리고 스프링5 서블릿 리퀘스트에 대한 처리를 동적으로 만들어줄 때 사용하는 자바로 만들어진 API HTTP 한단계 추상화해서 표준화(인터페이스)한 것 : 서블릿을 구현하면 됨 서블릿을 추상화한 것이 스프링 : HTTP > 서블릿 > 스프링 톰캣(WAS) 서버에서 관리됨 : 서블릿의 구현체는 서블릿 컨테이너에서 라이프사이클(컨테이너의 역할)을 관리 - 초기화부터 제거까지 서블릿이라는 표준이 있어서 좋은 점은 서블릿 컨테이너를 다른 것으로 바꿔도 똑같이 동작할 수 있음 : jetty가 있음 톰캣은 HttpServlet을 상속받아야 컨테이너에서 관리하고, 스프링 컨테이너는 POJO를 어노테이션으로 설정하면...
-
[프로젝트 개발] spring-security OAuth2 - JWT 어제까지 개발한 것 정리 어제까지 클라이언트가 인증서버에 인증을 하면 redirect 되어서 액세스코드가 서버로 가게 해놨음, 어플리케이션 서버는 인증서버에 액세스코드 검증 후 JWT를 발급해주는 것까지 만듦 오늘은 만든 JWT를 클라이언트가 응답받아서 어떻게 보관할지에 대해서 공부하고 개발하면 됨 - 두가지 방법 중 1가지를 택, 장단점을 확실히 파악해야함 secure, HttpOnly 쿠키 사용 클라이언트(브라우저) 로컬 스토리지 사용 XSS와 HTTP Only 쿠키 그리고 CSRF XSS 크로스 사이트 스크립팅(XSS) : 악의적인 사용자가 스크립트를 심어놓고(게시판 등)...
-
[프로젝트 개발] Spring Security - OAuth 인증서버, JWT 액세스토큰과 JWT 액세스토큰 : 인증서버에서 발급해주는 토큰으로 해당 서버에서 발급했다는 증명과도 같은 String값 즉, 아무런 데이터가 들어있지않음 인증 작업을 인증서버에 어플리케이션 서버가 위임한 것 JWT(json web token) : 어플리케이션 서버는 클라이언트에 대한 정보를 가지고 있지않고, 클라이언트가 자신이 인증받은 사용자임을 알리려고 토큰을 준다고 할 때 인증서버가 발급해준 액세스토큰만으로는 클라이언트의 정보를 알 수가 없기때문에 액세스토큰을 가진 클라이언트에 한 해 json 형식을 빌려 필요한 최소한의 정보를 담고 암호화 시켜 만들어서...
-
SQL JOIN 두 개의 테이블에 대한 쿼리 실행을 할 떄 사용됨 - PK, FK를 활용해서 JOIN 여러 타입의 JOIN이 있음 Inner Join : ON으로 지정한 결합 조건에 일치하는 두 테이블의 행만을 가져오는 것 - 어디 테이블도 다 가지고 오는게 아니라 딱 공통되는 행만 Outer Join : 방향에 따라서(테이블을 쿼리문에서 어디에 놓느냐 - LEFT / RIGHT) 기준이 되는 테이블의 행은 모두 가져오고, 이외 테이블의 행은 ON 결합 조건에 해당하는 행만 가져옴, 나머지 데이터는 NULL로 처리됨(기준 행의...
-
spring-security 인증 구현하기 반복 Form Login - generate JWT flow 로그인 페이지로 감 로그인 정보를 입력한 후 submit 버튼을 누름 - http://domain.com/login과 같은 정해진 URL 요청을 함 서블릿 필터에서 걸림 - FormLoginFilter, 필터의 대상으로 지정된 요청이라면 DespatcherServlet으로 가지않고 프로바이더로 가게끔 필터에서 입력한 정보를 가지고 인증 전 객체를 만듦 - PreAuthenticationToken 적당한 프로바이더를 찾아서 처리를 함 - AccountService와 협업 프로바이더에서 인증이 성공하면 인증 후 객체를 만듦 - PostAuthentication 필터로 다시 돌아와 성공, 실패 핸들러 메소드를 거치게...
-
어플리케이션 성능 개선 banwidth와 latency : latency 이슈가 더 많음(얼마나 빠르게 응답을 주느냐) - 서버와의 거리, 우리 개발력(서버 처리 시간…, 동적인 컨텐츠에 대한 처리) CDN : 지역마다 컨텐츠만 전달하는 용도로 두는 서버, latency를 낮추기위해서 물리적인 거리를 줄임(리전 별로 - 전세계 주요 거점에 서버를 둠) - 정적인 콘텐츠 성능 이슈 css, js, img 자원에 대한 응답이 가장 많이 생김, 특히 이미지 개선 방법 캐시 한번 다운로드 받은 파일을 다시 다운로드 받지 않는 것 : 무작정 하면...
-
spring [스프링빈 컨테이너와 DI] 컨테이너에서 관리하고 있어야 컨테이너에 있는 다른 디펜던시를 인젝션 받을 수 있음 : 그 대상을 골라낸다음 해당 클래스를 읽기때문에(streotype 어노테이션이 설정되어있어야함) [spring-mvc] 실행시킬 때 import.sql을 사용하지않고, Repository에 엔티티 등록하기 : CommandLineRunner - 부트 실행 시 커맨드 실행 args로 Autowired처럼 가져올 수 있음 @SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication.run(SecurityApplication.class, args); } @Bean CommandLineRunner test(AccountRepository accountRepository, PasswordEncoder encoder) { return args -> { Account account = new Account("colin",...
-
sql 테이블 생성, 수정하기 TINYINT와 INT 타입 : 가격 데이터를 저장해야하는데, TINYINT는 -127 ~ 128까지 저장가능함 -> 데이터 타입을 변경해야함, INT(21억) 늘릴 수 있지만 줄일 수 없음 > CREATE TABLE ITEM ( ITEM_ID INT AUTO_INCREMENT, NAME VARCHAR(50) NOT NULL, PRICE TINYINT DEFAULT 0, QUANTITY INT DEFAULT 0 PRIMARY KEY (ITEM_ID); ); > ALTER TABLE ITEM MODIFY COLUMNN PRICE INT DEFAULT 0; SELECT - ORDER BY 정렬하기 : ORDER BY 열 DESC ASC 복수열 정렬 가능...
-
SQL(using mysql) 테이블 구조 보기 DESC, DESCRIBE 컬럼명, 데이터 타입, 기본값, PK 설정 등이 나옴 > DESC $TABLE_NAME +-----------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+-------+ | MEMBER_ID | int(11) | NO | PRI | NULL | | | TEAM_ID | int(11) | YES | | NULL | | | NAME | varchar(255) | YES | | NULL | | +-----------+--------------+------+-----+---------+-------+ CHAR와 VARCHAR 차이 : 할당한 값보다 최대...
-
java-ims 객체지향적으로 프로그래밍하기 상태값을 꺼내어 외부에서 작업하지말고, 메세지로 요청을 날리자 path를 ControllerPool에 전달해서 ControllerPool이 원하는대로 작업을 하는게 아니라 path를 가진 Request에 요청할 수 있게 Request 객체만 전달해서 요청할 수 있게하기 매번 의식하는데 이런 사소한 부분에서 계속해서 객체지향적인 코딩을 하지못하네…. 계속 의식하면서 하기 /* 수정 전 */ public class ControllerPool<T extends Controller> { . . . public T search(String requestPath) { . . . } } /* 수정 후 */ public class ControllerPool<T extends Controller> {...
-
SQL(MySQL) 테이블 생성하기 데이터를 저장하기위해서 저장하고자하는 어떤 데이터를 어떤 타입으로 저장할지를 정한 후 표(테이블)를 생성해야함 테이블이 저장될 데이터베이스(원래는 스키마 계층이 하나 더 있어야하지만 mysql은 같은 계층으로 사용) 생성 or 선택 data type 참고 데이터베이스 내에 테이블 : 하나의 데이터서버에 여러 서비스의 데이터를 저장할 수 있으니 영역을 구분짓는 용도(?) > show databases; +--------------------+ | Database | +--------------------+ | information_schema | | exam | | mysql | | performance_schema | | sys | +--------------------+ > use exam;...
-
JPA 연관관계 맵핑 - 객체지향과 데이터베이스의 패러다임 불일치 인식하기 객체의 관계는 단방향이지만, 데이터베이스의 테이블은 fk 하나로 양방향 관계를 맺을 수 있음 반대쪽에 객체 참조 필드를 생성하기 전까지 단방향 관계임 : 테이블은 SQL FK로 JOIN을 사용하면 둘다 조회가능하지만 객체는 .get()과 같은 메소드를 사용해야하는데 참조 필드가 없으면 할 수가 없음(패러다임의 불일치) - .get()을 해야 내부적으로 SQL을 생성할텐데 없으면 그렇지도 못함(이 부분은 없애고 올리기) /****** 단방향 ******/ public class Member { private Long id; private Team team; }...
-
java-ims response 생성하기 request 정보와 controller 처리 결과를 가지고 response(outputstream)처리를 하는 객체 RequestHandler에서 response.response() 했을 때 비로소 outputstream 실행 : 연결된 클라이언트에 데이터(HTTP 응답메세지)를 보냄 public class Response { private HttpStatus status; private HttpHeader header; private HttpBody body; private DataOutputStream out; public Response(OutputStream out) { this.out = new DataOutputStream(out); header = new HttpHeader(); } public Response setStatus(HttpStatus status) { this.status = status; return this; } public Response setHeader(ResponseHeaderAttribute attribute, String value) { header.add(attribute.name(), value); return...
-
java-ims 내부 flow Request 메세지 파싱 Request 객체 생성 Request에 핸들러(컨트롤러) 요청 : path를 가지고 있기때문에 위임 컨트롤러에 Request 넘겨주며 처리 요청 ResponseEntity(HttpMethod, Header, Body) 생성 Response 객체 응답하기 Response 작성할 때 필요한 데이터를 가진 ResponseEntity 만들기 빌더 패턴으로 만들기 장점 : 조립하듯이 객체를 생성할 수 있음, 객체 생성 시 설정해야할 필드가 많아지면서 선택적으로 필드를 설정할 수 있게할 때 좋음(유연성), 특정 필드만 깔끔하게 기본값을 설정해둘 수 있음, 필드 각각의 할당 조건이 생길 때 분리해두면 코드가...
-
java-was RequestLine/Headers/Body 생성자에서 처리하는 작업을 유틸리티 클래스를 만들기 보기좋은 코드를 만들기위해서 인자를 처리하는 작업만을 하는 클래스를 따로 만들기 상태값을 가지지않고 메소드 인자로 처리 대상을 받아 처리하기 : static 메소드 public class RequestUtils { public static List<String> splitRequestLine(String requestLine) { return Arrays.asList(requestLine.split(" ")); } public static List<String> splitPathAndParams(String pathAndParams) { return Arrays.asList(pathAndParams.split("\\?")); } public static Map<String, String> splitQueryString(String queryString) { return splitValues(queryString, "&"); } private static Map<String, String> splitValues(String target, String regex) { if (Strings.isNullOrEmpty(target)) {...
-
java-was 기존 코드 분석하기 서버 소켓(8080 - 웹서버가 80을 사용하고, WAS는 8080 리버스 프록시)을 만들어두고 클라이언트 소켓의 연결 요청을 기다림 클라이언트 소켓이 연결되면 클라이언트의 요청을 처리할 핸들러(쓰레드)를 실행시킴 : 클라이언트 연결 Request 만들기 Request 담당 오브젝트 테스트하면서 만들기 Request 생성자 설계 : InputStream을 인자로 받음 매번 브라우저로 요청을 보내고 HTTP 메세지를 읽지않기위해 모의 HTTP 메세지로 내용이 구성된 파일(request.txt)로도 읽을 수 있게) request.txt 읽기 gradle, maven은 정해진 디렉토리에 정해진 파일을 넣어야함 : resource를 class path에 넣어두고...
-
java-ims 다운로드 기능 수정하기 다운로드 리턴 타입 수정 이전 코드 : AttachmentService에 download를 요청해서 리턴받는 데이터의 타입이 PathResource였음 : PathResource는 프로젝트 패스에 존재하는 파일을 가져오는 API, 특정한 유형의 파일에만 국한된 코드였음 변경하기 : WritableResource로 리턴타입 변경하기 - PathResource의 상위타입(인터페이스), FileSystemResource, FileUrlResource, PathResource의 인터페이스 구체적인 타입이 아닌 확장성을 고려해서 인터페이스와 같은 추상적인 개념을 리턴타입, 파라미터 타입, 필드 타입으로 지정해야함 @GetMapping("/{id}") public ResponseEntity<WritableResource> download(@LoginUser User loginUser, @PathVariable Long issueId, @PathVariable Long id) throws IOException { . ....
-
java-ims 다운로드 기능 만들기 업로드 했던 파일을 반대로 다운로드 하는 기능을 만들어야함 특정 이슈에 특정 유저가 올린 특정 파일을 다운로드 업로드 했을 때 AttachmentRepository에 업로드 정보를 저장함 : 이슈 id, 사용자 id, 첨부파일 uuid(식별자 - 런타임 시에 고정된 전략이라서 static 메소드를 사용했지만 AttachmentNameConverter도 런타임 시에 다양한 전략을 사용하게끔 한다면 DI로 변경해도됨)와 origin name 등 public class AttachmentService { public Issue upload(User loginUser, Issue issue, MultipartFile file) throws IOException { String savedFileName = fileSaver.save(file, AttachmentNameConverter.convertName(file.getOriginalFileName())); Attachment...
-
java-ims 파일 업로드 기능 만들기 먼저 자바 파일 IO부터 알아보기 파일 쓰기 jvm 데이터를 API를 통해 파일에 쓰기 FileOutputStream : 파일 쓰기 API, 생성할 때 경로를 지정하지않으면 해당 프로젝트 루트 경로에 생성됨(절대경로 지정이 아니면 프로젝트 루트 디렉토리를 기준으로 생성 혹은 쓰기) IO를 위한 자원 사용 후 해제까지 해줘야함 데이터 쓰기 : byte 타입(배열까지) - FileStream이라면 byte 단위 쓰기, FileWriter를 사용하면 문자, 문자열 입력가능 덮어쓰기와 붙여쓰기도 고려해야함 : 각 io API마다 덮어쓰기를 할 것인지 붙여쓰기를 할...
-
java-ims ControllerAdvice, RestControllerAdvice @RestController와 @Controller의 차이 : 응답 데이터가 json이냐 뷰(.html)냐 차이 @RestControllerAdvice : response를 json으로 변환해주는 역할, rest api 구현할 때 사용 컨트롤러의 타입에 따른 예외처리 분기 같은 타입의 예외지만 각기 다른 처리를 할 수 있음 : json 응답, redirect 혹은 특정 view 응답 /* RestController */ @RestControllerAdvice(annotations = RestController.class) @Order(1) public class SecurityRestControllerAdvice { ... } /* Controller */ @ControllerAdvice(annotations = Controller.class) @Order(2) public class SecurityControllerAdvice { ... } ResponseEntity static 메소드 ResponseEntity의...
-
JPA DDL : 테이블 생성, 변경 등의 쿼리, 테스트 서버에서는 자동 변경하도록 설정하는 것이 괜찮지만 실서버에서는 그러면 안됨 스키마 : 데이터베이스 테이블 정보를 집약해서 하나 만들어두고, 레퍼런스 삼아서 JPA(정확히는 구현체) 작업을 함 키(pk) 생성할 때 : 대리키를 사용하라 키 생성 전략(자동 - 대리키) : 엔티티에 키를 할당하는 전략, 데이터베이스 마다 각각 다른 전략을 취하고 있음 IDENTITY : 키 생성부터 할당까지 데이터베이스에서 함, auto_increment 전략을 사용하려면 해당 전략을 사용해야함 SEQUENCE : 키 생성은 데이터베이스 시퀀스(키 생성...
-
java-ims layerd architecture - 계층을 만들어놨으면 이용하기 계층을 만들어놨으면 뛰어넘으려고 하지말고 해당 계층을 거치도록 코딩하기 아래 코드의 상황은 IssueController에서 Milestone의 정보를 얻어야하는데, 곧바로 MilestoneRepository로 가지말고 서비스 계층을 거치도록(직접적으로 사용하지말자 - 중간 계층이 상황에 따라 요청에 따른 응답 결과를 달리할 수 있도록) @Controller @RequestMapping("/issues") public class IssueController { @Autowired private MilestoneService milestoneService; @GetMapping("/{id}") public String show(@PathVariable Long id, Model model) { model.addAttribute(getEntityName(ISSUE), issueService.get(id)); model.addAttribute(getMultipleEntityName(MILESTONE), milestoneService.get()); return String.format("/%s/show", getEntityName(ISSUE)); } } 통합테스트(AcceptanceTest) 할 때, 테스트 할 때...
-
토비의 스프링으로 스프링 들여다보기 AOP 핵심 핵심 기능은 아니지만 필요한 부가기능이면서, 산발적으로 퍼져있는 것을 따로 모은 뒤 API를 통해서 핵심 기능을 가진 타겟 객체에 부가 기능을 적용시키는 것 부가기능의 모듈화 ProxyFactoryBean 사용해서 타겟의 메소드에 어드바이스 적용하기 Advise 인스턴스를 타겟마다 만들지않고 재사용할 수 있게 됨 : DI(타겟을 Advise에서 없애버리고 하나의 판을 만들고 advise와 target을 DI 받도록 해서 적용) 문제점 : 프록시를 적용할 타겟마다 ProxyFactoryBean을 사용해서 프록시 객체를 만들고 있음 - 이 자체도 낭비다(중복된 코드) @Test public...
-
JPA - 영속성 컨텍스트 영속성 컨텍스트란 순수 객체와 데이터베이스의 중간에 위치한 계층 : 중간 계층(레이어)을 둠으로써 얻는 이점이 있기때문에, JPA는 영속성 컨텍스트라는 레이어를 둠 엔티티 매니져를 통해서 접근한다고 생각하면 됨 J2EE 환경 : 엔티티매니져 당 하나의 영속성 컨텍스트를 가지고 있음 스프링 사용 환경 : 트랜잭션 내에서 여러 엔티티매니져가 하나의 영속성 컨텍스트에 접근(사용), 영속성 컨텍스트는 트랜잭션 끝나면 삭제 영속성 컨텍스트 특징 @Id로 엔티티 식별 : 식별자 값이 없으면 안됨(에러 발생) /* 엔티티를 영속성 컨텍스트에 저장해두고 관리...
-
AOP 핵심 로직과 부가 기능을 분리하기 : 중복 제거도 되면서 핵심 로직 개발에 더 집중할 수 있도록 완전한 분리 : 핵심 로직 부분에서 부가 기능이 적용되는지 모르도록(의존하지않도록 - 의존 관계 설정해두면 로직에서 사용되어야 부가기능이 적용됨) 분리 1단계 : 메소드 분리 @Service("userService") public class UserService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private UserRepository userRepository; public void upgradeLevels() throws Exception { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { upgradeLevelsInternal(userRepository.findAll()); transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); }...
-
스프링 프로젝트 - java-ims Mockito를 통한 Service 단위테스트와 도메인 단위테스트 다른 의미의 테스트임 : 같아보이지만 Service 계층을 테스트 하는 것과 도메인에 대한 단독 테스트는 다름 서버 자원을 사용하는 것과 일반 자바 객체를 테스트 하는 것에서 차이 삭제 기능 바로 삭제를 하지않고, 삭제 상태로 만들어놓음 : 삭제 상태로 변경된 엔티티를 또다른 엔티티(히스토리)로 만들어서 보관함 일정 기간이 지났을 때 엔티티를 실제로 삭제함 기록 또한 일정기간 보관 @Entity public class DeleteHistory { @Id @GeneratedValue(strategy = GenerationType.IDENTIFY) private long...
-
스프링 스프링 빈 생성과 DI 시점 : 모두 스프링이 시작될 때 컨테이너에 생성(streotype 어노테이션으로 스프링빈 설정)해두고 DI까지 모두 해둔 상태 스프링 빈은 무상태여야함 : 상태를 가지는 객체를 관리하면 개발자가 고려해야할 부분이 굉장히 많아짐(race condition) - 굳이? 할 필요가 없음, 멀티쓰레드 환경 임을 잊지 말아야함 TDD 테스트 주도 개발을 하면서 중간에 끝내고 이어나가려고 할 때 어떻게 알아보나? 실패 케이스가 아직 구현되지않았기때문에 실패 케이스인 것, 실패 케이스인 부분부터 개발을 하면 됨 레이어 구조 생각해봐야할 점 : DTO를...
-
@Annotation 어노테이션 자바 1.5부터 등장한 API 코드에 메타 데이터를 설정 : 자신에 대한 부가 정보를 담고 있음 @Transactional(rollbackFor = CannotDeleteException.class) public void deleteQuestion(User loginUser, Long id) throws CannotDeleteException { deleteHistoryService.saveAll(findQuestionById(id).delete(loginUser)); } 이렇게 사용된다 컴파일러에 정보 제공 : @FunctionalInterface, @SuppressWarnings 이렇게 사용된다 코드 생성 : 롬복 @Setter, @Getter 등 런타임 프로세싱(조작) : Spring의 @Autowired(DI), JUnit의 @Test(테스트 할 메소드), Jackson의 @JsonIgnore(json 생성 시 참고) 등 종류 빌트인 어노테이션 : 제공되는 어노테이션 @Override : 상위 클래스의 메소드를 오버라이드...
-
스프링과 스프링모듈 하나(이상)씩 알아(만)가기 Spring J2EE로 자바 어플리케이션을 개발할 때 편하게 개발할 수 있도록 제공하는 프레임워크 모듈 형태로 개발 편의를 제공함 : Spring MVC, Spring Data 등 흔히들 하는 착각 : Spring == Spring MVC <– 아닙니다! 모듈과 함께 스프링빈 컨테이너를 제공함 컨테이너 : 어떤 것의 라이프사이클을 관리해주는 역할, 여기서 어떤 것은, 라이프사이클은 인스턴스의 생성부터 소멸까지를 말함, 인스턴스는 기본적으로 싱글톤으로 관리됨 스프링빈 : 스프링 컨텍스트에서 사용되는 인스턴스(스프링 빈)을 말함, 스프링 컨테이너에서 관리되는 인스턴스 즉 스프링빈이...
-
Issue 서비스 구현 개발 flow AcceptanceTest(인수테스트) 케이스를 먼저 작성함 : 서비스에 대한 요청을 했을 때 클라이언트는 어떤 응답을 받을 것인지 먼저 정함 - TestRestTemplate 사용 Controller / Service / domain 객체 테스트케이스에 맞게 프로그래밍 Service 테스트(단위 테스트) : 앞서 2단계에서 구현한 로직이 상황에 맞게 제대로 수행되는지 메소드(액션) 단위테스트 - Mockito 사용 create @RequestBody : RestController와 함께 사용하는 것, json 데이터를 받아서 객체로 변환할 때 사용하는 것 API 보기 : 메세지 컨버터를 거치게 되어있음 Annotation indicating...
-
인수테스트는 클라이언트 입장 인수테스트를 할 때 서버의 자원을 끌어다 사용하면 안됨 : 클라이언트 입장에서 테스트를 하는 것인데, 클라이언트는 알 필요가 없음 클라이언트 - 서버가 나뉘어져있는데, 클라이언트가 서버 입장에서 서버의 자원을 사용하는 것과 같음 서버가 외부로 공개해놓은 API를 콜 했을 때 어떤 결과가 받아질 것인지 예상한다음 응답 결과가 왔을 때 실제 그런지를 테스트하면 됨 end to end 테스트인 점을 망각한 코드 첫번째 예시 : 서버에서 예외를 캐치한 후 예외에 대한 특정 응답을 만들어서 클라이언트에 응답해줘야하는데, 클라이언트...
-
REST API ATDD REST API REST 디자인 원칙을 지켜서 만든 Web/HTTP API : 여기서 API는 원격에서 다른 시스템의 메소드를 콜하는 인터페이스를 말함(리소스 핸들링을 위한 - 기본적으로 CRUD) REST 등장 배경 : 현재 형성된 웹 환경을 파괴하지않으면서도 HTTP를 발전 시킬 수 없을까? 웹서버에 변경이 생기더라도 클라이언트에는 아무런 영향을 미치지않도록 발전시킬 수 없을까? 궁극적으로 서버와 클라이언트의 디펜던시를 제거함으로서 얻을 수 있는 이점을 얻기위해서 원칙을 만들게 됨 어떻게 디펜던시를 제거하나? 일관된 URI 디자인(요청), 요청에 대한 응답 결과의 메세지만으로도...
-
REST API REST 디자인 원칙을 지킨 WEB API/HTTP API API 여기에서는 원격으로 다른 시스템의 메소드를 콜하는 의미 : 메소드는 서버 측에서 (일부)공개해놓은 메소드만 - 어떻게 처리되는지는 모르나 외부 인터페이스를 통해서 작업을 요청할 수 있음 메소드를 사용하는 이유는 자원(resource)에 대한 핸들링을 하기위해서 REST API의 궁극적인 목표는 클라이언트와 서버의 디펜던시를 없애는 것 독립적인 발전을 위해서 : 서버에 변경이 생겨도 클라이언트는 변경을 하지않아도 됨(완전히 기능을 없애지않는다면…) 유지보수 관점에서도 좋음 : stateless 원칙을 지키고 있다면 서버의 인프라를 확장시킬 때...
-
REST API, 그리고 스프링에서 REST API 디자인해보기 REST한 API(REST API) 간단하게 말하자면 API 디자인 가이드라인(원칙) API란? 원격으로 다른 시스템의 메소드 콜을 할 수 있도록 하는 것 어떤 클라이언트라도 일관된 방법으로 콜 할 수 있게, 서버에 변동이 생겨도 클라이언트는 아무런 영향 받지 않도록 - 하위 호환성, 일관성을 띄는 API 디자인 가이드라인(원칙) REST 왜 만들었을까? 현재의 웹 환경을 파괴하지않고도 HTTP를 발전시킬 수는 없을까 라는 생각 아래에 만들어짐 REST한 API가 되려면 지켜야하는 디자인 원칙 : 각각의 디자인 원칙은...
-
테스트 코드 중복 없애기 테스트 코드 중복을 없애기 위해서 2가지 방법(+@)이 있음 @Before 메소드를 사용 : 모든 테스트메소드가 거치기때문에 필요없는 메소드도 호출하는 단점이 있음 일반 메소드(prehandle 개념 메소드)를 정의해두고 prehandle을 거쳐야하는 @Test에서 호출하는 방법 : 코드양은 늘어나지만 필요한 메소드에만 적용시킬 수 있음 +@ 방법은 2번째에서 상속을 사용해서 중복을 제거하는 것 테스트 코드 또한 중복을 제거하지않으면 테스트 케이스가 늘어날수록 중복 제거한 코드보다 코드양이 훨씬 더 늘어남 2번째 방법으로 중복 제거하기 public class QnaAcceptanceTest extends AcceptanceTest {...
-
테스트하기 TestRestTemplate 활용 인수테스트하기 인수테스트 : end to end 테스트, 요청에 대한 응답 테스트(컨트롤러 테스트) 브라우저를 사용하지않고 클라이언트 역할을 하는 TestRestTemplate 사용 꼭 브라우저만이 클라이언트가 아니라는 것을 알 수 있음 : 외부에서도 HTTP만 지켜서 요청을 날릴 수 있다는 것을 알아야함 RestTemplate 래핑한 TestRestTemplate : RestTemplate는 스프링에서 제공하는 외부 API 콜 할 수 있는 API, Test는 래핑해서 테스트에 적합하게 만듦 테스트 코드 짜보기 - QnaAcceptanceTest AcceptanceTest : Qna 이외에도 인수테스트를 해야할 것들이 있는데 필요 조건이 중복되는...
-
스프링부트 HTTP 세션 데이터 쉽게 가져오기 - 커스텀 파라미터 만들기 HandleMethodArgumentResolver를 사용함 파라미터를 커스텀하는 역할, 두개의 메소드를 오버라이드 한 후 스프링 MVC에 리졸버를 등록하고, 실제로 적용할 부분에 선언해서 사용함 Interceptor와 컨트롤러 로직 사이에 존재하는 것으로 생각 : 코드 중복을 줄일 수 있음(같은 파라미터를 가지고 기능 구현을 한다면) 어노테이션 생성하기 : 커스텀 파라미터로 사용할 파라미터라는 표시(설정) @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface LoginUser { public boolean required() default true; } 커스텀 파라미터 만들기 - HandleMethodArgumentResolver public class LoginUserHandlerMethodArgumentResolver...
-
쓰면서 배우는 스프링(부트) 로그인 관련 기능 테스트 피드백 받은 내용 중 가장 뼈져리게 아픈 부분은 테스트 케이스를 작성하면서 실패 케이스를 깜빡했다는 것 테스트 케이스를 작성할 때에는 성공 케이스보다 실패 케이스가 더 중요함 : 실패 케이스일 때 브라우저가 어떤 응답을 받을지 테스트 꼭 해야함 @Test public void login_fail_invalid_password() { String userId = "javajigi"; builder.addParameter("userId", userId); builder.addParameter("password", "1111"); HttpEntity<MultiValueMap<String, Object>> request = builder.build(); ResponseEntity<String> response = template.postForEntity("/users/login", request, String.class); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); } @Test public void login_fail_invalid_userId() {...
-
스프링부트 - 테스트하면서 만들기 인수테스트(Acceptance Test) - TestRestTemplate 단위테스트가 단위별로 태스트를 한다면 인수테스트는 end to end 테스트라고 해서 전체적으로 합쳤을 때 동작을 제대로 하는가를 테스트하는 것 고객 테스트, 시스템 테스트라고도 함 : 인수테스트보단 이름에서 뜻을 유추할 수 있을 것 같음 단순 도메인 로직을 테스트하는 것이 아니라 고객이 사용할 서비스의 일부분 테스트 : 특정 URL 맵핑된 서비스 정상 동작 테스트 테스트 코드 작성해보기 @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class HomeControllerTest { @AutoWired private TestRestTemplate template @Test...
-
스프링 @RestController와 @Controller의 내부 동작 차이 @Controller : 선언한 컨트롤러는 뷰 이름을 리턴하고, 뷰 리졸버가 뷰를 찾아 응답하는 형태 : text/html @RestController : @Controller 선언과 @ResponseBody 선언을 합쳐둔 어노테이션 @ResponseBody : Http response message body에 컨버팅된 리턴 데이터를 써서 응답함 리턴 데이터가 MessageConverter를 거쳐 요청자의 요청 형태로 컨버팅(json, xml)하여 응답 메세지 바디에 입력해서 응답함 MessageConverter 라이브러리 : Jacson(json), Marshalling(xml) @RestController 적용 코드 @RestController @RequestMapping("/api/questions/{questionId}/answers") public class ApiAnswerController { @PostMapping public Answer create(@PathVariable Long questionId, String...
-
스프링 리팩토링 하기 - 관심사 분리(역할 분리) 해야할 일, 언제 어떻게 변화될지 구분되는 것 : 하나의 객체는 하나의 관심사(역할, 책임)만 담당해야함 다른 관심사가 하나에 모여있다면 하나의 관심사 변경이 다른 관심사 변경에 영향을 미칠 수 있기 때문에 분리해서 감추는 것이 좋음 : 사용만 하게끔 변경점은 클래스 단위가 아니라 메소드에서 같은 코드를 사용하고있고, 변경이 된다면 여러 변경점이라 보면 됨 - 같은 코드를 사용하더라도 표준 방법을 사용하게 리팩토링하기 독립적으로 관리하면서 필요에 의해 의존성을 주입(Dependency Injection)해주는 것임 : 필요에...
-
스프링 스프링이 추구하는 가치에 맞게 개발해보기 - 스프링이 DI를 사용하게된 이유 자바가 추구하는 가치 그대로 객체지향이다 : 이전 엔터프라이즈 기술은 기술 개발에만 치중해있었음 오브젝트 중심 개발 : 객체 존재, 객체 관계, 객체지향적인 설계(역할 분리, 변경이 생기더라도 한 곳에만 변경을 할 수 있게 확장을 고려한 설계, 쪼갤 수 있을 때까지) User(자바빈)와 UserDAO(데이터베이스 - 데이터 핸들링) 관심사란? 객체가 처리해야할 일 UserDAO를 예를 들어서 : DB 커넥션, SQL 생성 / 실행, 사용한 자원 반환 아래 UserDAO의 문제점은 무엇일까?...
-
ajax로 서버에 콜하기 ajax란? asyncronous javascript and xml의 줄임말 비동기로 서버에 요청을 하고, 응답 데이터를 받아 랜더링까지 하는 기술 : 백그라운드 작업, 부분적으로 새로고침 효과를 얻을 수 있음 응답 데이터로 초기에는 xml을 사용하다가 json을 사용함 json이란? 자바스크립트는 아니지만 자바스크립트의 객체 문법처럼 짜인 데이터 key - value로 맵핑되어있음 : 변수에 json을 할당하면 변수.key로 value를 찾을 수 있음 json docs 보기 xml 대신 json을 사용하는 이유? 가벼움 : xml은 마크업 언어로 의미있는 태그 내에 데이터가 감싸져있는 형태...
-
스프링부트 일급객체 사용하기 : @Embeddable, @Embeded 객체지향적으로 코드 변경하기 : 컬렉션을 그대로 사용하지않고, wrapper 클래스를 만들어 객체.메소드로 요청하게끔 코드 짜기 응집도가 높은 엔티티를 분리해서 각각 관리하면서(역할 분리 - 유지보수에 유리함) 쓸 때는 하나에서 쓸 수 있게 객체지향 생활체조 원칙 객체지향 언어를 쓰면서 객체지향 개발을 지양하는 개발자가 되지말자! @Entity public class Question { . . . @Embeded private Answers answers; . . . } @Embeddable public class Answers { @OneToMany(mappedBy = "question") @Where(clause = "deleted =...
-
스프링부트 게시글 상태 구현하기 게시글 바로 삭제가 아닌 상태만 변경하기 복구 요청, 보관 개념으로 상태만 변경해두었다가 일정 기간이 지났을 때 데이터베이스에서 삭제하도록 만들기 deleted 상태 : true / false로 구분 Question 엔티티 boolean을 저장하는 방법으로 해결 /* Entity */ @Entity public class Qusetion { . . . @Column(nullable = false) private boolean deleted; } Question 엔티티 boolean 대신 문자 혹은 0, 1로 저장하는 방법으로 해결 방법1 : JPA 기능 중 컨버터 기능을 사용하면 됨 -...
-
스프링부트 스프링 인터셉터 - 로그인 확인 로그인 기능이 들어가는 기능마다 세션 확인 로직을 구현하거나 각 컨트롤러마다 별도 메소드로 빼고 사용하는 방식으로 개발해야하는데, 각각 구현해두지않고 별도로 구현해두고 요청이 들어왔을 때 거치도록 하는 방법이 있음 방법 : 인터셉터, 필터 공통적으로 처리해야하는 로직을 구현해두고, 공통적으로 처리되도록 하는 기능 필터와 인터셉터의 차이 필터 : J2EE에서 정의된 기능, Dispatcher Servlet(아래 설명)의 앞단에서 처리(스프링 컨텍스트 외부, 스프링과 무관한 자원에 대해 동작) 인터셉터 : 스프링 프레임워크에서 자체적으로 제공하는 기능, Dispatcher Servlet에서 컨트롤러로...
-
스프링부트 Entity 관계 설정하기 : 게시글 쓰기 관계를 설정해주기위해서 테이블에 관계 키를 설정해줘야함 : FK(foreign key) 외래키 FK : 테이블의 컬럼 중 다른 테이블의 레코드를 같이 조회(참조)하기위해 필요한 키 - 다른 테이블의 ID를 FK로 사용함(데이터 무결성을 보장하기위해 - NULL이거나 존재하거나(PK)) 관계 설계하기 어디에서 조회할 것인지에 따라 단방향, 양방향 관계 맺기가 가능함 : 어노테이션으로 관계를 설정할 수 있음 게시글 쓰기 : 1명의 유저가 여러 게시글 ID를 가지는 레코드를 저장할 수 있으니 OneToMany, 여러 게시글은 레코드 저장할...
-
스프링부트 로그인 구현하기 로그인 구현 전에 알아야할 개념 : HTTP, 쿠키와 세션 HTTP : 문서를 주고받기위해 고안된 프로토콜로 1회 통신 후 소켓 연결을 끊어버림(이전 통신 정보, 상태를 알 수 없음) 쿠키와 세션 : HTTP의 단점을 채우기위한 방법 쿠키 : 로컬에 클라이언트 상태 정보를 그대로 기록한 데이터 파일, 만료 시간 정보까지 있음 세션 : 쿠키를 사용하지만 담는 값이 다름, 서버에서 발급해준 ID값을 담음, 웹서버에 접속한 이후로 브라우저를 종료할 때까지 해당 세션ID로 요청을 보내면 같은 요청자로 봄(상태...
-
리눅스 커널과 배포판의 프리 소프트웨어 리눅스는 리눅스 커널(OS 핵심)과 리눅스 배포판을 구성하는 프리 소프트웨어(배포판 사용자들에게 편의 제공을 위한)에 의해 구성됨 배포판에는 ubuntu, opensuse, redhat 등이 있음 터미널 에뮬레이터와 쉘 그리고 쉘프롬프트 터미널 (에뮬레이터) : 쉘에 접근할 수 있도록 하는 프로그램 쉘 : 사용자의 명령을 운영체제에 전달(번역)하여 실행될 수 있도록 함 쉘프롬프트 : 쉘이 입력가능할 때 나타나는 명령줄 달러($)가 아닌 # 이라면 현재 슈퍼 유저로 쉘을 사용할 수 있는 것 [ubuntu] $ 터미널 세션 종료 :...
-
스프링부트 알고 개발하기 (JPA) 자바를 사용해서 데이터를 유지하는 기술(그 중 ORM)의 표준 스펙 : 인터페이스 ORM : 객체 - 테이블 레코드를 맵핑해서, 로직 처리와 데이터베이스 데이터 관리 한방에 할 수 있음, 객체지향적으로 개발할 수 있음 테이블 주도 개발이 아닌 객체 주도 개발을 할 수 있음 : 비즈니스 로직에 더 신경쓰고 개발할 수 있음 단점 : 쿼리를 직접 만들지않고, 메소드로 다루기때문에 성능 튜닝이 어려움, 쿼리를 직접 만들어서 실행시킬 수도 있지만 쿼리에 얽메이는 개발을 하게되므로 ORM 장점을...
-
자바 어노테이션 java 1.5부터 추가된 기능 소스코드에 메타코드(추가적인 정보)를 붙이는 것 추가적인 정보에 따라 기존의 실행과 다르게 실행될 수 있음 컴파일, 런타임 모두 활용 가능 컴파일 타임에 메타 데이터가 적용된 코드에 코드를 추가할 수도 있고, 런타임 때 메타데이터에 의해 실행 흐름이 바뀔 수도 있음 런타임에는 리플렉션을 활용해서 어노테이션이 적용되어있는지 체크할 수 있음 @Override public String toString() { } 사용자 정의 가능함 : 정의 -> 사용 -> 실행 Annotation 파일 만들기 Annotation 적용되었는지 리플렉션으로 확인 /*...
-
Time BaseEntity 만들기 - 생성시간, 수정시간 기록 자동화 Entity 클래스: 데이터베이스 테이블과 연결되는 클래스 Entity 객체: 테이블의 레코드, 객체지향적으로 생각하기(인스턴스) Entity 중 생성일 - 수정일이 필요한 Entity가 있을텐데, 클래스마다 정의하지않고 상속관계 활용하기 참고 : 기억보다 기록을, SpringBoot & JPA로 간단 API 만들기 @Getter @MappedSupperclass @EntityListeners(AuditingEntityListener.class) public abstract class TimeEntity { @CreateDate private LocalDateTime createdDate; @LastModifiedDate private LocalDateTime modifiedDate; } @NoArgsConstructor @Getter @Setter @ToString @Entity public class Question extends TimeEntity { } @MappedSupperclass : 여러 엔티티의...
-
스프링부트 h2 데이터베이스 연결 - 사용하기 데이터베이스 사용 : 메모리에 저장하면 프로세스 종료 후 데이터가 모두 날아감, 데이터를 공유하기위해서 복잡도가 높아질 수 있음 복잡도 문제 : 접근 객체(XXXRepository)만 만들면 됨, 같은 곳 접근 JDBC : DB 변경할 때마다 코드 변경을 최대한 없애기위해 표준 인터페이스를 마련함 h2 : 순수 자바로 짜여진 임베디드 데이터베이스, jar 파일만 임포트하면 사용할 수 있음(타 db는 드라이버 임포트까지 해줘야함) JPA : 데이터베이스 테이블을 객체지향적으로 다루는 ORM의 표준 인터페이스 - 구현체로 Hibernate 등이...
-
스프링부트 redirect 처리하기 redirect 란? 요청에 대한 처리 후 응답할 때 새로운 URI와 응답코드(3xx)를 주어서 클라이언트가 새로운 URI로 요청하도록 만드는 것을 말함 @Controller @RequestMapping("/users") public class UserController { private Users users = new Users(); @GetMapping public String show(Model model) { model.addAttribute("users", users.get()); return "/users/list"; } @PostMapping public String create(User user) { users.add(user); return "redirect:/users"; } } POST /users 에 대한 처리 후 redirect 응답 : 아래는 이에 대한 리스폰스 메세지 클라이언트(웹브라우저)는 Location으로 재요청함(이전 요청과는 전혀...
-
쓰면서 배우는 스프링부트 뷰 중복 코드 없애기 뷰 중 container(contents)부분만 다르고, head, nav, footer는 코드가 중복됨 하나가 변경되면 모든 뷰 파일 코드 변경해야했음 템플릿 엔진 기능 중 부분(partial)뷰를 만들고 템플릿 문법으로 include 시키는 기능이 있음 아래와 같이 디렉토리를 새로 만들어서 부분 뷰를 만들어놓음 /* /partial/header */ <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>Colin</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link href="/css/bootstrap.min.css" rel="stylesheet"> <!--[if lt IE 9]> <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link href="/css/styles.css" rel="stylesheet"> </head> 템플릿엔진 문법을...
-
리눅스와 친해지기 명령어 pipe 두개의 프로그램을 연결해주는 명령어, 앞의 프로그램 결과를 뒤의 프로그램에 전달해줌 redirection 입출력을 변경해주는 명령어 표준 입력 : 키보드 / 표준 출력 : 화면(모니터) ’>’ : 출력을 변경함 $ ls -al > list.txt ’<’, ‘«’ : 입력을 변경함, ‘<’ 와 ‘«’ 의 차이는 덮어쓰기냐 덮어쓰지않느냐임 $ head < list.txt filter 결과를 필터링할 때 쓰는 명령어들 grep, head, tail, awk(패턴 매칭) 등이 있음 pgrep 프로세스의 ID나 속성값을 기반으로 특정 프로세스를 찾거나 특정 프로세스에...
-
git 버젼관리시스템 : 파일의 버젼을 직접 관리하지않고, 명령어를 통해서 관리 프로그램을 사용함 기본 work flow : 아래 사진을 보면서 아래 내용을 참고해본다 로컬 기준 버젼관리(파일 추적)는 3개 공간(단계), 2가지 작업으로 나뉜다 3개 공간 working tree(space) : 작업 공간, 보통 프로젝트 디렉토리 staging area : 변경 추적하고 있는 파일의 공간 local repository : 변경 기록(commit == save data)을 보관하고 있는 공간 2가지 작업 add : git을 통해서 파일관리를 하기위해서는 등록해야함, add 명령어를 통해 등록(Staged)함 commit :...
-
알고리즘 하나를 풀더라도 제대로 풀자 풀면서 알게된 것 1. 어떤 연산이라도 나머지 연산부터 해도 결과는 같음 : 숫자의 크기를 줄이는 것도 하나의 방법 2. 최대한 최대값으로 많이 나누려면 거기 조건에 맞을 때까지 맞춰주는게.... 3. 코드짜고 성공 케이스, 실패 케이스 최소 4개씩 돌려보기 4. 자바 포맷 출력 : System.out.format("$format", value) 오늘 푼 유형 1. 조합 중에 합이 가장 작은 것 구하기 : 작은 것을 하나씩 빼가면서 큰 것으로 나눠질 수 있도록 2. 연산 순서 : 나머지...
-
알고리즘 오늘 한 문제도 풀지못했지만 몇가지 배운 점이 있다 1. 문제를 빠르게 이해하기위해서 변수의 의미부터 파악해야한다는 것 2. 시간복잡도부터 보고 구현방법을 생각해야한다는 것 3. prefix 라는 방법 : 연산 횟수를 줄이기위해서 미리 일정 범위까지 연산해뒀다가 꺼내쓰는 방식 spring-boot 환경설정 후 run 시켜보기 기존 스프링을 그대로 사용하면 많은 설정을 해줘야하는데, 스프링부트를 사용하면 간단하게 설정할 수 있음 express로 웹어플리케이션을 개발한 경험이 있는데, express-generator와 같은 개념이라고 생각됨 인텔리j에서 스프링부트 프로젝트 시작하기(환경설정) : 간단하게 필요한 라이브러리 설정을 할 수...
-
[코드스쿼드 레벨3 과정 첫날] - 준비하기 과정에서 배운 것 자바 객체지향에 대한 이해가 필요하고, 실제로 객체지향 프로그래밍할 줄 알아야해 API 사용은 해봤어야 필요할 때 뭘 쓸지 알 수 있지 Spring 예전 같았으면 데이터를 어떻게 주고 받아야하는지에 대한 표준만을 가지고(CGI) 실제로 개발은 개발자가 다했었어야하지만, 지금은 다름! 그 다름을 느끼기 위해선 일정 시간의 노력이 필요함 Spring 진입장벽이 높았던 것을 Spring boot로 낮췄다는데, 이제부터 공부 시작! 웹 기본지식 웹의 탄생 : 어떠한 시스템(CPU, OS)이든지 간에 같은 문서를 주고...
-
코드스쿼드 레벨2 과정이 거의 끝나가고 있다. 레벨2의 목표는 객체지향프로그래밍 익히기이다. 그동안 5가지의 미션을 하면서 책을 통해서만 공부하던 객체지향을 직접 느껴보았다. 과정 중에 와닿았던 것, 그리고 객체지향프로그래밍을 한다면 반드시 그래야만 하는 것, 기억해야할 것들을 이 글을 쓰면서 정리해보았다. 글에 쓰일 예제 코드들은 모두 5번째 미션이었던 볼링 프로그램 코드 중 일부(직접 짠 코드보다 다 짜고난 뒤 비교해본 마스터의 코드이다 - 코드 비교 리뷰를 하면서 느낀점이 굉장히 많아 마스터의 코드를 바탕으로 글을 써보았다) 이다. 볼링 프로그램을 택한 이유는...
-
enum 상수값을 모아서 관리하기 문자열이었다면 많은 예외처리를 해야할 수 있지만, 값의 범위를 강제해버리기떄문에 안전한 프로그래밍이 가능함 예를 들어 0 ~ 6까지 전달받아야하는데 래핑시켜서 그 값들만 받게끔 할 수 있음 : 유효성 체크 메소드 따로 만들지않고도 예시 2 : 방향 4가지만 줄 수 있도록 강제 /* example */ public enum Direction { NORTH, SOUTH, EAST, WEST; } public class Ladder { public void move(Direction direction) { } } 클래스의 인스턴스 개수를 제한해버리고 만듦 : static 환경에서...
-
통신 쌍방 간의 통신 요청과 응답 프로토콜 통신을 위해 꼭 필요함 통신 상대를 찾기도, 어떤 내용을 어떻게 전달할지도 약속에 의해 모든게 진행됨 : 서로 다른 하드웨어, 소프트웨어 환경 TCP/IP 네트워크에 연결된 컴퓨터(IP Address 부여)간에 데이터(패킷 형태로 됨)를 주고 받기위한 프로토콜 프로토콜에서 핵심적으로 사용되는 프로토콜이 TCP(패킷 프로토콜 - 연결을 어떻게 하고, 데이터 순서 형태), IP(인터넷 환경 프로토콜 - 어느 라우터로 가야할지)라 TCP/IP로 불림 계층형 프로토콜 : 한번에 정보를 작성하는게 아니라 4개의 계층별(각각 프로토콜 그게 4개)로 각각이...
-
객체 간의 관계 자바는 객체지향 언어 객체지향언어는 객체 간의 협력이라는 관점 아래 프로그래밍 서로 관계를 맺는데 그 중 중요한 상속 관계와 인터페이스 구현 관계에 대해 공부한 내용을 정리하였음 자바 객체지향의 상속과 인터페이스 자바는 객체지향 상속을 extends로 구현했음 확장(extends) 의미 구체화(특수화) 의미 : is a kind of 분류도를 만들어나감 자바는 다중 상속 안되게 막아놓음 : 지원한다면 개발자가 고려해야할게 많아짐 - 필드, 메소드명 중복되었을 때 객체의 인터페이스로 능력 확장이 가능함 : is able to 다중 상속은 못하지만...
-
TDD 시작하기 테스트 주도 개발! 요구사항, 결과 출력 화면만 보고 필요 객체, 설계를 예상하면서 만드는 궁예가 되지말자 기능 상 아주 작은 부분으로 쪼개서 실패 테스트 케이스를 작성하고 성공 케이스로 만들기위해 설계, 코드 리팩토링을 하자 한꺼번에 설계를 해두고 개발하는게 아니라 작은 기능부터 설계하고 개발하면서 설계를 리팩토링 하는 방식으로 개발하자는 것! TDD로 개발해보기 코드스쿼드 프로그래밍 미션을 일부 가져와서 TDD 예시를 들어보려한다. 로또 프로그램 진행 화면 : 당첨번호 6개를 입력받아 로또 인스턴스를 생성해야하는 과정이다. 지난 주 당첨 번호를...
-
상속은 inheritance가 아니라 확장(extend) public class Car { } public class Sonata extends Car { } 상속을 한다는 것은 타입을 세분화(하위 타입 생성)시키겠다는 것 하위클래스는 상위타입의 한 종류이다 : is a kind of 하위클래스와 상위클래스의 관계 상-하위 관계를 설계해두면? 중복 코드를 줄이면서도, 다형성을 적극 활용할 수 있음 추상클래스(abstract class) public abstract class Car implements Movable { public abstract void method(); } public class Sonata extends Car { @Override public void method() { } } 자바에서는...
-
시작하기 코드스쿼드에 들어와서 프로그래밍을 하고 피드백 받는 과정에서 그동안 어렴풋한 개념으로 알고 있었던 것들을 확실하게 알게됨 그 내용들을 두고두고 참고하기위해서 정리를 시작함 많은 내용이 있지만 먼저 정리한 것부터 조금씩 조금씩 글을 쓸 예정 객체 간의 요청 - 응답으로 프로그램이 완성시키기 // CoordinateMain.java List<Point> points = Input.getPoints("좌표를 입력해주세요."); Figure triangle = new Triangle(points); Viewer.viewAtCoordinate(triangle); 객체에 역할을 할당했다면, 역할에 해당하는 일을 싸그리 맡기기 역할을 맡은 객체가 어떻게 처리하는지는 중요하지않고, 응답 결과만 얻어오면됨 보기 좋은 코드 만들기 for...