묻고 답해요
138만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPA DTO 직접조회 질문 드립니다.
안녕하세요 강사님. 강의 복습 중에 질문이 생겨서 문의 드립니다 JPA 에서 DTO 직접조회를 하는데 (일대다 조회) 일반적으로 엔티티를 DTO 로 변환해서 조회하는 방법보다 더 불편하고 유지보수할때 복잡해 보이는데, 실제 운영에서도 DTO를 직접조회해서 사용을 많이 할까요 ??
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
JPA Update에 관한 질문입니다.
안녕하세요 김영한님! 제가 드리고싶은 질문은 두가지입니다. 예를 들어 게시글에는 이미지를 넣을 수 있으며 게시글과 이미지는 OneToMany관계로 이루어져있습니다. 그리고 Board(게시글) 엔티티에는 @OneToMany(mappedBy = "board", Cascade.ALL, orphonRemoval = true, fetch = LAZY) List<BoardImage> images = new ArrayList<>(); 로 설정했습니다. 질문1. 예를 들어 이미지가 [image1, image2, image3](타입은 이미지객체타입) 에서 [image2, image3, image4] 로 update 할 경우에는 1. delete all & insert all 2. 코드로 기존과 하나하나 비교하면서 delete1 & insert 4 인가? 주로 현업에서는 어떻게 사용하는지 궁금합니다. 질문2. List<BoardImage> images = [image1, image2, image3] 을 갖고 있습니다. 여기서 update 메소드를 사용하여 this.images = List.of(image1, image3, image4)로 덮을경우에는 JPA에서 전부 delete하는지 궁금합니다. 감사합니다
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
Category의 parent_id 생성 관련
안녕하세요, 영한쌤. Category에서 private Category parent에 있지도 않은 parent_id를 @JoinColumn 기준으로 잡아주는 것이 너무 이상했는데 create table할 때 parent_id 필드가 만들어지더라구요. 명시적으로 만든 적이 없는 parent_id를 가지고 @JoinColumn에 이걸로 연결하라고 사용해도 오류가 나지 않을 뿐더러 심지어 parent_id가 생성되는 이유가 궁금합니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
MemberRepository 와 ItemRepository에서의 em 차이점
김영한 강사님 안녕하세요. 좋은 강의 항상 잘 보고있습니다! ㅎㅎ 다름이 아니라 강의를 쭉 듣던 중 궁금증이 생겼습니다. MemberRepository에서 em은 @PersistenceContext를 붙였는데 ItemRepository에서는 @PersistenceContext를 붙이지 않고 그냥 final 처리만 되어있습니다. 제가 보기엔 둘다 같은 역할을 하는 em인것 같은데 소스코드에서는 왜 다르게 구현하신건지 궁금합니다!
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
Eureka 실행하게 되면 상태값이 왜 저는 데스크탑이라고 나오나요?
첫번째가 정상인데 두번째 사진이 제가 한겁니다.. 왜 이렇게 나오는건가요? 그리고 게이트 웨이 서버에서 설정파일에 가시면 routes: - id: first-service# uri: http://localhost:8081/ uri: lb://MY-FIRST-SERVICE 이렇게 설정시 에러가 발생되면서 첫번째 서버쪽으로 안가지네요... java.net.UnknownHostException: failed to resolve 'DESKTOP-KD56ARJ' after 4 queries at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.63.Final.jar:4.1.63.Final] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): |_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain] |_ checkpoint ⇢ HTTP GET "/first-service/welcome" [ExceptionHandlingWebHandler] Stack trace: ㅇ무엇이 문제일까요? ㅠ,ㅠ
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
한 애플리케이션에서 OSIV를 어떻게 나누어 관리하나요?!?!
마지막 참고에서는 트래픽이 많은 API는 OSIV를 끄고, 많은 트래픽이 없어 커넥션을 유지해도 되는 상태인 ADMIN같은 경우는 OSIV를 켜두는 것이 좋다고 하셨습니다!!! 여기서 궁금한 점이 spring.jpa.open-in-view는 글로벌 설정인데 한 애플리케이션에서는 화면 의존적인 서비스가 있을 수도 있고 아닐 수도 있다고 생각합니다. (여러 서비스가 있을 수도 있다고 생각합니다.) 그렇다면 개별적으로 osiv를 설정하는 방법이 있는건가요? (항상 좋은 강의 감사합니다.)
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
상품 서비스 테스트코드
안녕하세요 선생님! 혼자 복습하다가 문득 호기심이 생겨, 상품 서비스의 테스트를 진행해보다 . @SpringBootTestclass ItemServiceTest { @Autowired private ItemService itemService; @Test void 상품_등록() { Book book = new Book(); book.setName("jpa"); book.setPrice(10000); Long itemId = itemService.saveItem(book); Assertions.assertThat(book).isEqualTo(itemService.findOne(itemId)); }} 이렇게 되면 테스트가 실패하는데 그 이유가 객체 타입이 달라서 그런건가요? 테스트 코드의 객체는 Book이고 service 계층에서의 반환형은 Item이라 생각하여 Repository 계층과 Service 계층의 반환형을 모두 Book으로 해도 테스트가 실패합니다. 혹시 이유를 알 수 있을까요?
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
MySQL Dialect 커스텀 관련해서 문의드립니다. (group_concat)
안녕하세요. 영한님 오랜만에 인사드립니다. MySQL Dialect 중 하나인 group_concat을 추가하여 사용해야 하는 상황이라.. 다음과 같이 Custom을 만들고 프로퍼티로 해당 CustomDialect까지 등록되어 정상 동작하는 상황입니다. public class CustomMySQL57Dialect extends MySQL57Dialect { public CustomMySQL57Dialect() { registerFunction("GROUP_CONCAT", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING)); } } 문제는, Native Query로는 `GROUP_CONCAT(DISTINCT xxx)` 처럼 사용이 가능하나, QueryDSL을 이용한 상황에서 해당 DISTINCT가 동작하지 않습니다.. 위와 같은 상황을 겪어보셨을 지 않을까 싶어 여쭤봅니다! QueryDSL 코드 중 일부는 다음과 같습니다. select(Projections.constructor(PaymentFilterConditionDTO.class, transaction.merchantMemberNo, Expressions.stringTemplate("group_concat(DISTINCT {0})", new CaseBuilder().when(transaction.userType.eq(UserType.LINE_PAY)) .then(transaction.transactionType.stringValue() .concat(transaction.paymentMethod.stringValue())) .otherwise(transaction.transactionType.stringValue().concat(transaction.paymentMethod.stringValue()) .concat(SUFFIX_AFFILIATE))))) from(...) where(...) 위의 QueryDSL 코드에서 DISTINCT가 제외되면 예외없이 동작하구요. DISTINCT가 있을 때는 다음과 같이 예외가 발생합니다. - unexpected token : group_concat - unexpected token : DISTINCT 항상 도움주셔서 다시 한 번 감사합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
TDD 관련 질문
안녕하세요 영한님 드디어 야생형 코스가 끝났습니다! 스프링 MVC도 이제 곧 구매 대기 중입니다ㅎㅎ 다름이 아니라 TDD 관련 질문입니다. 질문을 어디다 해야될지 모르겠어서 여기 다 질문합니다.. 1. 보통 Spring에서 각 계층별로 TDD를 진행하나요? 예를 들어, entity -> repository -> service -> controller 순으로 수업을 진행하셨는데 실무에서는 entity 개발 후에 entity 로직에 대한 tdd, respository tdd, service tdd, controller tdd 이런 식으로 다하나요? 2. 각 계층별로 단위 테스트와 통합 테스트를 전부 다 하는 건가요? 현재 프로젝트를 진행하는 데 계층별로 단위 테스트와 통합 테스트를 다 해야되는 건지 궁금했는데 구글링해도 자료가 잘 없네요ㅠㅠ
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
질문
안녕하세요! 간단한 질문이 있습니다. 7:48 초에 defaultZone에서 서비스를 등록할 서버의 주소로 8761 포트에 등록한다는 것까지는 이해가 되었는데 뒤에 /eureka를 붙여주는 이유는 뭔가요?
-
미해결실전! 스프링 데이터 JPA
벌크성 수정 쿼리 질문
안녕하세요 영한님 벌크성 수정 쿼리 강의해주실 때 em.flush() em.clear() 를해야한다(영속성 컨텍스트에 있는 캐시정보들을 DB에 반영하기 위해)고 말씀해주셨는데 만약 어떤 user들의 age가 20이 넘는 사람의 인원수가 5명이라고 가정하고 이들의 나이를 1씩 올렸다고 가정했을때 캐시에는 반영이 안되고 바로 DB에만 반영이 되는데 이때 제가 궁금했던것은 em.flush를 하면 1치캐시에 있는것을 db에 반영시키는것(더티체킹을 포함하여) 이라고 생각해서 이 경우에는 1차캐시가 반영되면 안되는것 아닌가요? 캐시 DB -> 벌크성수정쿼리-> 캐시 DB -> em.flush() -> 캐시 DB 40 40 40 41 40 40
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
join fetch 와 그냥 join 이 동일한 결과를 가지고 오나요?
안녕하세요. 강의 재밌게 잘 보고 있습니다. jpql 예제에서 V3 에는 join fetch 를 사용하고, V4 에서는 join 만 사용하셨는데 동일한 inner join 쿼리가 생성된 것 같습니다. 두 개의 사용 유형이 같은 방식으로 동작하는 것인지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
DTO를 만드는 레이어에 관한 질문
안녕하세요! - 서비스에서 DTO를 만들어서 컨트롤러에게 리턴하는 방식 - 서비스에서는 엔티티를 리턴하고 컨트롤러에서 최종적으로 응답을 내보낼 때 DTO로 감싸서 내보내는 방식 두가지의 방법중에서 어떠한것이 더 좋은 선택일까 고민하고 있습니다. 인터넷을 찾아봐도 많은 논쟁들이 있었지만 무엇이 더 나은 방법이라고 확실하게 답변해주는 건 없는 것 같아요. 개인적으로 서비스에서 DTO를 반환하는게 핵심 비즈니스 로직을 감출 수 있고 의존성을 낮출 수 있다고 생각합니다. 그런데 여기서 문제점이 생기는데, 예를 들어 UserService에 아래와 같은 메소드 2개가 있다고 가정할게요. - findByUserId(Long id) - 내부에서 repo호출하여 유저 엔티티를 가져온 후 DTO로 반환 - updateUser(Long id, ...) `updateUser()`에서는 `findByUserId()`를 호출하여 유저를 가져오고 특정 로직에 따라 업데이트하는 구문을 수행하는 목적입니다. 그런데 `findByUserId()`에서 엔티티를 반환했기때문에 엔티티를 가져오기 위해 다시 한번 repo를 호출하여 실제 엔티티를 가져온 후 정보를 변경하는 로직을 수행해야합니다. 따라서 추가적인 쿼리가 발생하는 문제가 생깁니다. 사실 위 예제는 조금 극단적인 예제이긴 합니다만, 실무에서 개발하다보니 서비스에서 서비스를 호출하는 경우가 빈번하게 발생하더라구요. 하지만 엔티티 자체를 컨트롤러까지 노출하는건 뭔가 꺼려집니다. 질문을 요약하자면, DTO를 서비스에서 리턴하는 방식과 서비스는 엔티티를 리턴하고 컨트롤러에서 DTO로 조합하여 최종 응답을 내보내는 방식 중 어떠한 것이 더 좋다고 생각하시는지 알고 싶습니다. (또는 실무에서 자주 사용하는 방식) 감사합니다 :)
-
미해결실전! Querydsl
2개 이상의 OneToMany 관계에서 fetch join 문제
안녕하세요 영한님! 좋은 강의 너무너무 잘 듣고 있습니다! 다름이 아니라 JPA와 Querydsl을 공부하던 중 궁금한 점이 생겨 이렇게 질문을 드립니다. OneToMany 관계에서는 N+1 문제를 해결하기 위해 fetch join을 사용해 자식 엔티티도 모두 함께 가져오는 것으로 배웠습니다. 만약 아래처럼 하나의 엔티티와 자식 엔티티, 자식 엔티티의 자식 엔티티가 모두 OneToMany 관계인 경우 최상위 엔티티를 가져올 때 한꺼번에 모든 자식 엔티티를 가져올 수 있는 방법이 있는지 여쭤보고 싶습니다..! @Entity public class Forest{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "forest_id") private Long id; @OneToMany(mappedBy = "forest") private List<Tree> trees= new ArrayList<>(); } @Entity public class Tree{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "tree_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "forest_id") private Forest forest; @OneToMany(mappedBy = "tree", cascade = CascadeType.ALL) private List<Leaf> leaves= new ArrayList<>(); } @Entity public class Leaf{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "leaf_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "Tree_id") private Tree tree; } 위 코드를 기준으로 제가 원하는 것은 모든 Forest을 가져올 때, Forest의 자식인 Tree와 Tree의 자식인 Leaf를 함께 가져오는 것인데, 처음엔 단순히 fetch join을 두번 사용하면 될 것이라고 생각했습니다. 따라서 코드를 다음과 같이 작성했습니다. public List<Forest> findAllFetch() { return queryFactory .selectFrom(forest) .leftJoin(forest.trees, tree).fetchJoin() .leftJoin(tree.leaves).fetchJoin() .fetch(); } 하지만 위 코드처럼 두개 이상의 OneToMany 관계에서 fetch join을 여러번 사용하면 MultipleBagFetchException이 발생했습니다. 찾아보니 JPQL에서는 xToMany에서는 일반적으로 fetch join은 한번만 허용된다고 하더라구요... 따라서 제가 생각한 해결책은 위 과정을 2번의 쿼리로 나누어 실행시키는 방법이었습니다. public List<Forest> findAllFetch() { List<Forest> result = queryFactory .selectFrom(forest).distinct() .leftJoin(forest.trees).fetchJoin() .fetch(); List<Long> selectedIds = result.stream() .map(Forest::getId) .collect(Collectors.toList()); queryFactory .selectFrom(tree).distinct() .leftJoin(tree.leaves).fetchJoin() .where(tree.forest.id.in(selectedIds )) .fetch(); return result ; } 혹시 위 코드보다 더 나은 방법이 있는지 아니면 한번의 쿼리로 모든 자식 엔티티를 받아올 수 있는 방법이 있는지 궁금합니다.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
엔티티에 FK컬럼값 관련 질문입니다.
안녕하세요. 엔티티에 @ManyToOne, @OneToMany등과 같이 관계로 설정된 컬럼에 접근하는 방법에 대해 알고 싶습니다. 예를 들어 Order 엔티티가 - id(PK) - user(관계로 설정된 값) 로 설정되어있다고 가정한다면 실제 테이블에는 user_id(FK)가 들어가게 될텐데요. Order.getUser().getId()를 통해 user_id를 가져오게 된다면 불필요하게 user테이블에 쿼리가 한번 더 나가더라구요. 따라서 단순히 Order테이블을 조회한다음 user_id컬럼값을 가져오고 싶은데 이에 대한 방법이 궁금합니다. 인터넷을 좀 찾아보니 @Column(name = "user_id", insertable = false, updatable = false)private Long userId; 위와 같은 형태로 설정해준다음 Order.getUserId()를 통해 가져오라고 나와있던데 맞는 방식인지 헷갈리네요. <질문> 1. API작업을 하다보면 연관관계의 객체를 통해 접근하는게 아닌 위처럼 단순 FK컬럼의 값만 가져오고 싶을때가 있을 것 같은데 어떻게 접근하는게 옳은 방식일까요? 2. 관계를 같이 저장할 때 객체를 통한 저장이 아닌 FK키를 직접 입력해서 저장해주고 싶습니다. 위 코드를 예로 들자면 Order엔티티에 user객체를 직접 저장하는게 아닌 user_id를 입력시켜서 저장시키고 싶습니다. (user객체를 직접 저장하는 경우 무조건 user를 한번 가져와야하기 때문에) 이런 경우에는 어떻게 접근하는게 좋을까요? 감사합니다.
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
Entity 지정 시, persistence.xml에 해당 클래스가 존재하지 않는다는 오류
안녕하세요, 강의를 들으면서 첫 실습 예제를 처음부터 생성해서 따라하던 도중 Entity 어노테이션을 이용하여 클래스를 매핑할 때, 위와 같은 오류가 나더라구요. 구글링을 통해서 해당 오류는 persistence.xml 설정에 <class> 속성을 이용해서 처리되긴 했는데, 제가 책이랑 강의를 다시 다 찾아봐도 해당 설정하신 것은 보질 못해서.. 설정 부분에서 차이가 있어서 그런지 확인 차 문의드립니다. 아! 그리고 프로젝트 생성 방식은 Dynamic Web Content로 첫 생성 -> Configure to Maven Project -> Configure to JPA 위와 같은 단계를 밟아서 생성했습니다. 혹시나 JPA버전과 library 설정 차이일까요...? DB를 오라클을 사용하고, 이클립스를 사용하면서 따라가다보니 설정 디테일 차이가 발생한 것 같은데.. 의견 부탁드리겠습니다..!
-
해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
강사님 데이터베이스 스키마 자동생성 실습에서 방언 테스트할때 MySQL로 하면 에러가 발생합니다.
<!-- 필수 속성 --><property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/><property name="javax.persistence.jdbc.user" value="sa"/><property name="javax.persistence.jdbc.password" value=""/><property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/><property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/><!-- 옵션 --><property name="hibernate.show_sql" value="true"/><property name="hibernate.format_sql" value="true"/><property name="hibernate.use_sql_comments" value="true"/><property name="hibernate.jdbc.batch_size" value="10"/><property name="hibernate.hbm2ddl.auto" value="create" />Hibernate: drop table if exists Member Hibernate: create table Member ( id bigint not null, age integer not null, name varchar(255), primary key (id) ) engine=MyISAM 5월 01, 2021 2:29:55 오전 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@6bda1d19] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. 5월 01, 2021 2:29:55 오전 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@671facee] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. 5월 01, 2021 2:29:55 오전 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " create table Member ( id bigint not null, age integer not null, name varchar(255), primary key (id) ) engine=MyISAM" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table Member ( id bigint not null, age integer not null, name varchar(255), primary key (id) ) engine=MyISAM" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:440) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:424) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:315) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:166) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:135) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:121) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:155) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54) at hellojpa.JpaMain.main(JpaMain.java:10) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement " CREATE TABLE MEMBER ( ID BIGINT NOT NULL, AGE INTEGER NOT NULL, NAME VARCHAR(255), PRIMARY KEY (ID) ) ENGINE=[*]MYISAM"; expected "identifier"; SQL statement: create table Member ( id bigint not null, age integer not null, name varchar(255), primary key (id) ) engine=MyISAM [42001-200]이런식으로 에러가 발생합니다 ㅜ
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
1:1 관계에서 대상 테이블에 외래키가 있는 경우의 질문입니다.
강의에서는 대상 테이블에 외래키가 있는 경우 양방향만 가능하다라고 설명 하셨는데, 강의의 예시는 어디에 FK가 있던 Member 는 Locker 를 가지고 있다는 가정인것 같습니다. 만약 Locker가 FK를 가지고 있는 상태에서 Member 는 Locker를 가지고 있지 않다면 이는 Locker를 주로 보는 것과 동일한 상황일테니 단방향 이어도 상관 없겠지요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Spring Security 관련 질문입니다.
안녕하세요! 로드맵대로 강의를 마치고 이제 실제로 토이 프로젝트를 구현해보고 있습니다. Authorization 헤더에 JWT토큰을 태워서 보내는 형태로 인증을 구현하려고 하는데요. 보통 Spring Security를 사용한다고 나와있어서 해당 라이브러리를 같이 설치한다음 작업하고 있습니다. 관련해서 검색하면서 살펴보고 있는데 제공하는 기능들이 너무나도 많아서 실무에서는 어떤걸 많이 사용하는지 정말 헷갈리네요. 찾아보니 @Secured, @PreAuthorize, @RolesAllowed 라는 3가지의 방법이 존재하는 것 같은데, 실무에서는 어떠한 방법을 사용하나요? (물론 요구사항에 따라 다르겠지만 일반적으로 사용하는걸 알려주시면 제가 검색해서 찾아보겠습니다ㅎㅎ개인적으로는 @PreAuthorize를 사용해서 엔드포인트마다 권한을 세분화하는게 좋다고 생각합니다.)
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Controller DTO리턴 질문
안녕하세요. 영한님의 강좌에서는 컨트롤러에서 DTO를 리턴하는 방식을 사용하고 있더라구요. 그런데 인터넷을 찾아보니 ResponseEntity로 한번 감싸서 리턴하는 방식도 종종 사용하는 것 같습니다. (ResponseEntity를 사용하면 응답코드, 헤더등과 함께 좀 더 세밀하게 리턴값을 조절할 수 있기 때문인 것 같네요) 실무에서는 DTO를 그대로 반환하는 방식과 ResponseEntity로 감싸서 반환하는 방식 중 어떤 방식을 사용하나요? 감사합니다 :)