# **Spring Boot: 세션 & 쿠키, 파일 업로드 & 다운로드**  

Spring Boot 애플리케이션에서 **세션과 쿠키**는 사용자 상태를 관리하는 데 유용하며, **파일 업로드 및 다운로드** 기능은 다양한 애플리케이션에서 필수적인 기능입니다.  
이번 글에서는 **세션과 쿠키의 개념 및 사용법**을 살펴보고, **파일 업로드 및 다운로드를 처리하는 방법**을 예제와 함께 설명하겠습니다.  

---

# **1. 세션(Session)과 쿠키(Cookie)**  

### **📌 세션(Session)이란?**  
- **서버 측에서 사용자 상태를 유지하는 기술**  
- **각 사용자에게 고유한 세션 ID(Session ID)를 부여하고, 서버에서 해당 사용자의 데이터를 저장**  
- 로그인 정보, 장바구니 데이터 등 **사용자의 지속적인 상태 유지**가 필요한 경우 사용  

### **📌 쿠키(Cookie)란?**  
- **클라이언트(브라우저)에 저장되는 작은 데이터 조각**  
- 서버에서 응답 시 쿠키를 설정하면, 클라이언트는 이후 요청에서 해당 쿠키를 함께 전송  
- **세션과 달리 서버가 아닌 클라이언트에 저장됨**  
- 로그인 유지, 사이트 설정 저장 등에 활용  

---

## **1.1 세션(Session) 사용하기**  

### **✅ 세션 저장 및 조회 예제**  
Spring Boot에서는 `HttpSession`을 사용하여 **세션 데이터를 저장 및 조회**할 수 있습니다.  

```java
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/session")
public class SessionController {

    @PostMapping("/set")
    public String setSession(HttpSession session) {
        session.setAttribute("username", "JohnDoe");  // 세션에 저장
        return "세션에 username=JohnDoe 저장 완료";
    }

    @GetMapping("/get")
    public String getSession(HttpSession session) {
        String username = (String) session.getAttribute("username");
        return username != null ? "세션 값: " + username : "세션 값이 없습니다.";
    }

    @PostMapping("/remove")
    public String removeSession(HttpSession session) {
        session.invalidate();  // 세션 삭제
        return "세션 삭제 완료";
    }
}
```
✔ `setSession()`: `"username"` 값을 세션에 저장  
✔ `getSession()`: 저장된 세션 값을 조회  
✔ `removeSession()`: 세션 데이터를 삭제  

---

## **1.2 쿠키(Cookie) 사용하기**  

### **✅ 쿠키 설정 및 조회 예제**  
Spring Boot에서는 `HttpServletResponse`와 `HttpServletRequest`를 사용하여 쿠키를 설정하고 조회할 수 있습니다.  

```java
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/cookie")
public class CookieController {

    @PostMapping("/set")
    public String setCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("userId", "12345");
        cookie.setMaxAge(60 * 60); // 1시간 동안 유지
        cookie.setPath("/"); // 모든 경로에서 유효
        response.addCookie(cookie);
        return "쿠키 설정 완료: userId=12345";
    }

    @GetMapping("/get")
    public String getCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("userId".equals(cookie.getName())) {
                    return "쿠키 값: " + cookie.getValue();
                }
            }
        }
        return "쿠키가 없습니다.";
    }

    @PostMapping("/delete")
    public String deleteCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("userId", null);
        cookie.setMaxAge(0); // 즉시 삭제
        cookie.setPath("/");
        response.addCookie(cookie);
        return "쿠키 삭제 완료";
    }
}
```
✔ `setCookie()`: `"userId"` 쿠키를 설정  
✔ `getCookie()`: 저장된 쿠키 값을 조회  
✔ `deleteCookie()`: `"userId"` 쿠키를 삭제  

---

# **2. 파일 업로드 및 다운로드**  

Spring Boot에서는 `MultipartFile`을 사용하여 **파일 업로드 및 다운로드**를 간편하게 처리할 수 있습니다.  

---

## **2.1 파일 업로드 처리**  

### **✅ 파일 업로드 예제**
아래는 **Spring Boot에서 파일을 업로드하여 로컬 저장소에 저장하는 코드**입니다.  

```java
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/file")
public class FileUploadController {

    private static final String UPLOAD_DIR = "uploads/";

    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            File uploadDir = new File(UPLOAD_DIR);
            if (!uploadDir.exists()) {
                uploadDir.mkdirs(); // 디렉토리 생성
            }
            String filePath = UPLOAD_DIR + file.getOriginalFilename();
            file.transferTo(new File(filePath)); // 파일 저장
            return "파일 업로드 성공: " + filePath;
        } catch (IOException e) {
            return "파일 업로드 실패: " + e.getMessage();
        }
    }
}
```
✔ `MultipartFile`을 받아서 `uploads/` 디렉토리에 저장  
✔ `file.transferTo(new File(filePath))`로 실제 파일을 저장  
✔ `@RequestParam("file")`로 HTML 폼에서 파일을 받을 수 있음  

### **✅ HTML 파일 업로드 폼 예제**
```html
<form action="/file/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <button type="submit">파일 업로드</button>
</form>
```

---

## **2.2 파일 다운로드 처리**  

### **✅ 파일 다운로드 예제**
Spring Boot에서는 `ResponseEntity`를 사용하여 **파일을 다운로드할 수 있습니다**.  

```java
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.nio.file.Path;
import java.nio.file.Paths;

@RestController
@RequestMapping("/file")
public class FileDownloadController {

    private static final String UPLOAD_DIR = "uploads/";

    @GetMapping("/download/{filename}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String filename) {
        try {
            Path filePath = Paths.get(UPLOAD_DIR).resolve(filename).normalize();
            Resource resource = new UrlResource(filePath.toUri());

            if (!resource.exists()) {
                return ResponseEntity.notFound().build();
            }

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }
}
```
✔ `UrlResource`를 이용하여 파일을 읽어옴  
✔ `CONTENT_DISPOSITION`을 설정하여 **다운로드 가능한 형태로 응답**  
✔ `/file/download/{filename}` 경로로 요청하면 해당 파일을 다운로드 가능  

### **✅ 파일 다운로드 요청 예제**
```html
<a href="/file/download/sample.txt">파일 다운로드</a>
```

---

# **3. 정리**  

✔ **세션(Session)**: 서버 측에서 사용자 정보를 관리 (로그인 상태 유지 등)  
✔ **쿠키(Cookie)**: 클라이언트 측에 저장되며, 서버와의 요청에서 사용 가능  
✔ **파일 업로드**: `MultipartFile`을 이용하여 서버에 파일 저장  
✔ **파일 다운로드**: `ResponseEntity<Resource>`를 활용하여 파일 제공  

Spring Boot에서 **세션과 쿠키를 활용하여 사용자 상태를 관리**하고, **파일 업로드 및 다운로드를 구현하는 방법**을 익히면 다양한 웹 애플리케이션에서 활용할 수 있습니다!