[LG CNS 6기] 본 과정 26일차 TIL / [Spring Boot] - Swagger, mybatis, CORS

김승진·2026년 9월 2일

LG CNS AM 6기 TIL

목록 보기
35/46

1. 오늘의 한 줄 요약

어렵다,,,

2. 오늘 배운 것

2.1 .env로 접속 정보 분리하기

어제까지는 yml에 DB 계정을 그대로 적어뒀는데, 오늘은 그걸 .env 파일로 뺐다. 자바는 .env를 알아서 읽어들이지 않기 때문에, dotenv-java 라이브러리로 직접 읽어서 System.setProperty()로 등록해줘야 yml의 ${DB_URL} 같은 참조가 동작한다. .env는 .gitignore에 넣어서 git에 올라가지 않게 막는 것까지가 한 세트다.

2.2 Swagger — 코드가 문서를 만든다

Swagger는 프론트 없이도 API를 눈으로 확인하고 테스트할 수 있게 해준다. 컨트롤러 위에 @Tag로 이 API들이 어떤 그룹인지 이름 붙이고, 메서드마다 @Operation으로 뭘 하는 API인지 설명을 달고, @ApiResponses로 어떤 상태 코드가 나올 수 있는지 나열해둔다. 다만 착각하기 쉬운 지점이 있다. Swagger 문서에 적은 응답 코드는 사람이 참고하라고 붙여둔 안내문일 뿐, 컴파일러는 그 내용을 신경 쓰지 않는다. 실제로 프론트에 내려가는 상태 코드는 메서드 안에서 ResponseEntity.status(...)로 직접 지정한 값이라서, 문서 고치는 걸 깜빡해도 빌드는 멀쩡히 된다.

2.3 생성자 주입이 표준인 이유

어제는 @Autowired/@Resource로 필드에 바로 주입했는데, 오늘은 @RequiredArgsConstructor + final 조합으로 바꿨다. final은 한 번 값이 들어가면 다시 못 바꾸는 필드라서, 값을 넣을 수 있는 순간이 인스턴스를 만드는 딱 그 시점, 즉 생성자 한 번뿐이다. @RequiredArgsConstructor는 이 final 필드들을 매개변수로 받는 생성자를 롬복이 자동으로 만들어주고, 스프링은 클래스에 생성자가 이거 하나만 있으면 별다른 어노테이션 없이도 그 생성자로 필요한 Bean을 넣어준다. 반대로 필드 주입(@Autowired)은 객체를 일단 빈 채로 만들어놓고 나중에 값을 채우는 방식이라, 그 사이에 의존성이 안 채워진 불완전한 객체가 잠깐 존재한다. 생성자 주입은 값이 없으면 애초에 객체 생성 자체가 안 되니까, 뭔가 빠졌을 때 서버 뜨는 순간 바로 오류로 걸린다는 것이 차이이다.

2.4 로그인과 토큰 — 왜 헤더로 보내는가

로그인이 성공하면 "누가 요청했는지" 확인하는 인증(Authentication)까지는 끝나지만, 이후 요청마다 이 사람을 계속 기억하게 하려면 증표가 필요하다. 그게 토큰이고, 로그인 한 번에 Access Token과 Refresh Token 두 개를 같이 발급한다(지금은 진짜 JWT가 아니라 고정 문자열을 돌려주는 더미 구현). 회원 정보와 토큰은 성격이 달라서 하나의 DTO에 같이 담지 않고 Map으로 묶어서 서비스에서 컨트롤러로 넘기고, 컨트롤러에서 회원 정보는 바디에, 토큰은 HttpHeaders에 나눠 담는다. 이때 Access-Control-Expose-Headers를 빼먹으면 응답은 200으로 정상 와도 브라우저가 그 헤더를 프론트 코드에서 못 읽게 가려버린다.

2.5 CORS와 preflight

리액트(3000번)와 스프링(8000번)은 포트가 다르다는 이유만으로 브라우저가 서로 다른 출처로 취급해서 요청을 막는다. 이게 CORS다. 해결은 WebMvcConfigurer라는 프레임워크가 제공하는 인터페이스를 @Configuration 클래스에서 구현해서, 허용할 출처·메서드·헤더를 명세하는 방식으로 한다. 여기서 allowedMethods에 OPTIONS를 빼먹으면, 브라우저가 실제 요청 전에 미리 보내는 사전 확인 요청(preflight)이 거절당해서 본 요청 자체가 못 나간다.

3. 실습 / 적용

직접 해본 것:

  • Swagger UI(/swagger-ui/index.html)에서 회원가입·로그인 API를 직접 실행해봤다.
  • 리액트 화면에서 로그인 버튼을 눌러 CORS 에러를 브라우저 콘솔에서 직접 확인했다.
  • .env 파일을 만들고 서버를 띄워서 ${DB_URL} 같은 값이 제대로 치환되는지 확인했다.
  • API 호출 후 응답 헤더에 토큰(Authorization, Refresh-Token)이 실려오는 것을 확인했다.

4. 오늘의 회고

  • 느낀 점: 어렵지만, 프론트엔드 파트 때부터 해왔던 빌드업이 연결되는 느낌을 받았다. 7일차에 "토큰은 body가 아니라 header에 담아 통신한다"고 개념으로만 적어뒀던 걸 오늘 2.4에서 직접 코드로 만들었고, 9일차에 CORS와 Preflight를 정리했던 게 오늘 CorsConfig로 실제로 푸는 쪽을 배운 거였다. 18일차에 code/message/data를 담는 제네릭 클래스를 직접 만들었던 것도, 오늘 쓴 Spring의 ResponseEntity였다.
  • 다음에 할 것: CORS에 대해서 더 자세히 알아보기

#LGCNS #LGCNS6기 #개발자 #LGCNSINSPIRECAMP

profile
이것저것

0개의 댓글