목차
안녕하세요! 오늘은 Java Spring Boot를 통해 Maven으로 빌드하고 배포하는 과정을 처음 접하는 개발자분들을 위한 가이드를 준비했습니다. 처음 시작하는 분들은 환경 설정부터 배포까지 막막하게 느껴질 수 있어요. 하지만 걱정 마세요. 이 글에서는 PostgreSQL 데이터베이스 설정부터 pom.xml 의존성 추가, 설정 파일 구성, 간단한 엔티티/레포지토리/컨트롤러 구성, 그리고 Maven으로 프로젝트를 빌드하고 실행하여 배포하는 모든 과정을 차근차근 다뤄보겠습니다. 🙌 함께 따라 하며 Spring Boot Maven 프로젝트를 완성해 봐요!
※이전글
2025.07.17 - [IT 트렌드/알아두면 좋은 IT 상식] - VSCode Java Spring 프로젝트: Maven 스프링 부트 예제 설정부터 디버깅까지
VSCode Java Spring 프로젝트: Maven 스프링 부트 예제 설정부터 디버깅까지
목차소개 (Introduction)VS Code(비주얼 스튜디오 코드) 환경에서 Java Spring Boot 프로젝트를 생성하고 실행해 본 후기입니다. 이번 포스트에서는 Spring Initializr를 통해 Maven 기반 Spring Boot HelloWorld 프로젝
kberry.tistory.com
Introduction (소개)
프로그래밍을 처음 시작할 때 무엇이 가장 어려웠나요? 아마 환경 설정과 배포 과정이 아닐까 싶습니다. 특히 Spring Boot와 Maven을 처음 다루는 분들은 설정해야 할 파일들과 개념들이 한꺼번에 쏟아져 나와서 당황하기 쉽죠. 저도 처음엔 같은 고민을 했답니다.
이 글에서는 초보 개발자들의 눈높이에 맞춰 쉽고 친절한 설명을 드릴게요. 😀 PostgreSQL 데이터베이스 연결 설정에서 시작해, Maven의 pom.xml 의존성 추가, application.properties 구성, 그리고 간단한 엔티티(Entity), 레포지토리(Repository), 컨트롤러(Controller) 코드 작성까지 함께 해보겠습니다. 마지막으로 Maven으로 프로젝트를 빌드하고 실행(배포)하는 방법까지 다룰 예정이니, 이 글 하나로 처음부터 끝까지 흐름을 잡을 수 있을 거예요.
그럼 이제 본격적으로 시작해 볼까요? Spring Boot + Maven으로 내 블로그 애플리케이션 만들기 여정, 지금부터 출발합니다! 🚀
PostgreSQL 기반 DB 환경 설정
Spring Boot 애플리케이션을 만들 때 가장 먼저 고려해야 할 것이 데이터베이스(DB) 설정입니다. 이번 예제에서는 PostgreSQL을 사용합니다. 데이터베이스를 설정하는 과정은 처음엔 복잡해 보일 수 있지만, 순서대로 따라 하면 어렵지 않아요.
우리는 pgAdmin4라는 GUI 툴을 사용하여 PostgreSQL 서버에 접속하고, 애플리케이션 전용 데이터베이스와 사용자를 만들어보겠습니다. 'blog_db'라는 데이터베이스와 'blog_user'라는 전용 사용자를 만들어서, 애플리케이션이 이 계정으로만 DB에 접근하도록 설정할 거예요 (보안을 위해 권장되는 방법입니다).
pgAdmin으로 로컬 PostgreSQL 서버 연결하기
- pgAdmin4 실행: 컴퓨터에 PostgreSQL을 설치하면 함께 설치된 pgAdmin4 프로그램을 실행합니다. 실행하면 좌측 패널에 'Servers' 목록이 보입니다.
- 서버 추가/연결: 만약 기본 서버(PostgreSQL 14 등)가 등록되어 있지 않다면, 좌측 'Servers'를 우클릭하고 Register > Server... 메뉴를 선택합니다.
- General 탭: 서버에 임의의 이름을 지정합니다 (예: "Local PostgreSQL").
- Connection 탭:
- Host name/address: localhost
- Port: 5432 (PostgreSQL 기본 포트)
- Maintenance database: postgres (기본관리 DB 이름)
- Username: postgres (PostgreSQL 설치 시 생성된 기본 관리자 계정)
- Password: PostgreSQL 설치 시 설정한 postgres 계정 비밀번호
- 설정을 마쳤으면 Save를 눌러 서버를 등록합니다.

DB구성
- 서버 연결 확인: 이제 좌측 패널에 방금 추가한 서버가 보일 거예요. 해당 서버를 클릭하면 비밀번호 입력을 다시 묻는데, 앞서 입력한 postgres 비밀번호를 입력하면 연결됩니다.
애플리케이션용 데이터베이스 사용자 생성 (blog_user)
이제 애플리케이션 전용 DB 사용자 계정을 만들겠습니다. 기본 postgres 관리자 계정을 그대로 사용하기보다는, 별도의 일반 권한 계정을 만들어 사용하는 것이 보안에 좋아요.
- Login/Group Role 생성: pgAdmin4 좌측 패널에서 등록된 서버의 Login/Group Roles를 우클릭하고 Create > Login/Group Role...을 선택합니다.
- General 탭:
- Name: blog_user (애플리케이션에서 사용할 사용자 이름)
- Definition 탭:
- Password: your_password (원하는 비밀번호를 입력합니다. 반드시 기억하고, 안전한 비밀번호를 사용하세요!)
- Privileges 탭: 기본값으로 두고 넘어갑니다. (필요한 경우 여기서 LOGIN 권한 등을 줄 수 있지만, 기본적으로 Login 역할로 생성됩니다.)
- 완료: Save를 클릭하여 사용자를 생성합니다.

blog_user 생성
참고: 방금 생성한 blog_user가 로그인 가능한 역할(Login role)이어야 애플리케이션이 DB에 접속할 수 있습니다. pgAdmin의 Login Roles로 생성하면 기본적으로 LOGIN 권한이 설정되지만, 혹시 직접 SQL로 만들 경우 CREATE USER를 사용하거나 CREATE ROLE... LOGIN 옵션을 주어야 합니다. blog_user에 로그인 권한(CAN LOGIN)이 있어야 데이터베이스 연결이 가능하다는 점 기억하세요.
블로그 데이터베이스 생성 (blog_db)
이제 실제 데이터를 저장할 데이터베이스(blog_db)를 만들어보겠습니다.
- pgAdmin4 좌측 패널에서 Databases를 우클릭하고 Create > Database...를 선택합니다.
- General 탭:
- Database: blog_db (데이터베이스 이름을 지정합니다. 여기서는 블로그용으로 blog_db라고 합니다)
- Owner: 드롭다운에서 방금 만든 blog_user를 선택합니다. 이렇게 하면 데이터베이스의 소유자가 blog_user가 되어, 이 사용자가 해당 DB에 대한 권한을 기본적으로 갖습니다.
- Save: 설정을 마쳤으면 Save 버튼을 눌러 데이터베이스를 생성합니다.
이제 blog_db라는 빈 데이터베이스가 생성되었습니다. 기본적으로 PostgreSQL에서 새 DB를 만들면 내부에 public 스키마가 하나 존재합니다 (모든 테이블은 기본적으로 이 public 스키마에 만들어집니다).

권한 부여 및 접속 확인
마지막으로, blog_user에게 blog_db에 대한 권한을 부여하겠습니다. 비록 앞서 Owner로 지정하여 기본 권한을 갖지만, 명시적으로 스키마 권한을 설정하면 좋습니다. 또한, DB에 접속(connect)할 권한도 확인해야 합니다.
- 스키마 권한 부여: pgAdmin4에서 새로 생성한 blog_db를 확장하고, 하위의 Schemas > public을 선택합니다. 상단 메뉴에서 Tools > Query Tool을 열고, 아래 SQL 구문을 실행하세요.

Query Tool
-- blog_db 데이터베이스의 public 스키마에 blog_user에게 모든 권한 부여
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO blog_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO blog_user;
GRANT USAGE ON SCHEMA public TO blog_user;
GRANT CREATE ON SCHEMA public TO blog_user;
-- (선택) 향후 생성될 객체들에 대한 기본 권한 부여
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO blog_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO blog_user;
위 명령은 blog_user에게 public 스키마 내의 모든 테이블 및 시퀀스(자동증가 ID 등)에 대한 모든 권한을 주고, 스키마 사용 및 테이블 생성 권한도 부여합니다. 또한, ALTER DEFAULT PRIVILEGES 구문을 통해 향후 생성되는 테이블들에도 자동으로 권한을 주도록 설정합니다. 개발 단계에서는 이렇게 넉넉한 권한을 주어 편하게 작업하고, 운영 환경에서는 필요한 최소 권한만 주는 것을 권장합니다.
- 접속 권한 확인: 이제 방금 만든 blog_user 계정으로 blog_db에 접속이 되는지 확인해 보겠습니다. pgAdmin 좌측 Servers 항목을 다시 우클릭하고 Register > Server...를 선택하여 새 연결을 하나 만듭니다.
- Name: 자유롭게 (예: "Blog DB user connection")
- Connection 탭에서, Host는 localhost, Port는 5432로 동일합니다.
- Maintenance database: blog_db (매우 중요! 접속할 DB 이름을 지정해야 합니다)
- Username: blog_user
- Password: 앞서 설정한 blog_user의 비밀번호
- Save를 눌러 연결합니다.
- 연결 성공 시 이제 blog_user로 해당 DB에 접근할 수 있습니다. 좌측 패널에 새로운 서버로 연결된 blog_db가 표시되고, 그 아래로 테이블 등을 만들어볼 수 있어요. 🎉

blog_user 권한
# pg_hba.conf에 추가 (IPv4/IPv6 로컬 연결 설정):
host blog_db blog_user 127.0.0.1/32 md5
host blog_db blog_user ::1/128 md5
위 내용은 blog_user가 blog_db 데이터베이스에 로컬(localhost)에서 MD5(비밀번호) 방식으로 접속하는 것을 허용하는 설정입니다. 수정 후 PostgreSQL 서버를 재시작해야 반영됩니다.
DB 설정은 여기까지입니다. 이제 애플리케이션 쪽 설정으로 넘어가 볼까요? 🙂
pom.xml 설정 및 의존성 추가
이제 Spring Boot Maven 프로젝트의 설정 파일(pom.xml)을 살펴보겠습니다. pom.xml은 Maven 프로젝트의 의존성(dependencies)과 빌드 설정을 관리하는 핵심 파일이죠. 우리가 만들 블로그 애플리케이션에는 어떤 의존성이 필요할까요?
처음 프로젝트를 만들 때 Spring Initializr를 사용하면 편리하지만, 여기서는 중요한 의존성을 직접 추가하면서 하나씩 알아보겠습니다. 이미 Maven으로 생성된 Spring Boot 프로젝트가 있다고 가정하고, 그 pom.xml을 수정하는 방식으로 진행할게요 (만약 Spring Initializr로 미리 Spring Boot Starter들을 선택해서 생성했다면 대부분 포함되었겠지만, 개념 정리를 위해 수동으로 추가해 봅시다).
pom.xml을 열어서 <dependencies> 섹션에 다음과 같은 필수 라이브러리 의존성들을 추가해 주세요:
- Spring Boot Web 스타터 (spring-boot-starter-web): 내장 톰캣(Tomcat) 서버를 포함하여 웹 애플리케이션 구동에 필요한 의존성 모음입니다. REST API 또는 웹 MVC를 만들 때 기본으로 필요해요.
- Spring Boot Thymeleaf 스타터 (spring-boot-starter-thymeleaf): Spring Boot에서 Thymeleaf 템플릿 엔진을 사용할 수 있게 해주는 의존성입니다. HTML 뷰(View)를 만들어서 데이터를 화면에 보여줄 계획이라면 추가합니다.
- Spring Boot JPA 스타터 (spring-boot-starter-data-jpa): JPA (Java Persistence API)를 통해 관계형 DB와 상호작용하기 위한 의존성입니다. 쉽게 말해, 자바 객체를 DB 테이블에 ORM으로 매핑하고 CRUD 작업을 편하게 할 수 있도록 도와줍니다. 우리의 블로그 글이나 사용자 정보를 DB에 저장하는 데 사용할 거예요.
- PostgreSQL JDBC 드라이버 (org.postgresql:postgresql): 애플리케이션이 PostgreSQL 데이터베이스에 연결할 수 있도록 해주는 드라이버입니다. scope는 runtime으로 설정해서, 컴파일 시에는 필요 없고 실행 시에만 해당 라이브러리가 사용되도록 합니다.
- Spring Boot DevTools (spring-boot-devtools): (선택 사항) 개발 편의를 위한 도구 모음입니다. 이 의존성을 넣어두면 코드를 변경하고 저장할 때 자동으로 애플리케이션이 재시작되므로, 개발 생산성이 올라갑니다. 운영 환경에서는 사용되지 않으므로 runtime에는 포함되지 않습니다.
- Lombok (org.projectlombok:lombok): (선택 사항) 자바에서 반복되는 Getter/Setter, 생성자 코드 등을 줄여주는 편의 라이브러리입니다. Lombok을 사용하면 엔티티 등의 코드를 깔끔하게 작성할 수 있어요. 다만 Lombok은 컴파일 타임에만 필요하고 런타임에는 불필요하므로, 빌드 시에 포함되지 않도록 설정하는 것이 좋습니다. (예: Spring Boot Maven 플러그인 설정에서 Lombok을 exclude 하는 설정)
- 기타: 그 외에 테스트용 라이브러리(spring-boot-starter-test 등)는 기본 포함되어 있을 것이고, 필요에 따라 추가하면 됩니다.
위 의존성들을 추가했다면, pom.xml 파일의 일부는 아마 이렇게 될 것입니다 (예시):
<dependencies>
<!-- 웹 서버 및 MVC 기능 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf 템플릿 엔진 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- PostgreSQL JDBC 드라이버 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope> <!-- 실행시에만 사용 -->
</dependency>
<!-- (선택) 개발 편의성 도구 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope> <!-- 개발시에만 사용, 런타임에 포함되지 않음 -->
</dependency>
<!-- (선택) Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope> <!-- 컴파일 시에만 사용 -->
</dependency>
</dependencies>
각 항목 옆에 주석으로 어떤 역할을 하는지 적어두었습니다. 👍 이렇게 의존성을 나열해두고 나서, Maven을 통해 라이브러리를 다운로드해야 합니다. 명령줄에서 프로젝트 루트 디렉터리로 이동한 후, mvn dependency:resolve 또는 IDE 상에서 Maven 프로젝트 리로드를 해주세요. 예를 들어 VS Code를 쓰신다면, Ctrl + Shift + P로 명령 팔레트를 열고 "Maven: Reload All Maven Projects"를 실행하면 pom.xml에 추가한 라이브러리들을 자동으로 내려받습니다.
팁: Spring Initializr(https://start.spring.io)을 사용하면 위 과정을 수월하게 할 수 있습니다. 웹에서 Spring Boot 버전, Maven 프로젝트, 자바 버전 등을 선택하고, Dependencies에 위에서 언급한 Web, Thymeleaf, JPA, PostgreSQL, Lombok, DevTools 등을 선택한 뒤 프로젝트를 생성하면, 초기 설정이 완료된 상태의 프로젝트(zip 파일)를 받을 수 있답니다. 😊 물론 이 글에서는 과정을 이해하기 위해 수동 설정을 해봤지만요!
이제 프로젝트에 웹, DB 관련 필요한 모든 라이브러리가 준비되었습니다. 다음 단계로 애플리케이션 설정 파일을 구성해 보겠습니다.
application.properties 설정
Spring Boot 프로젝트에서는 src/main/resources 경로 아래에 application.properties (또는 application.yml) 파일이 있습니다. 이 파일에서 애플리케이션의 각종 설정을 할 수 있어요. 데이터베이스 정보도 여기에 설정하게 됩니다.
PostgreSQL 연결 설정과 JPA 관련 설정을 중심으로 application.properties를 채워보겠습니다. (yml 형식을 선호한다면 application.yml에 동일하게 작성하면 됩니다.)
다음은 예시입니다:
spring.application.name=modern-spring-demo # 애플리케이션 이름 (선택)
server.port=8080 # 서버 포트 (기본 8080)
# ===============================
# Database Configuration (PostgreSQL)
# ===============================
spring.datasource.url=jdbc:postgresql://localhost:5432/blog_db
spring.datasource.username=blog_user
spring.datasource.password=your_password # blog_user 생성 시 정한 비밀번호
spring.datasource.driver-class-name=org.postgresql.Driver
# ===============================
# JPA / Hibernate Configuration
# ===============================
spring.jpa.hibernate.ddl-auto=update # DDL 자동 반영 (update 모드)
spring.jpa.show-sql=true # 실행되는 SQL을 콘솔에 출력
spring.jpa.properties.hibernate.format_sql=true # SQL 출력 시 보기 좋게 포맷
# ===============================
# Thymeleaf Configuration
# ===============================
spring.thymeleaf.cache=false # 개발 편의를 위해 Thymeleaf 캐시 비활성화
위 설정에 대해 하나씩 설명해 볼게요:
- spring.datasource.url: 애플리케이션이 연결할 DB 주소입니다. PostgreSQL의 경우 JDBC URL 형식은 jdbc:postgresql://<host>:5432/<DB이름>입니다. 로컬에서 동작 중인 PostgreSQL에 접속하므로 host는 localhost, 포트는 기본 5432, DB 이름은 우리가 만든 blog_db로 설정했습니다.
- spring.datasource.username / password: DB에 접속할 계정 정보를 입력합니다. 방금 생성한 blog_user와 그 비밀번호를 써주면 됩니다. (절대로 postgres 관리자 계정을 여기 넣지 마세요! 😅 별도 계정을 만든 보람이 없으니까요.)
- spring.datasource.driver-class-name: PostgreSQL JDBC 드라이버 클래스 이름입니다. 보통 Maven 의존성을 추가하면 Spring Boot가 자동으로 감지하지만, 명시적으로 작성해 주는 경우도 있습니다. (postgresql의 경우 org.postgresql.Driver가 드라이버 클래스입니다.)
- spring.jpa.hibernate.ddl-auto: JPA에서 DDL(Data Definition Language) 자동 생성 모드를 지정하는 옵션입니다.
- update로 설정하면 애플리케이션 실행 시 엔티티 클래스의 변경사항에 따라 DB 테이블을 업데이트합니다. 개발 환경에서 편리하며, 기존 데이터는 지키려고 노력합니다.
- create-drop은 실행 시 스키마를 새로 만들고 애플리케이션 종료 시 삭제합니다 (테스트 용도).
- create는 실행 시 항상 새로운 스키마를 만들고 기존 데이터는 다 지웁니다.
- none은 자동으로 아무것도 하지 않습니다.
개발 단계에서는 update를 많이 사용하지만, 운영(production) 환경에서는 none으로 두고 대신 DB 마이그레이션 도구(Flyway, Liquibase 등)를 사용하는 게 일반적입니다. 여기서는 편의를 위해 update로 설정했습니다.
- spring.jpa.show-sql: JPA가 생성하는 SQL 쿼리를 콘솔에 출력할지 여부입니다. true로 해두면, 애플리케이션 실행 시 콘솔창에 SQL이 찍혀서 디버깅에 도움이 됩니다.
- spring.jpa.properties.hibernate.format_sql: 콘솔에 출력되는 SQL을 읽기 좋게 포맷팅 할지 여부입니다. true로 두면 줄 바꿈과 들여 쓰기가 적용되어 쿼리를 보기 편해집니다.
- spring.thymeleaf.cache: 개발 중에는 템플릿 캐시를 끄는 것이 좋아요. false로 설정하면 HTML 파일을 수정하고 새로고침했을 때 즉시 변경사항이 반영됩니다. (운영 환경에서는 기본값 true로 두어 성능을 높입니다.)
위 설정들을 적용한 후, 애플리케이션을 실행하면 Spring Boot가 PostgreSQL 데이터베이스에 연결하여 엔티티에 따라 테이블을 생성하고 (ddl-auto=update 덕분에), 로그에 SQL문도 출력하게 됩니다. 이제 비즈니스 로직을 구성할 차례입니다!
Entity, Repository, Controller 구성
이제 본격적으로 Spring Boot 애플리케이션의 핵심 코드인 엔티티, 레포지토리, 컨트롤러를 만들어보겠습니다. 우리의 예제는 블로그 게시글을 다루는 간단한 애플리케이션이므로, Post 엔티티 (게시물) 하나와 그것을 저장할 PostRepository, 그리고 게시물 목록을 화면에 전달하는 PostController를 작성하겠습니다.
먼저 패키지 구조를 정리해 볼게요. 보통 Maven 프로젝트의 기본 패키지 구조는 다음과 같습니다:
src/main/java/com/example/ 프로젝트이름 / ... (자바 코드들)
src/main/resources/templates/ ... (Thymeleaf 템플릿들)
src/main/resources/static/ ... (정적 파일들: CSS, JS 등)
예시로, com.example.modernspringdemo라는 패키지를 사용한다고 하면, 해당 패키지 아래에 Entity, Repository, Controller 클래스를 만들어보겠습니다 (이름은 자유롭게 정하셔도 됩니다).
엔티티(Entity) 클래스 작성 - Post.java
엔티티는 데이터베이스 테이블과 매핑되는 자바 클래스입니다. JPA를 사용하여 엔티티를 정의하면, Spring Boot JPA/Hibernate가 자동으로 테이블을 생성하거나 관리해 줍니다.
Post 엔티티에는 게시글 번호(id), 제목(title), 내용(content), 생성일시(createdAt) 같은 필드가 있다고 해봅시다. JPA 매핑을 위해 @Entity와 @Table 등 어노테이션을 붙이고, 기본키와 컬럼 제약조건도 설정할 수 있습니다. Lombok 라이브러리를 사용하면 Getter/Setter 등을 자동 생성할 수 있어 편리합니다.
// src/main/java/com/example/modernspringdemo/Post.java
package com.example.modernspringdemo;
import java.time.LocalDateTime;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity // 이 클래스를 JPA 엔티티로 지정 (데이터베이스 테이블로 매핑)
@Table(name = "posts") // 매핑할 테이블 이름을 "posts"로 지정
@Getter // Lombok: 모든 필드의 Getter 자동 생성
@Setter // Lombok: 모든 필드의 Setter 자동 생성
@NoArgsConstructor // Lombok: 파라미터 없는 기본 생성자 생성
@AllArgsConstructor // Lombok: 모든 필드를 파라미터로 받는 생성자 생성
public class Post {
@Id // 기본 키 필드
@GeneratedValue(strategy = GenerationType.IDENTITY) // 기본 키를 DB가 자동 생성 (AUTO_INCREMENT)
private Long id; // 게시물 ID
@Column(nullable = false, length = 255) // NOT NULL, 길이 255 제한
private String title; // 게시물 제목
@Lob // Large Object, 긴 텍스트용 컬럼 (CLOB)
@Column(nullable = false)
private String content; // 게시물 내용
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성 시간
// 엔티티가 저장(persist)되기 전에 실행되는 콜백 (생성 시간 자동 설정)
@PrePersist
protected void onCreate() {
this.createdAt = LocalDateTime.now();
}
}
위 코드에서 보듯이, 어노테이션 기반으로 간결하게 매핑을 정의할 수 있습니다. @Entity가 붙은 클래스는 JPA가 관리하며, @Table(name="posts")를 통해 DB의 "posts" 테이블과 연결됩니다. 각 필드에는 @Id (기본 키), @Column(컬럼 세부 설정), @Lob(큰 컨텐츠용), @PrePersist(엔티티 저장 전 동작) 등을 달아주었습니다. Lombok 어노테이션(@Getter 등)을 통해 보일러플레이트 코드를 줄였고요.
참고로, Lombok을 사용하려면 IDE에 Lombok 플러그인이 설치되어 있어야 합니다. Lombok이 번거롭다면 직접 Getter/Setter를 작성해도 무방합니다. 😊
레포지토리(Repository) 인터페이스 생성 - PostRepository.java
다음으로 레포지토리를 만들 차례입니다. 레포지토리는 데이터베이스에 접근하는 메소드를 모아두는 DAO(Data Access Object) 계층이라고 생각하면 돼요. Spring Data JPA를 사용하면, JpaRepository<엔티티, PK타입>를 상속받는 인터페이스만 만들어두면 기본적인 CRUD 메소드를 자동으로 사용할 수 있습니다.
// src/main/java/com/example/modernspringdemo/PostRepository.java
package com.example.modernspringdemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository // 레포지토리로 스프링에 등록 (생략 가능)
public interface PostRepository extends JpaRepository<Post, Long> {
// 커스텀 쿼리 메소드 예시: 제목에 특정 단어를 포함하는 게시물 찾기
List<Post> findByTitleContaining(String keyword);
// 게시물 최신순 정렬하여 모두 가져오기
List<Post> findAllByOrderByCreatedAtDesc();
}
PostRepository는 JpaRepository<Post, Long>를 확장하여, 기본 CRUD (save, findAll, findById, delete 등) 구현을 자동으로 제공합니다. 우리는 추가로 findAllByOrderByCreatedAtDesc() 메소드를 선언했는데요, 이는 Spring Data JPA가 규칙에 따라 구현체를 만들어줄 것입니다. 이 메소드는 createdAt 필드를 기준으로 내림차순(Desc) 정렬된 모든 Post 리스트를 반환하게 됩니다. 나중에 컨트롤러에서 이걸 써먹겠죠! 😉 (findByTitleContaining은 제목에 특정 키워드가 포함된 Post 목록을 찾는 예시로 추가해 보았습니다.)
Note: @Repository 어노테이션은 생략해도 스프링이 JpaRepository 상속 인터페이스를 자동으로 빈으로 등록해주지만, 명시적으로 달아주었습니다.
컨트롤러(Controller) 클래스 작성 - PostController.java
마지막으로 컨트롤러입니다. 컨트롤러는 웹 요청을 받아서 필요한 처리를 한 후 뷰(view)에 데이터를 전달하는 역할을 합니다. Spring MVC의 컨트롤러는 @Controller 어노테이션으로 표시하며, 요청 URL과 메소드를 맵핑하기 위해 @GetMapping, @PostMapping 등을 사용합니다.
우리의 PostController는 메인 페이지 요청 ("/")을 받아서 DB에서 모든 게시물을 가져와 모델에 담고, 홈 화면 템플릿을 리턴하는 간단한 기능을 구현해 보겠습니다.
// src/main/java/com/example/modernspringdemo/PostController.java
package com.example.modernspringdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller // 이 클래스는 MVC 컨트롤러임을 선언
public class PostController {
private final PostRepository postRepository;
// 생성자 주입을 사용하여 PostRepository를 받습니다.
@Autowired
public PostController(PostRepository postRepository) {
this.postRepository = postRepository;
}
@GetMapping("/") // 루트 경로로 GET 요청이 오면 아래 메소드 실행
public String home(Model model) {
// 데이터베이스에서 모든 게시물을 최신순으로 가져오기
List<Post> posts = postRepository.findAllByOrderByCreatedAtDesc();
// 가져온 게시물 리스트를 모델에 추가하여 뷰에 전달
model.addAttribute("posts", posts);
// 'home'이라는 이름의 템플릿 반환 (src/main/resources/templates/home.html)
return "home";
}
}
설명에 적어둔 것처럼, home() 메소드는 루트 URL 요청이 들어왔을 때 실행됩니다. 여기서 postRepository.findAllByOrderByCreatedAtDesc()를 호출하여 모든 게시글 목록을 가져오고, Model 객체에 "posts"라는 이름으로 리스트를 담았습니다. 최종적으로 "home"이라는 뷰 이름을 반환하는데, 이는 home.html 템플릿을 가리킵니다. Spring Boot는 기본적으로 templates/ 폴더에서 뷰이름.html 파일을 찾아 렌더링 해줍니다.
템플릿(View): 여기서는 Thymeleaf를 사용하기로 했으니, src/main/resources/templates/home.html 파일을 만들어야 합니다. 이 HTML 파일 안에서 ${posts} 변수를 이용해 게시물 리스트를 출력할 수 있어요. 예를 들어, <th:block th:each="post : ${posts}"> ... </th:block> 구조로 루프를 돌며 제목과 내용을 보여줄 수 있습니다. (Thymeleaf에 대한 상세한 내용은 여기서 다루지 않지만, 기본 사용법은 어렵지 않으니 공식 문서를 참고해 주세요. 😀)
이렇게 엔티티, 레포지토리, 컨트롤러 구성이 완료되었습니다. 결국 사용자의 요청이 들어오면 컨트롤러가 그것을 받아서, 레포지토리를 통해 DB에서 데이터(엔티티 리스트)를 조회하고, 모델에 담아 뷰에 전달하는 흐름이 만들어졌습니다. 이제 남은 건 이 애플리케이션을 빌드하고 실행(배포)하는 일이겠네요!
Maven 빌드와 실행, 배포까지
드디어 우리의 Spring Boot 애플리케이션을 Maven으로 빌드하고 실행해 볼 차례입니다. 😀 지금까지 설정한 것들이 제대로 동작하는지 확인하려면 프로젝트를 패키징(package)하고 애플리케이션을 띄워봐야겠죠.
Maven으로 프로젝트 빌드하기
Maven 빌드는 보통 프로젝트를 컴파일하고, 테스트를 수행하고, 패키징 하는 과정을 거칩니다. 우리는 간단히 패키징(jar 파일 생성)까지 해보겠습니다.
터미널(명령 프롬프트)을 열고, 프로젝트 최상위 디렉터리(pom.xml이 있는 위치)에서 다음 명령을 실행하세요:
mvn clean install
위 명령은 현재 프로젝트의 의존성 라이브러리들을 모두 다운로드하고 (이미 Reload 등을 통해 다운로드했다면 캐시에서 사용할 겁니다), 기존 빌드 산출물(target 폴더)을 깨끗이(clean) 지운 후, 프로젝트를 컴파일 및 테스트하고, 최종적으로 패키징까지 수행합니다. install 목표는 결과물을 로컬 Maven 저장소에 설치까지 하는 것이지만, 여기서는 빌드의 일부 단계라고만 이해하셔도 무방합니다.
빌드가 성공하면, target/ 폴더 아래에 .jar 파일이 생성됩니다. 예를 들어 프로젝트 이름이 modern-spring-demo이고 버전이 0.0.1-SNAPSHOT이라면 modern-spring-demo-0.0.1-SNAPSHOT.jar 가 생길 거예요.
만약 빌드 과정에서 테스트 코드가 실패하거나, 혹은 테스트가 없는데 굳이 실행하고 싶지 않다면 mvn clean package (테스트를 포함) 또는 mvn clean package -DskipTests (테스트 생략) 등을 사용할 수도 있습니다.
애플리케이션 실행하기 (로컬 배포)
이제 빌드된 Spring Boot 애플리케이션을 실행(deploy) 해보겠습니다. 실행 방법은 두 가지가 일반적으로 사용됩니다:
- Maven을 통한 실행:
Maven Spring Boot 플러그인이 제공하는 명령을 사용할 수 있습니다. 프로젝트 경로에서 다음을 실행해 보세요
mvn spring-boot:run
이 명령은 빌드 없이 바로 애플리케이션을 실행해 줍니다 (내부적으로는 compile 후 java -cp... org.springframework.boot.loader.JarLauncher 비슷하게 동작). 개발 중에 간편하게 쓸 수 있는 방법입니다.
- JAR 파일 직접 실행:
빌드 결과 생성된 jar 파일을 Java로 직접 실행할 수도 있습니다.
java -jar target/modern-spring-demo-0.0.1-SNAPSHOT.jar
위처럼 java -jar 명령으로 실행하면, 스프링 부트 내장 톰캣이 올라가면서 애플리케이션이 구동됩니다. 이 방법은 빌드한 산출물을 별도의 서버에 배포할 때 주로 사용됩니다. 예를 들어, 운영 서버에 이 jar 파일만 복사해서 Java가 설치된 환경에서 실행하면 바로 웹 서비스가 동작하죠.
두 방법 중 편한 것으로 실행하세요. 실행하면 콘솔에 Spring Boot 로고와 함께 이런 메시지들이 보일 거예요:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.x.x)
... (중략) ...
Tomcat started on port(s): 8080 (http) with context path ''
Started ModernSpringDemoApplication in 4.5 seconds (JVM running for 5.0)
이와 함께 우리가 설정한 내용에 따라 DDL 생성 SQL과 애플리케이션 로그 등이 출력될 수 있습니다. 특별한 오류가 없다면 "Started ... in X seconds" 라는 문구까지 확인하면 성공입니다! 🎉
브라우저를 열어 http://localhost:8080/에 접속해보세요. 우리가 만든 PostController의 "/" 매핑이 동작하면서, 현재 DB에 저장된 (만약 있다면) 게시물 목록을 보여주는 home.html 템플릿이 렌더링될 것입니다. 아무것도 등록한 적 없다면 아마 빈 화면이 나오겠지만요. 😉 어쨌든 전체 Spring Boot + Maven + PostgreSQL 스택이 정상적으로 구동된 것입니다.

(참고) 배포하기
여기까지 따라오느라 정말 고생하셨습니다. 🙏 이제 애플리케이션을 원하는 곳에 배포(deploy)할 일만 남았는데요. 사실 위에서 jar 파일 실행 방법이 곧 배포와 같습니다. Spring Boot 애플리케이션은 빌드한 jar 파일 하나만으로 실행 가능한 독립 실행형 애플리케이션이기 때문에, 해당 파일을 가지고 원하는 서버에 올려서 java -jar로 실행하면 그게 배포입니다.
예를 들어, 클라우드 서비스(AWS EC2 등)나 사내 서버에 이 파일을 복사한 뒤 백그라운드 실행하면 서비스가 계속 동작하겠죠. Docker를 활용한다면 기본 JDK 이미지 위에 jar를 올려서 컨테이너 화하고 배포할 수도 있고요. 배포 방식은 여러 가지가 있지만, 이 글의 범위를 넘어가므로 여기서는 자세히 다루지 않겠습니다. 😅
중요한 건 Maven으로 빌드하여 산출물을 만들고, 그것을 실행 가능한 형태로 가져다 놓는 일까지 여러분이 해냈다는 것입니다! 이제 여러분만의 멋진 Java Spring Boot 블로그 애플리케이션을 완성해 보세요. 😊
마무리 및 다음 단계 (Summary & CTA)
지금까지 Java Spring Boot와 Maven을 활용하여 PostgreSQL DB 설정부터 빌드 및 배포 과정까지 쭉 따라와 보았습니다. 처음엔 복잡해 보였던 과정이지만, 하나씩 순서를 밟아가니 생각보다 할 만했죠? 😎
우리는 데이터베이스 환경 구성으로 시작해서, Maven 프로젝트의 pom.xml 의존성 추가, 애플리케이션의 설정 파일 작성, 간단한 Entity/Repository/Controller 코드 구현, 그리고 Maven 빌드 및 실행을 통해 애플리케이션을 구동해 보았습니다. 이러한 흐름은 앞으로 Spring Boot 프로젝트를 진행할 때 기본적인 뼈대가 될 거예요. 처음 한 번 어려울 뿐, 이제 반복해서 프로젝트를 만들다 보면 점점 익숙해질 것입니다.
이 글이 여러분의 개발 여정에 작은 밑거름이 되었길 바랍니다. 🙏 이제 직접 여러분만의 프로젝트에도 도전해 보세요! 필요한 부분은 복사/붙여 넣기 하셔도 좋고, 새로운 기능들을 추가하면서 조금씩 성장해 나가시길 응원합니다.
혹시 궁금한 점이나 문제가 생기면 아래 FAQ를 참고해 보세요. 그리고 댓글로 남겨주시면 함께 고민해 보고 해결해 드릴게요. 😄 즐거운 개발되세요! Happy Coding! 🎉
함께 읽어주셔서 감사합니다. 이 글이 유용했다면 주위에 공유해 주시고, 앞으로도 유익한 Spring Boot & Maven 튜토리얼을 많이 올릴 예정이니 많은 관심 부탁드려요! ✨
다음글
2025.07.25 - [IT 트렌드/알아두면 좋은 IT 상식] - VSCode Spring 게시판 만들기: 드디어 새 게시물 페이지 구현
VSCode Spring 게시판 만들기: 드디어 새 게시물 페이지 구현
목차 지난 포스트에서는 VSCode로 Spring 게시판 만들기 프로젝트를 세팅하면서 PostgreSQL 데이터베이스까지 연동해 보았습니다. 빈 게시판이라 리스트 페이지는 만들어졌지만 아직 게시물이 하나도
kberry.tistory.com
2025.07.29 - [IT 트렌드/알아두면 좋은 IT 상식] - Git 없이 S3로 구축하는 AWS DevOps 배포 파이프라인
Git 없이 S3로 구축하는 AWS DevOps 배포 파이프라인
목차전체 아키텍처 개요Git 저장소를 사용하지 않고도 AWS 서비스만으로 CI/CD 파이프라인을 구성할 수 있습니다. 이번 구성에서는 Amazon S3 버킷을 코드 패키지 저장소로 사용하고, AWS CodeDeploy를 통
kberry.tistory.com
2025.07.31 - [IT 트렌드/알아두면 좋은 IT 상식] - AWS CodePipeline에서 GitHub 연동 – 실무 후기 및 CI/CD 구축 가이드
AWS CodePipeline에서 GitHub 연동 – 실무 후기 및 CI/CD 구축 가이드
목차GitHub에 있는 코드를 AWS CodePipeline으로 빌드하고 배포하는 CI/CD 파이프라인을 구축해보았습니다. 이번 포스트에서는 “AWS CodePipeline에서 GitHub 연동”하는 방법을 실무 관점에서 공유하고, 자
kberry.tistory.com
AWS Elastic Beanstalk를 활용한 Spring Boot 자동 배포: CodePipeline 연동 가이드
목차 AWS Elastic Beanstalk, Spring Boot 자동 배포, CodePipeline 연동 – 이 세 가지 키워드로 대표되는 이번 가이드에서는 Spring Boot 애플리케이션을 AWS 클라우드에 자동 배포하는 방법을 단계별로 알아봅
kberry.tistory.com
FAQ (자주 묻는 질문)
Q1. Maven으로 빌드할 때 자주 발생하는 오류는 어떻게 해결하나요?
A: 초보자분들이 Maven 빌드시 겪는 흔한 오류로는 mvn 명령어를 인식 못하는 문제가 있습니다. 이것은 시스템에 Maven이 설치되어 있지 않아서 생기는 경우가 많아요. 이럴 땐 Maven 공식 사이트에서 Maven을 설치하고 환경변수를 설정해주면 됩니다. 대안으로, Spring Initializr로 생성한 프로젝트에는 Maven Wrapper(mvnw 파일)가 포함되어 있으니, ./mvnw clean install 처럼 mvnw를 대신 사용하면 로컬에 Maven이 없어도 빌드할 수 있어요.
또 다른 오류로는 의존성 다운로드 실패나 빌드 실패가 있는데, 인터넷 연결을 확인하고 pom.xml에 타이포가 없는지 확인해보세요. 방화벽이나 프록시 환경에서는 Maven이 리포지토리에 접속 못하는 경우도 있으니 회사 네트워크에서는 설정이 필요할 수 있습니다. 만약 테스트 실패로 빌드가 멈춘다면 -DskipTests 옵션으로 일단 테스트를 건너뛰고 빌드할 수도 있습니다. 문제 발생 시 오류 로그를 잘 읽어보고, 해당 오류 메시지를 구글링하면 대부분 해결책을 찾을 수 있습니다! 😉
Q2. PostgreSQL에 blog_user로 접속이 안 될 때는 어떻게 해야 하나요?
A: 애플리케이션을 실행했는데 DB 연결 오류가 나는 경우, 우선 우리가 설정한 DB 접속 정보가 정확한지 확인하세요 (application.properties에서 URL, username, password 부분). 타이포가 없어야 합니다. 그래도 문제가 있다면 권한 설정 문제일 수 있습니다. blog_user에게 blog_db에 대한 CONNECT 권한이 부여됐는지 다시 확인해보세요. 기본적으로 DB를 생성할 때 Owner로 지정했으면 CONNECT 권한이 따라가지만, 확실하지 않을 때는 GRANT CONNECT ON DATABASE blog_db TO blog_user; 명령을 추가로 실행해주면 좋습니다. 그리고 public 스키마에 대한 USAGE 권한도 필요하면 GRANT USAGE ON SCHEMA public TO blog_user;로 주는 걸 확인합니다.
또, pg_hba.conf 설정도 체크해보세요. 로컬에서 blog_user로 접속하려면 pg_hba에 해당 사용자에 대한 규칙이 있어야 합니다 (앞서 글에서 다룬 127.0.0.1/32 md5 규칙 등). 이 부분이 누락되면 인증 실패가 발생할 수 있어요. 마지막으로, pgAdmin으로 blog_user로 접속 시도를 해보는 것도 좋습니다. pgAdmin에서 연결이 안 된다면 애플리케이션에서도 안 될 것이므로, 그 때 나오는 오류 메시지로 원인을 파악할 수 있습니다. 일반적으로는 권한 쿼리나 pg_hba 설정으로 해결되는 경우가 많으니 차근차근 살펴보세요. 필요하다면 postgres 관리자 계정으로 접속해 ALTER ROLE blog_user WITH LOGIN; 처럼 로그인 권한을 부여하는 것도 체크하세요 (pgAdmin으로 만들 때는 이미 로그인 롤이지만, 직접 SQL로 만들었다면 놓쳤을 수 있습니다).
Q3. 추가로 MySQL 같은 다른 DB를 사용하고 싶다면 변경해야 할 부분은?
A: 우리 예제에선 PostgreSQL을 사용했지만, MySQL이나 다른 RDBMS를 쓰고 싶다면 설정을 조금만 바꾸면 됩니다. 우선 pom.xml의 PostgreSQL 드라이버 의존성을 MySQL 드라이버로 교체하고 (groupId: mysql, artifactId: mysql-connector-java), application.properties의 접속 URL, username, driver 클래스를 MySQL 형식으로 바꿔주면 돼요. 예를 들어 URL은 jdbc:mysql://<host>:3306/<DB이름> 형태고, driver-class-name은 com.mysql.cj.jdbc.Driver입니다. JPA를 쓰는 방식은 동일하므로 엔티티/레포지토리 코드는 건드릴 필요 없습니다. 다만 MySQL의 경우 GenerationType.IDENTITY 전략 사용 시 약간의 Dialect 이슈 등이 있는데, Spring Boot가 자동으로 적절한 Dialect를 선택해주므로 큰 문제는 없을 겁니다. 권한 설정 부분은 MySQL은 다른 방식이니, DB 사용자 생성과 권한 부여는 MySQL에 맞게 해주셔야 합니다 (예: CREATE USER 'blog_user'@'%' IDENTIFIED BY '...' 그리고 GRANT ALL ON blog_db.* TO 'blog_user'@'%'; 등).
Q4. 개발 단계에서 H2 같은 메모리 DB를 써도 되나요?
A: 물론입니다! 간단히 테스트해보고 싶다면 H2 Database 같은 인메모리 DB를 사용하면 설치나 사용자 생성 과정 없이 편하게 쓸 수 있어요. H2를 쓰는 경우 pom.xml에 com.h2database:h2 의존성을 추가하고, application.properties에서 spring.datasource.url=jdbc:h2:mem:testdb (혹은 파일 경로) 등으로 설정을 바꾸면 됩니다. 다만 H2는 가벼운 테스트용이므로, 실제 프로덕션 환경이나 복잡한 쿼리에는 PostgreSQL/MySQL 같은 상용 DB를 쓰시는 게 좋아요. 우리 글의 핵심인 Maven 빌드/배포 흐름에는 변화가 없으니, DB만 바꿔서 실습해보는 것도 추천합니다!
궁금증이 조금 풀리셨나요? 이 외에도 Maven이나 Spring Boot 관련 질문이 있으면 언제든지 댓글로 남겨주세요. 함께 고민하면서 성장해봐요! 🙌
'IT 트렌드 > 알아두면 좋은 IT 상식' 카테고리의 다른 글
| 개발자의 Git 브랜치 전략 일기 (0) | 2025.10.17 |
|---|---|
| Tomcat server.xml 설정 완벽 가이드: 운영/DevOps 실무 베스트 프랙티스 (5) | 2025.08.26 |
| VS Code 우클릭 메뉴 없어서 당황했다면? 레지스트리 수정으로 5분 만에 해결! (4) | 2025.08.01 |
| VSCode Spring 게시판 만들기: 드디어 새 게시물 페이지 구현 (5) | 2025.07.25 |
| VSCode Java Spring 프로젝트: Maven 스프링 부트 예제 설정부터 디버깅까지 (4) | 2025.07.17 |