풀스택 개발자 과정 28일차

너구·2026년 6월 16일

풀스택 성장과정

목록 보기
28/79

JOIN

공통 속성을 기준으로 두 테이블을 합치는 것(join)을 의미합니다.
조인을 통해 두 테이블의 정보를 조합해서 조회할 수 있다.
다음은 조인을 수행하는 방법이다.

...FROM테이블1 JOIN테이블2 ON테이블1.컬럼 = 테이블2.컬럼;

JOIN 예제 (1)

학생, 학과 테이블을 활용해 학생들을 그들이 속한 학과 정보와 함께 조회하라.

-- student, department 테이블을 조인한다.
SELECT*FROM student JOIN department
-- 조인의 조건: 학생의 학과번호(외래키)와 학과의 기본키가 같은 행끼리 합친다
ON student.dept_id = department.dept_id;

student 테이블에는 학생 정보가 department 테이블에는 학과정보가 저장되어있다.
학생 테이블의 dept_id는 외래키이며 학과 테이블의 dept_id는 기본키이다.
JOIN은 두 테이블을 연결하는 기능이다.
학생의 학과번호와 학과 테이블의 학과번호가 같은 데이터끼리 연결하라는 뜻이다.

JOIN 예제 (2)

학생, 학과 테이블을 활용해 학생들을 그들이 속한 학과 정보와 함께 조회하라.
이때 학생 테이블로부터 학번, 이름 컬럼을 가져오고 학과 테이블로부터 학과번호, 학과 이름을 가져오라.

-- dept_id가 두 테이블에 모두 존재하기 때문에 어디서 가져올지 지정해야 한다
-- 가져올 테이블.속성
-- 어디서 가져오든 결과는 같다
SELECT student_id, student_name, department.dept_id, dept_name
FROM student JOIN department 
ON student.dept_id=department.dept_id;

student 테이블과 department 테이블에는 모두 dept_id 컬럼이 존재한다.
따라서 sql은 단순히 dept_id만 작성하면 어느 테이블의 dept_id를 의미하는지 알 수 없다.
그래서 테이블명을 함께 작성해야 한다.
department.dept_id 이 의미는 department 테이블의 dept_id 컬럼을 가져오라는 의미이다.


별칭 (Alias)

SELECT문을 작성할 때 컬럼이나 테이블에 별칭을 부여할 수 있다.

  • 컬럼 별칭 (Column Alias)
    추출 결과의 가독성을 향상시키기 위해 사용됩니다. '컬럼명 (AS) 별칭'으로 작성합니다.

  • 테이블 별칭 (Table Alias)
    SQL문을 빠르고 효율적으로 작성하기 위해 사용됩니다. 특히 조인처럼 SQL문에서 테이블을 여러번 언급해야할 때 효과적입니다. '테이블 (AS) 별칭'으로 작성합니다.

컬럼별칭 예제

제품 테이블로부터 제품의 총 판매량을 추출하라.
단 컬럼의 이름을 총판매량으로 정하라.

-- 별칭을 쓰지 않았을 때 컬럼 이름: SUM(sales)
-- 별칭을 쓴 경우 컬럼 이름: 총판매량
-- AS는 생략 가능
SELECT SUM(sales) AS 총판매량 FROM product;

SUM()함수는 특정 컬럼의 값들을 모두 더한 결과를 반환한다.
위 쿼리는 product 테이블의 sales 컬럼 값을 모두 더하여 총 판매량을 계산하라는 의미이다.
그 다음 AS를 사용해 원하는 이름(총판매량)을 지정하였다.
이렇게하면 결과 컬럼명이 총판매량으로 표시되어 의미를 쉽게 파악할 수 있다.
또한 AS는 생략이 가능하다.

테이블별칭 예제

학생, 학과 테이블을 조인하라.
이 때 학생 테이블의 별칭을 s, 학과 테이블의 별칭을 d로 지정하라.
단 AS는 생략하라.

-- AS를 생략할 경우 띄어쓰기 필수
SELECT*FROM student s JOIN department d
ON s.dept_id = d.dept_id;

student 테이블에 s라는 별칭을 부여하고 department 테이블에 d라는 별칭을 부여하였다.
별칭은 테이블 이름을 짧게 줄여 SQL을 읽기 쉽고 작성하게 편하게 만들어주는 기능이다.


데이터베이스 연습하기

테이블 생성 (1)

부서번호(정수), 부서이름(최대 100자), 전화번호(최대 100자)로 구성된 부서 테이블을 생성하라.
단 다음의 제약 조건을 고려하라.

  • 부서이름, 전화번호는 NULL일 수 없습니다.
  • 부서번호가 기본키이며 데이터 삽입시 1부터 자동으로 할당됩니다.
CREATE TABLE department (
부서번호 int AUTO_INCREMENT,
부서이름 varchar(100) NOT NULL,
전화번호 varchar(100) NOT NULL,
PRIMARY KEY(부서번호)
);

테이블 생성 (2)

사원번호(정수), 사원이름(최대 100자), 나이(정수), 연봉(정수), 직급(최대 100자), 부서ID(정수)로 구성된 사원 테이블을 생성하라.
단 다음의 제약 조건을 고려하라.

  • 사원이름, 부서ID, 직급은 NULL일 수 없습니다.
  • 나이, 연봉은 음수가 될 수 없습니다.
  • 직급은 {사원, 대리, 과장, 차장, 부장} 중에 하나만 가질 수 있습니다
  • '사원번호'가 기본키이며 데이터 삽입시 1부터 자동으로 할당됩니다.
  • 부서ID는 <부서>테이블의 기본키를 참조합니다
CREATE TABLE staff(
사원번호 int AUTO_INCREMENT,
사원이름 varchar(100) NOT NULL,
나이 int unsigned,
연봉 int unsigned,
직급 varchar(100) NOT NULL,
부서ID int NOT NULL,

CHECK (직급 IN ('사원', '대리', '과장', '차장', '부장')),

PRIMARY KEY(사원번호),
FOREIGN KEY(부서ID) REFERENCES department (부서번호)
);

데이터 삽입하기 (1)

부서 테이블에 다음의 데이터를 삽입하라.

INSERT INTO department (부서번호, 부서이름, 전화번호) VALUES (1, '인사팀', '1234-5678');
INSERT INTO department (부서번호, 부서이름, 전화번호) VALUES (2, '영업팀', '2345-6789');
INSERT INTO department (부서번호, 부서이름, 전화번호) VALUES (3, '개발팀', '3456-7890');

데이터 삽입하기 (2)

사원 테이블에 다음의 데이터를 삽입하라.

INSERT INTO staff (사원번호, 사원이름, 나이, 연봉, 직급, 부서ID) VALUES (1, '김부장', 43, 8000, '부장', 1);
INSERT INTO staff (사원번호, 사원이름, 나이, 연봉, 직급, 부서ID) VALUES (2, '이과장', 39, 7000, '과장', 2);
INSERT INTO staff (사원번호, 사원이름, 나이, 연봉, 직급, 부서ID) VALUES (3, '김대리', 36, 6500, '대리', 3);
INSERT INTO staff (사원번호, 사원이름, 나이, 연봉, 직급, 부서ID) VALUES (4, '최대리', 30, 6000, '대리', 2);
INSERT INTO staff (사원번호, 사원이름, 나이, 연봉, 직급, 부서ID) VALUES (5, '정사원', 28, 5000, '사원', 1);

DML 응용

  1. 사원 테이블로부터 모든 직원의 이름과 직급을 조회하라.
SELECT 사원이름, 직급 FROM staff;
  1. 부장, 과장 직급을 가진 직원들만 조회하라.
SELECT*FROM staff WHERE 직급 IN ('부장', '과장')
  1. 성이 '김'씨인 직원들만 조회하라.
SELECT*FROM staff WHERE 사원이름 LIKE '김%';
  1. 나이가 30대인 직원을 조회하라.
SELECT*FROM staff WHERE 나이 BETWEEN 30 AND 39;
  1. 이 회사의 평균 연봉을 구하라.
SELECT AVG(연봉) FROM staff;
  1. 연봉의 최대값과 최소값을 구하라. 이때 각각 '최대연봉', '최소연봉'이라는 별칭을 사용하라.
SELECT MAX(연봉) '최대연봉' , MIN(연봉) '최소연봉' FROM staff;
  1. 부서, 사원 테이블을 활용해 각 사원의 이름과 그들이 속한 부서의 부서ID, 부서 이름을 한 번에 조회하라.
SELECT 사원이름, 부서ID, 부서이름
FROM staff JOIN department
ON staff.부서ID = department.부서번호;

서버 (Server)

서버는 클라이언트에게 서비스를 제공하는 컴퓨터를 의미한다.
역할에 따라 서버의 종류를 다음과 같이 나눌 수 있다.

  • 웹 서버
  • WAS (웹 애플리케이션 서버)
  • 파일 서버
  • 메일 서버
  • Batch 서버

서버/클라이언트 아키텍처

서버 구조

계층형 아키텍처(Layered Archiecture)로 구축된다.


계층 개요


HTTP 통신

웹 서비스는 클라이언트와 서버간의 상호작용으로 이루어지며 HTTP 푸로토콜을 통해 정보를 교환한다.
클라이언트는 서비스를 요청하고 서버는 이를 처리하여 결과를 반환하는 방식이다.


요청 (Request)

클라이언트가 서버의 리소스를 요청할 때 전달하는 메시지로 다음 항목들로 구성된다.

  • Header (헤더) : 요청 방식, 브라우저 정보, 콘텐츠 형식 등 메타 데이터를 포함합니다.
  • Body (본문) : 서버로 전송할 실제 데이터(Payload)를 포함하며, 주로 JSON 형식을 사용합니다.

요청 메서드 (Request Methods)

메서드를 통해 요청 작업의 종류를 명시한다.

  • GET : 데이터 조회 요청
  • POST : 데이터 생성 요청
  • PUT : 데이터 수정 요청
  • DELETE : 데이터 삭제 요청

응답 (Response)

클라이언트의 요청을 처리하고 난 다음 서버가 반환하는 결과물을 의미한다.

  • Header (헤더) : 응답 데이터의 형식, 처리 상태 등 부가적인 정보(메타 데이터)를 포함합니다.
  • Body (본문) : 요청에 대한 결과물(HTML, 이미지, 또는 JSON 데이터 등)이 위치합니다.

응답 코드 (Status Code)

클라이언트 요청에 대한 서버의 응답 상태를 나타내는 코드이다.


서버 프레임워크 (Server Framework)

백엔드 개발 시 데이터베이스 연동, 라우팅, 보안, 데이터처리 등 반복되는 핵심 기능을 미리 구현해 둔 소프트웨어이다.


인증 (Authentication)

인증은 클라이언트가 누구인지 확인하고 서비스 접근 권한을 부여하는 핵심 메커니즘이다.

다음은 주요 인증 매커니즘입니다.

  1. 세션/쿠키 방식
  2. 토큰 기반 인증(JWT)
  3. OAuth2.0 / OIDC

세션/쿠키 기반 인증 (Session-based)

전통적인 서버 중심의 인증방식이다.
서버에 인증 상태를 유지하는(Stateful) 특징이있다.
다음은 인증 흐름이다.

1 사용자가 로그인하면 서버가 사용자의 정보를 확인하고, 메모리에 세션(Session)을 생성한다.
2 서버는 생성된 세션의 고유 식별자인 세션 ID(Session ID)를 클라이언트에게 보낸다.
3 클라이언트는 이 세션 ID를 브라우저의 쿠키(Cookie)에 저장한다.
4 이후 요청마다 쿠키에 세션 ID를 실어 보내면, 서버는 세션 저장소에서 해당 ID를 조회해 인증을 처리한다.

  • 장점
    중요한 사용자 정보가 클랄이언트에 노출되지 않고 서버에만 저장되어 안전하다.
    서버가 세션을 강제로 만료시키거나(로그아웃, 중복 로그인 차단 등) 탈취된 세션을 즉시 무효화할 수 있다.

  • 단점
    사용자가 늘어날수록 서버 메모리(또는 DB) 부하가 커진다.
    서버를 여러대 두는 분산 환경(Scale-out)시 세션을 공유하기 위한 추가 인프라(Redis 등)가 필수적이다.
    쿠키를 사용하므로 웹 브라우저 외의 모바일 앱 등에서는 관리가 번거로울 수 있으며 CSRF(사이트 간 요청 위조)공격에 취약할 수 있다.

토큰 기반 인증 (Token-based)

최근 모바일 환경과 REST API, MSA(마이크로서비스 아키텍처)에서 가장 많이 사용하는 방식이다. 다음은 인증 흐름이다.

1 사용자가 로그인하면 서버는 사용자의 검증된 정보와 권한을 담은 토큰(JWT)을 생성합니다.
2 서버는 Secret-Key를 이용해 이 토큰을 디지털 서명한 뒤 클라이언트에게 발급합니다.
3 클라이언트는 브라우저의 로컬 스토리지(Local Storage)나 쿠키에 토큰을 저장합니다.
4 이후 요청 시 HTTP 헤더에 토큰을 담아 보냅니다.
5 서버는 별도의 DB 조회 없이, 자신이 가진 비밀키로 토큰의 서명(Signature)을 검증합니다.

  • 장점
    서버가 사용자의 상태를 저장하지 않으므로(Stateless) 서버 부하가 낮고 확장성(Scale-out)이 매우 뛰어나다.
    웹, 모바일 앱, 타 서버 간 통신 등 어떤 플랫폼이든 상관 없이 HTTP 헤더를 통해 쉽게 인증할 수 있다.

  • 단점
    토큰이 탈취될 경우 위험하다.
    이를 보완하기 위해 짧은 만료시간과 Access Token과 이를 재발급하기 위한 보관용 Refresh Token을 함께 사용한다.

OAuth 2.0 / OIDC (소셜 로그인 및 인가)

자체적으로 인증 시스템을 구축하는 대신 구글, 카카오, 깃허브 등 신뢰할 수 있는 외부 플랫폼에게 인증을 위탁하는 방식이다.

  • OAuth 2.0 (Authorization): 엄밀히 말하면 '인증'이 아니라 타사 서비스의 자원을 이용할 수 있는 '권한(인가)'을 부여하는 프로토콜이다.

  • OIDC (OpenID Connect): OAuth 2.0 기반 위에서 '인증(Authentication)' 기능을 강화하여 사용자의 신원 정보(ID 토큰)까지 안전하게 받아올 수 있도록 확장한 표준이다.

  • 장점
    회원가입 절차가 생략되어 사용자의 편의성이 극대화된다.
    서버 개발자가 비밀번호 암호화 저장, 2차 인증 등 복잡한 보안 책임을 직접 지지 않아도 된다.

  • 단점
    공유하는 인증 서비스가 탈취되는 경우도 발생할 수 있다.

세션VS토큰 기반 비교


마무리

이번 학습에서는 데이터베이스와 서버의 기본 개념을 함께 학습하며 백엔드 개발의 전반적인 흐름을 이해할 수 있었다.

먼저 SQL을 활용하여 테이블을 생성하고 데이터를 삽입, 수정, 조회하는 방법을 익혔다. 기본키와 외래키를 이용해 테이블 간의 관계를 설계해 보았고, JOIN을 통해 여러 테이블의 데이터를 하나로 결합하여 조회하는 방법도 실습하였다. 또한 집계 함수와 별칭(Alias)을 사용하면서 데이터를 더욱 효율적으로 다루는 방법을 배울 수 있었다.

데이터베이스 학습 이후에는 서버의 역할과 서버-클라이언트 구조에 대해 학습하였다. 사용자가 요청을 보내면 서버가 이를 처리하고 데이터베이스와 통신한 뒤 결과를 다시 반환하는 과정을 이해하면서 웹 서비스가 동작하는 전체 흐름을 파악할 수 있었다.

또한 HTTP 프로토콜과 요청(Request), 응답(Response)의 구조를 살펴보았으며 GET, POST, PUT, DELETE와 같은 요청 메서드의 역할도 학습하였다. 이를 통해 클라이언트와 서버가 어떤 방식으로 데이터를 주고받는지 이해할 수 있었다.

마지막으로 세션 기반 인증, JWT 토큰 기반 인증, OAuth 2.0과 같은 인증 방식들을 비교해 보면서 사용자 인증이 실제 서비스에서 어떻게 이루어지는지 학습하였다. 각 방식마다 장단점이 존재하며 서비스 환경에 따라 적절한 인증 방식을 선택해야 한다는 점도 알게 되었다.

이번 학습을 통해 데이터베이스와 서버가 서로 독립적인 기술이 아니라 하나의 서비스 안에서 유기적으로 연결되어 동작한다는 사실을 이해할 수 있었다. 앞으로는 Spring과 데이터베이스를 연동하여 직접 API를 만들고, 클라이언트의 요청부터 데이터 저장 및 인증 처리까지 구현해 보면서 백엔드 개발 역량을 더욱 키워나가고 싶다.

0개의 댓글