Intellij IDEA 단축키

산뜻한 월요일 출근길 아침에 한통의 메시지를 받았다.

얼마전에 요런 이벤트에 응모했는데

오오…? 당첨된 것이다. 신가하게 개발 서적 혹은 강의 관련된 이벤트에 자주 당첨되는것 같다. 자세히 보니 5명 뽑는 이벤트에 15명이 지원한건가…
그래도 당첨됐다는 사실에 기뻤다!
평소에 자주보는 페이지이기도 하고 위의 IntelliJ 강의는 처음 나왔을 때, 들어보고 싶었다는 생각이 있었지만 공부할게 너무 많아 미뤄놨었는데 마침 당첨된 기념으로 월요일 퇴근 후 바로 끝장을 보았다.

어디에 도움이 될까?

대부분의 개발자는 자신만의 개발 환경을 구축해서 사용한다. 예를 들면, 자신만의 dot file 들을 만들어 사용한다던가 IDEA의 세팅들을 커스터마이징해서 사용하는 것들이 있다.
나도 처음에는 IDEA의 “자동 정렬”과 같은 가장 간단한 단축키부터 사용하기 시작해 현재는 IntelliJ에 IdeaVim 플러그인 설치해서 사용할 정도로 나만의 개발환경을 구축하는데 적지 않은 시간을 쏟았다.

처음에는 물론 사용하기 쉽지 않다. 그러나 적응하기 시작하는 순간 엄청난 생산성의 향상을 가져온다. 손이 마우스로 가지 않고 vim을 사용하면 심지어 방향키 까지도 손이 가지 않는다.

이런 개발 환경을 구축하는데 있어 한가지 문제가 있다. 어떤 기능들이 있는지 알아야 찾아서 사용할텐데 어떤 기능들이 있는지 조차 파악하기가 마냥 쉬운게 아니라는 것이다. 대부분 내가 모르는 기능을 누군가 사용할때는 “이런 기능이 있었어?” 라는 반응이 많은데 이게 문제다! 한 번 사용하면 계속 사용하게 되는데 처음 사용하기가 어려운 이유이기도 하다.

다행히도 위의 강의는 이런 문제를 해소해준다! IntelliJ를 처음 사용하는 사람도! 이미 사용하고 있던 사람도! 모두 도움이 될 것이다. 어떤 기능이 있는지, 해당 기능을 어떤 단축키를 통해 사용할 수 있는지 강의를 보고 배워보자!

강의는 인프런을 통해서 수강할 수 있다. -> IntelliJ를 시작하는 분들을 위한 가이드

강의를 수강하며 새롭게 알게된 기능중 라인 합치기의 경우 Vim의 Shift + J 단축키를 이용해 사용하고 있었는데, 단순히 두 라인을 합쳐주는 기능하는 걸 넘어서, IntelliJ의 Shift + Cmd + J는 문자열을 합칠 경우 더 유용하게 사용 가능했다. 그래서 Shift + Cmd + J를 Shift + J로 변경해버렸다!

단축키

수강하며 실습해 볼 수 있는 단축키 리스트

  • 코드 템플릿
    메인 메소드 : psvm
    System.out.println() : sout
  • 실행환경 실행
    현재 포커스 : Ctrl + Shift + R
    이전 실행 : Ctrl + R
  • 코드 Edit
    메인 메소드 실행 :
    라인 복사 : Cmd + D
    라인 삭제 : Cmd + 백스페이스
    라인 합치기 : Ctrl + Shift + J
    라인 이동 : Shfit + Option + 위 (아래)
    구문 이동 : Shift + Cmd + 위 (아래)
    Element 단위 이동 : Option + Shift + Cmd + 좌 (우)
    인자값 즉시 보기 : Cmd + P
    코드 구현부 즉시 보기 : Option + Space
    Doc 즉시 보기 : F1
  • 포커스
    단어별 이동 : Option + <, >
    단어별 선택 : Shift + Option + <, >
    라인 첫/끝 이동 : Fn + <, >
    라인 전체 선택 : Shift + Cmd + <, > / Shift + Fn + <, >
    Page Up/Down : Fn + 위/아래
    포커스 범위 한 단계씩 늘리기 : Option + 위 (아래)
    포커스 뒤로/앞으로 가기 : Cmd + [, ]
    멀티 포커스 : Option + Option + 아래
    오류 라인 자동 포커스 : F2
  • 검색
    현재 파일에서 검색 : Cmd + F
    현재 파일에서 교체 : Cmd + R
    전체에서 검색 : Shift + Cmd + F
    전체에서 교체 : Shift + Cmd + R
    정규표현식으로 검색, 교체 : Regex 체크
    파일 검색 : Shift + Cmd + O
    메소드 검색 : Option + Cmd + O
    Action 검색 : Shift + Cmd + A
    최근 열었던 파일 목록 보기 : Cmd + E
    최근 수정했던 파일 목록 보기 : Shift + Cmd + E
  • 자동완성
    스마트 자동 완성 : Shift + Ctrl + Space
    스태틱 메소드 자동 완성 : Ctrl + Space + Space
    Getter/Setter/생성자 자동 완성 : Cmd + N
    Override 메소드 자동완성 : Ctrl + I
    Live Template 목록 보기 : Cmd + J
  • 리팩토링
    변수 추출하기 : Cmd + Option + V
    파라미터 추출하기 : Cmd + Option + P
    메소드 추출하기 : Cmd + Option + M
    이너클래스 추출하기 : F6
    이름 일괄 변경하기 : Shift + F6
    타입 일괄 변경하기 : Shift + Cmd + F6
    Import 정리하기 : Ctrl + Option + O
    코드 자동 정렬하기 : Cmd + Option + L
  • 디버깅
    Debug 모드로 실행하기 (현재 위치의 메소드) : Shift + Ctrl + D
    Debug 모드로 실행하기 (이전에 실행한 메소드) : Ctrl + D
    Resume (다음 브레이크 포인트로 이동하기) : Cmd + Option + R
    Step Over (현재 브레이크에서 다음 한줄로 이동하기) : F8
    Step Into (현재 브레이크의 다음 메소드로 이동) : F7
    Step Out (현재 메소드의 밖으로 이동) : Shift + F8
    Evaluate Expression (브레이크된 상태에서 코드 사용하기) : Option + F8
    Watch (브레이크 이후의 코드 변경 확인하기) : 단축키 X
  • Git
    Git View On : Cmd + 9
    Git Option Popup : Ctrl + V
    Git History : Ctrl + V => 4
    Branch : Ctrl + V => 7
    Commit : Cmd + K
    Push : Shift + Cmd + K
    Pull : Shift + Cmd + A => git pull
    Github 연동하기 : Shift + Cmd + A => share GitHub

IntelliJ에서 SpringBoot 프로젝트 생성하기

서론

Spring은 J2EE나 JEE로 알려진 자바 엔터프라이즈 에디션을 경량화하기 위해 시작되었다. 스프링은 무거운 엔터프라이즈 자바 빈(EJB)로 컴포넌트를 개발하지 않았다. 그 대신 의존성 주입(DI)과 관점 지향 프로그래밍(AOP)을 활용해서 EJB의 기능을 평범한 자바 객체(POJO)로 구현할 수 있게 하여 간단하게 엔터프라이즈 자바 개발에 접근할 수 있도록 했다.
컴포넌트 코드 작성은 가벼워졌지만, Spring Framework 기반의 웹 프로젝트를 진행하게되면 최초 개발 구성(설정)하는 부분에 많은 시간이 소모되었다. 결국 애플리케이션 로직 작성이 아닌 프로젝트 구성 작업에 쓰는 시간이 많이 Gk소모되는 것이다.
SpringBoot는 Spring의 복잡한 설정을 최소화하여 빠르게 프로젝트 개발을 시작할 수 있게 해준다. 이 포스팅에서는 IntelliJ에서 SpringBoot로 웹 프로젝트를 시작하는 방법을 소개하며 SpringBoot의 특징을 소개한다.

IntelliJ에서 SpringBoot 프로젝트 생성

Spring Initializr는 SpringBoot 프로젝트 구조를 만드는 웹 애플리케이션이다. 기본적인 프로젝트 구조와 코드를 빌드하는 데 필요한 maven이나 gradle 빌드 명세를 만들어준다. 그러므로 Spring Initializr가 만든 프젝트에 애플리케이션 코드만 작성하면 된다.
Spring Initializr는 웹 기반 인터페이스, Spring Tool Suite(STS), IntelliJ IDE, SpringBoot CLI로 사용할 수 있다. 그 중 IntelliJ를 사용해 프로젝트를 생성해보자.

IntelliJ를 시작하여 Create New Project를 선택하고 새로운 프로젝트 다이얼로그를 연다. New Project 다이얼로그에서 Spring Initializr 프로젝트를 선택하고 자바 SDK를 설정한 후 Next 버튼을 누른다.

두 번째 화면에서는 프로젝트 이름, 빌드할 때 maven과 gradle 중 어느 것을 사용할지, 자바 버전 등 프로젝트의 기본적인 사항을 물어본다. 프로젝트 정보를 입력하고 Next 버튼을 누른다.

세 번째 화면에서는 프로젝트에서 필요한 종류의 의존성을 추가한다. Web, Thymeleaf, JPA, H2를 선택한 후 Next 버튼을 누른다.

다음으로 프로젝트가 저장되는 경로를 지정한다.

Gradle 설정을 지정한다.

코드 작성

도메인 정의 (Diary.java)

src/main/java/com.example.demo/Diary.java 파일을 작성한다.
일기를 나타내는 엔티티 정의한다. 간단하게 id, title, ocntent 필드를 갖고 있는 POJO 객체로 만든다. @Entity 어노테이션을 붙여 클래스를 JPA 엔티티로 지정했고, id 필드에는 @Id@GeneratedValue 어노테이션을 붙여 엔티티의 유일성을 식별하고 자동으로 값을 제공하는 필드로 지정했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Diary {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String user;
private String title;
private String content;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getUser() {
return user;
}

public void setUser(String user) {
this.user = user;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

레파지토리 인터페이스 선언 (DiaryListRepository.java)

src/main/java/com.example.demo/DiaryListRepository.java 파일을 작성한다.
데이터베이스에 Diary 객체를 저장할 수 있는 레파지토리를 선언한다. 스프링 JPA를 사용하므로 스프링 데이터 JAP의 인터페이스를 상속하여 인터페이스를 만든다. JpaRepository 인터페이스는 타입 매개변수 두 개를 받는다. 첫 번째는 레파지토리가 사용할 도메인 타입, 두번 째는 클래스의 ID 프로퍼티 타입이다. 지정한 유저의 이름으로 도서 목록을 검색하는 findByUser() 메서드를 추가했다.
DiaryListRepository는 JpaRepository 인터페이스를 상속받아 18개의 메서드를 구현해야 한다. 그러나 스프링 데이터는 레파지토리를 인터페이스로 정의만 해도 잘 작동할 수 있게 런타임 시에 자동으로 구현해준다.

1
2
3
4
5
6
7
8
9
10
package com.example.demo;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

public interface DiaryListRepository extends JpaRepository<Diary, Long> {

List<Diary> findByUser(String user);
}

일기 목록 애플리케이션의 스프링 MVC 컨트롤러 (DiaryListController.java)

src/main/java/com.example.demo/DiaryListController.java 파일을 작성한다.
클래스에 @Controller 어노테이션을 추가하면, 자동 컴포넌트 검색으로 DiaryListController를 발견해 자동으로 스프링 애플리케이션 컨텍스트에 빈으로 등록한다. 요청을 처리하는 모든 메서드를 기본 URL 경로인 /로 매핑하기 위해 @RequestMapping 어노테이션을 붙였다.
usersDiarys() 메서드는 “diaryList”를 논리적 뷰 이름으로 반환한다. 그러므로 이 뷰도 만들어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/")
public class DiaryListController {

private static final String user="jongmin";

private DiaryListRepository diaryListRepository;

@Autowired
public DiaryListController(DiaryListRepository diaryListRepository) {
this.diaryListRepository = diaryListRepository;
}

@RequestMapping(method= RequestMethod.GET)
public String usersDiarys(Model model) {
List<Diary> diaryList = diaryListRepository.findByUser(user);
if (diaryList != null) {
model.addAttribute("diarys", diaryList);
}
return "diaryList";
}

@RequestMapping(method = RequestMethod.POST)
public String addToReadingList(Diary diary) {
diary.setUser(user);
diaryListRepository.save(diary);
return "redirect:/";
}
}

일기 목록을 보여주는 Thymeleaf 탬플릿 (diaryList.html)

src/main/resources/template/diaryList.html 파일을 작성한다.
유저의 일기 목록 부분과 일기를 일기 목록에 추가할 때 사용하는 입력 폼을 작성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.springframework.org/schema/data/jaxb">
<head>
<meta charset="UTF-8" />
<title>일기 리스트</title>
</head>
<body>
<h2>일기 목록</h2>
<div th:unless="${#lists.isEmpty(diarys)}">
<dl th:each="diary : ${diarys}">
<dt>
<span th:if="${diary.title}" th:text="${diary.title}">Title</span>
</dt>
<dd>
<span th:if="${diary.content}" th:text="${diary.content}">Content</span>
</dd>
</dl>
</div>

<hr />

<h3>일기 작성</h3>
<form method="POST" th:action="@{/}">
<label for="title">Title:</label>
<input type="text" name="title" size="50" /><br />
<label for="content">Content:</label>
<input type="text" name="content" size="100" /><br />
<input type="submit" value="추가" />
</form>
</body>
</html>

실행 결과

SpringBoot 특징 살펴보기

SpringBoot를 이용해 간단한 애플리케이션을 만들어 보았다. 이 애플리케이션을 바탕으로 SpringBoot의 특징을 알아보자.

스타터 의존성

처음 프로젝트를 생성하며 Spring Initializr에서 필요한 Dependencies들(Web, Thymeleaf, JPA, H2)을 쉽게 추가했었다. 만약 이런 스타터 의존성이 없었다면, 애플리케이션을 개발하기도 전에 build.gradle 또는 pom.xml에서 필요한 Dependencies를 직접 추가해야했을 것이다. (또햔, 여러 의존성들 사이에 잘 호환이 되는지도 확인해야 한다.)

프로젝트의 build.gradle 코드를 잠시 살펴보자.

1
2
3
4
5
6
7
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('com.h2database:h2')
testCompile('org.springframework.boot:spring-boot-starter-test')
}

Spring Initializr에서 체크했던 의존성들이 gradle에 추가되어 있는것을 볼 수 있다. 또한 각 라이브러리의 버전이 명시되어 있지 않은데, 이는 SpringBoot 버전에 따라 스타터 의존성 버전이 결정되기 때문이다. 즉, 사용자는 스타터 의존성만 지정하면 어떤 라이브러리와 어떤 버전을 사용해야 하는지 걱정없이 구성에서 자유로워질 수 있는 것이다.

자동 구성

SpringBoot Auto-configuration스프링 구성을 적용해야 할지 말지를 결정하는 요인들을 판단하는 런타임 과정이다. 애플리케이션이 시작될 때마다 스프링 부트는 보안, 통합, 데이터 저장, 웹 개발 영역 등을 커버하기 위해 자도성에서 대략 200가지 정도 결정을 내린다. 이 자동 구성 덕분에 필요한 상황이 아니면 명시적으로 구성을 작성하지 않아도 된다.

참고