묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
'회원 이름 필수 입력' 기능
안녕하세요. 웹계층 회원등록 부분 강의 따라서 코딩하고, HTML 파일도 복붙했는데홈페이지에 이름을 입력 안 해도 '회원 이름을 필수입니다' 메세지가 뜨는 반응이 없이 redirect됩니다. h2에는 이름이 비어 있는 상태로 데이터가 들어와 있습니다. @NotEmpty가 왜 작동하지 않는지 질문드립니다. https://drive.google.com/file/d/1jvu4wiWz3GwoZ3YazNDJWsFTOxgSqt-M/view?usp=sharing
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
readonly 트랜잭션에 update를 수행하는 분리된 트랜잭션 메서드를 호출 할 때 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]안녕하세요 영한님이번에 트랜잭션 적용하면서 @Transactional(readOnly = true) 가 붙은 조회 메서드 내부에 @Transactional(propagation = Propagation.REQUIRES_NEW)가 붙은 외부 클래스의 메서드가 사용 될 때물리 트랜잭션이 분리되었고 각각 다른 트랜잭션임에도변경감지가 적용안되는 부분이 궁금했습니다.아래는 궁금한 부분에 대한 테스트를 진행한 코드입니다. @Service @RequiredArgsConstructor public class TeamService { private final TeamRepository teamRepository; private final TeamExternalService externalService; @Transactional(readOnly = true) public Team findTeamWithNameChangeExternal(Team team, String name) { Team findTeam = teamRepository.findByName(team.getName()); externalService.changeName(findTeam, name); return findTeam; } } @Service @RequiredArgsConstructor public class TeamExternalService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void changeName(Team findTeam, String name) { findTeam.setName(name); } } @Test void findTeamWithNameChangeExternal() { Team team = new Team("team"); Team savedTeam = teamRepository.save(team); teamService.findTeamWithNameChangeExternal(savedTeam, "changeName"); Team findTeam = teamRepository.findByName("changeName"); assertThat(findTeam.getName()).isEqualTo("changeName"); }같은 클래스에서 내부 호출 할 경우에는 REQUIRES_NEW를 적용하더라도 같은 프록시 객체로 해당 메서드가 호출된 상위 트랜잭션의 옵션을 그대로 따라 가기 때문에 변경 감지가 적용안된다고 생각했어요 하지만 이와 다른 외부 클래스의 분리된 트랜잭션에서는 변경 감지가 일어나는 것이 정상이라고 생각했는데왜 변경 감지가 일어나지 않는 것일 까요 ..? 아래는 궁금해서 디버그를 찍어봤어요보니가 두 트랜잭션의 번호가 Transaction@13592로 같고 REQUIRES_NEW가 적용된 트랜잭션의 경우에는 oldTrasactionInfo 이라는 정보를 갖고 해당 메서드를 실행하는 @Transactional(readOnly = true)옵션이 적혀있더라구요 ??그렇다면 내부 호출이 아닌 외부 호출이라도readOnly = true로 조회 성능을 챙기면서 변경 감지를 사용할 순 없는 것인가요 ??
-
해결됨스프링 핵심 원리 - 기본편
lombok과 autowired의 관계
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]lombok은 생성자나 set, get 등 코드를 간결하게 해주는 라이브러리라는 걸 확인했습니다.그리고 lombok으로 @---ArgsConstructor 와 같이 애노테이션을 지정해주어서 생성자를 생략했을 때,lombok 라이브러리 안에 생성자가 존재 -> Spring Container에서 생성자를 찾을 때 lombok 에서 정의된 생성자 참조 -> 생성자가 하나이므로 Autowired가 호출되고 이어서 의존관계 주입의 과정을 거치는 게 맞나요?
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
restSecurityFilterChian에서 addFilterBefore와 authenticationManger 질문
httpSecurity.formLogin()을 설정해주지 않으면, securityFilterChain에 UsernamePasswordAuthenticationFilter가 없지 않나요? restAuthenticationFilter를 UsernamePasswordAuthenticationFilter 앞에 추가할 수 있나요? restAuthenticationFilter에서 authenticationManager를 사용할 수 있도록 설정해주었는데, httpSecurity에 또 세팅해줘야 하는 이유가 있는걸까요?
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
질문드립니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. validation/v3/editForm.html 여기에서form action="item.html" 이게 잘 이해가안됩니다validation/v3/editForm.html 여기에서 검증한걸 @PostMapping("/{itemId}/edit") 여기로 보내야하는거 아닌가요? 근데 이렇게하면 어떻게 가죠?
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
@Transactional을 사용한 테스트에 대해서 질문드립니다
안녕하세요 영한님 강의 정말 잘 듣고 있습니다. ㅎㅎ@Transactional에 대해서 궁금한 점이 생겨서 질문드립니다.@Test @Transactional public void 상품주문() throws Exception { //given Member member = createMember(); Book book = createBook("시골 JPA", 10000, 10); int orderCount = 2; //when Long orderId = orderService.order(member.getId(), book.getId(), orderCount); //then Order getOrder = orderRepository.findOne(orderId); assertEquals("상품 주문시 상태는 ORDER", OrderStatus.ORDER, getOrder.getStatus()); assertEquals("주문한 상품 종류 수가 정확해야 한다.", 1, getOrder.getOrderItems().size()); assertEquals("주문 가격은 가격 * 수량이다.", 10000 * orderCount, getOrder.getTotalPrice()); assertEquals("주문 수량만큼 재고가 줄어야 한다.", 8, book.getStockQuantity()); }해당 코드는 강의에서 작성한 테스트 코드 입니다.지만 저는 지금까지 @Transactional을 테스트 코드에 작성하지 않는 것이 좋다고 알고 있었습니다. 그 이유는 @Transactional을 깜빡하고 작성하지 않는 문제를 테스트 코드에서 잡아 낼 수 있고, 테스트 트랜잭션의 롤백 정책으로 인해 실제 로직과 다르게 작동하기 때문입니다.아래는 제가 @Transactional을 제거하고 코드를 작성해 보았습니다.@Test public void 상품주문() throws Exception { //given Member member = createMember(); Book book = createBook("시골 JPA", 10000, 10); int orderCount = 2; //when Long orderId = orderService.order(member.getId(), book.getId(), orderCount); //then Order getOrder = orderRepository.findOne(orderId); assertEquals("상품 주문시 상태는 ORDER", OrderStatus.ORDER, getOrder.getStatus()); assertEquals("주문한 상품 종류 수가 정확해야 한다.", 1, getOrder.getOrderItems().size()); assertEquals("주문 가격은 가격 * 수량이다.", 10000 * orderCount, getOrder.getTotalPrice()); //Transactional이 없기 때문에 객체를 다시 불러와서 조회 Item findBook = itemRepository.findOne(book.getId()); assertEquals("주문 수량만큼 재고가 줄어야 한다.", 8, findBook.getStockQuantity()); } private Book createBook(String name, int price, int stockQuantity) { Book book = new Book(); book.setName(name); book.setPrice(price); book.setStockQuantity(stockQuantity); itemService.saveItem(book); // service에서 저장 return book; } private Member createMember() { Member member = new Member(); member.setName("회원1"); member.setAddress(new Address("서울", "강가", "123-123")); memberService.join(member); // service에서 저장 return member; } @Repository public class OrderRepository { private final EntityManager em; public OrderRepository(EntityManager em) { this.em = em; } // fetch join으로 LazyLoding 문제 해결 public Order findOne(Long id) { return em.createQuery( "select o from Order o join fetch o.orderItems where o.id = :id", Order.class ) .setParameter("id", id) .getSingleResult(); }위와 같이 코드를 수정해서 @Transactional이 없어도 테스트를 통과하도록 변경하였습니다. 하지만 아래의 코드는 모든 객체를 테스트 작성자가 신경써야 하고 JPA가 관리하는 여러 가지 기능들을 사용하지 못하게 됩니다. 또한 rollback 기능을 사용하지 못해 테스트 작성자가 일일이 DB에 저장된 값을 지워줘야 합니다.영한님은 이와 같은 상황에서는 어떤 선택이 좋다고 생각하는지 궁금합니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
배포 환경에서의 세션, 쿠키
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 아니오[질문 내용]여기에 질문 내용을 남겨주세요.http 프로토콜의 로컬 환경에서는 별도의 설정 없이 클라이언트에서 jsessionid를 헤더에 넣어서 서버에 전송하는 반면, 프론트엔드 서버와 분리된 배포 환경에서는 cors 설정 뿐만 아니라 https 프로토콜로 변경, yml 파일에server: servlet: session: cookie: same-site: none secure: true와 같은 별도의 설정을 완료함으로써 쿠키가 서버로 전달되었습니다. (same-site가 none이면 secure은 꼭 true여야 해서요) 비교적 쿠키-세션 방식이 간단한 것 같지만, 이러한 별도의 설정 그리고 stateful한 쿠키-세션 방식 때문에 배포 환경에서 jwt를 쓰는 것이 좋은지, 아니면 쿠키-세션 방식을 쓰는 것이 좋을 지 잘 모르겠습니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
스프링 프로젝트 초기 설정
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]여기서 Gradle JVM에서 Project SDK(openjdk-21)로 할까요? 아니면 다른 선택지인 21 (Oracle OPenJDK 21.0.2)로 해야 하나요?감사합니다.
-
미해결3. 웹개발 코스 [Enterprise Architecture(EA) X 전자정부프레임워크]
질문있습니다
강의 중에 웹사업 1개에서 응용프로그램 사업100개 +안드로이드 사업100개라는 게 있습니다. 아쉽게도 저는 이게 영상을 보고 도 무슨 말인지 모르겠습니다. 이게 뭘 설명하시는 걸까요? ㅠㅠ
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
강의 순서 질문
기본편 들은 상태인 지금 활용 1만듣고, data jpa 강의 들어도 되나요?jpa를 당장 써야돼서 data jpa 들은 후에 활용2를 들으려고 하는데요, 괜찮을련지 궁금하네요.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
HandlerExceptionResolver 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. was 에 예외가 던져지면 BasicErrorController 를 호출해서 적절한 뷰를 찾아 주는건 알았습니다 근데 was 에 정상 요청이 도착하는데 그 안에 4xx 이나 5xx같은 에러 상태코드가 있는경우 response에 아무런 내용을 채우지도 않고 모델앤뷰도 아무것도 없는걸 리턴할경우를 보내보았는데 이런 뷰는 어디서 생기는걸까요 ? 기본 브라우저에서 제공하는 화면인걸까요 ?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
jdbc 등록 강의에서 레포지터리 테스트코드 돌려서 오류는 안뜨는데 테이블에 값이 안들어가져요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]jdbc 강의중 등록 이라는 강의 순서에서 MemberRepositoryV0 테스트 돌려서 오류는 안나는데 Member라는 h2의 테이블에 아무 값도 안들어가졌습니다. MemberRepositoryV0 코드는 강사님이 알려주신대로 똑같이 했는데 오류가 계속 나서 ppt에 있는 코드 가져와서 오류뜨는거 한개 정도만 잡았는데 레포지터리 코드가 이상한 걸까요? Repository코드package hello.jdbc.repository; import hello.jdbc.connection.DBConnectionUtil; import hello.jdbc.domain.Member; import lombok.extern.slf4j.Slf4j; import java.sql.*; /** * JDBC - DriverManager 사용 */ @Slf4j public class MemberRepositoryV0 { public Member save(Member member) throws SQLException { String sql = "insert into member(member_id, money) values(?, ?)"; Connection con = null; PreparedStatement pstmt = null; try { con = getConnection(); pstmt = con.prepareStatement(sql); pstmt.setString(1, member.getMemberId()); pstmt.setInt(2, member.getMoney()); pstmt.executeUpdate(); return member; } catch (SQLException e) { log.error("db error", e); throw e; } catch (IllegalAccessException e) { throw new RuntimeException(e); } finally { close(con, pstmt, null); } } private void close(Connection con, Statement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { log.info("error", e); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { log.info("error", e); } } if (con != null) { try { con.close(); } catch (SQLException e) { log.info("error", e); } } } private Connection getConnection() throws IllegalAccessException { return DBConnectionUtil.getConnection(); } }
-
미해결스프링 핵심 원리 - 기본편
Context 객체 생성 시 받을 타입 지정
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);이전 강의에선 자기 자신의 타입으로 받게 설정을 했는데xml 설정 형식에선 부모타입인 ApplicationContext 으로 받으신 이유가 있을까요...?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
스프링 공부전에 미리 공부해야할 것이 있을까요?
자바 공부를 마치고 스프링공부를 하려고 강의를 듣는도중 뭔가 한두단계를 건너뛰고 스프링 공부를 시작하는 느낌이 들었습니다..지금 쓰고 있는 annotation, 라이브러리들이 뭔지 하나도 감이 잡히지 않았네요 저런 지식들은 스프링 공부하면서 외우거나 익히는 건가요? 아니면 선행 학습이 필요한 과목이 있나요?
-
해결됨스프링 핵심 원리 - 고급편
유틸성 클래스의 경우 어떻게 LogTrace를 적용할 수 있을까요?
스프링 빈으로 등록하여 사용하지 않는 예를 들어 유틸성 클래스 혹은 직접 인스턴스를 생성하여 사용하는 클래스 등의 경우 LogTrace를 적용시키는 요구사항을 어떻게 만족시킬 수 있을까요? 지금까지 배운 방법은 사용하는 클래스를 빈으로 등록하여서 Proxy로 바꿔치기 하는 방법인데 그렇다면 LogTrace를 적용하고 싶은 모든 클래스를 빈으로 등록해주어야 하나요?
-
미해결3. 웹개발 코스 [Enterprise Architecture(EA) X 전자정부프레임워크]
현강의 및 국비지원 수강생입니다.
다름이아니라 3차과제로 saas를 만들려고합니다. 전자정부프레임에서 제공해주는 것들을 이용해서 작업하려고합니다. 문제는 전자정부프레임에서 기본적으로 다운되는 프로젝트 파일을 그대로 런칭하면, 홈페이지이지saas는 아니지 않나하는 생각에 걱정이되어서 이 전자정부프레임을 saas형태로 어떻게 바꿀 수 있을까 하는 생각이 들었습니다. 1차로는 개발자가 코드로 입력하는 이미지 등등의 부분을사용자가 입력하는 분으로 바꾸면되지않을까 하다가너무 일이 커지고 가능하기는 할까? 하는 생각도 들어서 전문가분께 염치 불구하고 문의드립니다. 어떻게 하면 가능할까요? 전자정부프레임 워크 깃허브에 들어가봤습니다. 혹시 이것 외에 saas형식으로 바꾸어서 사용하고 있는 예제가 있거나 찾을 수 있는 방법이 있을까요?
-
미해결스프링 핵심 원리 - 기본편
TestConfig에서 메서드와 return에 관한 질문입니다.
@Configuration static class TestConfig { @Bean public DiscountPolicy rateDiscountPolicy() { return new RateDiscountPolicy(); } @Bean public DiscountPolicy fixDiscountPolicy() { return new FixDiscountPolicy(); } }1. 여기서 메서드와 return의 관계는 DiscountPolicy rateDiscountPolicy = new RateDiscountPolicy(); 와 같이 다형성을 동반한 관계로 보면 될까요?2. 일반적으로 @Bean이 붙은 메서드의 이름으로 빈 이름이 지정되어 올라가는 것으로 알고 있는데 구현체도 빈 안에 같이 구현된다고 보면 될까요...?타입으로 빈을 조회하는 경우에 메서드의 타입으로 생각을 해서 DiscountPolicy.class 타입으로만 조회하는 줄 알았는데 @Test @DisplayName("특정 하위 타입으로 조회") void findBeanBySubType() { RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class); assertThat(bean).isInstanceOf(RateDiscountPolicy.class); }여기선 RateDiscountPolicy.class 타입으로 빈을 조회하는 것으로 나와서 헷갈려서 질문드립니다...
-
해결됨스프링 핵심 원리 - 기본편
프로토타입에 프록시 적용해보기
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]강의 프로토타입 예시에 프록시를 적용해 보았습니다.의도한 대로 다른 인스턴스를 호출해주는 것 까진 되는 걸 확인했습니다.다만 로그에 CGLIB라는 라이브러리로 상속 받은 가짜 프록시 객체라고 나오지 않는 것 같고, addCount 로직이 적용이 되지 않는 것 같습니다프로토타입 빈에는 프록시를 적용하면 안되는 걸까요? 왜그런걸까요
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
MemberRepository와 MemberService 중복 관련
MemberRepository에 findAll과 findOne이 있는데 MemberService에 findMembers와 findOne의, 실상 같은 역할을 하는 메소드를 중복으로 만들어주는 이유가 뭔가요?
-
미해결Practical Testing: 실용적인 테스트 가이드
잘못된 Interceptor 사용으로 인한 h2-console 접근 문제
안녕하세요. 강의에서 h2 db를 사용하시는 것을 보고 제 개인프로젝트에서 profile이 test일 경우에 h2 db를 써보기로 결정했습니다.그런데 제가 AuthInterceptor를 잘못 만들어서인지 localhost:8080/h2-console url로 접속하면 JSON 응답이 나와버립니다. 어떤 코드가 잘못되었는지, 어떻게 개선해야 하는지 봐주실 수 있으실까요..? 제가 작성한 코드와 설명을 남깁니다. application.ymlspring: profiles: default: local jpa: hibernate: ddl-auto: none mail: host: smtp.gmail.com port: 587 username: kanggi1997@gmail.com password: 보안을위해지웁니다 properties: mail: smtp: starttls: enable: true auth: true --- spring: config: activate: on-profile: local datasource: url: jdbc:postgresql://localhost:5432/forecast?useSSL=false driver-class-name: org.postgresql.Driver username: gunwoo jpa: properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect format_sql: true show-sql: true hibernate: ddl-auto: update --- spring: config: activate: on-profile: test h2: console: enabled: true # /h2-console 설정 datasource: url: jdbc:h2:mem:~/databasesByH2/forecastBE driver-class-name: org.h2.Driver username: sa password: jpa: properties: hibernate: format_sql: true show-sql: true hibernate: ddl-auto: create spring security를 사용하는데 어려움을 느껴 직접 인가를 구현하기 위해 AuthInterceptor와 WebConfig를 구성했고 사이트 회원만 api에 접근할 수 있게 만들었습니다. 로그인하지 않았을 경우 로그인이 필요하다는 메시지를 JSON형태로 전달합니다.AuthInterceptorpackage site.gunwoo.forecastBE.config; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import site.gunwoo.forecastBE.dto.ResponseDTO; @Component @Slf4j public class AuthInterceptor implements HandlerInterceptor { private ObjectMapper mapper = new ObjectMapper(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("OPTIONS".equals(request.getMethod())) { log.debug("preflight은 통과시킴"); return true; } String loggedInUserEmail = (String) request.getSession().getAttribute("loggedInUser"); if (loggedInUserEmail == null) { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpStatus.UNAUTHORIZED.value()); ResponseDTO responseDTO = new ResponseDTO("로그인이 필요합니다.", null); String jsonResponse = mapper.writeValueAsString(responseDTO); response.getWriter().write(jsonResponse); return false; } return true; } } 아래의 addInterceptors 메서드에서 AuthInterceptor의 처리를 거치지 않아도 되는 uri를 정의했습니다. h2 콘솔 접근을 위한 uri인 "/h2-console"도 포함시켰습니다. 하지만 여전히 로그인이 필요하다는 응답이 JSON 형식으로 나타납니다.WebConfigpackage site.gunwoo.forecastBE.config; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final AuthInterceptor authInterceptor; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:5173") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("Authorization", "Content-Type") .exposedHeaders("Custom-Header") .allowCredentials(true) .maxAge(3600); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns("/**") .excludePathPatterns("/user/join") .excludePathPatterns("/user/login") .excludePathPatterns("/test") .excludePathPatterns("/regions") .excludePathPatterns("/h2-console"); //적용이 안되는 듯 } }