풀스택 개발자 과정 29일차

너구·2026년 6월 17일

풀스택 성장과정

목록 보기
29/79

View (뷰)

웹이나 모바일 애플리케이션에서 사용자에게 보여지는 화면을 의미한다.
사용자 인터페이스(UI(라고도 부른다.

SSR (Server-Side Rendering)

전통적인 웹 애플리케이션 방식으로 서버가 화면(HTML)을 완성해서 클라이언트에게 내려주는 구조이다.

서버 프레임워크별 템플릿 엔진

  • Spring Boot : Thymeleaf, JSP
  • Django : Template
  • Express : EJS, Pug
  • Next.js : JSX

SSR 작동 방식

  1. 클라이언트가 특정 페이지를 요청합니다
  2. 서버가 DB에서 데이터를 조회합니다.
  3. 서버의 뷰 엔진(템플릿 엔진)을 통해 생성한 HTML 파일을 클라이언트에게 전송합니다
  4. 브라우저는 서버로부터 받은 완성된 HTML을 화면에 렌더링합니다.
  • 장점
    브라우저가 자바스크립트를 실행할 필요 없이 화면을 바로 그릴 수 있어 초기 로딩 속도가 빠르다.
    검색엔진 봇이 완성된 HTML에 접근할 수 있어 SEO(검색엔진 최적화)에 유리하다.

  • 단점
    서버가 매번 새로운 HTML을 생성해야 하므로 서버 컴퓨팅 자원을 많이 소모한다.
    페이지 이동 시 화면 전체가 새로고침되어 사용자 경험(UX)이 다소 부자연스럴울 수 있다.


CSR (Client-Side Rendering)

현대적인 SPA(Single Page Application)의 핵심 기술로 브라우저(클라이언트)가 자바스크립트로 직접 화면을 렌더링하는 구조이다.

CSR 기반의 프론트엔드 프레임워크

  • React
  • Vue.js
  • Angular
  • Svelte

CSR 작동 과정

  1. 클라이언트가 페이지를 요청합니다.
  2. 서버는 텅 빈 HTML( < div id="root" > < /div > )과 애플리케이션 구동에 필요한 대용량 자바스크립트(JS) 파일을 내려줍니다.
  3. JS가 실행되면서 API 통신을 통해 서버에서 데이터(JSON)를 가져온 뒤, 브라우저가 화면을 동적으로 조립합니다.

SSG (Static Site Generation)

빌드 시점에 모든 페이지의 HTML을 미리 만들어놓고 사용하는 방식이다.

SSG 주요 기술들

  • Next.js
  • Gatsby
  • Jekyll

SSG 작동 과정

  1. 개발자가 코드를 빌드(Build)하는 시점에 DB 데이터 등을 미리 가져온 다음 가능한 모든 페이지의 static HTML 파일을 컴퓨터에 미리 생성해 둡니다.
  2. 사용자가 요청하면 이미 만들어져 있는 정적 HTML 파일을 CDN 등을 통해 즉시 내보냅니다.
  • 장점
    압도적인 속도와 안정성. 서버 연산이 아예 없기 때문에 트래픽이 아무리 몰려도 서버가 터지지 않는다.

  • 단점
    실시간 데이터 변경이 불가능하다.
    데이터가 바뀌면 전체 사이트를 다시 빌드하고 배포해야 한다. (블로그, 소개 페이지, 약관 등에 적합)


API

API(Application Programming Interface)은 서로 다른 애플리케이션이 서로 데이터를 주고받고 상호작용할 수 있도록 연결해주는 규약(인터페이스)이다.

모던 API 구현 방식

  • REST API
  • gRPC
  • GraphQL

REST API (Representational State Transfer)

현재 웹 생태계에서 가장 널리 쓰이는 자원(Resource)지향적 아키텍처 스타일이다.
(표현된 상태(Representational State)는 JSON 데이터를 의미한다)

  1. 요청 자원 (Resource) 표현
    URI (주소)를 활용한다
    예) /posts, /member/join

  2. 행위 (Verb) 표현
    GET, POST, PUT, DELETE 등 HTTP 메서드를 활용한다.


gRPC (Remote Procedure Call)

구글에서 개발한 고성능, 오픈소스 원격 프로시저 호출(RPC) 프레임워크이다.
주로 시스템 내부 통신이나 MSA 환경에서 많이 사용된다.

주요 특징

  1. 데이터를 텍스트(JSON)가 아닌 구조화된 이진 데이터(Binary)로 압축하여 전송하므로 크기가 매우 작고 피싱 속도가 압도적으로 빠르다.

  2. HTTP/2 기반: 양방향 스트리밍, 멀티플렉싱 등을 지원해 대용량 데이터 전송과 실시간 통신에 최적화되어있다.


GraphQL

페이스북(Meta)에서 REST API의 단점(Over/Underfetching)을 해결하기 위해 개발한 쿼리 언어 기반의 API이다.
단 하나의 엔드포인트만을 사용한다.


API 통신

  1. . 동기 통신 (Synchronous Communication)
    클라이언트가 요청을 보내면, 서버가 응답을 줄 때까지 클라이언트는 대기하는 방식이다.
    가장 일반적인 구조입니다.
    예시) RESTful 웹 서비스, 사용자 인증, 실시간 조회가 필요한 UI 데이터 요청.

  2. 비동기 통신 (Asynchronous Communication)
    요청 후 응답을 기다리지 않고 다음 작업을 수행하는 방식입니다.
    성능 최적화와 시스템 간 결합도 완화(Decoupling)를 위해 필수적입니다.
    예시) 대용량 파일 업로드 처리, 외부 연동(결제), 이벤트 알림, 배치 작업.


API 데이터

API 통신에서 주고받는 데이터를 의미한다.
크게 다음의 두가지로 형식(Format)으로 구분된다.

  • XML
  • JSON

XML (eXtensible Markup Language)

HTML과 유사하게 태그(< >) 기반으로 데이터를 표현한다.
전자정부프레임워크의 레거시 시스템이나 오래된 공공데이터 API에서 여전히 자주 마주치게 된다.

<user>
    <id>101</id>
    <name>홍길동</name>
</user>

JSON (JavaScript Object Notation)

자바 스크립트의 객체 표기 방식을 활용하는 포맷이다.
현재 웹, 모바일, MSA 환경에서 가장 널리 쓰이는 표준(De fato standard)데이터 형식이다.

{
  "id":101,
  "name": "홍길동",
  "skill":["Java", "Python"]
}

스프링부트

복잡한 설정 없이도 독립 실행형 프로덕션급 Java 애플리케이션을 빠르고 쉽게 구축할 수 있도록 돕는 Spring 프레임워크의 서브 프로젝트이다.
자동구성(Auto-configuration)과 내장서버(Embedded Server)를 제공하여 개발자가 인프라 설정이 아닌 비즈니스 로직에 집중하도록 지원한다.

특징

  • 자동구성(Auto-Configuration): 애플리케이션에 필요한 라이브러리를 기반으로 Spring 및 타사 라이브러리 설정을 자동으로 구성한다.

  • 내장서버: Tomcat, Jetty 또는 Undertow 같은 WAS(웹 애플리케이션 서버)를 내장하고 있어 별도의 서버 설정이나 WAR 파일 배포없이 .jar 파일로 즉시 애플리케이션을 실행할 수 있다.

  • 스타터(Starter) 의존성: 의존성 관리를 단순화하기 위해 미리 정의된 라이브러리 조합(예: spring-boot-starter-web)을 제공한다.

스프링부트 아키텍처

유지보수와 확장성을 위해 역할에 따라 계층을 명확히 분리하는 계층형 아키텍처를 표준으로 사용한다.
각 계층은 오직 인접한 아래 계층과만 소통하며 하나의 거대한 시스템을 독립적인 모듈로 쪼개는 역할을 한다.

표현 계층 (Presentation Layer)- Controller

역할: 사용자의 요청(HTTP Request)를 가장 먼저 맞이하고 최종 응답(HTTP Response)을 반환하는 문지기이다.

주요 임무

  • URL 매핑
  • 요청 파라미터 데이터 검증(Validation)
  • 비즈니스 로직(Service) 호출
  • 적절한 데이터 포맷(JSON/HTML) 응답.

비즈니스 계층 (Business Logic Layer)- Service

애플리케이션의 핵심 도메인 로직과 비즈니스 규칙이 수행되는 '프로그램의 핵심부'이다.

주요 임무

  • 트랜잭션 단위 처리(@Transactional)
  • 여러 리포지토리를 조합한 복잡한 데이터 가공 및 도메인 로직 제어

데이터 접근 계층 (Data Access Layer)- Repository

영속성 계층(Persistence Layer)이라고도 하며 실제 데이터베이스에 접근하여 데이터를 읽고 쓰는 역할을 한다.

주요 임무

  • JPA 등을 이용한 CRUD 쿼리 실행
  • DB 데이터 객체 매핑.

스프링 프로젝트 구조


주요 파일/폴더


스프링 빈(Spring Bean)

개발자가 직접 생성하지 않고 스프링 IoC 컨테이너에 의해 생성되고 관리되며 의존성이 주입되는 객체를 말한다.


IoC 컨테이너

제어의 역전(Inversion of Control)이란 객체의 생성부터 생명주기 관리, 의존성 조립 등의 제어권이 개발자에게서 프레임워크로 넘어가는 현상을 말한다.
스프링 부트에서 개발자가 직접 객체를 생성하고 관리하는 것이 아니라 스프링 컨테이너가 대신 객체의 생명주기를 관리한다.
즉 스프링 빈은 이 IoC 개념이 적용된 결과물이다.

IoC 구현체 = 스프링 컨테이너


DI (Dependency Injection)

컨트롤러, 서비스, DAO 등 스프링 빈(Bean)에서 의존이 필요한 객체를 정의하면 스프링이 자동으로 주입해주는 특징을 말한다.
이를 통해 개발자는 직접 객체를 생성하고 주입할 필요가 없다.

@Service
class MyService {
  Repository repository → 스프링이 자동으로 주입해줍니다
}

스프링 빈을 등록하는 방법

  1. 컴포넌트 스캔과 자동 빈 등록
  2. 설정 클래스 활용방식

컴포넌트 스캔 방식

클래스 위에 특정 어노테이션을 붙이면 서버가 시작될 때 패키지 내부를 훑어서(Scan) 빈으로 등록하는 방식이다.


설정 클래스 활용 방식

설정 파일에서 @Bean을 붙여 빈을 반환할 메서드를 정의한다.
다음은 사용 방식이다.

@Configuration // 설정 파일로 등록합니다
public class AppConfig {

  @Bean // 이 메서드가 반환하는 객체를 스프링 빈으로 등록합니다
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(); 
  }
}

Spring Security

Spring 애플리케이션의 인증(Authentication) 및 인가(Authorization), 일반적인 공격에 대한 보호 기능을 제공하는 인증 및 접근 제어 프레임워크이다.
애플리케이션 비즈니스 로직과 보안 로직을 분리하여 개발자가 보안 취약점에 신경쓰지 않고 핵심 서비스 개발에 집중할 수 있도록 돕는다.


인증/인가

  1. 인증 (Authentication)
    "당신은 누구인가?"에 대한 해답을 찾는 과정이다.
    시스템을 사용하는 주체(User, Principal)가 누군지 신원을 확인한다.

  2. 인가 (Authorization)
    "당신은 이 자원에 접근할 권한이 있는가?"를 검증하는 과정이다.
    인증을 마친 사용자가 시스템 내부의 특정 리소스(API, 페이지 등)에 접근할 수 있는 권한(Rule, Authority)이 있는지 확인한다.

ex) 일반 사용자 (USER)는 마이페이지만 접근할 수 있고 관리자(ADMIN)는 전체 회원 목록을 볼 수 있음


구조 및 동작 원리 (Archiecture)

Spring Security는 클라이언트의 요청을 가장 먼저 처리한다.


시큐리티 작동 7단계 (From 로그인 기준)

  1. 클라이언트가 ID/PW 제출 (POST /login)
    [DelegatingFilterProxy] (톰캣 영역에서 요청을 낚아채서 스프링 시큐리티에게 토스)

  2. UsernamePasswordAuthenticationFilter] (로그인 요청을 전담 마크하는 필터)
    아이디, 패스워드를 묶어서 '미인증 인증 객체(Authentication)'를 만듦

  3. AuthenticationManager (인증을 총괄하는 컨트롤 타워)
    "이거 누가 검사할래?" 하고 적절한 검사관을 찾음

  4. AuthenticationProvider (실제 인증 유효성을 검사하는 검사관)
    "DB에서 이 아이디 찾아와봐" 하고 서비스에게 요청

  5. CustomUserDetailsService
    loadUserByUsername() 호출 -> DB에서 회원 조회

  6. UserDetails (Member) (DB에서 꺼내온 회원 정보와 비밀번호)
    Provider가 이 정보와 사용자가 입력한 비밀번호(BCrypt 암호화)를 비교·검증

  7. SecurityContextHolder (인증 완료 보관함)
    검증 성공 시 '인증 완료 도장'을 찍어 세션 안의 비밀 금고에 보관
    [컨트롤러] -> 로그인 성공! 메인 페이지로 이동


대표적인 보안 필터들

  • UsernamePasswordAuthenticationFilter: 폼 로그인을 처리하는 필터로, 인증 요청(ID/PW)을 가로채 인증을 시도한다.

  • CsrfFilter: CSRF(사이트 간 요청 위조) 공격을 방어하기 위해 토큰을 검증하는 필터이다.

  • ExceptionTranslationFilter: 보호된 자원에 접근할 때 발생하는 인증/인가 예외(AuthenticationException, AccessDeniedException 등)를 잡아서 로그인 페이지로 이동시키거나 에러 응답을 반환한다.

  • AuthorizationFilter (기존 FilterSecurityInterceptor): 요청이 필터 체인의 마지막까지 도달했을 때, 최종적으로 접근 권한(인가)이 있는지 판단한다.


비밀번호 암호화 메커니즘 (Password Storage)

Spring Security는 보안 취약점 예방을 위해 데이터베이스에 비밀번호를 평문(Plain Text)으로 저장하는 것을 엄격히 금지한다.
비밀번호 암호화에 단방향 해시 알고리즘은 BCrtpt를 기본으로 채택한다.
암호화된 문자열은 다시 원래 비밀번호로 복호화가 불가능하며 검증 시에는 입력받은 비밀번호를 동일한 알고리즘으로 암호화하여 매칭 여부만 확인한다.
또한 동일한 비밀번호를 입력하더라도 매번다른 암호화 결과값을 생성하며 미리 계산된 암호 테이블(Rainbow Table)을 통한 해킹 공격을 원천 차단한다.

해시값 예시: 2a$10BpLgMNU1T5mqkuo4VW1uTOromcyh3ACVlV5qiRP4


아키텍처 확장 방향 (세션 VS 토큰)

  1. 전통적인 웹 애플리케이션 (Session 방식)
    서버가 사용자의 인증 정보 상태를 메모리(Session)에 유지하는 방식이다.
    스프링 시큐리티의 기본 폼 로그인(Form Login)이 이 방식을 따른다.

  2. 최신 프론트엔드 및 분산 환경 (JWT / Token 방식)
    REST API 기반의 SPA(React, Vue 등)나 MSA(마이크로서비스 아키텍처) 환경에서는 서버가 상태를 저장하지 않는(Stateless) JWT(JSON Web Token) 방식을 선호한다.


데이터 접근 기술

스프링 프레임워크가 지원하는 데이터베이스 연동 기술은 개발 생산성과 객체 지향성을 높이는 방향으로 발전해왔다.

  • 1세대 JDBC
  • 2세대 SQL Mapper
  • 3세대 ORM (현재 표준)


ORM (Object-Relational Mapping)

객체와 관계형 데이터베이스의 테이블을 매핑(연결)해주는 기술이다.
자바는 '객체지향' 패러다임을 따르고 데이터베이스는 '관계형' 패러다임을 따르기 때문에 발생하는 '패러다임의 불일치'문제를 해결하기위해 등장했다.
ORM을 사용하면 개발자는 자바 객체(Enity)를 다루듯 DB의 데이터를 다룰 수 있다.

JPA (Java Persistence API)

자바 진영의 ORM 명세(Interface)이다.
JPA는 인터페이스이며 이를 실제로 구현한 가장 대표적인 프레임워크가 바로 Hibernate(하이버네이트)이다.


뷰 (View)

스프링 프레임워크 웹 개발 역사에서 뷰(View) 구현 방식의 변화는 단순히 화면을 그리는 기술의 변경이 아니라 벡엔드/프론트엔드의 역할 분리와 아키텍처의 진화 과정 그 자체이다.

스프링 뷰 개발 방식의 변화

1세대 JSP와 스크립틀릿(Scriptlet)
2세대 jSP와 JSTL/EL
3세대 Thymeleaf
4세대 CSR

1세대. JSP & 스크립틀릿 (2000년대 초~중반)

초기 웹 개발은 JSP 파일 하나가 데이터베이스 연동, 비즈니스 로직, 화면 표시 등을 모두 처리하는 Model 1 아키텍처였다.
이후 스프링 MVC가 도입되면서 서블릿(Controller)과 JSP(View)의 역할이 분리된 Model 2로 발전했다.

HTML 코드 사이에 자바 for, if문이 뒤섞이면서 코드가 극도로 복잡해졌다.
화면만 수정하려 해도 자바 로직을 건드려야 했고, 디자이너와의 협업이 불가능에 가까웠다.

구현 방식

JSP 내부에서 자바 코드를 직접 사용하는 스크립틀릿(Scriptlet, <% %>) 구문을 활용해 화면을 동적으로 제어했다.

2세대. EL & JSTL (2000년대 후반 ~2010년대 초반)

JSP로부터 자바 코드를 완전히 퇴출하고, 태그 기반의 뷰를 완성한 시대이다.
스프링 MVC 아키텍처가 시장의 표준으로 자리 잡으면서 Controller가 데이터를 처리하고 JSP로 넘겨주는 구조가 정착되었다.

구현 방식

자바 코드를 대신해 HTML 태그 형태의 JSTL(JSP Standard Tag Library)로 제어 흐름을 관리했다.
데이터를 화면에 출력할 때는 가볍고 안전한 표현식인 EL(Expression Language)을 활용했다.

3세대. 타임리프(Thymeleaf) - 2010년대 중반

Spring Boot가 등장하면서 무거운 XML 설정과 복잡한 서블릿/JSP 의존성 대신, 가볍고 독립적으로 실행 가능한 임베디드 톰캣 환경이 주류가 되었다.

서버 가독성과 협업 효율은 극대화되었으나, 페이지를 이동할 때마다 서버가 매번 전체 HTML을 다시 그려서 보내야 하는 SSR(Server-Side Rendering)의 근본적인 비용(서버 부하, 화면 깜빡임)은 여전히 존재했다.

구현 방식

타임리프(Thymeleaf)는 HTML 태그의 속성(th:text, th:each 등)을 그대로 이용해 서버 데이터를 관리한다.

4세대. REST API/CSR (2010년대 후반 ~ 현재)

스마트폰 보급으로 모바일 앱(iOS/Android) 생태계가 커지고 웹 기술이 고도화되면서 하나의 백엔드로 웹과 앱에 동일한 데이터를 서빙하느 아키텍처가 대세가 되었다.
스프링은 더 이상 화면(HTML)을 만들지 않고, @RestController를 통해 정제된 데이터 포맷인 JSON만 반환한다.

프론트엔드 전문 프레임워크(React, Vue.js, Next.js)가 스프링 API 서버로부터 데이터를 받아 화면을 렌더링하는 구조이다.

구현 방식

클라이언트 측에서 서버에 데이터를 요청하고 수신하면, 그 데이터를 바탕으로 화면을 그린다.


빌드 (Build)

소스 코드로부터 하나의 실행 파일(jar)을 생성하는 과정을 의미한다.
빌드 도구(Build Tools)를 통해 빌드를 수행한다.

빌드 도구의 역할

  • 빌드 자동화(Build Automation)
    우리가 짠 수많은 코드들과 설정 파일, HTML을 다 모아서 컴파일하고 테스트한 뒤 최종적으로 서버에 올릴 수 있는 하나의 실행파일(.jar 또는 .war)로 패키징해준다.

  • 의존성 관리(Dependency Management)
    필요한 라이브러리를 선언하면 빌드 도구가 인터넷의 중앙 저장소(Central Repository)에서 자동으로 다운로드 해준다.

빌드 도구 종류

대표적으로 Gradle, Maven이 있다.

빌드 명령어

운영체제(OS)에 맞는 명령어를 터미널에 입력한다.
빌드 한 뒤 "java-jar 프로젝트명-0.0.1-SNAPSHOT.jar"를 입력해 실행한다.


배포 기술의 진화 흐름

1세대. 가상 서버 직접 배포
2세대. 컨테이너 기반 배포
3세대. 지속적 통합/배포

서버에 직접 배포하기

서버를 대여한 뒤 개발자가 SSH 통신을 통해 직접 터미널로 접속한다.
그 다음 JDK를 설치하고 빌드된 JAR 파일을 전송하여 백그라운드에서 실행하는 방식이다.
서버 환경을 바꿀 때마다 OS 설정, 자바 버전 등을 직접 세팅해야 되므로 "내 컴퓨터에서는 잘 되는데 배포 서버에서는 왜 안 되지?"라는 환경 불일치 문제가 발생할 수 있다.

Docker 컨테이너 기반 배포(현대 표준 가상화)

애플리케이션뿐만 아니라 자바 실행 환경(JRE), OS 환경까지 통째로 하나의 도커이미지(Doker Image)로 캡슐화 한다.
어떤 클라우드 인프라(AWS, Azure, 로컬 PC 등)위에서 구동하든 완벽히 동일한 격리 환경에서 스프링 부트가 실행됨을 보장한다.
스케일아웃(서버 늘리기)과 롤백이 매우 경량화되고 빨라진다.

CI/CD 파이프라인 자동화

개발자가 소스코드를 수정하여 GitHub 같은 원격 저장소에 push하면 자동화 도구(GitHub, Actions, Jenkins 등)가 이를 감지해 다음 과정을 자동으로 수행한다.

파이프라인 흐름

  1. Code Push
  2. 테스트 코드 자동 검증
  3. JAR 빌드
  4. Docker 이미지 생성 및 배포

Spring 실습

먼저 start.spring.io에 접속해 새로운 프로젝트를 만들어주었다.

기본 설정은 이렇게 하였다.

그 다음 Dependencies에서 의존성 목록들을 추가해주었다.

파일을 받아 압축파일을 vscode로 실행해보면

이런식으로 생성이 된 것을 확인할 수가 있다

그 다음 srs에 main에 resources에 들어가 Spring Boot 프로젝트의 설정파일(application.properties)를 작성하였다.

# 이 파일의 환경변수(이 앱에서 사용하는 변수)를 작성한다.

# 이 앱의 이름
spring.application.name=boardapp

# 데이터베이스 연결 설정

# 데이터베이스 주소(URL): localhost:3356(이 컴퓨터의 3306번 포트)
# boardapp_db: 우리 데이터베이스의 이름. 
# createDatabaseIfNotExist(이 데이터베이스가 없으면 만들어라)
spring.datasource.url=jdbc:mysql://localhost:3306/boardapp_db?createDatabaseIfNotExist=true
# 데이터베이스 관리자(root) 아이디 & 비밀번호
spring.datasource.username=root
spring.datasource.password=1234
# Mysql 드라이버 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis 설정
# 매퍼 파일(.xml)의 위치를 지정
mybatis.mapper-locations=classpath:mapper/**/*.xml
# 스네이크 케이스(데이터베이스)를 카멜 케이스(서버)로 변환
mybatis.configuration.map-underscore-to-camel-case=true

# sql 설정: resource에 schema.sql파일을 저장할 거다. 
# 서버가 시작될 때 schema.sql을 항상 실행하라는 뜻이다.
# 서버를 시작할 때 실행해야할 sql문이 있을 때 활용 ex) 테이블 생성 등
spring.sql.init.mode=always

# 타임리프 캐싱 설정: 개발 과정에서는 타임리프의 캐싱 기능을 끈다
spring.thymeleaf.cache=false

그 다음 schema.sql을 생성해 sql문을 작성하였다.

-- schema.sql: 서버가 시작될 때 실행할 sql문을 작성하는 곳

-- 멤버 테이블 생성하기
CREATE TABLE IF NOT EXISTS member ( -- if not exists(menber 테이블이 없으면): 테스트용
    id BIGINT AUTO_INCREMENT PRIMARY KEY, -- bigint: 일반 정수형(int)보다 더 큰 자료형
    username VARCHAR(50) NOT NULL UNIQUE, -- UNIQUE: 중복되면 안됨
    password VARCHAR(100) NOT NULL
);

-- 게시물 테이블 생성하기
CREATE TABLE IF NOT EXISTS post (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(200) NOT NULL, -- 게시물 제목
    content TEXT NOT NULL, -- 게시물 내용
    member_id BIGINT NOT NULL, -- 외래키 (게시물과 사용자를 연결)
    FOREIGN KEY (member_id) REFERENCES member(id)
);

그 다음 mapper 파일을 작성하였다.

<!-- mybatis 매퍼가 사용하는 메서드 내부의 sql 쿼리를 작성하는 곳-->

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--.xml 파일을 호출할 매퍼(MemberMapper)의 위치 -->
<mapper namespace="com.example.board.mapper.MemberMapper">

<!-- save 메서드 내부의 SQL을 정의한다 -->
<!-- save 메서드: 사용자 생성(회원가입 할 때 등)에 사용되는 메서드 -->
<insert id="save" parameterType="com.example.boardapp.domain.Member" useGeneratedKeys="true"
keyProperty="id">
<!-- SQL INSERT문 -->
    INSERT INTO member (username, password)
    VALUES(#{username}, #{password})
</insert>
<!-- save(member) => 이 객체의 데이터를 데이터베이스에 저장한다 -->


<!-- findByUsername 메서드 내부의 SQL을 정의한다 -->
<!-- findByUsername: 사용자이름(username)으로 사용자를 조회한다 -->
<select id="findByUsername" parameterType="String" resultType="com.example.boardapp.domain.Member">
    SELECT id, username, password, FROM member
    WHERE username = #{username}
    </select>
<!-- findByUsername("johndoe") => 데이터베이스에서 johndoe를 찾아줌 -->

</mapper>

마무리

오늘은 시간이 없어서 mapper 작성까지만 진행하였다.
이번 학습에서는 Spring Boot 프로젝트의 환경 설정과 데이터베이스 연동 과정을 학습하였다.

먼저 application.properties 파일을 통해 서버가 사용하는 여러 설정을 관리하는 방법을 배웠다. 데이터베이스 주소, 사용자 계정, 비밀번호, MyBatis 설정, Thymeleaf 설정 등을 하나의 파일에서 관리할 수 있다는 점이 인상적이었다. 특히 JDBC URL을 통해 데이터베이스와 연결하는 과정과 MySQL 드라이버를 지정하는 부분이 중요하다는 것을 알게 되었다.

또한 MyBatis의 Mapper 파일이 어떤 역할을 하는지 학습하였다. Mapper는 자바 코드와 SQL을 연결해주는 역할을 하며, SQL을 XML 파일에서 별도로 관리할 수 있다는 점을 이해할 수 있었다. 처음에는 Mapper 파일이 왜 필요한지 이해하기 어려웠지만, SQL과 자바 코드를 분리하여 관리할 수 있다는 장점을 알게 되었다.

가장 어려웠던 부분은 useGeneratedKeys와 keyProperty 설정이었다. 처음에는 id를 생성하는 기능이라고 생각했지만 실제로는 데이터베이스가 AUTO_INCREMENT를 통해 생성한 기본키 값을 자바 객체에 다시 저장해주는 기능이라는 것을 알게 되었다. 데이터베이스가 id를 생성하고 MyBatis가 그 값을 받아 객체에 넣어준다는 흐름을 이해하는 데 시간이 걸렸다.

또한 localhost와 포트 번호의 의미에 대해서도 배울 수 있었다. 같은 localhost를 사용하더라도 포트 번호에 따라 서로 다른 프로그램이 동작할 수 있다는 점을 이해하게 되었고, 데이터베이스가 왜 특정 포트를 사용하는지도 알게 되었다.

전체적으로 이번 내용은 이전에 학습했던 SQL보다 더 실제 프로젝트에 가까운 내용이었다. 설정 파일, 데이터베이스 연결, MyBatis, Mapper 등의 개념이 처음에는 어렵고 생소하게 느껴졌지만 서버와 데이터베이스가 어떻게 연결되어 동작하는지 조금씩 이해할 수 있었다. 아직은 헷갈리는 부분이 많지만 직접 오류를 해결하고 설정을 수정해보면서 점차 익숙해지고 있다는 점이 의미 있는 학습이었다.

0개의 댓글